dpdk ip分片报文重组处理

news2025/1/10 16:58:19

dpdk ip报文重组及分片API及处理逻辑介绍

DPDK的分片和重组实现零拷贝,详细介绍可以参阅DPDK分片与重组用户手则

相关数据结构

/*
 * Fragmented packet to reassemble.
 * First two entries in the frags[] array are for the last and first fragments.
 */
struct ip_frag_pkt {
	RTE_TAILQ_ENTRY(ip_frag_pkt) lru;      /* LRU list */
	struct ip_frag_key key;                /* fragmentation key */
	uint64_t start;                        /* creation timestamp */
	uint32_t total_size;                   /* expected reassembled size */
	uint32_t frag_size;                    /* size of fragments received */
	uint32_t last_idx;                     /* index of next entry to fill */
	struct ip_frag frags[IP_MAX_FRAG_NUM]; /* fragments */
} __rte_cache_aligned;

/* fragmentation table */
struct rte_ip_frag_tbl {
	uint64_t max_cycles;     /* ttl for table entries. */
	uint32_t entry_mask;     /* hash value mask. */
	uint32_t max_entries;    /* max entries allowed. */
	uint32_t use_entries;    /* entries in use. */
	uint32_t bucket_entries; /* hash associativity. */
	uint32_t nb_entries;     /* total size of the table. */
	uint32_t nb_buckets;     /* num of associativity lines. */
	struct ip_frag_pkt *last;     /* last used entry. */
	struct ip_pkt_list lru;       /* LRU list for table entries. */
	struct ip_frag_tbl_stat stat; /* statistics counters. */
	__extension__ struct ip_frag_pkt pkt[]; /* hash table. */
};

在这里插入图片描述

相关API

/**
 * Create a new IP fragmentation table.
 *
 * @param bucket_num
 *   Number of buckets in the hash table. // 哈希表桶数量
 * @param bucket_entries
 *   Number of entries per bucket (e.g. hash associativity).	// 每个桶下挂在的节点数量
 *   Should be power of two.	// 应该为2的幂次方
 * @param max_entries
 *   Maximum number of entries that could be stored in the table.	// 哈希表存储的最大节点数量
 *   The value should be less or equal then bucket_num * bucket_entries. // 该值需小于或等于 桶数量 * 桶节点数量
 * @param max_cycles
 *   Maximum TTL in cycles for each fragmented packet.	// 每个分片包最长超时时间(TTL)
 * @param socket_id
 *   The *socket_id* argument is the socket identifier in the case of	
 *   NUMA. The value can be *SOCKET_ID_ANY* if there is no NUMA constraints.
 * @return
 *   The pointer to the new allocated fragmentation table, on success. NULL on error.	// 返回值为哈希表的地址,创建失败则为NULL
 */
struct rte_ip_frag_tbl *
rte_ip_frag_table_create(uint32_t bucket_num, uint32_t bucket_entries,
	uint32_t max_entries, uint64_t max_cycles, int socket_id)
{
	struct rte_ip_frag_tbl *tbl;
	size_t sz;
	uint64_t nb_entries;

	nb_entries = rte_align32pow2(bucket_num);
	nb_entries *= bucket_entries;
	nb_entries *= IP_FRAG_HASH_FNUM;

	/* check input parameters. */
	if (rte_is_power_of_2(bucket_entries) == 0 ||
			nb_entries > UINT32_MAX || nb_entries == 0 ||
			nb_entries < max_entries) {
		RTE_LOG(ERR, USER1, "%s: invalid input parameter\n", __func__);
		return NULL;
	}

	sz = sizeof (*tbl) + nb_entries * sizeof (tbl->pkt[0]);
	if ((tbl = rte_zmalloc_socket(__func__, sz, RTE_CACHE_LINE_SIZE,
			socket_id)) == NULL) {
		RTE_LOG(ERR, USER1,
			"%s: allocation of %zu bytes at socket %d failed do\n",
			__func__, sz, socket_id);
		return NULL;
	}

	RTE_LOG(INFO, USER1, "%s: allocated of %zu bytes at socket %d\n",
		__func__, sz, socket_id);

	tbl->max_cycles = max_cycles;
	tbl->max_entries = max_entries;
	tbl->nb_entries = (uint32_t)nb_entries;
	tbl->nb_buckets = bucket_num;
	tbl->bucket_entries = bucket_entries;
	tbl->entry_mask = (tbl->nb_entries - 1) & ~(tbl->bucket_entries  - 1);

	TAILQ_INIT(&(tbl->lru));
	return tbl;
}

