← Documents Documentation/bpf/map_xskmap.rst GitHub 원문 ↗

Linux 6.18.37 · BPF

BPF_MAP_TYPE_XSKMAP

XSKMAP이 XDP frame을 AF_XDP socket으로 redirect하는 구조, queue binding 제약, kernel 및 user space API와 예제를 설명합니다.

Source pathDocumentation/bpf/map_xskmap.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

요약과 해설

map_xskmap.rst:1-192

XSKMAP은 XDP program이 raw frame을 user space AF_XDP socket으로 곧바로 전달할 때 사용하는 array map입니다. 각 key는 XSK FD를 가리키며, XSK는 특정 netdev queue 하나에 bind됩니다.

Redirect의 source queue와 XSK가 bind된 queue가 다르면 frame이 socket에 도달하지 않습니다. 따라서 보통 netdev마다 XSKMAP 하나를 만들고 `max_entries`를 netdev queue 수에 맞춥니다.

Kernel BPF에서는 lookup과 redirect를 수행하고, XSK entry의 추가·갱신·삭제는 user space에서만 수행합니다. 빈 index로 redirect하면 packet이 drop된다는 점도 traffic 구성에서 중요합니다.

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

원문 전체 펼치기
1 .. SPDX-License-Identifier: GPL-2.0-only
2 .. Copyright (C) 2022 Red Hat, Inc.
3
4 ===================
5 BPF_MAP_TYPE_XSKMAP
6 ===================
7
8 .. note::
9 - ``BPF_MAP_TYPE_XSKMAP`` was introduced in kernel version 4.18
10
11 The ``BPF_MAP_TYPE_XSKMAP`` is used as a backend map for XDP BPF helper
12 call ``bpf_redirect_map()`` and ``XDP_REDIRECT`` action, like 'devmap' and 'cpumap'.
13 This map type redirects raw XDP frames to `AF_XDP`_ sockets (XSKs), a new type of
14 address family in the kernel that allows redirection of frames from a driver to
15 user space without having to traverse the full network stack. An AF_XDP socket
16 binds to a single netdev queue. A mapping of XSKs to queues is shown below:
17
18 .. code-block:: none
19
20 +---------------------------------------------------+
21 | xsk A | xsk B | xsk C |<---+ User space
22 =========================================================|==========
23 | Queue 0 | Queue 1 | Queue 2 | | Kernel
24 +---------------------------------------------------+ |
25 | Netdev eth0 | |
26 +---------------------------------------------------+ |
27 | +=============+ | |
28 | | key | xsk | | |
29 | +---------+ +=============+ | |
30 | | | | 0 | xsk A | | |
31 | | | +-------------+ | |
32 | | | | 1 | xsk B | | |
33 | | BPF |-- redirect -->+-------------+-------------+
34 | | prog | | 2 | xsk C | |
35 | | | +-------------+ |
36 | | | |
37 | | | |
38 | +---------+ |
39 | |
40 +---------------------------------------------------+
41
42 .. note::
43 An AF_XDP socket that is bound to a certain <netdev/queue_id> will *only*
44 accept XDP frames from that <netdev/queue_id>. If an XDP program tries to redirect
45 from a <netdev/queue_id> other than what the socket is bound to, the frame will
46 not be received on the socket.
47
48 Typically an XSKMAP is created per netdev. This map contains an array of XSK File
49 Descriptors (FDs). The number of array elements is typically set or adjusted using
50 the ``max_entries`` map parameter. For AF_XDP ``max_entries`` is equal to the number
51 of queues supported by the netdev.
52
53 .. note::
54 Both the map key and map value size must be 4 bytes.
55
56 Usage
57 =====
58
59 Kernel BPF
60 ----------
61 bpf_redirect_map()
62 ^^^^^^^^^^^^^^^^^^
63 .. code-block:: c
64
65 long bpf_redirect_map(struct bpf_map *map, u32 key, u64 flags)
66
67 Redirect the packet to the endpoint referenced by ``map`` at index ``key``.
68 For ``BPF_MAP_TYPE_XSKMAP`` this map contains references to XSK FDs
69 for sockets attached to a netdev's queues.
70
71 .. note::
72 If the map is empty at an index, the packet is dropped. This means that it is
73 necessary to have an XDP program loaded with at least one XSK in the
74 XSKMAP to be able to get any traffic to user space through the socket.
75
76 bpf_map_lookup_elem()
77 ^^^^^^^^^^^^^^^^^^^^^
78 .. code-block:: c
79
80 void *bpf_map_lookup_elem(struct bpf_map *map, const void *key)
81
82 XSK entry references of type ``struct xdp_sock *`` can be retrieved using the
83 ``bpf_map_lookup_elem()`` helper.
84
85 User space
86 ----------
87 .. note::
88 XSK entries can only be updated/deleted from user space and not from
89 a BPF program. Trying to call these functions from a kernel BPF program will
90 result in the program failing to load and a verifier warning.
91
92 bpf_map_update_elem()
93 ^^^^^^^^^^^^^^^^^^^^^
94 .. code-block:: c
95
96 int bpf_map_update_elem(int fd, const void *key, const void *value, __u64 flags)
97
98 XSK entries can be added or updated using the ``bpf_map_update_elem()``
99 helper. The ``key`` parameter is equal to the queue_id of the queue the XSK
100 is attaching to. And the ``value`` parameter is the FD value of that socket.
101
102 Under the hood, the XSKMAP update function uses the XSK FD value to retrieve the
103 associated ``struct xdp_sock`` instance.
104
105 The flags argument can be one of the following:
106
107 - BPF_ANY: Create a new element or update an existing element.
108 - BPF_NOEXIST: Create a new element only if it did not exist.
109 - BPF_EXIST: Update an existing element.
110
111 bpf_map_lookup_elem()
112 ^^^^^^^^^^^^^^^^^^^^^
113 .. code-block:: c
114
115 int bpf_map_lookup_elem(int fd, const void *key, void *value)
116
117 Returns ``struct xdp_sock *`` or negative error in case of failure.
118
119 bpf_map_delete_elem()
120 ^^^^^^^^^^^^^^^^^^^^^
121 .. code-block:: c
122
123 int bpf_map_delete_elem(int fd, const void *key)
124
125 XSK entries can be deleted using the ``bpf_map_delete_elem()``
126 helper. This helper will return 0 on success, or negative error in case of
127 failure.
128
129 .. note::
130 When `libxdp`_ deletes an XSK it also removes the associated socket
131 entry from the XSKMAP.
132
133 Examples
134 ========
135 Kernel
136 ------
137
138 The following code snippet shows how to declare a ``BPF_MAP_TYPE_XSKMAP`` called
139 ``xsks_map`` and how to redirect packets to an XSK.
140
141 .. code-block:: c
142
143 struct {
144 __uint(type, BPF_MAP_TYPE_XSKMAP);
145 __type(key, __u32);
146 __type(value, __u32);
147 __uint(max_entries, 64);
148 } xsks_map SEC(".maps");
149
150
151 SEC("xdp")
152 int xsk_redir_prog(struct xdp_md *ctx)
153 {
154 __u32 index = ctx->rx_queue_index;
155
156 if (bpf_map_lookup_elem(&xsks_map, &index))
157 return bpf_redirect_map(&xsks_map, index, 0);
158 return XDP_PASS;
159 }
160
161 User space
162 ----------
163
164 The following code snippet shows how to update an XSKMAP with an XSK entry.
165
166 .. code-block:: c
167
168 int update_xsks_map(struct bpf_map *xsks_map, int queue_id, int xsk_fd)
169 {
170 int ret;
171
172 ret = bpf_map_update_elem(bpf_map__fd(xsks_map), &queue_id, &xsk_fd, 0);
173 if (ret < 0)
174 fprintf(stderr, "Failed to update xsks_map: %s\n", strerror(errno));
175
176 return ret;
177 }
178
179 For an example on how create AF_XDP sockets, please see the AF_XDP-example and
180 AF_XDP-forwarding programs in the `bpf-examples`_ directory in the `libxdp`_ repository.
181 For a detailed explanation of the AF_XDP interface please see:
182
183 - `libxdp-readme`_.
184 - `AF_XDP`_ kernel documentation.
185
186 .. note::
187 The most comprehensive resource for using XSKMAPs and AF_XDP is `libxdp`_.
188
189 .. _libxdp: https://github.com/xdp-project/xdp-tools/tree/master/lib/libxdp
190 .. _AF_XDP: https://www.kernel.org/doc/html/latest/networking/af_xdp.html
191 .. _bpf-examples: https://github.com/xdp-project/bpf-examples
192 .. _libxdp-readme: https://github.com/xdp-project/xdp-tools/tree/master/lib/libxdp#using-af_xdp-sockets
193

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

