DPDK----mbuf(直接网页翻译,过后修改)

  1. Mbuf 图书馆

mbuf 库提供了分配和释放缓冲区 (mbufs) 的能力, DPDK 应用程序可能会使用它来存储消息缓冲区。消息缓冲区存储在 mempool 中, 使用 mempool 库.

rte_mbuf 结构通常承载网络数据包缓冲区, 但实际上可以是任何数据 (控制数据、事件、…)。rte_mbuf 头结构尽可能小, 当前只使用两个缓存行, 其中最常用的字段位于两个高速缓存行的第一个。

7.1. 数据包缓冲区的设计

对于数据包数据 (包括协议标头) 的存储, 考虑了两种方法:
1.在单个内存缓冲区中嵌入元数据该结构后跟数据包数据的固定大小区域。
2.对元数据结构和数据包数据使用单独的内存缓冲区。

第一种方法的优点是它只需要一个操作就可以分配/释放数据包的整个内存表示。另一方面, 第二种方法更灵活, 并允许将元数据结构的分配与分组数据缓冲区的分配完全分离。

第一种方法是为 DPDK 选择的。元数据包含诸如消息类型、长度、数据起始偏移量以及允许缓冲区链接的其他 mbuf 结构的指针等控制信息。

用于传输网络数据包的消息缓冲区可以处理缓冲区链接, 其中需要多个缓冲区来保存完整的数据包。这是巨型框架的情况下, 由许多 mbufs 连接在一起通过他们的下一个领域。

对于新分配的 mbuf, 数据在消息缓冲区中开始的区域是缓冲区开始后的 RTE_PKTMBUF_HEADROOM 字节, 缓存对齐。消息缓冲区可用于携带系统中不同实体之间的控制信息、数据包、事件等。消息缓冲区还可以使用它们的缓冲区指针指向其他消息缓冲区数据节或其他结构。

图 7.1 和图 7.2 显示了其中的一些场景。

图 7.1带有一个线段的 mbuf

图 7.2三段的 mbuf

缓冲区管理器实现了一组相当标准的缓冲区访问函数来操作网络数据包。

7.2. 存储在内存池中的缓冲区

缓冲区管理器使用 Mempool 库分配缓冲区。因此, 它确保了数据包头在通道和 L3 处理级别之间的最佳交错。mbuf 包含一个字段, 指示它源自的池。调用 rte_pktmbuf_free (m) 时, mbuf 返回到其原始池。

7.3. 构造函数

数据包 mbuf 构造函数由 API 提供。rte_pktmbuf_init () 函数初始化 mbuf 结构中的某些字段, 这些域在创建后 (mbuf 类型、源池、缓冲区起始地址等) 未被用户修改。此函数在池创建时作为回调函数提供给 rte_mempool_create () 函数。

7.4. 分配和释放 mbufs

分配新的 mbuf 要求用户指定 mbuf 应采用的 mempool。对于任何新分配的 mbuf, 它包含一个段, 长度为0。数据的偏移量初始化为缓冲区 (RTE_PKTMBUF_HEADROOM) 中的某些字节的预留空间。

释放 mbuf 意味着将其返回原来的 mempool。mbuf 的内容在存储在池中时不会被修改 (作为自由 mbuf)。构造函数初始化的字段不需要在 mbuf 分配时重新初始化。

释放包含多个段的数据包 mbuf 时, 所有这些字段都将被释放并返回到原始 mempool。

7.5. 操纵 mbufs

此库提供了一些用于在数据包 mbuf 中操作数据的函数。例如:

•获取数据长度
•获取指向数据开始的指针
•数据前预置数据
•数据后追加数据
•删除缓冲区开始处的数据 (rte_pktmbuf_adj ())
•删除缓冲区末尾的数据 (rte_pktmbuf_trim ()) 参阅DPDK API 参考以了解详细信息。

7.6. 元信息

某些信息由网络驱动程序检索并存储在 mbuf 中以使处理更容易。例如, VLAN、RSS 哈希结果 (请参见轮询模式驱动程序) 和一个标志, 指示校验和是由硬件计算的。

mbuf 还包含输入端口 (它来自何处), 以及链中的段 mbufs 数。

对于链式缓冲区, 只有第一个 mbuf 存储此元信息。

例如, IEEE1588 包时间戳机制、VLAN 标记和 IP 校验和计算是 RX 方面的情况。

在 TX 方面, 如果应用程序支持它, 则也可以将某些处理委托给硬件。例如, PKT_TX_IP_CKSUM 标志允许卸载 IPv4 校验和的计算。

下面的示例说明如何在 vxlan 封装的 tcp 数据包上配置不同的 TX 减轻: out_eth/out_ip/out_udp/vxlan/in_eth/in_ip/in_tcp/payload

•计算 out_ip 的校验和:

mb->l2_len = len(out_eth)
mb->l3_len = len(out_ip)
mb->ol_flags |= PKT_TX_IPV4 | PKT_TX_IP_CSUM
set out_ip checksum to 0 in the packet

这在硬件广告 DEV_TX_OFFLOAD_IPV4_CKSUM 支持。

•计算 out_ip 和 out_udp 的校验和:

mb->l2_len = len(out_eth)
mb->l3_len = len(out_ip)
mb->ol_flags |= PKT_TX_IPV4 | PKT_TX_IP_CSUM | PKT_TX_UDP_CKSUM
set out_ip checksum to 0 in the packet
set out_udp checksum to pseudo header using rte_ipv4_phdr_cksum()