创建rte_ip_frag_tbl结构,用来暂存分片的表。其中max_cycles表示分片报文超时时间TTL,如10ms:

frag_cycle = (rte_get_tsc_hz()) + MS_PER_S –1) / MS_PER_S * 10;

rte_get_tsc_hz() 函数返回的是1s的CPU频率是多少HZ, 然后按毫秒到秒的进制转换对该值进行一个向上取整得到每一毫秒的CPU频率。之后乘以10就是10毫秒的CPU cycle了。

整个哈希表总的条目数nb_entries = bucket_num * bucket_entries * IP_FRAG_HASH_FNUM(2),后续哈希的时候也会同时查出两个bucket位置。

申请的总内存 sz = sizeof (*tbl) + nb_entries * sizeof (tbl->pkt[0]);
这里分配的是一段连续的内存,减少内存的碎片化。可变长部分可以使用entry_mask 按数组的方式访问所有nb_entries,详见ip_frag_lookup。

/*NO.2使用IPV4包的片段处理新的mbuf。传入的mbuf应该有它的l2_len/l3_len字段设置正确。
 *返回值,1)指向重新组装包的mbuf指针,
 *。     2)NULL;报文为收全;或者收取报文有错误,无法重组。
 *. 这里需要注意重组后的ip的checksum字段为0,需要自己更新。
 */
struct rte_mbuf *
rte_ipv4_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl,
	struct rte_ip_frag_death_row *dr, struct rte_mbuf *mb, uint64_t tms,
	struct ipv4_hdr *ip_hdr)

在这里插入图片描述

每个IP数据包由三个字段:<源IP地址>,<目标IP地址>,唯一标识。
请注意,报文分片表上的所有更新/查找操作都不是线程安全的。因此,如果不同的执行上下文(线程/进程)要同时访问同一个表,那么必须提供一些外部同步机制。每个表项可以保存最多RTE_LIBRTE_IP_FRAG_MAX(默认值为64)片段的数据包的信息。

ip_frag_lookup 利用ipv4_frag_hash获取两个sig值,再利用entry_mask获取到两个bucket的位置,后面紧跟着的位置就是bucket对应的entries。

#define	IP_FRAG_TBL_POS(tbl, sig)	\
	((tbl)->pkt + ((sig) & (tbl)->entry_mask))

struct ip_frag_pkt *
ip_frag_lookup(struct rte_ip_frag_tbl *tbl,
	const struct ip_frag_key *key, uint64_t tms,
	struct ip_frag_pkt **free, struct ip_frag_pkt **stale)
{
	struct ip_frag_pkt *p1, *p2;
	struct ip_frag_pkt *empty, *old;
	uint64_t max_cycles;
	uint32_t i, assoc, sig1, sig2;

	empty = NULL;
	old = NULL;

	max_cycles = tbl->max_cycles;
	assoc = tbl->bucket_entries;

	if (tbl->last != NULL && ip_frag_key_cmp(key, &tbl->last->key) == 0)
		return tbl->last;

	/* different hashing methods for IPv4 and IPv6 */
	if (key->key_len == IPV4_KEYLEN)
		ipv4_frag_hash(key, &sig1, &sig2);
	else
		ipv6_frag_hash(key, &sig1, &sig2);

	p1 = IP_FRAG_TBL_POS(tbl, sig1);
	p2 = IP_FRAG_TBL_POS(tbl, sig2);

	for (i = 0; i != assoc; i++) {
		if (ip_frag_key_cmp(key, &p1[i].key) == 0)
			return p1 + i;
		else if (ip_frag_key_is_empty(&p1[i].key))
			empty = (empty == NULL) ? (p1 + i) : empty;
		else if (max_cycles + p1[i].start < tms)
			old = (old == NULL) ? (p1 + i) : old;

		if (ip_frag_key_cmp(key, &p2[i].key) == 0)
			return p2 + i;
		else if (ip_frag_key_is_empty(&p2[i].key))
			empty = (empty == NULL) ?( p2 + i) : empty;
		else if (max_cycles + p2[i].start < tms)
			old = (old == NULL) ? (p2 + i) : old;
	}