XSKMAP과 AF_XDP queue 대응

1-55

`BPF_MAP_TYPE_XSKMAP` 문서는 `GPL-2.0-only` 라이선스와 `Copyright (C) 2022 Red Hat, Inc.`를 명시합니다.

`BPF_MAP_TYPE_XSKMAP`은 kernel version 4.18에서 도입되었습니다.

`BPF_MAP_TYPE_XSKMAP`은 `devmap`, `cpumap`처럼 XDP BPF helper `bpf_redirect_map()`과 `XDP_REDIRECT` action의 backend map으로 사용됩니다. 이 map type은 raw XDP frame을 `AF_XDP` socket, 즉 XSK로 redirect합니다.

`AF_XDP`는 frame이 전체 network stack을 거치지 않고 driver에서 user space로 전달되게 하는 kernel address family입니다. AF_XDP socket 하나는 netdev queue 하나에 bind됩니다.

XSKMAP의 XSK와 netdev queue 대응
XSKMAP keyAF_XDP socketbind 대상전달 영역
0xsk ANetdev eth0 / Queue 0User space
1xsk BNetdev eth0 / Queue 1User space
2xsk CNetdev eth0 / Queue 2User space
Redirect 경로Kernel: BPF prog -> redirect -> XSKMAP key -> matching XSK
Queue 제약User space와 Kernel의 경계 위에서 각 XSK는 정확히 하나의 netdev queue에 대응합니다.

