DPDK-Hash(2)

Hash 系列文章目录

DPDK Hash 基本原理



前言

第一章节介绍了DPDK的相关原理,和DPDK采用Cuckoo hash 相关性能指标。本章节主要是介绍DPDK hash 常用的 api 接口。


一、DPDK Hash

DPDK Hash Libary 提供函数主要是实现增加(add),删除(del), 查找(lookup),遍历(iterate)等功能。

二、DPDK hash 常用的API接口

1.DPDK 结构体

创建Hash 使用的参数结构体 如下:

/**
 * Parameters used when creating the hash table.
 */
struct rte_hash_parameters {
	const char *name;		/**< Name of the hash. */   //此名字具备唯一性, 在dpdk 中hash ,ring 等都需要唯一性名字
	uint32_t entries;		/**< Total hash table entries. */     // 创建的Hash 表容量,支持多少个条目
	uint32_t reserved;		/**< Unused field. Should be set to 0 */ // 保留
	uint32_t key_len;		/**< Length of hash key.*/ //每个Hash key 的长度。Hash 表中的Hash key 长度是统一的,有此处设置大小。
	rte_hash_function hash_func;	/**< Primary Hash function used to calculate hash. */ cuckoo Hask 需要两个Hash function,在这里设置Cuckoo Hash的主计算Function
	uint32_t hash_func_init_val;	/**< Init value used by hash_func. */
	int socket_id;			/**< NUMA Socket ID for memory. */ 此处表示Hash创建在那个物理socket_id 上。
	uint8_t extra_flag;		/**< Indicate if additional parameters are present. */
};

2. DPDK 常用接口

DPDK Hash API常用接口如下:

DPDK Hash API 大部分在<rte_hash.h>// Hash table 的创建函数
struct rte_hash *rte_hash_create(const struct rte_hash_parameters *params);

// Hash add API 提供了四种
// hash_header + key
int32_t rte_hash_add_key(const struct rte_hash *h, const void *key);
// Hash_header + key + data. 在对应的Hash 表中存储数据data.
int rte_hash_add_key_data(const struct rte_hash *h, const void *key, void *data);
// Hash_headr +key + hask_function(slaver function)
int32_t rte_hash_add_key_with_hash(const struct rte_hash *h, const void *key, hash_sig_t sig);
// Hash_hader+key+
int32_t rte_hash_add_key_with_hash_data(const struct rte_hash *h, const void *key,hash_sig_t sig, void *data);

// 删除
// 根据key 删除 
int32_t rte_hash_del_key(const struct rte_hash *h, const void *key);
// 根据key和slave Hash function vale 
int32_t rte_hash_del_key_with_hash(const struct rte_hash *h, const void *key, hash_sig_t sig);
// 重置真个hash table
void rte_hash_reset(struct rte_hash *h);

// 遍历整个表
int32_t rte_hash_iterate(const struct rte_hash *h, const void **key, void **data, uint32_t *next);

三、DPDK 提供的Hash 算法

DPDK hash 提供了默认的默认的Hash 计算primary function. 如果不设置h->hash_func 就使用初始化默认的hash 函数
在这里插入图片描述
在这里插入图片描述

Hash 计算的slave function 可以使用rte_hash_hash(const struct rte_hash *h, const void *key) 获取。

Hash 计算函数可以自己定义: 比如l3fwd中。哈希函数就是自定义的。在这里插入图片描述

四、DPDK Hash Demo

#include <stdio.h>
#include <arpa/inet.h>
#include <rte_eal.h>
#include <rte_ethdev.h>
//#include <rte_log.h>
#include <rte_hash.h>
#include <rte_jhash.h>

// hash表,也就是实现增删改查等功能
#define HASH_ENTRI_MAXNUM 1<<12
#define HUSH_KEY_COUNT   1<< 4

