dpdk hash 接口使用

1 某xx示例代码 dpdk 18.02


/* 使用dpdk hash 接口 */
#if 1
#include <arpa/inet.h>
#include <rte_common.h>
#include <rte_memory.h>
#include <rte_rwlock.h>
#include <rte_hash.h>
#include <rte_jhash.h>
#include <rte_mempool.h>

#define ALARM_SUPPRESS_ENTRY_CNT 4096    /* 支持4096个抑制节点 */
#define ALARM_SUPPRESS_INTERVAL  60  /* 60秒只需要同一对象告警1次 */
#define ALARM_SUPPRESS_NODE_OT   60  /* 告警抑制节点的超时时间为60秒 */

/* 告警抑制节点数据 */
typedef struct alarm_suppress_data
{
    uint64_t last_export_ts_sec;    /* 告警最后上报时间 */
    uint64_t last_update_ts_sec;    /* 节点最后更新时间 */
}ALARM_SUPPRESS_DATA_T;

/* 告警抑制节点key */
typedef struct alarm_suppress_key
{
    /* key */
    struct in_addr  address_un_ip4; /* 告警对象的ip */
    uint32_t sid;   /* 告警命中的规则id */
}ALARM_SUPPRESS_KEY_T;

/* 告警抑制表 */
typedef struct alarm_suppress_tbl
{
    rte_rwlock_t rwlock;    /* 表锁 */
    struct rte_hash *suppress_hash; /* 抑制表 */
    struct rte_mempool *mp; /* data的缓存池:SP|SC */
}ALARM_SUPPRESS_TBL_T;

static ALARM_SUPPRESS_TBL_T g_alarm_suppress_tbl = {0};

/*****************************************************
函数名: cleanup_alarm_suppress_tbl
功能    : 删除超时的告警抑制节点
入参    : now_sec - 调用时间:秒
出参    : 无
返回值: 无
作者    : 
时间    : 2023-08-08
说明    : 非线程安全
******************************************************/
static inline int cleanup_alarm_suppress_tbl(uint64_t now_sec)
{
    struct rte_hash *tbl = g_alarm_suppress_tbl.suppress_hash;
    struct rte_mempool *mp = g_alarm_suppress_tbl.mp;
    ALARM_SUPPRESS_KEY_T *key;
    ALARM_SUPPRESS_DATA_T *data;
    uint32_t next = 0;

    /* 遍历告警抑制表 */
    while ( rte_hash_iterate(tbl, (const void**)&key, (void**)&data, &next) >= 0 ) {
        /* 超时删除 */
        if ( data->last_update_ts_sec + ALARM_SUPPRESS_NODE_OT < now_sec ) {
            rte_mempool_put(mp, data);
            rte_hash_del_key(tbl, key);
        }
    }
        
}

