dpvs黑名单中的哈希算法

本文介绍dpvs中黑名单的哈希表的实现

哈希表初始化,申请有2^16个双向链表头的空间,next和prev都指向head。

static int blklst_lcore_init(void *args)
{
    int i;
    if (!rte_lcore_is_enabled(rte_lcore_id()))
    return EDPVS_DISABLED;
    this_blklst_tab = rte_malloc(NULL,
                        sizeof(struct list_head) * DPVS_BLKLST_TAB_SIZE,
                        RTE_CACHE_LINE_SIZE);
    if (!this_blklst_tab)
        return EDPVS_NOMEM;

    for (i = 0; i < DPVS_BLKLST_TAB_SIZE; i++)
        INIT_LIST_HEAD(&this_blklst_tab[i]);

    return EDPVS_OK;
}

哈希散列函数,目的ip和黑名单ip转为主机序后分别与各自数据类型的长度相乘,加上一个随机数,最后取低16位。DPVS_BLKLST_TAB_MASK是16位的全1。

static inline uint32_t blklst_hashkey(const union inet_addr *vaddr,
                                     const union inet_addr *blklst)
{
    /* jhash hurts performance, we do not use rte_jhash_2words here */
    return ((rte_be_to_cpu_32(vaddr->in.s_addr) * 31
                + rte_be_to_cpu_32(blklst->in.s_addr)) * 31
                + dp_vs_blklst_rnd) & DPVS_BLKLST_TAB_MASK;
}

添加黑名单,先检查是否已存在。不重复的话,通过散列函数计算hashkey。申请一个entry空间存储黑名单信息,this_blklst_tab表中hashkey为下标的位置作为链表头,下一跳指向刚申请的entry空间。

static int dp_vs_blklst_add_lcore(int af, uint8_t proto, const union inet_addr *vaddr,
                                  uint16_t vport, const union inet_addr *blklst)
{
    unsigned hashkey;
    struct blklst_entry *new, *blklst_node;

    blklst_node = dp_vs_blklst_lookup(af, proto, vaddr, vport, blklst);
    if (blklst_node) {
        return EDPVS_EXIST;
    }

    hashkey = blklst_hashkey(vaddr, blklst);

    new = rte_zmalloc("new_blklst_entry", sizeof(struct blklst_entry), 0);
    if (new == NULL)
        return EDPVS_NOMEM;

    new->af    = af;
    new->proto = proto;
    new->vport = vport;
    memcpy(&new->vaddr, vaddr, sizeof(union inet_addr));
    memcpy(&new->blklst, blklst, sizeof(union inet_addr));
    list_add(&new->list, &this_blklst_tab[hashkey]);
    rte_atomic32_inc(&this_num_blklsts);

    return EDPVS_OK;
}

list_add要使用 \dpvs\include\list.h的,跑偏了就看不明白了。

static inline void list_add(struct list_head *new, struct list_head *head)
{
    __list_add(new, head, head->next);
}

哈希查找,通过目的ip和黑名单ip计算hashkey,从this_blklst_tab表中hashkey为下标的位置的链表node开始查找,找到目的ip和黑名单ip都相同的node。

struct blklst_entry *dp_vs_blklst_lookup(int af, uint8_t proto, const union inet_addr *vaddr,
                                         uint16_t vport, const union inet_addr *blklst)
{
    unsigned hashkey;
    struct blklst_entry *blklst_node;

    hashkey = blklst_hashkey(vaddr, blklst);
    list_for_each_entry(blklst_node, &this_blklst_tab[hashkey], list) {
        if (blklst_node->af == af && blklst_node->proto == proto &&
            blklst_node->vport == vport &&
            inet_addr_equal(af, &blklst_node->vaddr, vaddr) &&
            inet_addr_equal(af, &blklst_node->blklst, blklst))
            return blklst_node;
    }
    return NULL;
}

理论上支持O(1) 查找的黑名单条目最多2^16个,若出现hashkey重复的情况那就是哈希冲突了。hashkey相同,目的ip和黑名单ip不同,这个entry会在this_blklst_tab[hashkey]这条链表下面顺延。典型的哈希表结构。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值