BPF_MAP_TYPE_XSKMAP

注意

  • BPF_MAP_TYPE_XSKMAP 是在核心版本 4.18 中引入的

BPF_MAP_TYPE_XSKMAP 用作 XDP BPF 輔助呼叫 bpf_redirect_map()XDP_REDIRECT 操作的後端對映,例如 ‘devmap’ 和 ‘cpumap’。此對映型別將原始 XDP 幀重定向到 AF_XDP 套接字 (XSK),這是一種核心中的新型地址族,允許將幀從驅動程式重定向到使用者空間,而無需遍歷完整的網路堆疊。AF_XDP 套接字繫結到單個 netdev 佇列。XSK 到佇列的對映如下所示

+---------------------------------------------------+
|     xsk A      |     xsk B       |      xsk C     |<---+ User space
=========================================================|==========
|    Queue 0     |     Queue 1     |     Queue 2    |    |  Kernel
+---------------------------------------------------+    |
|                  Netdev eth0                      |    |
+---------------------------------------------------+    |
|                            +=============+        |    |
|                            | key |  xsk  |        |    |
|  +---------+               +=============+        |    |
|  |         |               |  0  | xsk A |        |    |
|  |         |               +-------------+        |    |
|  |         |               |  1  | xsk B |        |    |
|  | BPF     |-- redirect -->+-------------+-------------+
|  | prog    |               |  2  | xsk C |        |
|  |         |               +-------------+        |
|  |         |                                      |
|  |         |                                      |
|  +---------+                                      |
|                                                   |
+---------------------------------------------------+

注意

繫結到特定 <netdev/queue_id> 的 AF_XDP 套接字將接受來自該 <netdev/queue_id> 的 XDP 幀。如果 XDP 程式嘗試從套接字繫結到的 <netdev/queue_id> 以外的 <netdev/queue_id> 重定向,則套接字將不會收到該幀。

通常,每個 netdev 建立一個 XSKMAP。此對映包含 XSK 檔案描述符 (FD) 的陣列。陣列元素的數量通常使用 max_entries 對映引數設定或調整。對於 AF_XDP,max_entries 等於 netdev 支援的佇列數。

注意

對映鍵和對映值的大小必須都是 4 個位元組。

用法

核心 BPF

bpf_redirect_map()

long bpf_redirect_map(struct bpf_map *map, u32 key, u64 flags)

將資料包重定向到 map 中索引為 key 的端點引用的位置。對於 BPF_MAP_TYPE_XSKMAP,此對映包含對連線到 netdev 佇列的套接字的 XSK FD 的引用。

注意

如果對映在索引處為空,則資料包將被丟棄。這意味著必須載入一個 XDP 程式,該程式在 XSKMAP 中至少有一個 XSK,才能透過套接字將任何流量傳送到使用者空間。

bpf_map_lookup_elem()

void *bpf_map_lookup_elem(struct bpf_map *map, const void *key)

可以使用 bpf_map_lookup_elem() 輔助程式檢索 struct xdp_sock * 型別的 XSK 條目引用。

使用者空間

注意

XSK 條目只能從使用者空間更新/刪除,而不能從 BPF 程式更新/刪除。嘗試從核心 BPF 程式呼叫這些函式將導致程式載入失敗並出現驗證器警告。

bpf_map_update_elem()

int bpf_map_update_elem(int fd, const void *key, const void *value, __u64 flags)

可以使用 bpf_map_update_elem() 輔助程式新增或更新 XSK 條目。key 引數等於 XSK 連線到的佇列的 queue_id。value 引數是該套接字的 FD 值。

在底層,XSKMAP 更新函式使用 XSK FD 值來檢索關聯的 struct xdp_sock 例項。

flags 引數可以是以下之一

  • BPF_ANY:建立新元素或更新現有元素。

  • BPF_NOEXIST:僅當新元素不存在時才建立新元素。

  • BPF_EXIST:更新現有元素。

bpf_map_lookup_elem()

int bpf_map_lookup_elem(int fd, const void *key, void *value)

返回 struct xdp_sock *,如果失敗,則返回負錯誤。

bpf_map_delete_elem()

int bpf_map_delete_elem(int fd, const void *key)

可以使用 bpf_map_delete_elem() 輔助程式刪除 XSK 條目。如果成功,此輔助程式將返回 0,如果失敗,則返回負錯誤。

注意

libxdp 刪除 XSK 時,它也會從 XSKMAP 中刪除關聯的套接字條目。

示例

核心

以下程式碼段顯示瞭如何宣告一個名為 xsks_mapBPF_MAP_TYPE_XSKMAP,以及如何將資料包重定向到 XSK。

struct {
        __uint(type, BPF_MAP_TYPE_XSKMAP);
        __type(key, __u32);
        __type(value, __u32);
        __uint(max_entries, 64);
} xsks_map SEC(".maps");


SEC("xdp")
int xsk_redir_prog(struct xdp_md *ctx)
{
        __u32 index = ctx->rx_queue_index;

        if (bpf_map_lookup_elem(&xsks_map, &index))
                return bpf_redirect_map(&xsks_map, index, 0);
        return XDP_PASS;
}

使用者空間

以下程式碼段顯示瞭如何使用 XSK 條目更新 XSKMAP。

int update_xsks_map(struct bpf_map *xsks_map, int queue_id, int xsk_fd)
{
        int ret;

        ret = bpf_map_update_elem(bpf_map__fd(xsks_map), &queue_id, &xsk_fd, 0);
        if (ret < 0)
                fprintf(stderr, "Failed to update xsks_map: %s\n", strerror(errno));

        return ret;
}

有關如何建立 AF_XDP 套接字的示例,請參閱 bpf-examples 目錄中 libxdp 儲存庫中的 AF_XDP-example 和 AF_XDP-forwarding 程式。有關 AF_XDP 介面的詳細說明,請參閱

注意

使用 XSKMAP 和 AF_XDP 最全面的資源是 libxdp