dpdk源码解析dpdk-ip_reassembly

本文详细解析DPDK的IP_reassembly样例,介绍了IP分片重组的功能,包括分片节点哈希表初始化、分片包重组接口和分片包回收过程。通过对超时时间、重组后的数据包形式以及最大分片数量的探讨,阐述了DPDK如何处理和重组IP分片数据包。最后,通过执行程序测试了超时、格式和最大分片包数量的情况。
摘要由CSDN通过智能技术生成

1、样例功能

样例代码主要实现重组IP层分片报文,然后将重组后的报文转发出去,如类型为IPV4的数据包A(包总长度1434)、B(包总长度1434)、C(包总长度42)重组后得到数据包D(包总长度2842),集齐完毕之后将数据包A、B、C、D依次根据匹配规则转发到指定端口,流程结束。

如果实现IP重组功能,理论上需要一个API接口,每次接收一个数据包,首先判断这个报文是否是分片包,如果是分片包则调用重组API接口,主要实现传入的数据包如果是最后一个包(就差它就重组完成了),那么将重组后的数据包作为返回值从API接口中获取到,如果不是最后一个包,那么将这个数据包插入到类似于HASH表或者链表中,流程到此结束,继续解析下一个数据包。

实际上DPDK的IP重组样例所实现流程就是这样,下面根据代码流程逐步进行了解。

2、IP重组模块

在此之前需要考虑几个问题:

  1. 是否需要考虑超时删除及如何确定超时时间?(时间太短容易缺失,不可能将分片包一直保留这样内存就爆了)

2. 重组后的数据包是什么形式存在的?(已经重组好为一个数据包 或者 将分片的数据包有序链接为一个链表)

3. 如何确定最多能够实现多少个分片包的重组?

一、分片节点哈希表初始化

从main函数开始,对于EAL初始化、接收发送队列初始化这些和重组功能不相干的这里不再赘述,首先,调用setup_queue_tbl对分片报文所需要的ip_frag_table表进行初始化,流程如下:

这里调用rte_ip_frag_table_create用来创建ip_frag_table,接口功能解释如下:

/**
 * 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);

二、分片包重组接口

进入到循环处理接口main_loop,对接收到的数据包调用reassemble接口进行数据包重组。

这里重点介绍reassemble接口流程

static inline void
reassemble(struct rte_mbuf *m, uint16_t portid, uint32_t queue,
	struct lcore_queue_conf *qconf, uint64_t tms)
{
	struct rte_ether_hdr *eth_hdr;
	struct rte_ip_frag_tbl *tbl;
	struct rte_ip_frag_death_row *dr;
	struct rx_queue *rxq;
	void *d_addr_bytes;
	uint32_t next_hop;
	uint16_t dst_port;

	rxq = &qconf->rx_queue_list[queue];

	eth_hdr = rte_pktmbuf_mtod(m, struct rte_ether_hdr *);

	dst_port = portid;

	/* if packet is IPv4 */ // 判断数据包类型IPV4 or IPV6
	if (RTE_ETH_IS_IPV4_HDR(m->packet_type)) {
		struct rte_ipv4_hdr *ip_hdr;
		uint32_t ip_dst;

		ip_hdr = (struct rte_ipv4_hdr *)(eth_hdr + 1);

		 /* if it is a fragmented packet, then try to reassemble. */ 
		if (rte_ipv4_frag_pkt_is_fragmented(ip_hdr)) { // 判断IPV4数据包是否时分片包
			struct rte_mbuf *mo;

			tbl = rxq->frag_tbl;
			dr = &qconf->death_row;

			/* prepare mbuf: setup l2_len/l3_len. */ // 获取数据链路层
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值