원문의 ASCII 그림을 key, XSK, eth0 queue, 실행 영역의 대응 관계가 드러나는 표로 구조화했습니다. XDP BPF program은 선택한 key를 `bpf_redirect_map()`에 전달하고, XSKMAP은 그 key의 XSK로 frame을 보냅니다.

특정 `<netdev/queue_id>`에 bind된 AF_XDP socket은 그 `<netdev/queue_id>`에서 온 XDP frame만 받습니다. XDP program이 socket의 bind 대상과 다른 `<netdev/queue_id>`에서 redirect하면 해당 frame은 socket에 수신되지 않습니다.

일반적으로 netdev마다 XSKMAP 하나를 만듭니다. 이 map은 XSK File Descriptor(FD)의 array이며, array element 수는 보통 map parameter `max_entries`로 설정하거나 조정합니다. AF_XDP에서 `max_entries`는 netdev가 지원하는 queue 수와 같습니다.

Map key와 map value의 크기는 모두 4 bytes여야 합니다.

Kernel BPF helper

56-84

`bpf_redirect_map()`은 `map`의 `key` index가 참조하는 endpoint로 packet을 redirect합니다.

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

`BPF_MAP_TYPE_XSKMAP`에서 map은 netdev queue에 attach된 socket의 XSK FD reference를 담습니다.