这在硬件广告 DEV_TX_OFFLOAD_IPV4_CKSUM 和 DEV_TX_OFFLOAD_UDP_CKSUM 支持。

•计算 in_ip 的校验和:

mb->l2_len = len(out_eth + out_ip + out_udp + vxlan + in_eth)
mb->l3_len = len(in_ip)
mb->ol_flags |= PKT_TX_IPV4 | PKT_TX_IP_CSUM
set in_ip checksum to 0 in the packet

这类似于案例 1), 但 l2_len 是不同的。它是支持的硬件广告 DEV_TX_OFFLOAD_IPV4_CKSUM。请注意, 如果外部 L4 校验和是 0, 则它只能工作。

•计算 in_ip 和 in_tcp 的校验和:

mb->l2_len = len(out_eth + out_ip + out_udp + vxlan + in_eth)
mb->l3_len = len(in_ip)
mb->ol_flags |= PKT_TX_IPV4 | PKT_TX_IP_CSUM | PKT_TX_TCP_CKSUM
set in_ip checksum to 0 in the packet
set in_tcp checksum to pseudo header using rte_ipv4_phdr_cksum()

这类似于案例 2), 但 l2_len 是不同的。它支持硬件广告 DEV_TX_OFFLOAD_IPV4_CKSUM 和 DEV_TX_OFFLOAD_TCP_CKSUM。请注意, 如果外部 L4 校验和是 0, 则它只能工作。

•段内 TCP:

mb->l2_len = len(out_eth + out_ip + out_udp + vxlan + in_eth)
mb->l3_len = len(in_ip)
mb->l4_len = len(in_tcp)
mb->ol_flags |= PKT_TX_IPV4 | PKT_TX_IP_CKSUM | PKT_TX_TCP_CKSUM |
PKT_TX_TCP_SEG;
set in_ip checksum to 0 in the packet
set in_tcp checksum to pseudo header without including the IP
payload length using rte_ipv4_phdr_cksum()

这在硬件广告 DEV_TX_OFFLOAD_TCP_TSO 支持。请注意, 如果外部 L4 校验和是 0, 则它只能工作。

•计算 out_ip、in_ip、in_tcp 的校验和:

mb->outer_l2_len = len(out_eth)
mb->outer_l3_len = len(out_ip)
mb->l2_len = len(out_udp + vxlan + in_eth)
mb->l3_len = len(in_ip)
mb->ol_flags |= PKT_TX_OUTER_IPV4 | PKT_TX_OUTER_IP_CKSUM | \
PKT_TX_IP_CKSUM | PKT_TX_TCP_CKSUM;
set out_ip checksum to 0 in the packet
set in_ip checksum to 0 in the packet
set in_tcp checksum to pseudo header using rte_ipv4_phdr_cksum()

这是支持的硬件广告 DEV_TX_OFFLOAD_IPV4_CKSUM, DEV_TX_OFFLOAD_UDP_CKSUM 和 DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM。

mbuf API 文档 (rte_mbuf) 中描述了标志列表及其精确含义。有关详细信息, 请参阅 testpmd 源代码 (特别是 csumonly 文件)。

7.7. 直接和间接缓冲器

直接缓冲区是完全独立和自包含的缓冲区。间接缓冲区的行为类似于直接缓冲区, 但由于缓冲区指针和数据偏移量引用另一个直接缓冲区中的数据。这在数据包需要重复或碎片化的情况下很有用, 因为间接缓冲区提供了在多个缓冲区中重用相同数据包的方法。

当缓冲区使用 rte_pktmbuf_attach () 函数 “附加” 到直接缓冲区时, 它会变成间接的。每个缓冲区都有一个引用计数器字段, 并且只要将间接缓冲区附加到直接缓冲区, 直接缓冲区上的引用计数器就会递增。同样, 每当分离间接缓冲区时, 直接缓冲区上的引用计数器就会递减。如果结果引用计数器等于 0, 则直接缓冲区将被释放, 因为它不再使用。

在处理间接缓冲区时, 有几件事情要记住。首先, 间接缓冲区从不附加到另一个间接缓冲区。试图将缓冲区 A 附加到附加到 c 的间接缓冲区 B, 使 rte_pktmbuf_attach () 自动附加 A 到 c, 有效地克隆 b. 第二, 为了使缓冲区成为间接的, 它的引用计数器必须等于 1, 即, 它不能已经由另一个间接缓冲区引用。最后, 不能将间接缓冲区重新附加到直接缓冲区 (除非首先将其分离)。

虽然可以使用推荐的 rte_pktmbuf_attach () 和 rte_pktmbuf_detach () 函数直接调用附加/分离操作, 但建议使用更高级的 rte_pktmbuf_clone () 函数, 它负责正确的初始化间接缓冲区, 并可以克隆多个段的缓冲区。

由于间接缓冲区不应实际保存任何数据, 因此应配置间接缓冲区的内存池以指示内存消耗减少。在几个示例应用程序 (例如, IPv4 多播示例应用程序) 中可以找到为间接缓冲区初始化内存池 (以及间接缓冲区的用例示例) 的示例。

7.8. 调试

在调试模式 (启用 CONFIG_RTE_MBUF_DEBUG) 中, MBUF 库的功能在任何操作之前执行健全检查 (如缓冲区损坏、类型错误等)。

7.9. 用例

所有网络应用程序都应使用 mbufs 传输网络数据包。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值