af_xdp: workaround kernel race between poll() and sendmsg()
[vpp.git] / src / plugins / af_xdp / af_xdp_doc.md
1 # AF_XDP Ethernet driver {#af_xdp_doc}
2
3 This driver relies on Linux AF_XDP socket to rx/tx Ethernet packets.
4
5 ## Maturity level
6 Under development: it should work, but has not been thoroughly tested.
7
8 ## Features
9  - copy and zero-copy mode
10  - multiqueue
11  - API
12  - custom eBPF program
13  - polling, interrupt and adaptive mode
14
15 ## Known limitations
16
17 ### MTU
18 Because of AF_XDP restrictions, the MTU is limited to below PAGE_SIZE
19 (4096-bytes on most systems) minus 256-bytes, and they are additional
20 limitations depending upon specific Linux device drivers.
21 As a rule of thumb, a MTU of 3000-bytes or less should be safe.
22
23 ### Number of buffers
24 Furthermore, upon UMEM creation, the kernel allocates a
25 physically-contiguous structure, whose size is proportional to the number
26 of 4KB pages contained in the UMEM. That allocation might fail when
27 the number of buffers allocated by VPP is too high. That number can be
28 controlled with the `buffers { buffers-per-numa }` configuration option.
29 Finally, note that because of this limitation, this plugin is unlikely
30 to be compatible with the use of 1GB hugepages.
31
32 ### Interrupt mode
33 Interrupt and adaptive mode are supported but is limited by default to single
34 threaded (no worker) configurations because of a kernel limitation prior to
35 5.6. You can bypass the limitation at interface creation time by adding the
36 `no-syscall-lock` parameter, but you must be sure that your kernel can
37 support it, otherwise you will experience double-frees.
38 See
39 https://lore.kernel.org/bpf/BYAPR11MB365382C5DB1E5FCC53242609C1549@BYAPR11MB3653.namprd11.prod.outlook.com/
40 for more details.
41
42 ### Mellanox
43 When setting the number of queues on Mellanox NIC with `ethtool -L`, you must
44 use twice the amount of configured queues: it looks like the Linux driver will
45 create separate RX queues and TX queues (but all queues can be used for both
46 RX and TX, the NIC will just not sent any packet on "pure" TX queues.
47 Confused? So I am.). For example if you set `combined 2` you will effectively
48 have to create 4 rx queues in AF_XDP if you want to be sure to receive all
49 packets.
50
51 ## Requirements
52 This drivers supports Linux kernel 5.4 and later. Kernels older than 5.4 are
53 missing unaligned buffers support.
54
55 The Linux kernel interface must be up and have enough queues before
56 creating the VPP AF_XDP interface, otherwise Linux will deny creating
57 the AF_XDP socket.
58 The AF_XDP interface will claim NIC RX queue starting from 0, up to the
59 requested number of RX queues (only 1 by default). It means all packets
60 destined to NIC RX queue `[0, num_rx_queues[` will be received by the
61 AF_XDP interface, and only them. Depending on your configuration, there
62 will usually be several RX queues (typically 1 per core) and packets are
63 spread accross queues by RSS. In order to receive consistent traffic,
64 you **must** program the NIC dispatching accordingly. The simplest way
65 to get all the packets is to specify `num-rx-queues all` to grab all
66 available queues or to reconfigure the Linux kernel driver to use only
67 `num_rx_queues` RX queues (ie all NIC queues will be associated with
68 the AF_XDP socket):
69 ```
70 ~# ethtool -L <iface> combined <num_rx_queues>
71 ```
72 Additionally, the VPP AF_XDP interface will use a MAC address generated at
73 creation time instead of the Linux kernel interface MAC. As Linux kernel
74 interface are not in promiscuous mode by default (see below) this will
75 results in a useless configuration where the VPP AF_XDP interface only
76 receives packets destined to the Linux kernel interface MAC just to drop
77 them because the destination MAC does not match VPP AF_XDP interface MAC.
78 If you want to use the Linux interface MAC for the VPP AF_XDP interface,
79 you can change it afterwards in VPP:
80 ```
81 ~# vppctl set int mac address <iface> <mac>
82 ```
83 Finally, if you wish to receive all packets and not only the packets
84 destined to the Linux kernel interface MAC you need to set the Linux
85 kernel interface in promiscuous mode:
86 ```
87 ~# ip link set dev <iface> promisc on
88 ```
89
90 ## Security considerations
91 When creating an AF_XDP interface, it will receive all packets arriving
92 to the NIC RX queue `[0, num_rx_queues[`. You need to configure the Linux
93 kernel NIC driver properly to ensure that only intented packets will
94 arrive in this queue. There is no way to filter the packets after-the-fact
95 using eg. netfilter or eBPF.
96
97 ## Quickstart
98 1. Put the Linux kernel interface up and in promiscuous mode:
99 ```
100 ~# ip l set dev enp216s0f0 promisc on up
101 ```
102 2. Create the AF_XDP interface:
103 ```
104 ~# vppctl create int af_xdp host-if enp216s0f0 num-rx-queues all
105 ```
106 3. Use the interface as usual, eg.:
107 ```
108 ~# vppctl set int ip addr enp216s0f0/0 1.1.1.1/24
109 ~# vppctl set int st enp216s0f0/0 up
110 ~# vppctl ping 1.1.1.100`
111 ```
112
113 ## Custom eBPF XDP program
114 This driver relies on libbpf and as such relies on the `xsks_map` eBPF
115 map.  The default behavior is to use the XDP program already attached
116 to the interface if any, otherwise load the default one.
117 You can request to load a custom XDP program with the `prog` option when
118 creating the interface in VPP:
119 ```
120 ~# vppctl create int af_xdp host-if enp216s0f0 num-rx-queues 4 prog extras/bpf/af_xdp.bpf.o
121 ```
122 In that case it will replace any previously attached program.  A custom
123 XDP program example is provided in `extras/bpf/`.
124
125 ## Performance consideration
126 AF_XDP relies on the Linux kernel NIC driver to rx/tx packets. To reach
127 high-performance (10's MPPS), the Linux kernel NIC driver must support
128 zero-copy mode and its RX path must run on a dedicated core in the NUMA
129 where the NIC is physically connected.