Merge tag 'clk-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux.git] / Documentation / networking / devmem.rst
blobd953636453314949260f181102787742f3dbe9c7
1 .. SPDX-License-Identifier: GPL-2.0
3 =================
4 Device Memory TCP
5 =================
8 Intro
9 =====
11 Device memory TCP (devmem TCP) enables receiving data directly into device
12 memory (dmabuf). The feature is currently implemented for TCP sockets.
15 Opportunity
16 -----------
18 A large number of data transfers have device memory as the source and/or
19 destination. Accelerators drastically increased the prevalence of such
20 transfers.  Some examples include:
22 - Distributed training, where ML accelerators, such as GPUs on different hosts,
23   exchange data.
25 - Distributed raw block storage applications transfer large amounts of data with
26   remote SSDs. Much of this data does not require host processing.
28 Typically the Device-to-Device data transfers in the network are implemented as
29 the following low-level operations: Device-to-Host copy, Host-to-Host network
30 transfer, and Host-to-Device copy.
32 The flow involving host copies is suboptimal, especially for bulk data transfers,
33 and can put significant strains on system resources such as host memory
34 bandwidth and PCIe bandwidth.
36 Devmem TCP optimizes this use case by implementing socket APIs that enable
37 the user to receive incoming network packets directly into device memory.
39 Packet payloads go directly from the NIC to device memory.
41 Packet headers go to host memory and are processed by the TCP/IP stack
42 normally. The NIC must support header split to achieve this.
44 Advantages:
46 - Alleviate host memory bandwidth pressure, compared to existing
47   network-transfer + device-copy semantics.
49 - Alleviate PCIe bandwidth pressure, by limiting data transfer to the lowest
50   level of the PCIe tree, compared to the traditional path which sends data
51   through the root complex.
54 More Info
55 ---------
57   slides, video
58     https://netdevconf.org/0x17/sessions/talk/device-memory-tcp.html
60   patchset
61     [PATCH net-next v24 00/13] Device Memory TCP
62     https://lore.kernel.org/netdev/20240831004313.3713467-1-almasrymina@google.com/
65 Interface
66 =========
69 Example
70 -------
72 tools/testing/selftests/net/ncdevmem.c:do_server shows an example of setting up
73 the RX path of this API.
76 NIC Setup
77 ---------
79 Header split, flow steering, & RSS are required features for devmem TCP.
81 Header split is used to split incoming packets into a header buffer in host
82 memory, and a payload buffer in device memory.
84 Flow steering & RSS are used to ensure that only flows targeting devmem land on
85 an RX queue bound to devmem.
87 Enable header split & flow steering::
89         # enable header split
90         ethtool -G eth1 tcp-data-split on
93         # enable flow steering
94         ethtool -K eth1 ntuple on
96 Configure RSS to steer all traffic away from the target RX queue (queue 15 in
97 this example)::
99         ethtool --set-rxfh-indir eth1 equal 15
102 The user must bind a dmabuf to any number of RX queues on a given NIC using
103 the netlink API::
105         /* Bind dmabuf to NIC RX queue 15 */
106         struct netdev_queue *queues;
107         queues = malloc(sizeof(*queues) * 1);
109         queues[0]._present.type = 1;
110         queues[0]._present.idx = 1;
111         queues[0].type = NETDEV_RX_QUEUE_TYPE_RX;
112         queues[0].idx = 15;
114         *ys = ynl_sock_create(&ynl_netdev_family, &yerr);
116         req = netdev_bind_rx_req_alloc();
117         netdev_bind_rx_req_set_ifindex(req, 1 /* ifindex */);
118         netdev_bind_rx_req_set_dmabuf_fd(req, dmabuf_fd);
119         __netdev_bind_rx_req_set_queues(req, queues, n_queue_index);
121         rsp = netdev_bind_rx(*ys, req);
123         dmabuf_id = rsp->dmabuf_id;
126 The netlink API returns a dmabuf_id: a unique ID that refers to this dmabuf
127 that has been bound.
129 The user can unbind the dmabuf from the netdevice by closing the netlink socket
130 that established the binding. We do this so that the binding is automatically
131 unbound even if the userspace process crashes.
133 Note that any reasonably well-behaved dmabuf from any exporter should work with
134 devmem TCP, even if the dmabuf is not actually backed by devmem. An example of
135 this is udmabuf, which wraps user memory (non-devmem) in a dmabuf.
138 Socket Setup
139 ------------
141 The socket must be flow steered to the dmabuf bound RX queue::
143         ethtool -N eth1 flow-type tcp4 ... queue 15
146 Receiving data
147 --------------
149 The user application must signal to the kernel that it is capable of receiving
150 devmem data by passing the MSG_SOCK_DEVMEM flag to recvmsg::
152         ret = recvmsg(fd, &msg, MSG_SOCK_DEVMEM);
154 Applications that do not specify the MSG_SOCK_DEVMEM flag will receive an EFAULT
155 on devmem data.
157 Devmem data is received directly into the dmabuf bound to the NIC in 'NIC
158 Setup', and the kernel signals such to the user via the SCM_DEVMEM_* cmsgs::
160                 for (cm = CMSG_FIRSTHDR(&msg); cm; cm = CMSG_NXTHDR(&msg, cm)) {
161                         if (cm->cmsg_level != SOL_SOCKET ||
162                                 (cm->cmsg_type != SCM_DEVMEM_DMABUF &&
163                                  cm->cmsg_type != SCM_DEVMEM_LINEAR))
164                                 continue;
166                         dmabuf_cmsg = (struct dmabuf_cmsg *)CMSG_DATA(cm);
168                         if (cm->cmsg_type == SCM_DEVMEM_DMABUF) {
169                                 /* Frag landed in dmabuf.
170                                  *
171                                  * dmabuf_cmsg->dmabuf_id is the dmabuf the
172                                  * frag landed on.
173                                  *
174                                  * dmabuf_cmsg->frag_offset is the offset into
175                                  * the dmabuf where the frag starts.
176                                  *
177                                  * dmabuf_cmsg->frag_size is the size of the
178                                  * frag.
179                                  *
180                                  * dmabuf_cmsg->frag_token is a token used to
181                                  * refer to this frag for later freeing.
182                                  */
184                                 struct dmabuf_token token;
185                                 token.token_start = dmabuf_cmsg->frag_token;
186                                 token.token_count = 1;
187                                 continue;
188                         }
190                         if (cm->cmsg_type == SCM_DEVMEM_LINEAR)
191                                 /* Frag landed in linear buffer.
192                                  *
193                                  * dmabuf_cmsg->frag_size is the size of the
194                                  * frag.
195                                  */
196                                 continue;
198                 }
200 Applications may receive 2 cmsgs:
202 - SCM_DEVMEM_DMABUF: this indicates the fragment landed in the dmabuf indicated
203   by dmabuf_id.
205 - SCM_DEVMEM_LINEAR: this indicates the fragment landed in the linear buffer.
206   This typically happens when the NIC is unable to split the packet at the
207   header boundary, such that part (or all) of the payload landed in host
208   memory.
210 Applications may receive no SO_DEVMEM_* cmsgs. That indicates non-devmem,
211 regular TCP data that landed on an RX queue not bound to a dmabuf.
214 Freeing frags
215 -------------
217 Frags received via SCM_DEVMEM_DMABUF are pinned by the kernel while the user
218 processes the frag. The user must return the frag to the kernel via
219 SO_DEVMEM_DONTNEED::
221         ret = setsockopt(client_fd, SOL_SOCKET, SO_DEVMEM_DONTNEED, &token,
222                          sizeof(token));
224 The user must ensure the tokens are returned to the kernel in a timely manner.
225 Failure to do so will exhaust the limited dmabuf that is bound to the RX queue
226 and will lead to packet drops.
228 The user must pass no more than 128 tokens, with no more than 1024 total frags
229 among the token->token_count across all the tokens. If the user provides more
230 than 1024 frags, the kernel will free up to 1024 frags and return early.
232 The kernel returns the number of actual frags freed. The number of frags freed
233 can be less than the tokens provided by the user in case of:
235 (a) an internal kernel leak bug.
236 (b) the user passed more than 1024 frags.
238 Implementation & Caveats
239 ========================
241 Unreadable skbs
242 ---------------
244 Devmem payloads are inaccessible to the kernel processing the packets. This
245 results in a few quirks for payloads of devmem skbs:
247 - Loopback is not functional. Loopback relies on copying the payload, which is
248   not possible with devmem skbs.
250 - Software checksum calculation fails.
252 - TCP Dump and bpf can't access devmem packet payloads.
255 Testing
256 =======
258 More realistic example code can be found in the kernel source under
259 ``tools/testing/selftests/net/ncdevmem.c``
261 ncdevmem is a devmem TCP netcat. It works very similarly to netcat, but
262 receives data directly into a udmabuf.
264 To run ncdevmem, you need to run it on a server on the machine under test, and
265 you need to run netcat on a peer to provide the TX data.
267 ncdevmem has a validation mode as well that expects a repeating pattern of
268 incoming data and validates it as such. For example, you can launch
269 ncdevmem on the server by::
271         ncdevmem -s <server IP> -c <client IP> -f eth1 -d 3 -n 0000:06:00.0 -l \
272                  -p 5201 -v 7
274 On client side, use regular netcat to send TX data to ncdevmem process
275 on the server::
277         yes $(echo -e \\x01\\x02\\x03\\x04\\x05\\x06) | \
278                 tr \\n \\0 | head -c 5G | nc <server IP> 5201 -p 5201