流量限速实现分析

版权声明:本文为博主原创文章,未经博主允许不得转载。 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;
}

猜你喜欢

转载自blog.csdn.net/javaxflinux/article/details/87922319