// 创建Hash key。 此处采用TUPLE5
struct net_key {
	uint32_t sip;
	uint32_t dip;
	uint16_t sport;
	uint16_t dport;
	char proto;
};

static void print_key (struct net_key *key) {
	printf("sip: %x dip: %x sport: %x dport %x proto:%d \n", 
		key->sip, key->dip, key->sport, key->dport, key->proto);	
}

// DPDK 创建表,队列等都需要自定义名字
static struct rte_hash * create_hash_table(const char *name){
	struct rte_hash_parameters *param = (struct rte_hash_parameters *) malloc(sizeof(struct rte_hash_parameters));
	if (!param) return NULL;

	param->name = name;
	param->entries = HASH_ENTRI_MAXNUM;
	param->key_len = sizeof(struct net_key);
	param->hash_func = rte_jhash; //  hash 函数
	param->hash_func_init_val = 0;
	param->socket_id =rte_socket_id();               // 进行NUMA, 这个是表示每一块内存上的寻址。
	
	struct rte_hash *hash = rte_hash_create(param);
	if (hash == NULL) {
		//RTE_LOG(INFO, Hash, "========================\n");		
	}
	return hash;
}

//DPDK 添加方式有四种
int main(int argc, char *argv[]){

	// DPDK 环境初始化
	rte_eal_init(argc, argv);
	int i = 0;
	uint32_t  net_sip;
	uint32_t  net_dip;
	uint16_t  sport;
	uint16_t  dport;
	inet_pton(AF_INET,"192.168.1.1",&net_sip);
	inet_pton(AF_INET,"192.168.2.1", &net_dip);
	sport = htons(5000);
	dport = htons(6000);

	struct rte_hash *hash  = create_hash_table("cuckoo hash table");
	
	for (i = 0; i < HUSH_KEY_COUNT; i++){
		struct net_key *nk = malloc(sizeof(struct net_key));
		
		nk->sip = net_sip + i;
		nk->dip = net_dip + i;
		nk->sport = sport+ i;
		nk->dport = dport + i;
		nk->proto = i % 2;
		// key 
		// key hash
		// key data+
		// key hash, data
		if(i % 4 == 0) {
			//rte_hash_add_key(hash, nk);
		}else if(i % 4 == 1){ // 第二种添加
			hash_sig_t key2 = rte_hash_hash(hash, nk);
			
			rte_hash_add_key_with_hash(hash, nk, key2);

		}
		else if (i %4 == 2){ // 第三种添加

			uint32_t* tmpdata = (uint32_t *)malloc(sizeof(uint32_t));
			*tmpdata = i;
			
			rte_hash_add_key_data(hash, nk, (void *)tmpdata);

		}else {
			hash_sig_t key4 = rte_hash_hash(hash, nk);
			uint32_t* tmp = (uint32_t *)malloc(sizeof(uint32_t));
			*tmp= i;
			rte_hash_add_key_with_hash_data(hash, nk, key4, (void *)tmp);
		}
		
	}
#if 0
	for (i = 0;i < HUSH_KEY_COUNT;i ++) {
		struct net_key *nk = malloc(sizeof(struct net_key));
		nk->sip = net_sip + i;
		nk->dip = net_dip + i;
		nk->sport = sport+ i;
		nk->dport = dport + i;
		nk->proto = i % 2;

		int idx = rte_hash_lookup(hash, nk);
		printf("hash lookup --> sip: %x, idx: %d\n", nk->sip, idx);
	
		rte_hash_del_key(hash, nk);

		free(nk);
  }	
#endif
	
	struct net_key *key = NULL;
	void *value = NULL;
	uint32_t next =0;
	
	while (rte_hash_iterate( hash, (const void **)&key, &value,&next) >= 0){
		print_key(key);
		if (value != NULL)
			printf("value : %u \n", *(uint32_t*)value);
	}
	
	return 0;
}

结果 :
在这里插入图片描述

总结

提示:这里对文章进行总结:

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

技术鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值