版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/javaxflinux/article/details/87922319
功能需求
对流量报文进行限速处理,一般表现为___Mbps,或者___秒___报文数等配置形式
即在规定时间内最多通过阀值报文数,后续报文进行丢弃处理。
实现逻辑
当限速周期内,对报文进行统计计数更新和判断,若小于阀值则通过,若大于阀值则丢弃。
当限制周期达到,对限速状态表进行重置。
实现代码
//报文限速
typedef struct advrule_pkt_limit_s {
struct pkt_limit_elemet {
//限速配置
uint64_t limit_time; //间隔时间
int32_t limit_burst; //报文次数
//管理结构
rte_rwlock_t lock; //多核保护
rte_atomic32_t matched_count; //规则匹配次数
uint64_t last_time; //最后更新时间
} rules[ADV_RULE_TOTAL_MAX];
} advrule_pkt_limit_t;
/**
* advrule_pkt_limit_add - advanced rule pkt limit add.
* @split_str: rule info.
*
* return: 0 for success. otherwise -1.
*/
static int advrule_pkt_limit_add(union advrule_line *split_str)
{
int rule_id = 0;
//获取规则id
rule_id = advrule_rule_id_get_by_action(atoi(split_str->handle_action));
if (rule_id < 0 || rule_id >= ADV_RULE_TOTAL_MAX) {
return -1;
}
//限速配置添加
g_advrule_limit->rules[rule_id].limit_time = atoi(split_str->limit_req_time) * rte_get_timer_hz();
g_advrule_limit->rules[rule_id].limit_burst = atoi(split_str->limit_req_burst);
return 0;
}
/**
* advrule_pkt_limit_handle - advanced rule packet limit handle.
* @rule_id: rule id.
*
* return: 0 for success. otherwise -1.
*/
static inline int advrule_pkt_limit_handle(int rule_id)
{
uint64_t cur_time;
if (unlikely(rule_id < 0 || rule_id >= ADV_RULE_TOTAL_MAX)) {
return -1;
}
//获取当前时间
cur_time = rte_rdtsc();
//判断限速周期是否达到
if (unlikely(cur_time > g_advrule_limit->rules[rule_id].last_time + g_advrule_limit->rules[rule_id].limit_time)) {
//阻塞,直到获取到写锁
rte_rwlock_write_lock(&g_advrule_limit->rules[rule_id].lock);
if (likely(cur_time > g_advrule_limit->rules[rule_id].last_time + g_advrule_limit->rules[rule_id].limit_time)) {
//重置限速周期初始状态
rte_atomic32_init(&g_advrule_limit->rules[rule_id].matched_count); //重置报文统计计数
g_advrule_limit->rules[rule_id].last_time = cur_time; //设置限速周期开始时间
rte_wmb();
}
rte_rwlock_write_unlock(&g_advrule_limit->rules[rule_id].lock);
}
//统计计数更新和比较
if (rte_atomic32_add_return(&g_advrule_limit->rules[rule_id].matched_count, 1) > g_advrule_limit->rules[rule_id].limit_burst) {
//限速周期内报文匹配次数超过阀值
return -1;
}
return 0;
}