DPDK中rte_pktmbuf_prepend等三个函数的使用场景及适用时机咨询
DPDK Mbuf操作核心函数的使用场景详解
rte_pktmbuf_prepend()
核心功能
将mbuf的data指针向内存起始方向移动指定字节数,同时增加pkt_len和data_len,为数据包头部预留空间——相当于在现有数据包内容的前面“挤”出一块区域用来添加新内容。
典型使用场景
- 转发时插入头部:比如给数据包添加VLAN标签、GRE隧道头部,或是在SDN场景中插入自定义转发标识标签。
- 反向构造数据包:先写好上层协议的payload(比如HTTP响应内容),再往前预留空间填充TCP、IP、以太网等下层协议头,避免反复调整指针位置。
注意事项
操作前必须确保mbuf有足够的头部预留空间(由编译时RTE_PKTMBUF_HEADROOM参数控制,默认128字节),否则函数会返回NULL甚至触发断言崩溃。
示例代码
// 预留14字节以太网头部空间 uint8_t *eth_hdr = rte_pktmbuf_prepend(mbuf, 14); if (eth_hdr == NULL) { // 处理空间不足的错误逻辑 } // 填充以太网目的MAC、源MAC和类型字段 memcpy(eth_hdr, dst_mac, 6); memcpy(eth_hdr + 6, src_mac, 6); *(uint16_t *)(eth_hdr + 12) = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
rte_pktmbuf_append()
核心功能
扩展mbuf的有效负载尾部,增加data_len和pkt_len的数值,返回指向新尾部空闲空间的指针,用来给数据包“追加尾巴”。
典型使用场景
- 添加尾部校验或标签:比如给以太网帧追加4字节的FCS校验和,或是在自定义协议中添加尾部身份标识标签。
- 拼接数据包内容:比如在应用层处理中,把额外的响应数据追加到现有数据包末尾,避免重新分配mbuf。
- 逐步构造数据包:从头部开始写数据,不断向尾部追加payload内容,直到数据包构造完成。
注意事项
要保证mbuf尾部有足够的空闲空间(由RTE_PKTMBUF_TAILROOM控制,默认512字节),否则函数返回NULL。
示例代码
// 追加4字节FCS校验和空间 uint8_t *fcs_ptr = rte_pktmbuf_append(mbuf, 4); if (fcs_ptr == NULL) { // 处理空间不足错误 } // 计算并填充以太网FCS(小端格式) *(uint32_t *)fcs_ptr = rte_ether_crc32_le(mbuf->data, mbuf->data_len);
rte_pktmbuf_adj()
核心功能
将mbuf的data指针向内存尾部方向移动指定字节数,同时减少pkt_len和data_len,本质是跳过数据包头部的指定内容,让后续处理直接从目标协议层开始。
典型使用场景
- 协议栈解析:比如收到以太网帧后,跳过14字节的以太网头,直接获取IP层头部指针;或是处理完IP头后,跳过对应长度的字节,获取TCP/UDP payload。
- 转发时剥离头部:比如去掉数据包的VLAN标签、或是移除隧道封装的外层头部,还原原始数据包后再转发。
- 跳过无效数据:处理异常数据包时,跳过前面的无效字节段,直接处理有效内容。
注意事项
指定的跳过字节数不能超过当前mbuf的data_len,否则会触发断言错误。如果不确定头部长度,要先做合法性检查。
示例代码
// 跳过14字节以太网头,获取IPv4头部指针 struct rte_ipv4_hdr *ip_hdr = (struct rte_ipv4_hdr *)rte_pktmbuf_adj(mbuf, 14); if (ip_hdr == NULL) { // 处理数据包长度不足的错误 } // 读取源IP地址并转换为主机字节序 uint32_t src_ip = rte_be_to_cpu_32(ip_hdr->src_addr);
内容的提问来源于stack exchange,提问作者codeflow
相关产品推荐
相关产品推荐