/*****************************************************
函数名  : alarm_suppress_now
功能    : 告警是否抑制
入参    : ipv4    - 告警对象的ip地址(ipv4)
        sid     - 告警对应的命中规则id
        now_sec - 告警时间:秒
出参    : 无
返回值: 不抑制返回0,抑制返回1
作者    : 
时间    : 2023-08-08
说明    : 1.暂只支持ipv4
        2.有锁,确保多线程安全
******************************************************/
int alarm_suppress_now(struct in_addr *ipv4, uint32_t sid, uint64_t now_sec)
{
    int ret;
    struct rte_hash *tbl = g_alarm_suppress_tbl.suppress_hash;
    struct rte_mempool *mp = g_alarm_suppress_tbl.mp;
    ALARM_SUPPRESS_KEY_T key;
    ALARM_SUPPRESS_DATA_T *data;
    ALARM_SUPPRESS_DATA_T *add_data;

    if ( unlikely(NULL == ipv4 
      || 0 == now_sec) )
        return 1;

    memcpy(&key.address_un_ip4, ipv4, sizeof(struct in_addr));
    key.sid = sid;
    
    rte_rwlock_write_lock(&g_alarm_suppress_tbl.rwlock);
    ret = rte_hash_lookup_data(tbl, &key, (void**)&data);
    /* 查询失败:不抑制,添加节点 */
    if ( ret < 0 ) {

        /* 获取新节点:失败则不抑制并清理超时节点 */
        ret = rte_mempool_get(mp, (void**)&add_data);
        if ( 0 != ret ) {
            printf("[0]add %u failed and alarm continue yes at ts:%lu\n", 
                key.address_un_ip4.s_addr,
                now_sec);
            cleanup_alarm_suppress_tbl(now_sec);
            rte_rwlock_write_unlock(&g_alarm_suppress_tbl.rwlock);
            return 0;
        }
        /* 填充新节点并加入抑制表 */
        add_data->last_export_ts_sec = now_sec;
        add_data->last_update_ts_sec = now_sec;
        rte_hash_add_key_data(tbl, &key, add_data);
        printf("[1]add %u ok and alarm up at ts:%lu\n", 
            key.address_un_ip4.s_addr,
            now_sec);
        rte_rwlock_write_unlock(&g_alarm_suppress_tbl.rwlock);
        return 0;
    }
    /* 查询成功+非抑制时效:不抑制,更新节点 */
    else if ( data->last_export_ts_sec + ALARM_SUPPRESS_INTERVAL < now_sec ) {
        data->last_update_ts_sec = now_sec;
        data->last_export_ts_sec = now_sec;
        rte_rwlock_write_unlock(&g_alarm_suppress_tbl.rwlock);
        printf("[3]another 60 sec, alarm %u up again at ts:%lu\n", 
            key.address_un_ip4.s_addr,
            now_sec);
        return 0;
    }
    /* 查询成功+抑制时效:抑制,更新节点 */
    else {
        data->last_update_ts_sec = now_sec;
        rte_rwlock_write_unlock(&g_alarm_suppress_tbl.rwlock);
        printf("[2]during 60 sec, alarm %u no at ts:%lu\n", 
            key.address_un_ip4.s_addr,
            now_sec);
        return 1;
    }
    
}

/*****************************************************
函数名: create_alarm_suppress_tbl
功能    : 创建告警抑制哈希表
入参    : 无
出参    : 无
返回值: 成功返回0,否则返回-1
作者    : 
时间    : 2023-08-08
说明    : 1.抑制表与缓存池,大小一样
******************************************************/
int create_alarm_suppress_tbl(void)
{
    struct rte_hash_parameters params = {0};

    /* 设置抑制表参数 */
    params.name               = "alarm_suppress_tbl";
    params.entries            = 8;
    params.reserved           = 0;
    params.key_len            = sizeof(ALARM_SUPPRESS_KEY_T);
    params.hash_func          = rte_jhash;
    params.hash_func_init_val = 0;
    params.socket_id          = SOCKET_ID_ANY;

    /* 初始锁/抑制表/缓存池 */
    rte_rwlock_init(&g_alarm_suppress_tbl.rwlock);
    g_alarm_suppress_tbl.suppress_hash = rte_hash_create(&params);
    if ( NULL == g_alarm_suppress_tbl.suppress_hash ) {
        return -1;
    }
    g_alarm_suppress_tbl.mp = rte_mempool_create("alarm_suppress_mp",
                                8,
                                sizeof(ALARM_SUPPRESS_DATA_T),
                                0, 0,
                                NULL, NULL, NULL, NULL,
                                SOCKET_ID_ANY, MEMPOOL_F_SP_PUT|MEMPOOL_F_SC_GET);
    if ( NULL == g_alarm_suppress_tbl.mp ) {
        return -1;
    }
    
    return 0;
}

#endif


2 说明 dpdk 18.02

  • rte_hash_add_key_data() :添加
    • 将 key-data 对存入hash表
    • key 拷贝复制:局部变量–>拷贝存入hash
    • data 仅存储指针:申请的空间–>放到hash
      • 最好来自mempool;
      • 在rte_hash_iterate && rte_del_key 时,手动释放data,避免空间满
    • 返回值:小于0,添加失败
  • rte_hash_lookup_data():查询
    • 返回值:小于0,查找失败
    • 查到的data,就是存储的指针
      • 最好来自mempool
      • 这样保证能访问的之前存储的数据
      • 这里存储指针,提供自定义的可能,具有通用性
  • rte_hash_iterate(): 遍历
    • 返回值:大于等于0,当前节点可用;小于0,遍历结束
    • 能配合while 进行hash表的遍历
    • 可用于超时删除、打印表等

3 参考资料

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值