doc: show how to include code in guides
[dpdk.git] / doc / guides / nics / memif.rst
1 ..  SPDX-License-Identifier: BSD-3-Clause
2     Copyright(c) 2018-2019 Cisco Systems, Inc.
3
4 ======================
5 Memif Poll Mode Driver
6 ======================
7
8 Shared memory packet interface (memif) PMD allows for DPDK and any other client
9 using memif (DPDK, VPP, libmemif) to communicate using shared memory. Memif is
10 Linux only.
11
12 The created device transmits packets in a raw format. It can be used with
13 Ethernet mode, IP mode, or Punt/Inject. At this moment, only Ethernet mode is
14 supported in DPDK memif implementation.
15
16 Memif works in two roles: server and client. Client connects to server over an
17 existing socket. It is also a producer of shared memory file and initializes
18 the shared memory. Each interface can be connected to one peer interface
19 at same time. The peer interface is identified by id parameter. Server
20 creates the socket and listens for any client connection requests. The socket
21 may already exist on the system. Be sure to remove any such sockets, if you
22 are creating a server interface, or you will see an "Address already in use"
23 error. Function ``rte_pmd_memif_remove()``, which removes memif interface,
24 will also remove a listener socket, if it is not being used by any other
25 interface.
26
27 The method to enable one or more interfaces is to use the
28 ``--vdev=net_memif0`` option on the DPDK application command line. Each
29 ``--vdev=net_memif1`` option given will create an interface named net_memif0,
30 net_memif1, and so on. Memif uses unix domain socket to transmit control
31 messages. Each memif has a unique id per socket. This id is used to identify
32 peer interface. If you are connecting multiple
33 interfaces using same socket, be sure to specify unique ids ``id=0``, ``id=1``,
34 etc. Note that if you assign a socket to a server interface it becomes a
35 listener socket. Listener socket can not be used by a client interface on same
36 client.
37
38 .. csv-table:: **Memif configuration options**
39    :header: "Option", "Description", "Default", "Valid value"
40
41    "id=0", "Used to identify peer interface", "0", "uint32_t"
42    "role=server", "Set memif role", "client", "server|client"
43    "bsize=1024", "Size of single packet buffer", "2048", "uint16_t"
44    "rsize=11", "Log2 of ring size. If rsize is 10, actual ring size is 1024", "10", "1-14"
45    "socket=/tmp/memif.sock", "Socket filename", "/tmp/memif.sock", "string len 108"
46    "socket-abstract=no", "Set usage of abstract socket address", "yes", "yes|no"
47    "mac=01:23:45:ab:cd:ef", "Mac address", "01:ab:23:cd:45:ef", ""
48    "secret=abc123", "Secret is an optional security option, which if specified, must be matched by peer", "", "string len 24"
49    "zero-copy=yes", "Enable/disable zero-copy client mode. Only relevant to client, requires '--single-file-segments' eal argument", "no", "yes|no"
50
51 **Connection establishment**
52
53 In order to create memif connection, two memif interfaces, each in separate
54 process, are needed. One interface in ``server`` role and other in
55 ``client`` role. It is not possible to connect two interfaces in a single
56 process. Each interface can be connected to one interface at same time,
57 identified by matching id parameter.
58
59 Memif driver uses unix domain socket to exchange required information between
60 memif interfaces. Socket file path is specified at interface creation see
61 *Memif configuration options* table above. If socket is used by ``server``
62 interface, it's marked as listener socket (in scope of current process) and
63 listens to connection requests from other processes. One socket can be used by
64 multiple interfaces. One process can have ``client`` and ``server`` interfaces
65 at the same time, provided each role is assigned unique socket.
66
67 For detailed information on memif control messages, see: net/memif/memif.h.
68
69 Client interface attempts to make a connection on assigned socket. Process
70 listening on this socket will extract the connection request and create a new
71 connected socket (control channel). Then it sends the 'hello' message
72 (``MEMIF_MSG_TYPE_HELLO``), containing configuration boundaries. Client interface
73 adjusts its configuration accordingly, and sends 'init' message
74 (``MEMIF_MSG_TYPE_INIT``). This message among others contains interface id. Driver
75 uses this id to find server interface, and assigns the control channel to this
76 interface. If such interface is found, 'ack' message (``MEMIF_MSG_TYPE_ACK``) is
77 sent. Client interface sends 'add region' message (``MEMIF_MSG_TYPE_ADD_REGION``) for
78 every region allocated. Server responds to each of these messages with 'ack'
79 message. Same behavior applies to rings. Client sends 'add ring' message
80 (``MEMIF_MSG_TYPE_ADD_RING``) for every initialized ring. Server again responds to
81 each message with 'ack' message. To finalize the connection, client interface
82 sends 'connect' message (``MEMIF_MSG_TYPE_CONNECT``). Upon receiving this message
83 server maps regions to its address space, initializes rings and responds with
84 'connected' message (``MEMIF_MSG_TYPE_CONNECTED``). Disconnect
85 (``MEMIF_MSG_TYPE_DISCONNECT``) can be sent by both server and client interfaces at
86 any time, due to driver error or if the interface is being deleted.
87
88 Files
89
90 - net/memif/memif.h *- control messages definitions*
91 - net/memif/memif_socket.h
92 - net/memif/memif_socket.c
93
94 Shared memory
95 ~~~~~~~~~~~~~
96
97 **Shared memory format**
98
99 Client is producer and server is consumer. Memory regions, are mapped shared memory files,
100 created by memif client and provided to server at connection establishment.
101 Regions contain rings and buffers. Rings and buffers can also be separated into multiple
102 regions. For no-zero-copy, rings and buffers are stored inside single memory
103 region to reduce the number of opened files.
104
105 region n (no-zero-copy):
106
107 +-----------------------+-------------------------------------------------------------------------+
108 | Rings                 | Buffers                                                                 |
109 +-----------+-----------+-----------------+---+---------------------------------------------------+
110 | S2M rings | M2S rings | packet buffer 0 | . | pb ((1 << pmd->run.log2_ring_size)*(s2m + m2s))-1 |
111 +-----------+-----------+-----------------+---+---------------------------------------------------+
112
113 S2M OR M2S Rings:
114
115 +--------+--------+-----------------------+
116 | ring 0 | ring 1 | ring num_s2m_rings - 1|
117 +--------+--------+-----------------------+
118
119 ring 0:
120
121 +-------------+---------------------------------------+
122 | ring header | (1 << pmd->run.log2_ring_size) * desc |
123 +-------------+---------------------------------------+
124
125 Descriptors are assigned packet buffers in order of rings creation. If we have one ring
126 in each direction and ring size is 1024, then first 1024 buffers will belong to S2M ring and
127 last 1024 will belong to M2S ring. In case of zero-copy, buffers are dequeued and
128 enqueued as needed.
129
130 **Descriptor format**
131
132 +----+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
133 |Quad|6| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |3|3| | | | | | | | | | | | | | |1|1| | | | | | | | | | | | | | | |
134 |    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
135 |Word|3| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |2|1| | | | | | | | | | | | | | |6|5| | | | | | | | | | | | | | |0|
136 +----+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
137 |0   |length                                                         |region                         |flags                          |
138 +----+---------------------------------------------------------------+-------------------------------+-------------------------------+
139 |1   |metadata                                                       |offset                                                         |
140 +----+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
141 |    |6| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |3|3| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
142 |    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
143 |    |3| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |2|1| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |0|
144 +----+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
145
146 **Flags field - flags (Quad Word 0, bits 0:15)**
147
148 +-----+--------------------+------------------------------------------------------------------------------------------------+
149 |Bits |Name                |Functionality                                                                                   |
150 +=====+====================+================================================================================================+
151 |0    |MEMIF_DESC_FLAG_NEXT|Is chained buffer. When set, the packet is divided into multiple buffers. May not be contiguous.|
152 +-----+--------------------+------------------------------------------------------------------------------------------------+
153
154 **Region index - region (Quad Word 0, 16:31)**
155
156 Index of memory region, the buffer is located in.
157
158 **Data length - length (Quad Word 0, 32:63)**
159
160 Length of transmitted/received data.
161
162 **Data Offset - offset (Quad Word 1, 0:31)**
163
164 Data start offset from memory region address. *.regions[desc->region].addr + desc->offset*
165
166 **Metadata - metadata (Quad Word 1, 32:63)**
167
168 Buffer metadata.
169
170 Files
171
172 - net/memif/memif.h *- descriptor and ring definitions*
173 - net/memif/rte_eth_memif.c *- eth_memif_rx() eth_memif_tx()*
174
175 Zero-copy client
176 ~~~~~~~~~~~~~~~~
177
178 Zero-copy client can be enabled with memif configuration option 'zero-copy=yes'. This option
179 is only relevant to client and requires eal argument '--single-file-segments'.
180 This limitation is in place, because it is too expensive to identify memseg
181 for each packet buffer, resulting in worse performance than with zero-copy disabled.
182 With single file segments we can calculate offset from the beginning of the file
183 for each packet buffer.
184
185 **Shared memory format**
186
187 Region 0 is created by memif driver and contains rings. Client interface exposes DPDK memory (memseg).
188 Instead of using memfd_create() to create new shared file, existing memsegs are used.
189 Server interface functions the same as with zero-copy disabled.
190
191 region 0:
192
193 +-----------------------+
194 | Rings                 |
195 +-----------+-----------+
196 | S2M rings | M2S rings |
197 +-----------+-----------+
198
199 region n:
200
201 +-----------------+
202 | Buffers         |
203 +-----------------+
204 |memseg           |
205 +-----------------+
206
207 Buffers are dequeued and enqueued as needed. Offset descriptor field is calculated at tx.
208 Only single file segments mode (EAL option --single-file-segments) is supported, as calculating
209 offset from multiple segments is too expensive.
210
211 Example: testpmd
212 ----------------------------
213 In this example we run two instances of testpmd application and transmit packets over memif.
214
215 First create ``server`` interface::
216
217     #./<build_dir>/app/dpdk-testpmd -l 0-1 --proc-type=primary --file-prefix=pmd1 --vdev=net_memif,role=server -- -i
218
219 Now create ``client`` interface (server must be already running so the client will connect)::
220
221     #./<build_dir>/app/dpdk-testpmd -l 2-3 --proc-type=primary --file-prefix=pmd2 --vdev=net_memif -- -i
222
223 You can also enable ``zero-copy`` on ``client`` interface::
224
225     #./<build_dir>/app/dpdk-testpmd -l 2-3 --proc-type=primary --file-prefix=pmd2 --vdev=net_memif,zero-copy=yes --single-file-segments -- -i
226
227 Start forwarding packets::
228
229     Client:
230         testpmd> start
231
232     Server:
233         testpmd> start tx_first
234
235 Show status::
236
237     testpmd> show port stats 0
238
239 For more details on testpmd please refer to :doc:`../testpmd_app_ug/index`.
240
241 Example: testpmd and VPP
242 ------------------------
243 For information on how to get and run VPP please see `<https://wiki.fd.io/view/VPP>`_.
244
245 Start VPP in interactive mode (should be by default). Create memif server interface in VPP::
246
247     vpp# create interface memif id 0 server no-zero-copy
248     vpp# set interface state memif0/0 up
249     vpp# set interface ip address memif0/0 192.168.1.1/24
250
251 To see socket filename use show memif command::
252
253     vpp# show memif
254     sockets
255      id  listener    filename
256       0   yes (1)     /run/vpp/memif.sock
257     ...
258
259 Now create memif interface by running testpmd with these command line options::
260
261     #./dpdk-testpmd --vdev=net_memif,socket=/run/vpp/memif.sock -- -i
262
263 Testpmd should now create memif client interface and try to connect to server.
264 In testpmd set forward option to icmpecho and start forwarding::
265
266     testpmd> set fwd icmpecho
267     testpmd> start
268
269 Send ping from VPP::
270
271     vpp# ping 192.168.1.2
272     64 bytes from 192.168.1.2: icmp_seq=2 ttl=254 time=36.2918 ms
273     64 bytes from 192.168.1.2: icmp_seq=3 ttl=254 time=23.3927 ms
274     64 bytes from 192.168.1.2: icmp_seq=4 ttl=254 time=24.2975 ms
275     64 bytes from 192.168.1.2: icmp_seq=5 ttl=254 time=17.7049 ms
276
277 Example: testpmd memif loopback
278 -------------------------------
279 In this example we will create 2 memif ports connected into loopback.
280 The situation is analogous to cross connecting 2 ports of the NIC by cable.
281
282 To set the loopback, just use the same socket and id with different roles::
283
284     #./dpdk-testpmd --vdev=net_memif0,role=server,id=0 --vdev=net_memif1,role=client,id=0 -- -i
285
286 Then start the communication::
287
288     testpmd> start tx_first
289
290 Finally we can check port stats to see the traffic::
291
292     testpmd> show port stats all