XDP RX 元数据¶
本文档介绍 eXpress Data Path (XDP) 程序如何使用一组辅助函数访问与数据包相关的硬件元数据,以及如何将该元数据传递给其他使用者。
通用设计¶
XDP 有权访问一组 kfunc 来操作 XDP 帧中的元数据。每个希望公开其他数据包元数据的设备驱动程序都可以实现这些 kfunc。kfunc 集在 include/net/xdp.h
中通过 XDP_METADATA_KFUNC_xxx
声明。
目前,支持以下 kfunc。将来,随着支持的元数据越来越多,此集合将会增加
-
__bpf_kfunc int bpf_xdp_metadata_rx_timestamp(const struct xdp_md *ctx, u64 *timestamp)¶
读取 XDP 帧 RX 时间戳。
参数
const struct xdp_md *ctx
XDP 上下文指针。
u64 *timestamp
返回值指针。
返回
成功返回 0,错误返回
-errno
。-EOPNOTSUPP
:表示设备驱动程序未实现 kfunc-ENODATA
:表示此帧没有 RX-timestamp 可用
-
__bpf_kfunc int bpf_xdp_metadata_rx_hash(const struct xdp_md *ctx, u32 *hash, enum xdp_rss_hash_type *rss_type)¶
读取 XDP 帧 RX 哈希。
参数
const struct xdp_md *ctx
XDP 上下文指针。
u32 *hash
返回值指针。
enum xdp_rss_hash_type *rss_type
RSS 类型的返回值指针。
描述
RSS 哈希类型 (rss_type) 指定 NIC 硬件在计算 RSS 哈希值时使用的数据包标头部分。可以通过 enum xdp_rss_hash_type
解码 RSS 类型,可以匹配单个 L3/L4 位 XDP_RSS_L*
或组合的传统 _RSS 哈希类型_ XDP_RSS_TYPE_L*
。
返回
成功返回 0,错误返回
-errno
。-EOPNOTSUPP
:表示设备驱动程序未实现 kfunc-ENODATA
:表示此帧没有 RX-hash 可用
-
__bpf_kfunc int bpf_xdp_metadata_rx_vlan_tag(const struct xdp_md *ctx, __be16 *vlan_proto, u16 *vlan_tci)¶
获取 XDP 数据包最外层 VLAN 标签
参数
const struct xdp_md *ctx
XDP 上下文指针。
__be16 *vlan_proto
VLAN 标签协议标识符 (TPID) 的目标指针。
u16 *vlan_tci
VLAN TCI(VID + DEI + PCP)的目标指针
描述
如果成功,vlan_proto
包含 _标签协议标识符 (TPID)_,通常为 ETH_P_8021Q
或 ETH_P_8021AD
,但有些网络可能使用自定义 TPID。vlan_proto
以 **网络字节顺序 (BE)** 存储,应按如下方式使用:if (vlan_proto == bpf_htons(ETH_P_8021Q)) do_something();
vlan_tci
包含 VLAN 标签的其余 16 位。驱动程序应以 **主机字节顺序(通常为 LE)** 提供这些位,因此 bpf 程序不应执行字节转换。根据 802.1Q 标准,_VLAN TCI(标签控制信息)_ 是一个位字段,包含:_VLAN 标识符 (VID)_,可以使用 vlan_tci & 0xfff
读取,_丢弃资格指示符 (DEI)_ - 1 位,_优先级代码点 (PCP)_ - 3 位。有关 DEI 和 PCP 的详细含义,请参阅其他来源。
返回
成功返回 0,错误返回
-errno
。-EOPNOTSUPP
:设备驱动程序未实现 kfunc-ENODATA
:VLAN 标签未剥离或不可用
XDP 程序可以使用这些 kfunc 将元数据读取到堆栈变量中以供自己使用。或者,要将元数据传递给其他使用者,XDP 程序可以将其存储到数据包前方的元数据区域中。并非所有数据包都一定具有所请求的元数据,在这种情况下,驱动程序会返回 -ENODATA
。
并非所有 kfunc 都必须由设备驱动程序实现;如果未实现,则将使用返回 -EOPNOTSUPP
的默认 kfunc 来指示设备驱动程序未实现此 kfunc。
在 XDP 帧中,元数据布局(通过 xdp_buff
访问)如下所示
+----------+-----------------+------+
| headroom | custom metadata | data |
+----------+-----------------+------+
^ ^
| |
xdp_buff->data_meta xdp_buff->data
XDP 程序可以将单个元数据项以其选择的任何格式存储到此 data_meta
区域中。元数据的后续使用者必须通过某种带外协议(例如 AF_XDP 用例,见下文)就格式达成一致。
AF_XDP¶
AF_XDP 用例意味着 BPF 程序与最终使用者之间存在协议,BPF 程序将 XDP 帧重定向到 AF_XDP
套接字 (XSK
)。因此,BPF 程序通过 bpf_xdp_adjust_meta
手动分配固定数量的元数据字节,并调用 kfunc 子集来填充它。用户空间 XSK
使用者计算 xsk_umem__get_data() - METADATA_SIZE
来找到该元数据。请注意,xsk_umem__get_data
在 libxdp
中定义,METADATA_SIZE
是应用程序特定的常量(AF_XDP
接收描述符_不_显式携带元数据的大小)。
这是 AF_XDP
使用者布局(请注意缺少 data_meta
指针)
+----------+-----------------+------+
| headroom | custom metadata | data |
+----------+-----------------+------+
^
|
rx_desc->address
XDP_PASS¶
这是 XDP 程序处理的数据包传递到内核的路径。内核从 xdp_buff
内容创建 skb
。目前,每个驱动程序都有自定义内核代码来解析描述符并在执行此 xdp_buff->skb
转换时填充 skb
元数据,并且内核在构建 skbs
时不使用 XDP 元数据。但是,TC-BPF 程序可以使用 data_meta
指针访问 XDP 元数据区域。
将来,我们希望支持这样一种情况:XDP 程序可以覆盖用于构建 skbs
的某些元数据。
bpf_redirect_map¶
bpf_redirect_map
可以将帧重定向到其他设备。某些设备(例如虚拟以太网链接)支持在重定向后运行第二个 XDP 程序。但是,最终使用者无法访问原始硬件描述符,也无法访问任何原始元数据。这同样适用于安装到 devmap 和 cpumap 中的 XDP 程序。
这意味着对于重定向的数据包,目前仅支持自定义元数据,必须由初始 XDP 程序在重定向之前准备好。如果该帧最终传递到内核,则从此帧创建的 skb
将不会在其 skb
中填充任何硬件元数据。如果此类数据包稍后重定向到 XSK
中,则也将只能访问自定义元数据。
bpf_tail_call¶
目前不支持将访问元数据 kfunc 的程序添加到 BPF_MAP_TYPE_PROG_ARRAY
。
支持的设备¶
可以通过 netlink 查询特定 netdev 实现的 kfunc。请参阅 Documentation/netlink/specs/netdev.yaml
中设置的 xdp-rx-metadata-features
属性。
示例¶
有关处理 XDP 元数据的 BPF 程序的示例,请参阅 tools/testing/selftests/bpf/progs/xdp_metadata.c
和 tools/testing/selftests/bpf/prog_tests/xdp_metadata.c
。