You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

DPDK 19.11.13启用多写标志删除哈希表键时崩溃

DPDK 19.11.13中rte_hash_del_key()崩溃问题分析与解决

问题背景

作为DPDK新手,我开发的应用需要将网络包信息存入哈希表,并在条目超时后执行删除操作。在DPDK 18.02.2版本中,使用带RTE_HASH_EXTRA_FLAGS_MULTI_WRITER_ADD标志的哈希参数可正常运行,但升级至19.11.13版本后,调用rte_hash_del_key()删除键时出现崩溃。移除该标志则无异常,但应用需要同时执行哈希表的增删操作。

原因分析

DPDK 19.11版本对哈希表的多写标志行为做了严格规范:

  • RTE_HASH_EXTRA_FLAGS_MULTI_WRITER_ADD仅保证哈希表添加操作的线程安全,内部仅对rte_hash_add_key*()系列接口做同步保护;
  • 18.02.2版本中对删除操作的线程安全检查较宽松,未严格限制并发删改;但19.11.13强化了哈希表内部结构的校验,当启用RTE_HASH_EXTRA_FLAGS_MULTI_WRITER_ADD时,rte_hash_del_key()接口无锁保护,并发增删会导致哈希表的桶链表、条目计数等内部结构被非法修改,触发段错误或崩溃。

可行解决方法

方法1:使用全多线程安全的哈希表标志

将哈希表初始化的extra_flag替换为RTE_HASH_EXTRA_FLAGS_MULTI_WRITER,该标志会为所有增删改操作提供线程安全保护,彻底避免并发冲突。缺点是会带来一定的性能开销,但能保证业务逻辑的正确性。

修改后的初始化代码:

struct rte_hash *create_hash_table() {
    struct rte_hash_parameters hash_params = {
        .name = "packet_hash",
        .entries = 16384,
        .key_len = sizeof(struct packet_key),
        .hash_func = rte_hash_crc,
        .hash_func_init_val = 0,
        .socket_id = rte_socket_id(),
        .extra_flag = RTE_HASH_EXTRA_FLAGS_MULTI_WRITER // 替换为全多写安全标志
    };
    return rte_hash_create(&hash_params);
}

方法2:为删除操作添加外部同步锁

如果不想承担全多写标志的性能开销,可以保留RTE_HASH_EXTRA_FLAGS_MULTI_WRITER_ADD,但用DPDK提供的rte_mutex为删除操作加锁,确保同一时间只有一个线程执行删除,避免与添加操作的内部锁冲突。

示例代码:

#include <rte_mutex.h>

rte_mutex_t hash_del_mutex;

// 初始化锁
void init_del_mutex() {
    rte_mutex_init(&hash_del_mutex);
}

// 加锁执行删除
int delete_timeout_entries(struct rte_hash *hash, struct packet_key *key) {
    rte_mutex_lock(&hash_del_mutex);
    int ret = rte_hash_del_key(hash, key);
    rte_mutex_unlock(&hash_del_mutex);
    return ret;
}

方法3:单线程处理删除操作

将超时删除逻辑集中到一个单独的线程中,所有删除请求都提交到该线程统一处理,从根源上避免并发删除与添加的冲突,同时保留RTE_HASH_EXTRA_FLAGS_MULTI_WRITER_ADD的添加操作性能优势。


附:完整源码片段与调试信息

哈希表初始化与删除操作源码

#include <rte_hash.h>
#include <rte_malloc.h>

typedef struct {
    uint32_t src_ip;
    uint32_t dst_ip;
} packet_key;

struct rte_hash *g_hash_table;

int init_hash_table() {
    struct rte_hash_params hash_params = {
        .name = "packet_flow_hash",
        .entries = 32768,
        .key_len = sizeof(packet_key),
        .hash_func = rte_hash_crc,
        .socket_id = rte_socket_id(),
        .extra_flag = RTE_HASH_EXTRA_FLAGS_MULTI_WRITER_ADD
    };
    g_hash_table = rte_hash_create(&hash_params);
    return g_hash_table ? 0 : -1;
}

int del_packet_entry(packet_key *key) {
    return rte_hash_del_key(g_hash_table, key); // 19.11版本中此处崩溃
}

调试信息

DPDK 18.02.2运行日志(无崩溃):

[APP] Added 1245 entries, deleted 321 entries, hash table count: 924
[APP] No errors detected during runtime

DPDK 19.11.13崩溃日志:

Segmentation fault (core dumped)
#0  0x00007f8b1a62d345 in rte_hash_del_key () from ./lib/librte_hash.so.19
#1  0x000055d7a77a2187 in del_packet_entry (key=0x7f8b0c000b60) at app/main.c:145
#2  0x000055d7a77a23a9 in timeout_check_thread (arg=0x0) at app/main.c:189

内容的提问来源于stack exchange,提问作者Vijayraagavan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 10:35:29