	*free = empty;
	*stale = old;
	return NULL;
}

参考资料:

https://zhuanlan.zhihu.com/p/578599037
https://blog.csdn.net/sjin_1314/article/details/105747246/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/580791.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【测试平台开发】

【测试平台开发】 一、 后端开发 1、常见的技术架构与组件 语言&#xff1a; 项目注重高并发&#xff1a;选用go 注重区块链&#xff1a;选用go、rust(主打高性能) 大型浏览网站&#xff08;如电商&#xff09;&#xff1a;Java 技术架构与组件&#xff1a; 前端技术架构&a…

多元回归预测 | Matlab白鲸算法(BWO)优化BP神经网络回归预测,BWO-BP回归预测,多变量输入模型

文章目录 效果一览文章概述部分源码参考资料效果一览 文章概述 多元回归预测 | Matlab白鲸算法(BWO)优化BP神经网络回归预测,BWO-BP回归预测,多变量输入模型 评价指标包括:MAE、RMSE和R2等,代码质量极高,方便学习和替换数据。要求2018版本及以上。 部分源码 %--------------…

供收藏:国内各种免费可用ChatGPT实测(兼验伪) 版本不断更新补充 更新日期:2023/05/28

文章目录 供收藏&#xff1a;国内各种免费可用ChatGPT实测(兼验伪) 版本不断更新补充 更新日期&#xff1a;2023/05/28国内大厂的人工智能语言模型国内可访问的ChatGPT资源&#xff08;创业公司&#xff09;ZelinAI&#xff08;国内可直接访问的ChatGPT&#xff09;注册邀请码网…

2023全国大学生信息安全竞赛(ciscn)初赛题解

战队信息 安全知识 甚至不用看视频&#xff0c;百度就有答案。除了那个最新的美国时政&#xff0c;其它的ChatGPT就能回答。 Misc 签到卡 关注公众号&#xff0c;根据提示&#xff0c;直接print(open(‘/flag’).read())&#xff1a; 国粹 脑洞题&#xff0c;给的题目原图…

【LeetCode热题100】打卡第6天:正则表达式匹配

文章目录 正则表达式匹配⛅前言&#x1f512;题目&#x1f511;题解 正则表达式匹配 ⛅前言 大家好&#xff0c;我是知识汲取者&#xff0c;欢迎来到我的LeetCode热题100刷题专栏&#xff01; 精选 100 道力扣&#xff08;LeetCode&#xff09;上最热门的题目&#xff0c;适合…

从原理总结chatGPT的Prompt的方法

一 什么是chatGPT chatGPT全称是Generative Pre-trained Transformer&#xff0c;它是一种专注于对话生成的语言模型&#xff0c;可以根据用户的文本输入&#xff0c;做出相应的智能回答。chatGPT是由OpenAI于2018年研发的语言模型&#xff0c;其中OpenAI是于2015年由特斯拉的…

Postman新手教程

博主简介&#xff1a;想进大厂的打工人博主主页&#xff1a;xyk:所属专栏: JavaEE初阶 目录 文章目录 一、Postman背景介绍 二、Postman下载地址 三、Postman简单使用 一、Postman背景介绍 Postman是Chrome插件类产品中的代表产品之一&#xff0c;这款网页调试工具不仅可以调…

位图布隆过滤器

位图 概念&#xff1a;就是用每一位来存放某种状态&#xff0c;适用于海量数据&#xff0c;数据无重复的场景。通常是用来判断某个数据存不存在的。 比如&#xff0c;需要在40亿个整数中&#xff0c;查看某个数是否存在&#xff1f; 1G1024M*1024KB*1024B~10亿字节~80亿比特。…

k8s实战篇1-用minikube发布服务hello-minikube

1 安装minikube curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-darwin-amd64 sudo install minikube-darwin-amd64 /usr/local/bin/minikube 2 Install kubectl binary with curl on macOS 1 Download the latest release: curl -LO "h…

Eclipse Ⅶ

哈喽各位&#xff0c;今天继续分享第七部分的内容&#xff0c;喜欢可以点赞和收藏&#xff0c;这是我的动力来源hahahhah&#xff01; 今天谈谈Eclipse 生成 jar 包、Eclipse 关闭项目以及Eclipse 编译项目。 废话不多说&#xff0c;开始咯&#xff01; Eclipse 生成 jar 包…

