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_8021QETH_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_datalibxdp 中定義,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.ctools/testing/selftests/bpf/prog_tests/xdp_metadata.c