해당 index가 비어 있으면 packet은 drop됩니다. 따라서 socket을 통해 user space traffic을 받으려면 XDP program이 load되어 있고 XSKMAP에 XSK가 최소 하나 들어 있어야 합니다.

Kernel BPF program은 `bpf_map_lookup_elem()` helper로 `struct xdp_sock *` type의 XSK entry reference를 가져올 수 있습니다.

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

User space CRUD

85-132

XSK entry의 update와 delete는 user space에서만 할 수 있고 BPF program에서는 할 수 없습니다. Kernel BPF program에서 이 function을 호출하려 하면 program load가 실패하고 verifier warning이 발생합니다.

User space의 `bpf_map_update_elem()`은 XSK entry를 추가하거나 갱신합니다.

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

`key` parameter는 XSK가 attach되는 queue의 `queue_id`이고, `value` parameter는 해당 socket의 FD 값입니다. 내부적으로 XSKMAP update function은 XSK FD 값으로 연결된 `struct xdp_sock` instance를 찾습니다.

`flags` argument는 다음 중 하나입니다.

  • `BPF_ANY`: 새 element를 만들거나 기존 element를 갱신합니다.
  • `BPF_NOEXIST`: element가 없을 때만 새 element를 만듭니다.
  • `BPF_EXIST`: 기존 element를 갱신합니다.

User space의 `bpf_map_lookup_elem()`은 XSKMAP entry를 조회합니다.

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

성공하면 `struct xdp_sock *`를 반환하고, 실패하면 negative error를 반환합니다.

`bpf_map_delete_elem()`은 XSK entry를 삭제합니다. 성공하면 0, 실패하면 negative error를 반환합니다.

int bpf_map_delete_elem(int fd, const void *key)

`libxdp`가 XSK를 삭제할 때는 XSKMAP에서 연결된 socket entry도 함께 제거합니다.

Kernel과 user space 예제

133-178

다음 kernel code는 `xsks_map`이라는 `BPF_MAP_TYPE_XSKMAP`을 선언하고 packet을 XSK로 redirect하는 방법을 보여 줍니다.

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;
}

Map은 `__u32` key와 value, `max_entries` 64를 사용합니다. `xsk_redir_prog()`는 `ctx->rx_queue_index`를 index로 삼아 entry가 있으면 `bpf_redirect_map(&xsks_map, index, 0)`을 반환하고, entry가 없으면 `XDP_PASS`를 반환합니다.

다음 user space code는 XSK entry로 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;
}

`update_xsks_map()`은 `bpf_map__fd(xsks_map)`과 `queue_id`, `xsk_fd`를 `bpf_map_update_elem()`에 전달합니다. 갱신이 실패하면 `strerror(errno)`로 error를 출력하고 return code를 호출자에게 돌려줍니다.

AF_XDP 예제와 참고 자료

179-192

AF_XDP socket 생성 예제는 `libxdp` repository의 `bpf-examples` directory에 있는 AF_XDP-example과 AF_XDP-forwarding program을 참고하십시오.

AF_XDP interface의 자세한 설명은 다음 자료에 있습니다.

  • `libxdp-readme`
  • `AF_XDP` kernel documentation

XSKMAP과 AF_XDP를 사용하는 방법을 가장 포괄적으로 다루는 자료는 `libxdp`입니다.

  • [https://github.com/xdp-project/xdp-tools/tree/master/lib/libxdp](https://github.com/xdp-project/xdp-tools/tree/master/lib/libxdp)
  • [https://www.kernel.org/doc/html/latest/networking/af_xdp.html](https://www.kernel.org/doc/html/latest/networking/af_xdp.html)
  • [https://github.com/xdp-project/bpf-examples](https://github.com/xdp-project/bpf-examples)
  • [https://github.com/xdp-project/xdp-tools/tree/master/lib/libxdp#using-af_xdp-sockets](https://github.com/xdp-project/xdp-tools/tree/master/lib/libxdp#using-af_xdp-sockets)