使用dpdk的hash流表增删查

在处理tcp流的时候,处理线程cpu总是很高,导致丢包,dpdk收包占用本来就高,流表的添加删除查找时候配置到百万就容易升到100%,改用了dpdk的hash表试试效果
streamtable.h

class CRteStreamTable
{
public:
    CRteStreamTable();
    ~CRteStreamTable();
    int init(unsigned int keySize, unsigned int tableSize, int index);
    RteStreamNode *add(CTuple4 *key, int &dir);
    RteStreamNode *search(CTuple4 *key, int &dir);
    int remove(CTuple4 *key, RteStreamNode *val);
    void periodProcess();

private:
    struct rte_hash_parameters hs_params;
    struct rte_hash *handle;
    u_int32_t totalCount;
    u_int32_t freeCount;

public:
    RteStreamNode* rteStreamNodes;
    CPcapTcpAssemble *tcpAccessble;
    char    hsStreamTabName[16];
};

streamtable.cpp

CRteStreamTable::CRteStreamTable()
{
    handle = NULL;
}

CRteStreamTable::~CRteStreamTable()
{
    rte_hash_free(handle);
    if(rteStreamNodes)
        delete rteStreamNodes;
}

int CRteStreamTable::init(unsigned int keySize, unsigned int tableSize, int index)
{
    totalCount = freeCount = tableSize;
    snprintf(hsStreamTabName,16,"%s%d","hsStreamTable",index);
    hs_params.name = hsStreamTabName;//多线程,每个线程流表的名称
    hs_params.entries = tableSize;
    hs_params.key_len = keySize;
    hs_params.hash_func = rte_jhash;
    hs_params.hash_func_init_val = 0;
    hs_params.socket_id = 0;
    handle = rte_hash_create(&hs_params);
    RTE_LOG(ERR, HASH, "rte_hash_create :%s\n",rte_strerror(rte_errno));
    if(handle)
    {
        rteStreamNodes = new RteStreamNode[tableSize];
        if(rteStreamNodes)
        {
            return 0;
        }
    }

    return -1;
}

RteStreamNode* CRteStreamTable::add(CTuple4 *key, int& dir)
{
    if(!freeCount)
        return NULL;
    int pos = 0;
    RteStreamNode* val = NULL;
    if(key->isUplink())
    {
        pos = rte_hash_add_key(handle,key);
        if(pos < 0)
        {
            printf("CRteStreamTable::add fail!\n");
            return NULL;
        }
        val = &rteStreamNodes[pos];
        val->dir = dir;
    }
    else
    {
        key->reverse2();
        pos = rte_hash_add_key(handle,key);
        if(pos < 0)
        {
            printf("CRteStreamTable::add fail!\n");
            return NULL;
        }
        key->reverse2();
        val = &rteStreamNodes[pos];
        val->dir = !dir;
    }
    freeCount--;
    return val;
}

RteStreamNode* CRteStreamTable::search(CTuple4 *key, int& dir)
{
    int pos;
    RteStreamNode* val = NULL;
    if(key->isUplink())
    {
        pos = rte_hash_lookup(handle, (const void *)key);
        if(0 <= pos)
        {
            val = &rteStreamNodes[pos];
            dir = val->dir;
        }
    }
    else
    {
        key->reverse2();
        pos = rte_hash_lookup(handle, (const void *)key);
        if(0 <= pos)
        {
            val = &rteStreamNodes[pos];
            dir = !val->dir;
        }
        key->reverse2();
    }

    return val;
}

int CRteStreamTable::remove(CTuple4 *key, RteStreamNode* val)
{
    int pos = -1;
    if(key->isUplink())
        pos = rte_hash_del_key(handle, key);
    else
    {
        key->reverse2();
        pos = rte_hash_del_key(handle, key);
        key->reverse2();
    }
    if(pos < 0)
    {
        printf("CRteStreamTable::remove fail!\n");
        return pos;
    }
    freeCount++;
    return pos;
}

void CRteStreamTable::periodProcess()
{
    double rate = (double)(totalCount - freeCount)/(double)totalCount;
    struct timeval nowtime;
    if(rate > 0.90)
    {
        LOGGER_WARN(formatStr("%s CRteStreamTable::hashlist used rate %.4f", obj->getObjectName().c_str(), rate));
    }

    int tcpTimeout = obj->tcpTimeout/1000;
    gettimeofday(&nowtime, NULL); //获取当前时间
    uint32_t iter = 0;
    const void *next_key;
    void *next_data;

    int pos = 0;
    while ((pos = rte_hash_iterate(handle, &next_key, &next_data, &iter)) >= 0)
    {
        RteStreamNode* val = &rteStreamNodes[pos];
        unsigned int time = nowtime.tv_sec - val->lasttm;
        if(time > tcpTimeout)
        {
            remove((CTuple4*)next_key, val);
            if(val->state == STATE_SUPPORT)
            {
                obj->delStream(obj->streams[val->index]);
            }
        }
        else
        {
            if(val->state==STATE_SUPPORT && obj->streams[val->index]->bFailed)
            {
                remove((CTuple4*)next_key, val);
                obj->delStream(obj->streams[val->index]);            }
        }
    }
}

dpdk hash表有multi的用法不过没看到想要用的接口,性能些微改善了暂时满足就没试用,value可以一起插入到hash表里,也不知道我用的对不对,因为添加的时候也不知道添加的pos值,不想在添加的时候总是new,所以就用数组来放流表的value值了,hash表单独存流的key关系。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值