Linux常见指令-2

我们本期继续学习Linux基本指令&#xff0c;没有看过第一期的小伙伴建议先看第一期 (4条消息) Linux常见指令-1_KLZUQ的博客-CSDN博客 目录 15.时间相关指令 16.cal指令 17.find指令 18.grep指令 19.zip/unzip指令 20.tar指令 21.bc指令 22.uname –r指令 22.重要的几…

PMP考试总结-2023-05-27

目录 前言 为什么会参加PMP考试&#xff1f; 那么什么是PMP&#xff1f; Plan 目标&#xff1a; 方式方法&#xff1a; 达标标准&#xff1a; Do 执行内容&#xff1a; Check 执行效果 计划的复盘 一、考试前及当天的计划&#xff1a; 二、整个备考计划&#xff…

如何正确地使用ES6提高我们的代码质量

前言 相信每个前端工程师&#xff0c;或者了解前端的人都知道ES6。它是js的一次巨变&#xff0c;它为我们开发js前端项目的时候带来了许多更好的去书写代码的方式。但是很多时候我们可能都没有过度地去关注优化代码这一块内容&#xff0c;哪怕有也只是注意到了一些比较大众化&…

Linux进程概念引入

文章目录 冯诺依曼体系操作系统概念设计目的定位系统调用和库函数的概念 进程概念描述进程PCBtask_struct内容分类 组织进程查看进程通过系统调用获取进程标识符通过系统调用创建进程 冯诺依曼体系 目前我们的计算机基本都是遵守冯诺依曼体系的&#xff0c;在冯诺依曼体系中&am…

[Kubernetes] - RabbitMQ学习

1.消息队列 消息&#xff1a; 在应用间传送的数据队列&#xff0c;先进先出 1.2. 作用 好处&#xff1a;解耦&#xff0c; 容错&#xff0c;削峰坏处&#xff1a;降低系统可用性&#xff0c;系统复杂度提高&#xff0c;一致性问题&#xff1b; RabbitMQ组成部分&#xff1a…

云上高校导航 导入 与 配置教程

开通 云开发 功能&#xff08;首月免费&#xff0c;次月19.9&#xff09;&#xff0c;激活 云数据库、云存储和云函数 功能。 将 项目 文件夹下 最新版本的 文件夹下的 Cloud-based_University_Navigation 整个文件夹 复制到项目路径下&#xff08;比如 D:\WeChatProjects&…

Zabbix Server Api批量添加Zabbix Agent

脚本或使用自动化工具来批量添加Zabbix Agent&#xff0c;从而减少手动操作和提高效率 使用API添加主机可以减少人为错误的发生。通过自动化和脚本&#xff0c;可以确保正确的配置被应用到每个主机上&#xff0c;避免了手动操作可能导致的配置错误。 使用前提条件 1、zabbix…

C919用了哪些人工智能(AI)技术?

#国产大飞机C919商业首飞#近日&#xff0c;C919在国人的期盼下终于迎来了首次商飞&#xff0c;机票已公开售卖。众所周知&#xff0c;C919是一款全新的、先进的大飞机&#xff0c;那你知道它采用了哪些新的人工智能&#xff08;AI&#xff09;技术吗&#xff1f;下面让我来为大…

[golang 微服务] 2. RPC架构介绍以及通过RPC实现微服务

一.简介 在上一节简单了解了微服务定义和优缺点之后&#xff0c;在使用微服务框架之前&#xff0c;需要首先了解一下RPC架构,通过RPC可以更形象了解微服务的工作流程 RPC的概念 RPC(Remote Procedure Call Protocol)&#xff0c;是 远程过程调用的缩写&#xff0c;通俗的说就是…

【提示学习】HPT: Hierarchy-aware Prompt Tuning for Hierarchical Text Classification

论文信息 名称内容论文标题HPT: Hierarchy-aware Prompt Tuning for Hierarchical Text Classification论文地址https://arxiv.org/abs/2204.13413研究领域NLP, 文本分类, 提示学习, 层级标签文本分类提出模型HPT(Hierarchy-aware Prompt Tuning)来源EMNLP 2022源码https://gi…