AF_XDP TX 元数据

本文档描述了在使用 AF_XDP 传输数据包时如何启用卸载。 有关如何在接收端访问类似元数据的信息,请参阅 XDP RX 元数据

总体设计

元数据的预留空间通过 tx_metadata_lenstruct xdp_umem_reg 中的 XDP_UMEM_TX_METADATA_LEN 标志来完成。 因此,对于共享同一 umem 的每个套接字,元数据长度都是相同的。 元数据布局是固定的 UAPI,请参阅 include/uapi/linux/if_xdp.h 中的 union xsk_tx_metadata。 因此,通常,上面的 tx_metadata_len 字段应包含 sizeof(union xsk_tx_metadata)

请注意,在原始实现中,不需要 XDP_UMEM_TX_METADATA_LEN 标志。 应用程序可能会尝试先使用标志创建一个 umem,如果失败,则尝试不带标志的另一个尝试。

预留空间和元数据本身应位于 umem 帧中的 xdp_desc->addr 之前。 在一个帧中,元数据布局如下

       tx_metadata_len
 /                         \
+-----------------+---------+----------------------------+
| xsk_tx_metadata | padding |          payload           |
+-----------------+---------+----------------------------+
                            ^
                            |
                      xdp_desc->addr

AF_XDP 应用程序可以请求大于 sizeof(struct xsk_tx_metadata) 的预留空间。 内核将忽略填充(并且仍将使用 xdp_desc->addr - tx_metadata_len 来定位 xsk_tx_metadata)。 对于不应携带任何元数据的帧(即,没有 XDP_TX_METADATA 选项的帧),内核也会忽略元数据区域。

flags 字段启用特定的卸载

  • XDP_TXMD_FLAGS_TIMESTAMP:请求设备将传输时间戳放入 union xsk_tx_metadatatx_timestamp 字段中。

  • XDP_TXMD_FLAGS_CHECKSUM:请求设备计算 L4 校验和。 csum_start 指定应开始校验和的字节偏移量,csum_offset 指定设备应存储计算出的校验和的字节偏移量。

  • XDP_TXMD_FLAGS_LAUNCH_TIME:请求设备在预定的时间(称为启动时间)安排数据包的传输。 启动时间的值由 union xsk_tx_metadatalaunch_time 字段指示。

除了上述标志之外,为了触发卸载,第一个数据包的 struct xdp_desc 描述符应在 options 字段中设置 XDP_TX_METADATA 位。 另请注意,在多缓冲区数据包中,只有第一块应该携带元数据。

软件 TX 校验和

出于开发和测试目的,可以传递 XDP_UMEM_TX_SW_CSUM 标志到 XDP_UMEM_REG UMEM 注册调用。 在这种情况下,当以 XDK_COPY 模式运行时,TX 校验和在 CPU 上计算。 不要在生产环境中启用此选项,因为它会 негативно 影响性能。

启动时间

所请求的启动时间的值应基于设备的 PTP 硬件时钟 (PHC) 以确保准确性。 AF_XDP 采用与 ETF 排队规则不同的数据路径,后者组织数据包并延迟其传输。 相反,AF_XDP 会立即将数据包传递给设备驱动程序,而不会重新排列它们的顺序或在传输之前保留它们。 由于驱动程序维护 FIFO 行为并且不执行数据包重新排序,因此具有启动时间请求的数据包将阻塞同一 Tx 队列中的其他数据包,直到它被发送。 因此,建议为计划用于未来传输的流量分配单独的队列。

在启动时间卸载功能被禁用的情况下,设备驱动程序应该忽略启动时间请求。 为了正确解释和有意义的操作,启动时间永远不应设置为大于未来最远可编程时间(视界)的值。 不同的设备对启动时间卸载功能有不同的硬件限制。

stmmac 驱动程序

对于 stmmac,TSO 和启动时间 (TBS) 功能对于每个单独的 Tx 队列是互斥的。 默认情况下,驱动程序配置 Tx 队列 0 以支持 TSO,其余 Tx 队列支持 TBS。 可以使用 tc-etf 命令调用驱动程序的 ndo_setup_tc() 回调来启用或禁用启动时间硬件卸载功能。

在增强型正常传输描述符中编程的启动时间的值是一个 32 位值,其中最高有效 8 位表示以秒为单位的时间,其余 24 位表示以 256 纳秒为单位的时间。 编程的启动时间与 PTP 时间(bits[39:8])进行比较,并在 256 秒后翻转。 因此,dwmac4 和 dwxlgmac2 的启动时间视界是未来的 128 秒。

igc 驱动程序

对于 igc,所有四个 Tx 队列都支持启动时间功能。 可以使用 tc-etf 命令调用驱动程序的 ndo_setup_tc() 回调来启用或禁用启动时间硬件卸载功能。 当进入 TSN 模式时,igc 驱动程序将重置设备并创建一个默认的 Qbv 计划,周期时间为 1 秒,所有 Tx 队列始终保持打开状态。

在高级传输上下文描述符中编程的启动时间的值是相对于队列的 Qbv 传输窗口的开始时间的相对偏移量。 可以设置描述符的 Frst 标志以安排数据包用于下一个 Qbv 周期。 因此,i225 和 i226 的启动时间视界是队列的 Qbv 传输窗口的下一个周期的结束时间。 例如,当 Qbv 周期时间设置为 1 秒时,启动时间的视界范围从 1 秒到 2 秒,具体取决于 Qbv 周期当前运行的位置。

查询设备功能

每个设备都通过 netlink netdev 系列导出其卸载功能。 请参阅 Documentation/netlink/specs/netdev.yaml 中的 xsk-flags 功能位掩码。

  • tx-timestamp:设备支持 XDP_TXMD_FLAGS_TIMESTAMP

  • tx-checksum:设备支持 XDP_TXMD_FLAGS_CHECKSUM

  • tx-launch-time-fifo:设备支持 XDP_TXMD_FLAGS_LAUNCH_TIME

有关如何查询此信息,请参阅 tools/net/ynl/samples/netdev.c

示例

有关处理 TX 元数据的示例程序,请参阅 tools/testing/selftests/bpf/xdp_hw_metadata.c。 另请参阅 https://github.com/fomichev/xskgen 以获取更简单的示例。