Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright 2018-2019 Cisco Systems, Inc. All rights reserved.
3 : : */
4 : :
5 : : #include <stdlib.h>
6 : : #include <fcntl.h>
7 : : #include <unistd.h>
8 : : #include <sys/types.h>
9 : : #include <sys/socket.h>
10 : : #include <sys/un.h>
11 : : #include <sys/ioctl.h>
12 : : #include <sys/mman.h>
13 : : #include <linux/if_ether.h>
14 : : #include <errno.h>
15 : : #include <sys/eventfd.h>
16 : :
17 : : #include <rte_version.h>
18 : : #include <rte_mbuf.h>
19 : : #include <rte_ether.h>
20 : : #include <ethdev_driver.h>
21 : : #include <ethdev_vdev.h>
22 : : #include <rte_malloc.h>
23 : : #include <rte_kvargs.h>
24 : : #include <bus_vdev_driver.h>
25 : : #include <rte_string_fns.h>
26 : : #include <rte_errno.h>
27 : : #include <rte_memory.h>
28 : : #include <rte_memzone.h>
29 : : #include <rte_eal_memconfig.h>
30 : :
31 : : #include "rte_eth_memif.h"
32 : : #include "memif_socket.h"
33 : :
34 : : #define ETH_MEMIF_ID_ARG "id"
35 : : #define ETH_MEMIF_ROLE_ARG "role"
36 : : #define ETH_MEMIF_PKT_BUFFER_SIZE_ARG "bsize"
37 : : #define ETH_MEMIF_RING_SIZE_ARG "rsize"
38 : : #define ETH_MEMIF_SOCKET_ARG "socket"
39 : : #define ETH_MEMIF_SOCKET_ABSTRACT_ARG "socket-abstract"
40 : : #define ETH_MEMIF_OWNER_UID_ARG "owner-uid"
41 : : #define ETH_MEMIF_OWNER_GID_ARG "owner-gid"
42 : : #define ETH_MEMIF_MAC_ARG "mac"
43 : : #define ETH_MEMIF_ZC_ARG "zero-copy"
44 : : #define ETH_MEMIF_SECRET_ARG "secret"
45 : :
46 : : static const char * const valid_arguments[] = {
47 : : ETH_MEMIF_ID_ARG,
48 : : ETH_MEMIF_ROLE_ARG,
49 : : ETH_MEMIF_PKT_BUFFER_SIZE_ARG,
50 : : ETH_MEMIF_RING_SIZE_ARG,
51 : : ETH_MEMIF_SOCKET_ARG,
52 : : ETH_MEMIF_SOCKET_ABSTRACT_ARG,
53 : : ETH_MEMIF_OWNER_UID_ARG,
54 : : ETH_MEMIF_OWNER_GID_ARG,
55 : : ETH_MEMIF_MAC_ARG,
56 : : ETH_MEMIF_ZC_ARG,
57 : : ETH_MEMIF_SECRET_ARG,
58 : : NULL
59 : : };
60 : :
61 : : static const struct rte_eth_link pmd_link = {
62 : : .link_speed = RTE_ETH_SPEED_NUM_100G,
63 : : .link_duplex = RTE_ETH_LINK_FULL_DUPLEX,
64 : : .link_status = RTE_ETH_LINK_DOWN,
65 : : .link_autoneg = RTE_ETH_LINK_AUTONEG
66 : : };
67 : :
68 : : #define MEMIF_MP_SEND_REGION "memif_mp_send_region"
69 : :
70 : :
71 : : static int memif_region_init_zc(const struct rte_memseg_list *msl,
72 : : const struct rte_memseg *ms, void *arg);
73 : :
74 : : const char *
75 : 0 : memif_version(void)
76 : : {
77 : 0 : return ("memif-" RTE_STR(MEMIF_VERSION_MAJOR) "." RTE_STR(MEMIF_VERSION_MINOR));
78 : : }
79 : :
80 : : /* Message header to synchronize regions */
81 : : struct mp_region_msg {
82 : : char port_name[RTE_DEV_NAME_MAX_LEN];
83 : : memif_region_index_t idx;
84 : : memif_region_size_t size;
85 : : };
86 : :
87 : : static int
88 : 0 : memif_mp_send_region(const struct rte_mp_msg *msg, const void *peer)
89 : : {
90 : : struct rte_eth_dev *dev;
91 : : struct pmd_process_private *proc_private;
92 : : const struct mp_region_msg *msg_param = (const struct mp_region_msg *)msg->param;
93 : : struct rte_mp_msg reply;
94 : : struct mp_region_msg *reply_param = (struct mp_region_msg *)reply.param;
95 : :
96 : : /* Get requested port */
97 : 0 : dev = rte_eth_dev_get_by_name(msg_param->port_name);
98 [ # # ]: 0 : if (!dev) {
99 : 0 : MIF_LOG(ERR, "Failed to get port id for %s",
100 : : msg_param->port_name);
101 : 0 : return -1;
102 : : }
103 [ # # ]: 0 : proc_private = dev->process_private;
104 : :
105 : : memset(&reply, 0, sizeof(reply));
106 [ # # ]: 0 : strlcpy(reply.name, msg->name, sizeof(reply.name));
107 : 0 : reply_param->idx = msg_param->idx;
108 [ # # ]: 0 : if (proc_private->regions[msg_param->idx] != NULL) {
109 : 0 : reply_param->size = proc_private->regions[msg_param->idx]->region_size;
110 : 0 : reply.fds[0] = proc_private->regions[msg_param->idx]->fd;
111 : 0 : reply.num_fds = 1;
112 : : }
113 : 0 : reply.len_param = sizeof(*reply_param);
114 [ # # ]: 0 : if (rte_mp_reply(&reply, peer) < 0) {
115 : 0 : MIF_LOG(ERR, "Failed to reply to an add region request");
116 : 0 : return -1;
117 : : }
118 : :
119 : : return 0;
120 : : }
121 : :
122 : : /*
123 : : * Request regions
124 : : * Called by secondary process, when ports link status goes up.
125 : : */
126 : : static int
127 : 0 : memif_mp_request_regions(struct rte_eth_dev *dev)
128 : : {
129 : : int ret, i;
130 : 0 : struct timespec timeout = {.tv_sec = 5, .tv_nsec = 0};
131 : : struct rte_mp_msg msg, *reply;
132 : : struct rte_mp_reply replies;
133 : : struct mp_region_msg *msg_param = (struct mp_region_msg *)msg.param;
134 : : struct mp_region_msg *reply_param;
135 : : struct memif_region *r;
136 : 0 : struct pmd_process_private *proc_private = dev->process_private;
137 : 0 : struct pmd_internals *pmd = dev->data->dev_private;
138 : : /* in case of zero-copy client, only request region 0 */
139 [ # # ]: 0 : uint16_t max_region_num = (pmd->flags & ETH_MEMIF_FLAG_ZERO_COPY) ?
140 : : 1 : ETH_MEMIF_MAX_REGION_NUM;
141 : :
142 : 0 : MIF_LOG(DEBUG, "Requesting memory regions");
143 : :
144 [ # # ]: 0 : for (i = 0; i < max_region_num; i++) {
145 : : /* Prepare the message */
146 : : memset(&msg, 0, sizeof(msg));
147 : : strlcpy(msg.name, MEMIF_MP_SEND_REGION, sizeof(msg.name));
148 : 0 : strlcpy(msg_param->port_name, dev->data->name,
149 : : sizeof(msg_param->port_name));
150 : 0 : msg_param->idx = i;
151 : 0 : msg.len_param = sizeof(*msg_param);
152 : :
153 : : /* Send message */
154 : 0 : ret = rte_mp_request_sync(&msg, &replies, &timeout);
155 [ # # # # ]: 0 : if (ret < 0 || replies.nb_received != 1) {
156 : 0 : MIF_LOG(ERR, "Failed to send mp msg: %d",
157 : : rte_errno);
158 : 0 : return -1;
159 : : }
160 : :
161 : 0 : reply = &replies.msgs[0];
162 : : reply_param = (struct mp_region_msg *)reply->param;
163 : :
164 [ # # ]: 0 : if (reply_param->size > 0) {
165 : 0 : r = rte_zmalloc("region", sizeof(struct memif_region), 0);
166 [ # # ]: 0 : if (r == NULL) {
167 : 0 : MIF_LOG(ERR, "Failed to alloc memif region.");
168 : 0 : free(reply);
169 : 0 : return -ENOMEM;
170 : : }
171 : 0 : r->region_size = reply_param->size;
172 [ # # ]: 0 : if (reply->num_fds < 1) {
173 : 0 : MIF_LOG(ERR, "Missing file descriptor.");
174 : 0 : free(reply);
175 : 0 : return -1;
176 : : }
177 : 0 : r->fd = reply->fds[0];
178 : 0 : r->addr = NULL;
179 : :
180 : 0 : proc_private->regions[reply_param->idx] = r;
181 : 0 : proc_private->regions_num++;
182 : : }
183 : 0 : free(reply);
184 : : }
185 : :
186 [ # # ]: 0 : if (pmd->flags & ETH_MEMIF_FLAG_ZERO_COPY) {
187 : 0 : ret = rte_memseg_walk(memif_region_init_zc, (void *)proc_private);
188 [ # # ]: 0 : if (ret < 0)
189 : : return ret;
190 : : }
191 : :
192 : 0 : return memif_connect(dev);
193 : : }
194 : :
195 : : static int
196 : 0 : memif_dev_info(struct rte_eth_dev *dev __rte_unused, struct rte_eth_dev_info *dev_info)
197 : : {
198 : 0 : dev_info->max_mac_addrs = 1;
199 : 0 : dev_info->max_rx_pktlen = RTE_ETHER_MAX_LEN;
200 : 0 : dev_info->max_rx_queues = ETH_MEMIF_MAX_NUM_Q_PAIRS;
201 : 0 : dev_info->max_tx_queues = ETH_MEMIF_MAX_NUM_Q_PAIRS;
202 : 0 : dev_info->min_rx_bufsize = 0;
203 : 0 : dev_info->tx_offload_capa = RTE_ETH_TX_OFFLOAD_MULTI_SEGS;
204 : :
205 : 0 : return 0;
206 : : }
207 : :
208 : : static memif_ring_t *
209 : : memif_get_ring(struct pmd_internals *pmd, struct pmd_process_private *proc_private,
210 : : memif_ring_type_t type, uint16_t ring_num)
211 : : {
212 : : /* rings only in region 0 */
213 : 0 : void *p = proc_private->regions[0]->addr;
214 : 0 : int ring_size = sizeof(memif_ring_t) + sizeof(memif_desc_t) *
215 : 0 : (1 << pmd->run.log2_ring_size);
216 : :
217 : 0 : p = (uint8_t *)p + (ring_num + type * pmd->run.num_c2s_rings) * ring_size;
218 : :
219 : : return (memif_ring_t *)p;
220 : : }
221 : :
222 : : static memif_region_offset_t
223 : : memif_get_ring_offset(struct rte_eth_dev *dev, struct memif_queue *mq,
224 : : memif_ring_type_t type, uint16_t num)
225 : : {
226 : 0 : struct pmd_internals *pmd = dev->data->dev_private;
227 : 0 : struct pmd_process_private *proc_private = dev->process_private;
228 : :
229 : 0 : return ((uint8_t *)memif_get_ring(pmd, proc_private, type, num) -
230 : : (uint8_t *)proc_private->regions[mq->region]->addr);
231 : : }
232 : :
233 : : static memif_ring_t *
234 : : memif_get_ring_from_queue(struct pmd_process_private *proc_private,
235 : : struct memif_queue *mq)
236 : : {
237 : : struct memif_region *r;
238 : :
239 : 0 : r = proc_private->regions[mq->region];
240 [ # # # # ]: 0 : if (r == NULL)
241 : : return NULL;
242 : :
243 : 0 : return (memif_ring_t *)((uint8_t *)r->addr + mq->ring_offset);
244 : : }
245 : :
246 : : static void *
247 : : memif_get_buffer(struct pmd_process_private *proc_private, memif_desc_t *d)
248 : : {
249 : 0 : return ((uint8_t *)proc_private->regions[d->region]->addr + d->offset);
250 : : }
251 : :
252 : : /* Free mbufs received by server */
253 : : static void
254 : 0 : memif_free_stored_mbufs(struct pmd_process_private *proc_private, struct memif_queue *mq)
255 : : {
256 : : uint16_t cur_tail;
257 [ # # ]: 0 : uint16_t mask = (1 << mq->log2_ring_size) - 1;
258 : : memif_ring_t *ring = memif_get_ring_from_queue(proc_private, mq);
259 : :
260 : : /* FIXME: improve performance */
261 : : /* The ring->tail acts as a guard variable between Tx and Rx
262 : : * threads, so using load-acquire pairs with store-release
263 : : * in function eth_memif_rx for C2S queues.
264 : : */
265 : 0 : cur_tail = __atomic_load_n(&ring->tail, __ATOMIC_ACQUIRE);
266 [ # # ]: 0 : while (mq->last_tail != cur_tail) {
267 [ # # ]: 0 : RTE_MBUF_PREFETCH_TO_FREE(mq->buffers[(mq->last_tail + 1) & mask]);
268 [ # # ]: 0 : rte_pktmbuf_free_seg(mq->buffers[mq->last_tail & mask]);
269 : 0 : mq->last_tail++;
270 : : }
271 : 0 : }
272 : :
273 : : static int
274 : : memif_pktmbuf_chain(struct rte_mbuf *head, struct rte_mbuf *cur_tail,
275 : : struct rte_mbuf *tail)
276 : : {
277 : : /* Check for number-of-segments-overflow */
278 [ # # ]: 0 : if (unlikely(head->nb_segs + tail->nb_segs > RTE_MBUF_MAX_NB_SEGS))
279 : : return -EOVERFLOW;
280 : :
281 : : /* Chain 'tail' onto the old tail */
282 : 0 : cur_tail->next = tail;
283 : :
284 : : /* accumulate number of segments and total length. */
285 : 0 : head->nb_segs = (uint16_t)(head->nb_segs + tail->nb_segs);
286 : :
287 : 0 : tail->pkt_len = tail->data_len;
288 : 0 : head->pkt_len += tail->pkt_len;
289 : :
290 : 0 : return 0;
291 : : }
292 : :
293 : : static uint16_t
294 : 0 : eth_memif_rx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
295 : : {
296 : : struct memif_queue *mq = queue;
297 : 0 : struct pmd_internals *pmd = rte_eth_devices[mq->in_port].data->dev_private;
298 [ # # ]: 0 : struct pmd_process_private *proc_private =
299 : : rte_eth_devices[mq->in_port].process_private;
300 : : memif_ring_t *ring = memif_get_ring_from_queue(proc_private, mq);
301 : : uint16_t cur_slot, last_slot, n_slots, ring_size, mask, s0;
302 : : uint16_t pkts, rx_pkts, n_rx_pkts = 0;
303 [ # # ]: 0 : uint16_t mbuf_size = rte_pktmbuf_data_room_size(mq->mempool) -
304 : : RTE_PKTMBUF_HEADROOM;
305 : : uint16_t src_len, src_off, dst_len, dst_off, cp_len;
306 : 0 : memif_ring_type_t type = mq->type;
307 : : memif_desc_t *d0;
308 : : struct rte_mbuf *mbuf, *mbuf_head, *mbuf_tail;
309 : : uint64_t b;
310 : : ssize_t size __rte_unused;
311 : : uint16_t head;
312 : : int ret;
313 : : struct rte_eth_link link;
314 : :
315 [ # # ]: 0 : if (unlikely((pmd->flags & ETH_MEMIF_FLAG_CONNECTED) == 0))
316 : : return 0;
317 [ # # ]: 0 : if (unlikely(ring == NULL)) {
318 : : /* Secondary process will attempt to request regions. */
319 : 0 : ret = rte_eth_link_get(mq->in_port, &link);
320 [ # # ]: 0 : if (ret < 0)
321 : 0 : MIF_LOG(ERR, "Failed to get port %u link info: %s",
322 : : mq->in_port, rte_strerror(-ret));
323 : 0 : return 0;
324 : : }
325 : :
326 : : /* consume interrupt */
327 [ # # # # ]: 0 : if (((ring->flags & MEMIF_RING_FLAG_MASK_INT) == 0) &&
328 : 0 : (rte_intr_fd_get(mq->intr_handle) >= 0))
329 : 0 : size = read(rte_intr_fd_get(mq->intr_handle), &b,
330 : : sizeof(b));
331 : :
332 : 0 : ring_size = 1 << mq->log2_ring_size;
333 : 0 : mask = ring_size - 1;
334 : :
335 [ # # ]: 0 : if (type == MEMIF_RING_C2S) {
336 : 0 : cur_slot = mq->last_head;
337 : 0 : last_slot = __atomic_load_n(&ring->head, __ATOMIC_ACQUIRE);
338 : : } else {
339 : 0 : cur_slot = mq->last_tail;
340 : 0 : last_slot = __atomic_load_n(&ring->tail, __ATOMIC_ACQUIRE);
341 : : }
342 : :
343 [ # # ]: 0 : if (cur_slot == last_slot)
344 : 0 : goto refill;
345 : 0 : n_slots = last_slot - cur_slot;
346 : :
347 [ # # ]: 0 : if (likely(mbuf_size >= pmd->cfg.pkt_buffer_size)) {
348 : : struct rte_mbuf *mbufs[MAX_PKT_BURST];
349 : 0 : next_bulk:
350 : 0 : ret = rte_pktmbuf_alloc_bulk(mq->mempool, mbufs, MAX_PKT_BURST);
351 [ # # ]: 0 : if (unlikely(ret < 0))
352 : 0 : goto no_free_bufs;
353 : :
354 : : rx_pkts = 0;
355 : 0 : pkts = nb_pkts < MAX_PKT_BURST ? nb_pkts : MAX_PKT_BURST;
356 [ # # ]: 0 : while (n_slots && rx_pkts < pkts) {
357 : 0 : mbuf_head = mbufs[rx_pkts];
358 : : mbuf = mbuf_head;
359 : :
360 : 0 : next_slot1:
361 : 0 : mbuf->port = mq->in_port;
362 : 0 : s0 = cur_slot & mask;
363 : 0 : d0 = &ring->desc[s0];
364 : :
365 : 0 : cp_len = d0->length;
366 : :
367 : 0 : rte_pktmbuf_data_len(mbuf) = cp_len;
368 : 0 : rte_pktmbuf_pkt_len(mbuf) = cp_len;
369 [ # # ]: 0 : if (mbuf != mbuf_head)
370 : 0 : rte_pktmbuf_pkt_len(mbuf_head) += cp_len;
371 : :
372 [ # # ]: 0 : rte_memcpy(rte_pktmbuf_mtod(mbuf, void *),
373 : : (uint8_t *)memif_get_buffer(proc_private, d0), cp_len);
374 : :
375 : 0 : cur_slot++;
376 : 0 : n_slots--;
377 : :
378 [ # # ]: 0 : if (d0->flags & MEMIF_DESC_FLAG_NEXT) {
379 : : mbuf_tail = mbuf;
380 : 0 : mbuf = rte_pktmbuf_alloc(mq->mempool);
381 [ # # ]: 0 : if (unlikely(mbuf == NULL)) {
382 : 0 : rte_pktmbuf_free_bulk(mbufs + rx_pkts,
383 : 0 : MAX_PKT_BURST - rx_pkts);
384 : 0 : goto no_free_bufs;
385 : : }
386 : : ret = memif_pktmbuf_chain(mbuf_head, mbuf_tail, mbuf);
387 [ # # ]: 0 : if (unlikely(ret < 0)) {
388 : 0 : MIF_LOG(ERR, "number-of-segments-overflow");
389 : 0 : rte_pktmbuf_free(mbuf);
390 : 0 : rte_pktmbuf_free_bulk(mbufs + rx_pkts,
391 : 0 : MAX_PKT_BURST - rx_pkts);
392 : 0 : goto no_free_bufs;
393 : : }
394 : 0 : goto next_slot1;
395 : : }
396 : :
397 : 0 : mq->n_bytes += rte_pktmbuf_pkt_len(mbuf_head);
398 : 0 : *bufs++ = mbuf_head;
399 : 0 : rx_pkts++;
400 : 0 : n_rx_pkts++;
401 : : }
402 : :
403 [ # # ]: 0 : if (rx_pkts < MAX_PKT_BURST) {
404 : 0 : rte_pktmbuf_free_bulk(mbufs + rx_pkts, MAX_PKT_BURST - rx_pkts);
405 : : } else {
406 : 0 : nb_pkts -= rx_pkts;
407 [ # # ]: 0 : if (nb_pkts)
408 : 0 : goto next_bulk;
409 : : }
410 : : } else {
411 [ # # ]: 0 : while (n_slots && n_rx_pkts < nb_pkts) {
412 : 0 : mbuf_head = rte_pktmbuf_alloc(mq->mempool);
413 [ # # ]: 0 : if (unlikely(mbuf_head == NULL))
414 : 0 : goto no_free_bufs;
415 : : mbuf = mbuf_head;
416 : 0 : mbuf->port = mq->in_port;
417 : :
418 : 0 : next_slot2:
419 : 0 : s0 = cur_slot & mask;
420 : 0 : d0 = &ring->desc[s0];
421 : :
422 : 0 : src_len = d0->length;
423 : : dst_off = 0;
424 : : src_off = 0;
425 : :
426 : : do {
427 : 0 : dst_len = mbuf_size - dst_off;
428 [ # # ]: 0 : if (dst_len == 0) {
429 : : dst_off = 0;
430 : : dst_len = mbuf_size;
431 : :
432 : : /* store pointer to tail */
433 : : mbuf_tail = mbuf;
434 : 0 : mbuf = rte_pktmbuf_alloc(mq->mempool);
435 [ # # ]: 0 : if (unlikely(mbuf == NULL))
436 : 0 : goto no_free_bufs;
437 [ # # ]: 0 : mbuf->port = mq->in_port;
438 : : ret = memif_pktmbuf_chain(mbuf_head, mbuf_tail, mbuf);
439 [ # # ]: 0 : if (unlikely(ret < 0)) {
440 : 0 : MIF_LOG(ERR, "number-of-segments-overflow");
441 : 0 : rte_pktmbuf_free(mbuf);
442 : 0 : goto no_free_bufs;
443 : : }
444 : : }
445 : 0 : cp_len = RTE_MIN(dst_len, src_len);
446 : :
447 : 0 : rte_pktmbuf_data_len(mbuf) += cp_len;
448 : 0 : rte_pktmbuf_pkt_len(mbuf) = rte_pktmbuf_data_len(mbuf);
449 [ # # ]: 0 : if (mbuf != mbuf_head)
450 : 0 : rte_pktmbuf_pkt_len(mbuf_head) += cp_len;
451 : :
452 [ # # ]: 0 : rte_memcpy(rte_pktmbuf_mtod_offset(mbuf, void *,
453 : : dst_off),
454 : : (uint8_t *)memif_get_buffer(proc_private, d0) +
455 : : src_off, cp_len);
456 : :
457 : 0 : src_off += cp_len;
458 : 0 : dst_off += cp_len;
459 : 0 : src_len -= cp_len;
460 [ # # ]: 0 : } while (src_len);
461 : :
462 : 0 : cur_slot++;
463 : 0 : n_slots--;
464 : :
465 [ # # ]: 0 : if (d0->flags & MEMIF_DESC_FLAG_NEXT)
466 : 0 : goto next_slot2;
467 : :
468 : 0 : mq->n_bytes += rte_pktmbuf_pkt_len(mbuf_head);
469 : 0 : *bufs++ = mbuf_head;
470 : 0 : n_rx_pkts++;
471 : : }
472 : : }
473 : :
474 : 0 : no_free_bufs:
475 [ # # ]: 0 : if (type == MEMIF_RING_C2S) {
476 : 0 : __atomic_store_n(&ring->tail, cur_slot, __ATOMIC_RELEASE);
477 : 0 : mq->last_head = cur_slot;
478 : : } else {
479 : 0 : mq->last_tail = cur_slot;
480 : : }
481 : :
482 : 0 : refill:
483 [ # # ]: 0 : if (type == MEMIF_RING_S2C) {
484 : : /* ring->head is updated by the receiver and this function
485 : : * is called in the context of receiver thread. The loads in
486 : : * the receiver do not need to synchronize with its own stores.
487 : : */
488 : 0 : head = __atomic_load_n(&ring->head, __ATOMIC_RELAXED);
489 : 0 : n_slots = ring_size - head + mq->last_tail;
490 : :
491 [ # # ]: 0 : while (n_slots--) {
492 : 0 : s0 = head++ & mask;
493 : 0 : d0 = &ring->desc[s0];
494 : 0 : d0->length = pmd->run.pkt_buffer_size;
495 : : }
496 : 0 : __atomic_store_n(&ring->head, head, __ATOMIC_RELEASE);
497 : : }
498 : :
499 : 0 : mq->n_pkts += n_rx_pkts;
500 : 0 : return n_rx_pkts;
501 : : }
502 : :
503 : : static uint16_t
504 : 0 : eth_memif_rx_zc(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
505 : : {
506 : : struct memif_queue *mq = queue;
507 : 0 : struct pmd_internals *pmd = rte_eth_devices[mq->in_port].data->dev_private;
508 [ # # ]: 0 : struct pmd_process_private *proc_private =
509 : : rte_eth_devices[mq->in_port].process_private;
510 : : memif_ring_t *ring = memif_get_ring_from_queue(proc_private, mq);
511 : : uint16_t cur_slot, last_slot, n_slots, ring_size, mask, s0, head;
512 : : uint16_t n_rx_pkts = 0;
513 : : memif_desc_t *d0;
514 : : struct rte_mbuf *mbuf, *mbuf_tail;
515 : : struct rte_mbuf *mbuf_head = NULL;
516 : : int ret;
517 : : struct rte_eth_link link;
518 : :
519 [ # # ]: 0 : if (unlikely((pmd->flags & ETH_MEMIF_FLAG_CONNECTED) == 0))
520 : : return 0;
521 [ # # ]: 0 : if (unlikely(ring == NULL)) {
522 : : /* Secondary process will attempt to request regions. */
523 : 0 : rte_eth_link_get(mq->in_port, &link);
524 : 0 : return 0;
525 : : }
526 : :
527 : : /* consume interrupt */
528 [ # # ]: 0 : if ((rte_intr_fd_get(mq->intr_handle) >= 0) &&
529 [ # # ]: 0 : ((ring->flags & MEMIF_RING_FLAG_MASK_INT) == 0)) {
530 : : uint64_t b;
531 : : ssize_t size __rte_unused;
532 : 0 : size = read(rte_intr_fd_get(mq->intr_handle), &b,
533 : : sizeof(b));
534 : : }
535 : :
536 : 0 : ring_size = 1 << mq->log2_ring_size;
537 : 0 : mask = ring_size - 1;
538 : :
539 : 0 : cur_slot = mq->last_tail;
540 : : /* The ring->tail acts as a guard variable between Tx and Rx
541 : : * threads, so using load-acquire pairs with store-release
542 : : * to synchronize it between threads.
543 : : */
544 : 0 : last_slot = __atomic_load_n(&ring->tail, __ATOMIC_ACQUIRE);
545 [ # # ]: 0 : if (cur_slot == last_slot)
546 : 0 : goto refill;
547 : 0 : n_slots = last_slot - cur_slot;
548 : :
549 [ # # ]: 0 : while (n_slots && n_rx_pkts < nb_pkts) {
550 : 0 : s0 = cur_slot & mask;
551 : :
552 : 0 : d0 = &ring->desc[s0];
553 : 0 : mbuf_head = mq->buffers[s0];
554 : : mbuf = mbuf_head;
555 : :
556 : 0 : next_slot:
557 : : /* prefetch next descriptor */
558 [ # # ]: 0 : if (n_rx_pkts + 1 < nb_pkts)
559 : 0 : rte_prefetch0(&ring->desc[(cur_slot + 1) & mask]);
560 : :
561 : 0 : mbuf->port = mq->in_port;
562 : 0 : rte_pktmbuf_data_len(mbuf) = d0->length;
563 : 0 : rte_pktmbuf_pkt_len(mbuf) = rte_pktmbuf_data_len(mbuf);
564 : :
565 : 0 : mq->n_bytes += rte_pktmbuf_data_len(mbuf);
566 : :
567 : 0 : cur_slot++;
568 : 0 : n_slots--;
569 [ # # ]: 0 : if (d0->flags & MEMIF_DESC_FLAG_NEXT) {
570 : 0 : s0 = cur_slot & mask;
571 : 0 : d0 = &ring->desc[s0];
572 : : mbuf_tail = mbuf;
573 [ # # ]: 0 : mbuf = mq->buffers[s0];
574 : : ret = memif_pktmbuf_chain(mbuf_head, mbuf_tail, mbuf);
575 [ # # ]: 0 : if (unlikely(ret < 0)) {
576 : 0 : MIF_LOG(ERR, "number-of-segments-overflow");
577 : 0 : goto refill;
578 : : }
579 : 0 : goto next_slot;
580 : : }
581 : :
582 : 0 : *bufs++ = mbuf_head;
583 : 0 : n_rx_pkts++;
584 : : }
585 : :
586 : 0 : mq->last_tail = cur_slot;
587 : :
588 : : /* Supply server with new buffers */
589 : 0 : refill:
590 : : /* ring->head is updated by the receiver and this function
591 : : * is called in the context of receiver thread. The loads in
592 : : * the receiver do not need to synchronize with its own stores.
593 : : */
594 : 0 : head = __atomic_load_n(&ring->head, __ATOMIC_RELAXED);
595 : 0 : n_slots = ring_size - head + mq->last_tail;
596 : :
597 [ # # ]: 0 : if (n_slots < 32)
598 : 0 : goto no_free_mbufs;
599 : :
600 : 0 : ret = rte_pktmbuf_alloc_bulk(mq->mempool, &mq->buffers[head & mask], n_slots);
601 [ # # ]: 0 : if (unlikely(ret < 0))
602 : 0 : goto no_free_mbufs;
603 : :
604 [ # # ]: 0 : while (n_slots--) {
605 : 0 : s0 = head++ & mask;
606 [ # # ]: 0 : if (n_slots > 0)
607 : 0 : rte_prefetch0(mq->buffers[head & mask]);
608 : 0 : d0 = &ring->desc[s0];
609 : : /* store buffer header */
610 : 0 : mbuf = mq->buffers[s0];
611 : : /* populate descriptor */
612 [ # # ]: 0 : d0->length = rte_pktmbuf_data_room_size(mq->mempool) -
613 : : RTE_PKTMBUF_HEADROOM;
614 : 0 : d0->region = 1;
615 : 0 : d0->offset = rte_pktmbuf_mtod(mbuf, uint8_t *) -
616 : 0 : (uint8_t *)proc_private->regions[d0->region]->addr;
617 : : }
618 : 0 : no_free_mbufs:
619 : : /* The ring->head acts as a guard variable between Tx and Rx
620 : : * threads, so using store-release pairs with load-acquire
621 : : * in function eth_memif_tx.
622 : : */
623 : 0 : __atomic_store_n(&ring->head, head, __ATOMIC_RELEASE);
624 : :
625 : 0 : mq->n_pkts += n_rx_pkts;
626 : :
627 : 0 : return n_rx_pkts;
628 : : }
629 : :
630 : : static uint16_t
631 : 0 : eth_memif_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
632 : : {
633 : : struct memif_queue *mq = queue;
634 : 0 : struct pmd_internals *pmd = rte_eth_devices[mq->in_port].data->dev_private;
635 [ # # ]: 0 : struct pmd_process_private *proc_private =
636 : : rte_eth_devices[mq->in_port].process_private;
637 : : memif_ring_t *ring = memif_get_ring_from_queue(proc_private, mq);
638 : : uint16_t slot, saved_slot, n_free, ring_size, mask, n_tx_pkts = 0;
639 : : uint16_t src_len, src_off, dst_len, dst_off, cp_len, nb_segs;
640 : 0 : memif_ring_type_t type = mq->type;
641 : : memif_desc_t *d0;
642 : : struct rte_mbuf *mbuf;
643 : : struct rte_mbuf *mbuf_head;
644 : : uint64_t a;
645 : : ssize_t size;
646 : : struct rte_eth_link link;
647 : :
648 [ # # ]: 0 : if (unlikely((pmd->flags & ETH_MEMIF_FLAG_CONNECTED) == 0))
649 : : return 0;
650 [ # # ]: 0 : if (unlikely(ring == NULL)) {
651 : : int ret;
652 : :
653 : : /* Secondary process will attempt to request regions. */
654 : 0 : ret = rte_eth_link_get(mq->in_port, &link);
655 [ # # ]: 0 : if (ret < 0)
656 : 0 : MIF_LOG(ERR, "Failed to get port %u link info: %s",
657 : : mq->in_port, rte_strerror(-ret));
658 : 0 : return 0;
659 : : }
660 : :
661 : 0 : ring_size = 1 << mq->log2_ring_size;
662 : 0 : mask = ring_size - 1;
663 : :
664 [ # # ]: 0 : if (type == MEMIF_RING_C2S) {
665 : : /* For C2S queues ring->head is updated by the sender and
666 : : * this function is called in the context of sending thread.
667 : : * The loads in the sender do not need to synchronize with
668 : : * its own stores. Hence, the following load can be a
669 : : * relaxed load.
670 : : */
671 : 0 : slot = __atomic_load_n(&ring->head, __ATOMIC_RELAXED);
672 : 0 : n_free = ring_size - slot +
673 : 0 : __atomic_load_n(&ring->tail, __ATOMIC_ACQUIRE);
674 : : } else {
675 : : /* For S2C queues ring->tail is updated by the sender and
676 : : * this function is called in the context of sending thread.
677 : : * The loads in the sender do not need to synchronize with
678 : : * its own stores. Hence, the following load can be a
679 : : * relaxed load.
680 : : */
681 : 0 : slot = __atomic_load_n(&ring->tail, __ATOMIC_RELAXED);
682 : 0 : n_free = __atomic_load_n(&ring->head, __ATOMIC_ACQUIRE) - slot;
683 : : }
684 : :
685 : : uint16_t i;
686 : : struct rte_mbuf **buf_tmp = bufs;
687 : 0 : mbuf_head = *buf_tmp++;
688 : 0 : struct rte_mempool *mp = mbuf_head->pool;
689 : :
690 [ # # ]: 0 : for (i = 1; i < nb_pkts; i++) {
691 : 0 : mbuf_head = *buf_tmp++;
692 [ # # ]: 0 : if (mbuf_head->pool != mp)
693 : : break;
694 : : }
695 : :
696 : 0 : uint16_t mbuf_size = rte_pktmbuf_data_room_size(mp) - RTE_PKTMBUF_HEADROOM;
697 [ # # # # ]: 0 : if (i == nb_pkts && pmd->cfg.pkt_buffer_size >= mbuf_size) {
698 : : buf_tmp = bufs;
699 [ # # ]: 0 : while (n_tx_pkts < nb_pkts && n_free) {
700 : 0 : mbuf_head = *bufs++;
701 : 0 : nb_segs = mbuf_head->nb_segs;
702 : : mbuf = mbuf_head;
703 : :
704 : : saved_slot = slot;
705 : :
706 : 0 : next_in_chain1:
707 : 0 : d0 = &ring->desc[slot & mask];
708 : 0 : cp_len = rte_pktmbuf_data_len(mbuf);
709 : :
710 : 0 : rte_memcpy((uint8_t *)memif_get_buffer(proc_private, d0),
711 [ # # ]: 0 : rte_pktmbuf_mtod(mbuf, void *), cp_len);
712 : :
713 : 0 : d0->length = cp_len;
714 : 0 : mq->n_bytes += cp_len;
715 : 0 : slot++;
716 : 0 : n_free--;
717 : :
718 [ # # ]: 0 : if (--nb_segs > 0) {
719 [ # # ]: 0 : if (n_free) {
720 : 0 : d0->flags |= MEMIF_DESC_FLAG_NEXT;
721 : 0 : mbuf = mbuf->next;
722 : 0 : goto next_in_chain1;
723 : : } else {
724 : : slot = saved_slot;
725 : 0 : goto free_mbufs;
726 : : }
727 : : }
728 : :
729 : 0 : n_tx_pkts++;
730 : : }
731 : 0 : free_mbufs:
732 : 0 : rte_pktmbuf_free_bulk(buf_tmp, n_tx_pkts);
733 : : } else {
734 [ # # ]: 0 : while (n_tx_pkts < nb_pkts && n_free) {
735 : 0 : mbuf_head = *bufs++;
736 : 0 : nb_segs = mbuf_head->nb_segs;
737 : : mbuf = mbuf_head;
738 : :
739 : : saved_slot = slot;
740 : 0 : d0 = &ring->desc[slot & mask];
741 : : dst_off = 0;
742 [ # # ]: 0 : dst_len = (type == MEMIF_RING_C2S) ?
743 : 0 : pmd->run.pkt_buffer_size : d0->length;
744 : :
745 : 0 : next_in_chain2:
746 : : src_off = 0;
747 : 0 : src_len = rte_pktmbuf_data_len(mbuf);
748 : :
749 [ # # ]: 0 : while (src_len) {
750 [ # # ]: 0 : if (dst_len == 0) {
751 [ # # ]: 0 : if (n_free) {
752 : 0 : slot++;
753 : 0 : n_free--;
754 : 0 : d0->flags |= MEMIF_DESC_FLAG_NEXT;
755 : 0 : d0 = &ring->desc[slot & mask];
756 : : dst_off = 0;
757 [ # # ]: 0 : dst_len = (type == MEMIF_RING_C2S) ?
758 : 0 : pmd->run.pkt_buffer_size : d0->length;
759 : 0 : d0->flags = 0;
760 : : } else {
761 : : slot = saved_slot;
762 : 0 : goto no_free_slots;
763 : : }
764 : : }
765 : 0 : cp_len = RTE_MIN(dst_len, src_len);
766 : :
767 : 0 : rte_memcpy((uint8_t *)memif_get_buffer(proc_private,
768 : : d0) + dst_off,
769 [ # # ]: 0 : rte_pktmbuf_mtod_offset(mbuf, void *, src_off),
770 : : cp_len);
771 : :
772 : 0 : mq->n_bytes += cp_len;
773 : 0 : src_off += cp_len;
774 : 0 : dst_off += cp_len;
775 : 0 : src_len -= cp_len;
776 : 0 : dst_len -= cp_len;
777 : :
778 : 0 : d0->length = dst_off;
779 : : }
780 : :
781 [ # # ]: 0 : if (--nb_segs > 0) {
782 : 0 : mbuf = mbuf->next;
783 : 0 : goto next_in_chain2;
784 : : }
785 : :
786 : 0 : n_tx_pkts++;
787 : 0 : slot++;
788 : 0 : n_free--;
789 : 0 : rte_pktmbuf_free(mbuf_head);
790 : : }
791 : : }
792 : :
793 : 0 : no_free_slots:
794 [ # # ]: 0 : if (type == MEMIF_RING_C2S)
795 : 0 : __atomic_store_n(&ring->head, slot, __ATOMIC_RELEASE);
796 : : else
797 : 0 : __atomic_store_n(&ring->tail, slot, __ATOMIC_RELEASE);
798 : :
799 [ # # # # ]: 0 : if (((ring->flags & MEMIF_RING_FLAG_MASK_INT) == 0) &&
800 : 0 : (rte_intr_fd_get(mq->intr_handle) >= 0)) {
801 : 0 : a = 1;
802 : 0 : size = write(rte_intr_fd_get(mq->intr_handle), &a,
803 : : sizeof(a));
804 [ # # ]: 0 : if (unlikely(size < 0)) {
805 : 0 : MIF_LOG(WARNING,
806 : : "Failed to send interrupt. %s", strerror(errno));
807 : : }
808 : : }
809 : :
810 : 0 : mq->n_pkts += n_tx_pkts;
811 : 0 : return n_tx_pkts;
812 : : }
813 : :
814 : : static int
815 : 0 : memif_tx_one_zc(struct pmd_process_private *proc_private, struct memif_queue *mq,
816 : : memif_ring_t *ring, struct rte_mbuf *mbuf, const uint16_t mask,
817 : : uint16_t slot, uint16_t n_free)
818 : : {
819 : : memif_desc_t *d0;
820 : 0 : uint16_t nb_segs = mbuf->nb_segs;
821 : : int used_slots = 1;
822 : :
823 : 0 : next_in_chain:
824 : : /* store pointer to mbuf to free it later */
825 : 0 : mq->buffers[slot & mask] = mbuf;
826 : : /* populate descriptor */
827 : 0 : d0 = &ring->desc[slot & mask];
828 : 0 : d0->length = rte_pktmbuf_data_len(mbuf);
829 : 0 : mq->n_bytes += rte_pktmbuf_data_len(mbuf);
830 : : /* FIXME: get region index */
831 : 0 : d0->region = 1;
832 : 0 : d0->offset = rte_pktmbuf_mtod(mbuf, uint8_t *) -
833 : 0 : (uint8_t *)proc_private->regions[d0->region]->addr;
834 : 0 : d0->flags = 0;
835 : :
836 : : /* check if buffer is chained */
837 [ # # ]: 0 : if (--nb_segs > 0) {
838 [ # # ]: 0 : if (n_free < 2)
839 : : return 0;
840 : : /* mark buffer as chained */
841 : 0 : d0->flags |= MEMIF_DESC_FLAG_NEXT;
842 : : /* advance mbuf */
843 : 0 : mbuf = mbuf->next;
844 : : /* update counters */
845 : 0 : used_slots++;
846 : 0 : slot++;
847 : 0 : n_free--;
848 : 0 : goto next_in_chain;
849 : : }
850 : : return used_slots;
851 : : }
852 : :
853 : : static uint16_t
854 : 0 : eth_memif_tx_zc(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
855 : : {
856 : : struct memif_queue *mq = queue;
857 : 0 : struct pmd_internals *pmd = rte_eth_devices[mq->in_port].data->dev_private;
858 [ # # ]: 0 : struct pmd_process_private *proc_private =
859 : : rte_eth_devices[mq->in_port].process_private;
860 : : memif_ring_t *ring = memif_get_ring_from_queue(proc_private, mq);
861 : : uint16_t slot, n_free, ring_size, mask, n_tx_pkts = 0;
862 : : struct rte_eth_link link;
863 : :
864 [ # # ]: 0 : if (unlikely((pmd->flags & ETH_MEMIF_FLAG_CONNECTED) == 0))
865 : : return 0;
866 [ # # ]: 0 : if (unlikely(ring == NULL)) {
867 : : /* Secondary process will attempt to request regions. */
868 : 0 : rte_eth_link_get(mq->in_port, &link);
869 : 0 : return 0;
870 : : }
871 : :
872 : 0 : ring_size = 1 << mq->log2_ring_size;
873 : 0 : mask = ring_size - 1;
874 : :
875 : : /* free mbufs received by server */
876 : 0 : memif_free_stored_mbufs(proc_private, mq);
877 : :
878 : : /* ring type always MEMIF_RING_C2S */
879 : : /* For C2S queues ring->head is updated by the sender and
880 : : * this function is called in the context of sending thread.
881 : : * The loads in the sender do not need to synchronize with
882 : : * its own stores. Hence, the following load can be a
883 : : * relaxed load.
884 : : */
885 : 0 : slot = __atomic_load_n(&ring->head, __ATOMIC_RELAXED);
886 : 0 : n_free = ring_size - slot + mq->last_tail;
887 : :
888 : : int used_slots;
889 : :
890 [ # # ]: 0 : while (n_free && (n_tx_pkts < nb_pkts)) {
891 [ # # # # ]: 0 : while ((n_free > 4) && ((nb_pkts - n_tx_pkts) > 4)) {
892 [ # # ]: 0 : if ((nb_pkts - n_tx_pkts) > 8) {
893 : 0 : rte_prefetch0(*bufs + 4);
894 : 0 : rte_prefetch0(*bufs + 5);
895 : 0 : rte_prefetch0(*bufs + 6);
896 : 0 : rte_prefetch0(*bufs + 7);
897 : : }
898 : 0 : used_slots = memif_tx_one_zc(proc_private, mq, ring, *bufs++,
899 : : mask, slot, n_free);
900 [ # # ]: 0 : if (unlikely(used_slots < 1))
901 : 0 : goto no_free_slots;
902 : 0 : n_tx_pkts++;
903 : 0 : slot += used_slots;
904 : 0 : n_free -= used_slots;
905 : :
906 : 0 : used_slots = memif_tx_one_zc(proc_private, mq, ring, *bufs++,
907 : : mask, slot, n_free);
908 [ # # ]: 0 : if (unlikely(used_slots < 1))
909 : 0 : goto no_free_slots;
910 : 0 : n_tx_pkts++;
911 : 0 : slot += used_slots;
912 : 0 : n_free -= used_slots;
913 : :
914 : 0 : used_slots = memif_tx_one_zc(proc_private, mq, ring, *bufs++,
915 : : mask, slot, n_free);
916 [ # # ]: 0 : if (unlikely(used_slots < 1))
917 : 0 : goto no_free_slots;
918 : 0 : n_tx_pkts++;
919 : 0 : slot += used_slots;
920 : 0 : n_free -= used_slots;
921 : :
922 : 0 : used_slots = memif_tx_one_zc(proc_private, mq, ring, *bufs++,
923 : : mask, slot, n_free);
924 [ # # ]: 0 : if (unlikely(used_slots < 1))
925 : 0 : goto no_free_slots;
926 : 0 : n_tx_pkts++;
927 : 0 : slot += used_slots;
928 : 0 : n_free -= used_slots;
929 : : }
930 : 0 : used_slots = memif_tx_one_zc(proc_private, mq, ring, *bufs++,
931 : : mask, slot, n_free);
932 [ # # ]: 0 : if (unlikely(used_slots < 1))
933 : 0 : goto no_free_slots;
934 : 0 : n_tx_pkts++;
935 : 0 : slot += used_slots;
936 : 0 : n_free -= used_slots;
937 : : }
938 : :
939 : 0 : no_free_slots:
940 : : /* ring type always MEMIF_RING_C2S */
941 : : /* The ring->head acts as a guard variable between Tx and Rx
942 : : * threads, so using store-release pairs with load-acquire
943 : : * in function eth_memif_rx for C2S rings.
944 : : */
945 : 0 : __atomic_store_n(&ring->head, slot, __ATOMIC_RELEASE);
946 : :
947 : : /* Send interrupt, if enabled. */
948 [ # # ]: 0 : if ((ring->flags & MEMIF_RING_FLAG_MASK_INT) == 0) {
949 : 0 : uint64_t a = 1;
950 [ # # ]: 0 : if (rte_intr_fd_get(mq->intr_handle) < 0)
951 : 0 : return -1;
952 : :
953 : 0 : ssize_t size = write(rte_intr_fd_get(mq->intr_handle),
954 : : &a, sizeof(a));
955 [ # # ]: 0 : if (unlikely(size < 0)) {
956 : 0 : MIF_LOG(WARNING,
957 : : "Failed to send interrupt. %s", strerror(errno));
958 : : }
959 : : }
960 : :
961 : : /* increment queue counters */
962 : 0 : mq->n_pkts += n_tx_pkts;
963 : :
964 : 0 : return n_tx_pkts;
965 : : }
966 : :
967 : : void
968 : 0 : memif_free_regions(struct rte_eth_dev *dev)
969 : : {
970 : 0 : struct pmd_process_private *proc_private = dev->process_private;
971 : 0 : struct pmd_internals *pmd = dev->data->dev_private;
972 : : int i;
973 : : struct memif_region *r;
974 : :
975 : : /* regions are allocated contiguously, so it's
976 : : * enough to loop until 'proc_private->regions_num'
977 : : */
978 [ # # ]: 0 : for (i = 0; i < proc_private->regions_num; i++) {
979 : 0 : r = proc_private->regions[i];
980 [ # # ]: 0 : if (r != NULL) {
981 : : /* This is memzone */
982 [ # # # # ]: 0 : if (i > 0 && (pmd->flags & ETH_MEMIF_FLAG_ZERO_COPY)) {
983 : 0 : r->addr = NULL;
984 [ # # ]: 0 : if (r->fd > 0)
985 : 0 : close(r->fd);
986 : : }
987 [ # # ]: 0 : if (r->addr != NULL) {
988 : 0 : munmap(r->addr, r->region_size);
989 [ # # ]: 0 : if (r->fd > 0) {
990 : 0 : close(r->fd);
991 : 0 : r->fd = -1;
992 : : }
993 : : }
994 : 0 : rte_free(r);
995 : 0 : proc_private->regions[i] = NULL;
996 : : }
997 : : }
998 : 0 : proc_private->regions_num = 0;
999 : 0 : }
1000 : :
1001 : : static int
1002 : 0 : memif_region_init_zc(const struct rte_memseg_list *msl, const struct rte_memseg *ms,
1003 : : void *arg)
1004 : : {
1005 : : struct pmd_process_private *proc_private = (struct pmd_process_private *)arg;
1006 : : struct memif_region *r;
1007 : :
1008 [ # # ]: 0 : if (proc_private->regions_num < 1) {
1009 : 0 : MIF_LOG(ERR, "Missing descriptor region");
1010 : 0 : return -1;
1011 : : }
1012 : :
1013 : 0 : r = proc_private->regions[proc_private->regions_num - 1];
1014 : :
1015 [ # # ]: 0 : if (r->addr != msl->base_va)
1016 : 0 : r = proc_private->regions[++proc_private->regions_num - 1];
1017 : :
1018 [ # # ]: 0 : if (r == NULL) {
1019 : 0 : r = rte_zmalloc("region", sizeof(struct memif_region), 0);
1020 [ # # ]: 0 : if (r == NULL) {
1021 : 0 : MIF_LOG(ERR, "Failed to alloc memif region.");
1022 : 0 : return -ENOMEM;
1023 : : }
1024 : :
1025 : 0 : r->addr = msl->base_va;
1026 : 0 : r->region_size = ms->len;
1027 : 0 : r->fd = rte_memseg_get_fd(ms);
1028 [ # # ]: 0 : if (r->fd < 0)
1029 : : return -1;
1030 : 0 : r->pkt_buffer_offset = 0;
1031 : :
1032 : 0 : proc_private->regions[proc_private->regions_num - 1] = r;
1033 : : } else {
1034 : 0 : r->region_size += ms->len;
1035 : : }
1036 : :
1037 : : return 0;
1038 : : }
1039 : :
1040 : : static int
1041 : 0 : memif_region_init_shm(struct rte_eth_dev *dev, uint8_t has_buffers)
1042 : : {
1043 : 0 : struct pmd_internals *pmd = dev->data->dev_private;
1044 : 0 : struct pmd_process_private *proc_private = dev->process_private;
1045 : : char shm_name[ETH_MEMIF_SHM_NAME_SIZE];
1046 : : int ret = 0;
1047 : : struct memif_region *r;
1048 : :
1049 [ # # ]: 0 : if (proc_private->regions_num >= ETH_MEMIF_MAX_REGION_NUM) {
1050 : 0 : MIF_LOG(ERR, "Too many regions.");
1051 : 0 : return -1;
1052 : : }
1053 : :
1054 : 0 : r = rte_zmalloc("region", sizeof(struct memif_region), 0);
1055 [ # # ]: 0 : if (r == NULL) {
1056 : 0 : MIF_LOG(ERR, "Failed to alloc memif region.");
1057 : 0 : return -ENOMEM;
1058 : : }
1059 : :
1060 : : /* calculate buffer offset */
1061 : 0 : r->pkt_buffer_offset = (pmd->run.num_c2s_rings + pmd->run.num_s2c_rings) *
1062 : 0 : (sizeof(memif_ring_t) + sizeof(memif_desc_t) *
1063 : 0 : (1 << pmd->run.log2_ring_size));
1064 : :
1065 : 0 : r->region_size = r->pkt_buffer_offset;
1066 : : /* if region has buffers, add buffers size to region_size */
1067 [ # # ]: 0 : if (has_buffers == 1)
1068 : 0 : r->region_size += (uint32_t)(pmd->run.pkt_buffer_size *
1069 : 0 : (1 << pmd->run.log2_ring_size) *
1070 : : (pmd->run.num_c2s_rings +
1071 : : pmd->run.num_s2c_rings));
1072 : :
1073 : : memset(shm_name, 0, sizeof(char) * ETH_MEMIF_SHM_NAME_SIZE);
1074 : 0 : snprintf(shm_name, ETH_MEMIF_SHM_NAME_SIZE, "memif_region_%d",
1075 : 0 : proc_private->regions_num);
1076 : :
1077 : 0 : r->fd = memfd_create(shm_name, MFD_ALLOW_SEALING);
1078 [ # # ]: 0 : if (r->fd < 0) {
1079 : 0 : MIF_LOG(ERR, "Failed to create shm file: %s.", strerror(errno));
1080 : : ret = -1;
1081 : 0 : goto error;
1082 : : }
1083 : :
1084 : 0 : ret = fcntl(r->fd, F_ADD_SEALS, F_SEAL_SHRINK);
1085 [ # # ]: 0 : if (ret < 0) {
1086 : 0 : MIF_LOG(ERR, "Failed to add seals to shm file: %s.", strerror(errno));
1087 : 0 : goto error;
1088 : : }
1089 : :
1090 : 0 : ret = ftruncate(r->fd, r->region_size);
1091 [ # # ]: 0 : if (ret < 0) {
1092 : 0 : MIF_LOG(ERR, "Failed to truncate shm file: %s.", strerror(errno));
1093 : 0 : goto error;
1094 : : }
1095 : :
1096 : 0 : r->addr = mmap(NULL, r->region_size, PROT_READ |
1097 : : PROT_WRITE, MAP_SHARED, r->fd, 0);
1098 [ # # ]: 0 : if (r->addr == MAP_FAILED) {
1099 : 0 : MIF_LOG(ERR, "Failed to mmap shm region: %s.", strerror(ret));
1100 : : ret = -1;
1101 : 0 : goto error;
1102 : : }
1103 : :
1104 : 0 : proc_private->regions[proc_private->regions_num] = r;
1105 : 0 : proc_private->regions_num++;
1106 : :
1107 : 0 : return ret;
1108 : :
1109 : 0 : error:
1110 [ # # ]: 0 : if (r->fd > 0)
1111 : 0 : close(r->fd);
1112 : 0 : r->fd = -1;
1113 : :
1114 : 0 : return ret;
1115 : : }
1116 : :
1117 : : static int
1118 : 0 : memif_regions_init(struct rte_eth_dev *dev)
1119 : : {
1120 : 0 : struct pmd_internals *pmd = dev->data->dev_private;
1121 : : int ret;
1122 : :
1123 : : /*
1124 : : * Zero-copy exposes dpdk memory.
1125 : : * Each memseg list will be represented by memif region.
1126 : : * Zero-copy regions indexing: memseg list idx + 1,
1127 : : * as we already have region 0 reserved for descriptors.
1128 : : */
1129 [ # # ]: 0 : if (pmd->flags & ETH_MEMIF_FLAG_ZERO_COPY) {
1130 : : /* create region idx 0 containing descriptors */
1131 : 0 : ret = memif_region_init_shm(dev, 0);
1132 [ # # ]: 0 : if (ret < 0)
1133 : : return ret;
1134 : 0 : ret = rte_memseg_walk(memif_region_init_zc, (void *)dev->process_private);
1135 : : if (ret < 0)
1136 : : return ret;
1137 : : } else {
1138 : : /* create one memory region containing rings and buffers */
1139 : 0 : ret = memif_region_init_shm(dev, /* has buffers */ 1);
1140 : : if (ret < 0)
1141 : : return ret;
1142 : : }
1143 : :
1144 : : return 0;
1145 : : }
1146 : :
1147 : : static void
1148 : 0 : memif_init_rings(struct rte_eth_dev *dev)
1149 : : {
1150 : 0 : struct pmd_internals *pmd = dev->data->dev_private;
1151 : 0 : struct pmd_process_private *proc_private = dev->process_private;
1152 : : memif_ring_t *ring;
1153 : : int i, j;
1154 : : uint16_t slot;
1155 : :
1156 [ # # ]: 0 : for (i = 0; i < pmd->run.num_c2s_rings; i++) {
1157 : : ring = memif_get_ring(pmd, proc_private, MEMIF_RING_C2S, i);
1158 : 0 : __atomic_store_n(&ring->head, 0, __ATOMIC_RELAXED);
1159 : 0 : __atomic_store_n(&ring->tail, 0, __ATOMIC_RELAXED);
1160 : 0 : ring->cookie = MEMIF_COOKIE;
1161 : 0 : ring->flags = 0;
1162 : :
1163 [ # # ]: 0 : if (pmd->flags & ETH_MEMIF_FLAG_ZERO_COPY)
1164 : 0 : continue;
1165 : :
1166 [ # # ]: 0 : for (j = 0; j < (1 << pmd->run.log2_ring_size); j++) {
1167 : 0 : slot = i * (1 << pmd->run.log2_ring_size) + j;
1168 : 0 : ring->desc[j].region = 0;
1169 : 0 : ring->desc[j].offset =
1170 : 0 : proc_private->regions[0]->pkt_buffer_offset +
1171 : 0 : (uint32_t)(slot * pmd->run.pkt_buffer_size);
1172 : 0 : ring->desc[j].length = pmd->run.pkt_buffer_size;
1173 : : }
1174 : : }
1175 : :
1176 [ # # ]: 0 : for (i = 0; i < pmd->run.num_s2c_rings; i++) {
1177 : : ring = memif_get_ring(pmd, proc_private, MEMIF_RING_S2C, i);
1178 : 0 : __atomic_store_n(&ring->head, 0, __ATOMIC_RELAXED);
1179 : 0 : __atomic_store_n(&ring->tail, 0, __ATOMIC_RELAXED);
1180 : 0 : ring->cookie = MEMIF_COOKIE;
1181 : 0 : ring->flags = 0;
1182 : :
1183 [ # # ]: 0 : if (pmd->flags & ETH_MEMIF_FLAG_ZERO_COPY)
1184 : 0 : continue;
1185 : :
1186 [ # # ]: 0 : for (j = 0; j < (1 << pmd->run.log2_ring_size); j++) {
1187 : 0 : slot = (i + pmd->run.num_c2s_rings) *
1188 : 0 : (1 << pmd->run.log2_ring_size) + j;
1189 : 0 : ring->desc[j].region = 0;
1190 : 0 : ring->desc[j].offset =
1191 : 0 : proc_private->regions[0]->pkt_buffer_offset +
1192 : 0 : (uint32_t)(slot * pmd->run.pkt_buffer_size);
1193 : 0 : ring->desc[j].length = pmd->run.pkt_buffer_size;
1194 : : }
1195 : : }
1196 : 0 : }
1197 : :
1198 : : /* called only by client */
1199 : : static int
1200 : 0 : memif_init_queues(struct rte_eth_dev *dev)
1201 : : {
1202 : 0 : struct pmd_internals *pmd = dev->data->dev_private;
1203 : : struct memif_queue *mq;
1204 : : int i;
1205 : :
1206 [ # # ]: 0 : for (i = 0; i < pmd->run.num_c2s_rings; i++) {
1207 : 0 : mq = dev->data->tx_queues[i];
1208 : 0 : mq->log2_ring_size = pmd->run.log2_ring_size;
1209 : : /* queues located only in region 0 */
1210 : 0 : mq->region = 0;
1211 : 0 : mq->ring_offset = memif_get_ring_offset(dev, mq, MEMIF_RING_C2S, i);
1212 : 0 : mq->last_head = 0;
1213 : 0 : mq->last_tail = 0;
1214 [ # # ]: 0 : if (rte_intr_fd_set(mq->intr_handle, eventfd(0, EFD_NONBLOCK)))
1215 : 0 : return -rte_errno;
1216 : :
1217 [ # # ]: 0 : if (rte_intr_fd_get(mq->intr_handle) < 0) {
1218 : 0 : MIF_LOG(WARNING,
1219 : : "Failed to create eventfd for tx queue %d: %s.", i,
1220 : : strerror(errno));
1221 : : }
1222 : 0 : mq->buffers = NULL;
1223 [ # # ]: 0 : if (pmd->flags & ETH_MEMIF_FLAG_ZERO_COPY) {
1224 : 0 : mq->buffers = rte_zmalloc("bufs", sizeof(struct rte_mbuf *) *
1225 : 0 : (1 << mq->log2_ring_size), 0);
1226 [ # # ]: 0 : if (mq->buffers == NULL)
1227 : : return -ENOMEM;
1228 : : }
1229 : : }
1230 : :
1231 [ # # ]: 0 : for (i = 0; i < pmd->run.num_s2c_rings; i++) {
1232 : 0 : mq = dev->data->rx_queues[i];
1233 : 0 : mq->log2_ring_size = pmd->run.log2_ring_size;
1234 : : /* queues located only in region 0 */
1235 : 0 : mq->region = 0;
1236 : 0 : mq->ring_offset = memif_get_ring_offset(dev, mq, MEMIF_RING_S2C, i);
1237 : 0 : mq->last_head = 0;
1238 : 0 : mq->last_tail = 0;
1239 [ # # ]: 0 : if (rte_intr_fd_set(mq->intr_handle, eventfd(0, EFD_NONBLOCK)))
1240 : 0 : return -rte_errno;
1241 [ # # ]: 0 : if (rte_intr_fd_get(mq->intr_handle) < 0) {
1242 : 0 : MIF_LOG(WARNING,
1243 : : "Failed to create eventfd for rx queue %d: %s.", i,
1244 : : strerror(errno));
1245 : : }
1246 : 0 : mq->buffers = NULL;
1247 [ # # ]: 0 : if (pmd->flags & ETH_MEMIF_FLAG_ZERO_COPY) {
1248 : 0 : mq->buffers = rte_zmalloc("bufs", sizeof(struct rte_mbuf *) *
1249 : 0 : (1 << mq->log2_ring_size), 0);
1250 [ # # ]: 0 : if (mq->buffers == NULL)
1251 : : return -ENOMEM;
1252 : : }
1253 : : }
1254 : : return 0;
1255 : : }
1256 : :
1257 : : int
1258 : 0 : memif_init_regions_and_queues(struct rte_eth_dev *dev)
1259 : : {
1260 : : int ret;
1261 : :
1262 : 0 : ret = memif_regions_init(dev);
1263 [ # # ]: 0 : if (ret < 0)
1264 : : return ret;
1265 : :
1266 : 0 : memif_init_rings(dev);
1267 : :
1268 : 0 : ret = memif_init_queues(dev);
1269 : : if (ret < 0)
1270 : : return ret;
1271 : :
1272 : : return 0;
1273 : : }
1274 : :
1275 : : int
1276 : 0 : memif_connect(struct rte_eth_dev *dev)
1277 : : {
1278 : 0 : struct pmd_internals *pmd = dev->data->dev_private;
1279 : 0 : struct pmd_process_private *proc_private = dev->process_private;
1280 : : struct memif_region *mr;
1281 : : struct memif_queue *mq;
1282 : : memif_ring_t *ring;
1283 : : int i;
1284 : :
1285 [ # # ]: 0 : for (i = 0; i < proc_private->regions_num; i++) {
1286 : 0 : mr = proc_private->regions[i];
1287 [ # # ]: 0 : if (mr != NULL) {
1288 [ # # ]: 0 : if (mr->addr == NULL) {
1289 [ # # ]: 0 : if (mr->fd < 0)
1290 : : return -1;
1291 : 0 : mr->addr = mmap(NULL, mr->region_size,
1292 : : PROT_READ | PROT_WRITE,
1293 : : MAP_SHARED, mr->fd, 0);
1294 [ # # ]: 0 : if (mr->addr == MAP_FAILED) {
1295 : 0 : MIF_LOG(ERR, "mmap failed: %s\n",
1296 : : strerror(errno));
1297 : 0 : return -1;
1298 : : }
1299 : : }
1300 [ # # # # ]: 0 : if (i > 0 && (pmd->flags & ETH_MEMIF_FLAG_ZERO_COPY)) {
1301 : : /* close memseg file */
1302 : 0 : close(mr->fd);
1303 : 0 : mr->fd = -1;
1304 : : }
1305 : : }
1306 : : }
1307 : :
1308 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
1309 [ # # ]: 0 : for (i = 0; i < pmd->run.num_c2s_rings; i++) {
1310 [ # # ]: 0 : mq = (pmd->role == MEMIF_ROLE_CLIENT) ?
1311 : 0 : dev->data->tx_queues[i] : dev->data->rx_queues[i];
1312 : : ring = memif_get_ring_from_queue(proc_private, mq);
1313 [ # # # # ]: 0 : if (ring == NULL || ring->cookie != MEMIF_COOKIE) {
1314 : 0 : MIF_LOG(ERR, "Wrong ring");
1315 : 0 : return -1;
1316 : : }
1317 : 0 : __atomic_store_n(&ring->head, 0, __ATOMIC_RELAXED);
1318 : 0 : __atomic_store_n(&ring->tail, 0, __ATOMIC_RELAXED);
1319 : 0 : mq->last_head = 0;
1320 : 0 : mq->last_tail = 0;
1321 : : /* enable polling mode */
1322 [ # # ]: 0 : if (pmd->role == MEMIF_ROLE_SERVER)
1323 : 0 : ring->flags = MEMIF_RING_FLAG_MASK_INT;
1324 : : }
1325 [ # # ]: 0 : for (i = 0; i < pmd->run.num_s2c_rings; i++) {
1326 [ # # ]: 0 : mq = (pmd->role == MEMIF_ROLE_CLIENT) ?
1327 : 0 : dev->data->rx_queues[i] : dev->data->tx_queues[i];
1328 : : ring = memif_get_ring_from_queue(proc_private, mq);
1329 [ # # # # ]: 0 : if (ring == NULL || ring->cookie != MEMIF_COOKIE) {
1330 : 0 : MIF_LOG(ERR, "Wrong ring");
1331 : 0 : return -1;
1332 : : }
1333 : 0 : __atomic_store_n(&ring->head, 0, __ATOMIC_RELAXED);
1334 : 0 : __atomic_store_n(&ring->tail, 0, __ATOMIC_RELAXED);
1335 : 0 : mq->last_head = 0;
1336 : 0 : mq->last_tail = 0;
1337 : : /* enable polling mode */
1338 [ # # ]: 0 : if (pmd->role == MEMIF_ROLE_CLIENT)
1339 : 0 : ring->flags = MEMIF_RING_FLAG_MASK_INT;
1340 : : }
1341 : :
1342 : 0 : pmd->flags &= ~ETH_MEMIF_FLAG_CONNECTING;
1343 : 0 : pmd->flags |= ETH_MEMIF_FLAG_CONNECTED;
1344 : 0 : dev->data->dev_link.link_status = RTE_ETH_LINK_UP;
1345 : : }
1346 : 0 : MIF_LOG(INFO, "Connected.");
1347 : 0 : return 0;
1348 : : }
1349 : :
1350 : : static int
1351 : 0 : memif_dev_start(struct rte_eth_dev *dev)
1352 : : {
1353 : 0 : struct pmd_internals *pmd = dev->data->dev_private;
1354 : : int ret = 0;
1355 : : uint16_t i;
1356 : :
1357 [ # # # ]: 0 : switch (pmd->role) {
1358 : 0 : case MEMIF_ROLE_CLIENT:
1359 : 0 : ret = memif_connect_client(dev);
1360 : 0 : break;
1361 : 0 : case MEMIF_ROLE_SERVER:
1362 : 0 : ret = memif_connect_server(dev);
1363 : 0 : break;
1364 : 0 : default:
1365 : 0 : MIF_LOG(ERR, "Unknown role: %d.", pmd->role);
1366 : : ret = -1;
1367 : : break;
1368 : : }
1369 : :
1370 [ # # ]: 0 : if (ret == 0) {
1371 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++)
1372 : 0 : dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
1373 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++)
1374 : 0 : dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
1375 : : }
1376 : :
1377 : 0 : return ret;
1378 : : }
1379 : :
1380 : : static int
1381 : 0 : memif_dev_stop(struct rte_eth_dev *dev)
1382 : : {
1383 : : uint16_t i;
1384 : :
1385 : 0 : memif_disconnect(dev);
1386 : :
1387 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++)
1388 : 0 : dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
1389 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++)
1390 : 0 : dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
1391 : :
1392 : 0 : return 0;
1393 : : }
1394 : :
1395 : : static int
1396 : 0 : memif_dev_close(struct rte_eth_dev *dev)
1397 : : {
1398 : 0 : struct pmd_internals *pmd = dev->data->dev_private;
1399 : : int i;
1400 : :
1401 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
1402 : 0 : memif_msg_enq_disconnect(pmd->cc, "Device closed", 0);
1403 : :
1404 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++)
1405 : 0 : (*dev->dev_ops->rx_queue_release)(dev, i);
1406 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++)
1407 : 0 : (*dev->dev_ops->tx_queue_release)(dev, i);
1408 : :
1409 : 0 : memif_socket_remove_device(dev);
1410 : : }
1411 : :
1412 : 0 : rte_free(dev->process_private);
1413 : :
1414 : 0 : return 0;
1415 : : }
1416 : :
1417 : : static int
1418 : 0 : memif_dev_configure(struct rte_eth_dev *dev)
1419 : : {
1420 : 0 : struct pmd_internals *pmd = dev->data->dev_private;
1421 : :
1422 : : /*
1423 : : * CLIENT - TXQ
1424 : : * SERVER - RXQ
1425 : : */
1426 [ # # ]: 0 : pmd->cfg.num_c2s_rings = (pmd->role == MEMIF_ROLE_CLIENT) ?
1427 : 0 : dev->data->nb_tx_queues : dev->data->nb_rx_queues;
1428 : :
1429 : : /*
1430 : : * CLIENT - RXQ
1431 : : * SERVER - TXQ
1432 : : */
1433 [ # # ]: 0 : pmd->cfg.num_s2c_rings = (pmd->role == MEMIF_ROLE_CLIENT) ?
1434 : 0 : dev->data->nb_rx_queues : dev->data->nb_tx_queues;
1435 : :
1436 : 0 : return 0;
1437 : : }
1438 : :
1439 : : static int
1440 : 0 : memif_tx_queue_setup(struct rte_eth_dev *dev,
1441 : : uint16_t qid,
1442 : : uint16_t nb_tx_desc __rte_unused,
1443 : : unsigned int socket_id __rte_unused,
1444 : : const struct rte_eth_txconf *tx_conf __rte_unused)
1445 : : {
1446 : 0 : struct pmd_internals *pmd = dev->data->dev_private;
1447 : : struct memif_queue *mq;
1448 : :
1449 : 0 : mq = rte_zmalloc("tx-queue", sizeof(struct memif_queue), 0);
1450 [ # # ]: 0 : if (mq == NULL) {
1451 : 0 : MIF_LOG(ERR, "Failed to allocate tx queue id: %u", qid);
1452 : 0 : return -ENOMEM;
1453 : : }
1454 : :
1455 : : /* Allocate interrupt instance */
1456 : 0 : mq->intr_handle = rte_intr_instance_alloc(RTE_INTR_INSTANCE_F_SHARED);
1457 [ # # ]: 0 : if (mq->intr_handle == NULL) {
1458 : 0 : MIF_LOG(ERR, "Failed to allocate intr handle");
1459 : 0 : return -ENOMEM;
1460 : : }
1461 : :
1462 : 0 : mq->type =
1463 : 0 : (pmd->role == MEMIF_ROLE_CLIENT) ? MEMIF_RING_C2S : MEMIF_RING_S2C;
1464 : 0 : mq->n_pkts = 0;
1465 : 0 : mq->n_bytes = 0;
1466 : :
1467 [ # # ]: 0 : if (rte_intr_fd_set(mq->intr_handle, -1))
1468 : 0 : return -rte_errno;
1469 : :
1470 [ # # ]: 0 : if (rte_intr_type_set(mq->intr_handle, RTE_INTR_HANDLE_EXT))
1471 : 0 : return -rte_errno;
1472 : :
1473 : 0 : mq->in_port = dev->data->port_id;
1474 : 0 : dev->data->tx_queues[qid] = mq;
1475 : :
1476 : 0 : return 0;
1477 : : }
1478 : :
1479 : : static int
1480 : 0 : memif_rx_queue_setup(struct rte_eth_dev *dev,
1481 : : uint16_t qid,
1482 : : uint16_t nb_rx_desc __rte_unused,
1483 : : unsigned int socket_id __rte_unused,
1484 : : const struct rte_eth_rxconf *rx_conf __rte_unused,
1485 : : struct rte_mempool *mb_pool)
1486 : : {
1487 : 0 : struct pmd_internals *pmd = dev->data->dev_private;
1488 : : struct memif_queue *mq;
1489 : :
1490 : 0 : mq = rte_zmalloc("rx-queue", sizeof(struct memif_queue), 0);
1491 [ # # ]: 0 : if (mq == NULL) {
1492 : 0 : MIF_LOG(ERR, "Failed to allocate rx queue id: %u", qid);
1493 : 0 : return -ENOMEM;
1494 : : }
1495 : :
1496 : : /* Allocate interrupt instance */
1497 : 0 : mq->intr_handle = rte_intr_instance_alloc(RTE_INTR_INSTANCE_F_SHARED);
1498 [ # # ]: 0 : if (mq->intr_handle == NULL) {
1499 : 0 : MIF_LOG(ERR, "Failed to allocate intr handle");
1500 : 0 : return -ENOMEM;
1501 : : }
1502 : :
1503 : 0 : mq->type = (pmd->role == MEMIF_ROLE_CLIENT) ? MEMIF_RING_S2C : MEMIF_RING_C2S;
1504 : 0 : mq->n_pkts = 0;
1505 : 0 : mq->n_bytes = 0;
1506 : :
1507 [ # # ]: 0 : if (rte_intr_fd_set(mq->intr_handle, -1))
1508 : 0 : return -rte_errno;
1509 : :
1510 [ # # ]: 0 : if (rte_intr_type_set(mq->intr_handle, RTE_INTR_HANDLE_EXT))
1511 : 0 : return -rte_errno;
1512 : :
1513 : 0 : mq->mempool = mb_pool;
1514 : 0 : mq->in_port = dev->data->port_id;
1515 : 0 : dev->data->rx_queues[qid] = mq;
1516 : :
1517 : 0 : return 0;
1518 : : }
1519 : :
1520 : : static void
1521 : 0 : memif_rx_queue_release(struct rte_eth_dev *dev, uint16_t qid)
1522 : : {
1523 : 0 : struct memif_queue *mq = dev->data->rx_queues[qid];
1524 : :
1525 [ # # ]: 0 : if (!mq)
1526 : : return;
1527 : :
1528 : 0 : rte_intr_instance_free(mq->intr_handle);
1529 : 0 : rte_free(mq);
1530 : : }
1531 : :
1532 : : static void
1533 : 0 : memif_tx_queue_release(struct rte_eth_dev *dev, uint16_t qid)
1534 : : {
1535 : 0 : struct memif_queue *mq = dev->data->tx_queues[qid];
1536 : :
1537 [ # # ]: 0 : if (!mq)
1538 : : return;
1539 : :
1540 : 0 : rte_free(mq);
1541 : : }
1542 : :
1543 : : static int
1544 : 0 : memif_link_update(struct rte_eth_dev *dev,
1545 : : int wait_to_complete __rte_unused)
1546 : : {
1547 : : struct pmd_process_private *proc_private;
1548 : :
1549 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
1550 : 0 : proc_private = dev->process_private;
1551 [ # # ]: 0 : if (dev->data->dev_link.link_status == RTE_ETH_LINK_UP &&
1552 [ # # ]: 0 : proc_private->regions_num == 0) {
1553 : 0 : memif_mp_request_regions(dev);
1554 [ # # ]: 0 : } else if (dev->data->dev_link.link_status == RTE_ETH_LINK_DOWN &&
1555 [ # # ]: 0 : proc_private->regions_num > 0) {
1556 : 0 : memif_free_regions(dev);
1557 : : }
1558 : : }
1559 : 0 : return 0;
1560 : : }
1561 : :
1562 : : static int
1563 : 0 : memif_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
1564 : : {
1565 : 0 : struct pmd_internals *pmd = dev->data->dev_private;
1566 : : struct memif_queue *mq;
1567 : : int i;
1568 : : uint8_t tmp, nq;
1569 : :
1570 : 0 : stats->ipackets = 0;
1571 : 0 : stats->ibytes = 0;
1572 : 0 : stats->opackets = 0;
1573 : 0 : stats->obytes = 0;
1574 : :
1575 [ # # ]: 0 : tmp = (pmd->role == MEMIF_ROLE_CLIENT) ? pmd->run.num_s2c_rings :
1576 : : pmd->run.num_c2s_rings;
1577 : 0 : nq = (tmp < RTE_ETHDEV_QUEUE_STAT_CNTRS) ? tmp :
1578 : : RTE_ETHDEV_QUEUE_STAT_CNTRS;
1579 : :
1580 : : /* RX stats */
1581 [ # # ]: 0 : for (i = 0; i < nq; i++) {
1582 : 0 : mq = dev->data->rx_queues[i];
1583 : 0 : stats->q_ipackets[i] = mq->n_pkts;
1584 : 0 : stats->q_ibytes[i] = mq->n_bytes;
1585 : 0 : stats->ipackets += mq->n_pkts;
1586 : 0 : stats->ibytes += mq->n_bytes;
1587 : : }
1588 : :
1589 [ # # ]: 0 : tmp = (pmd->role == MEMIF_ROLE_CLIENT) ? pmd->run.num_c2s_rings :
1590 : : pmd->run.num_s2c_rings;
1591 : 0 : nq = (tmp < RTE_ETHDEV_QUEUE_STAT_CNTRS) ? tmp :
1592 : : RTE_ETHDEV_QUEUE_STAT_CNTRS;
1593 : :
1594 : : /* TX stats */
1595 [ # # ]: 0 : for (i = 0; i < nq; i++) {
1596 : 0 : mq = dev->data->tx_queues[i];
1597 : 0 : stats->q_opackets[i] = mq->n_pkts;
1598 : 0 : stats->q_obytes[i] = mq->n_bytes;
1599 : 0 : stats->opackets += mq->n_pkts;
1600 : 0 : stats->obytes += mq->n_bytes;
1601 : : }
1602 : 0 : return 0;
1603 : : }
1604 : :
1605 : : static int
1606 : 0 : memif_stats_reset(struct rte_eth_dev *dev)
1607 : : {
1608 : 0 : struct pmd_internals *pmd = dev->data->dev_private;
1609 : : int i;
1610 : : struct memif_queue *mq;
1611 : :
1612 [ # # ]: 0 : for (i = 0; i < pmd->run.num_c2s_rings; i++) {
1613 [ # # ]: 0 : mq = (pmd->role == MEMIF_ROLE_CLIENT) ? dev->data->tx_queues[i] :
1614 : 0 : dev->data->rx_queues[i];
1615 : 0 : mq->n_pkts = 0;
1616 : 0 : mq->n_bytes = 0;
1617 : : }
1618 [ # # ]: 0 : for (i = 0; i < pmd->run.num_s2c_rings; i++) {
1619 [ # # ]: 0 : mq = (pmd->role == MEMIF_ROLE_CLIENT) ? dev->data->rx_queues[i] :
1620 : 0 : dev->data->tx_queues[i];
1621 : 0 : mq->n_pkts = 0;
1622 : 0 : mq->n_bytes = 0;
1623 : : }
1624 : :
1625 : 0 : return 0;
1626 : : }
1627 : :
1628 : : static const struct eth_dev_ops ops = {
1629 : : .dev_start = memif_dev_start,
1630 : : .dev_stop = memif_dev_stop,
1631 : : .dev_close = memif_dev_close,
1632 : : .dev_infos_get = memif_dev_info,
1633 : : .dev_configure = memif_dev_configure,
1634 : : .tx_queue_setup = memif_tx_queue_setup,
1635 : : .rx_queue_setup = memif_rx_queue_setup,
1636 : : .rx_queue_release = memif_rx_queue_release,
1637 : : .tx_queue_release = memif_tx_queue_release,
1638 : : .link_update = memif_link_update,
1639 : : .stats_get = memif_stats_get,
1640 : : .stats_reset = memif_stats_reset,
1641 : : };
1642 : :
1643 : : static int
1644 : 0 : memif_create(struct rte_vdev_device *vdev, enum memif_role_t role,
1645 : : memif_interface_id_t id, uint32_t flags,
1646 : : const char *socket_filename, uid_t owner_uid, gid_t owner_gid,
1647 : : memif_log2_ring_size_t log2_ring_size,
1648 : : uint16_t pkt_buffer_size, const char *secret,
1649 : : struct rte_ether_addr *ether_addr)
1650 : : {
1651 : : int ret = 0;
1652 : : struct rte_eth_dev *eth_dev;
1653 : : struct rte_eth_dev_data *data;
1654 : : struct pmd_internals *pmd;
1655 : : struct pmd_process_private *process_private;
1656 [ # # ]: 0 : const unsigned int numa_node = vdev->device.numa_node;
1657 : : const char *name = rte_vdev_device_name(vdev);
1658 : :
1659 : 0 : eth_dev = rte_eth_vdev_allocate(vdev, sizeof(*pmd));
1660 [ # # ]: 0 : if (eth_dev == NULL) {
1661 : 0 : MIF_LOG(ERR, "%s: Unable to allocate device struct.", name);
1662 : 0 : return -1;
1663 : : }
1664 : :
1665 : : process_private = (struct pmd_process_private *)
1666 : 0 : rte_zmalloc(name, sizeof(struct pmd_process_private),
1667 : : RTE_CACHE_LINE_SIZE);
1668 : :
1669 [ # # ]: 0 : if (process_private == NULL) {
1670 : 0 : MIF_LOG(ERR, "Failed to alloc memory for process private");
1671 : 0 : return -1;
1672 : : }
1673 : 0 : eth_dev->process_private = process_private;
1674 : :
1675 [ # # ]: 0 : pmd = eth_dev->data->dev_private;
1676 : : memset(pmd, 0, sizeof(*pmd));
1677 : :
1678 : 0 : pmd->id = id;
1679 : : pmd->flags = flags;
1680 : 0 : pmd->flags |= ETH_MEMIF_FLAG_DISABLED;
1681 : 0 : pmd->role = role;
1682 : : /* Zero-copy flag irelevant to server. */
1683 [ # # ]: 0 : if (pmd->role == MEMIF_ROLE_SERVER)
1684 : 0 : pmd->flags &= ~ETH_MEMIF_FLAG_ZERO_COPY;
1685 : 0 : pmd->owner_uid = owner_uid;
1686 : 0 : pmd->owner_gid = owner_gid;
1687 : :
1688 : 0 : ret = memif_socket_init(eth_dev, socket_filename);
1689 [ # # ]: 0 : if (ret < 0)
1690 : : return ret;
1691 : :
1692 [ # # ]: 0 : memset(pmd->secret, 0, sizeof(char) * ETH_MEMIF_SECRET_SIZE);
1693 [ # # ]: 0 : if (secret != NULL)
1694 : : strlcpy(pmd->secret, secret, sizeof(pmd->secret));
1695 : :
1696 : 0 : pmd->cfg.log2_ring_size = log2_ring_size;
1697 : : /* set in .dev_configure() */
1698 : 0 : pmd->cfg.num_c2s_rings = 0;
1699 : 0 : pmd->cfg.num_s2c_rings = 0;
1700 : :
1701 [ # # ]: 0 : pmd->cfg.pkt_buffer_size = pkt_buffer_size;
1702 : : rte_spinlock_init(&pmd->cc_lock);
1703 : :
1704 : 0 : data = eth_dev->data;
1705 : 0 : data->dev_private = pmd;
1706 : 0 : data->numa_node = numa_node;
1707 : 0 : data->dev_link = pmd_link;
1708 : 0 : data->mac_addrs = ether_addr;
1709 : 0 : data->promiscuous = 1;
1710 : 0 : data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS;
1711 : :
1712 : 0 : eth_dev->dev_ops = &ops;
1713 : 0 : eth_dev->device = &vdev->device;
1714 [ # # ]: 0 : if (pmd->flags & ETH_MEMIF_FLAG_ZERO_COPY) {
1715 : 0 : eth_dev->rx_pkt_burst = eth_memif_rx_zc;
1716 : 0 : eth_dev->tx_pkt_burst = eth_memif_tx_zc;
1717 : : } else {
1718 : 0 : eth_dev->rx_pkt_burst = eth_memif_rx;
1719 : 0 : eth_dev->tx_pkt_burst = eth_memif_tx;
1720 : : }
1721 : :
1722 : 0 : rte_eth_dev_probing_finish(eth_dev);
1723 : :
1724 : 0 : return 0;
1725 : : }
1726 : :
1727 : : static int
1728 : 0 : memif_set_role(const char *key __rte_unused, const char *value,
1729 : : void *extra_args)
1730 : : {
1731 : : enum memif_role_t *role = (enum memif_role_t *)extra_args;
1732 : :
1733 [ # # ]: 0 : if (strstr(value, "server") != NULL) {
1734 : 0 : *role = MEMIF_ROLE_SERVER;
1735 [ # # ]: 0 : } else if (strstr(value, "client") != NULL) {
1736 : 0 : *role = MEMIF_ROLE_CLIENT;
1737 [ # # ]: 0 : } else if (strstr(value, "master") != NULL) {
1738 : 0 : MIF_LOG(NOTICE, "Role argument \"master\" is deprecated, use \"server\"");
1739 : 0 : *role = MEMIF_ROLE_SERVER;
1740 [ # # ]: 0 : } else if (strstr(value, "slave") != NULL) {
1741 : 0 : MIF_LOG(NOTICE, "Role argument \"slave\" is deprecated, use \"client\"");
1742 : 0 : *role = MEMIF_ROLE_CLIENT;
1743 : : } else {
1744 : 0 : MIF_LOG(ERR, "Unknown role: %s.", value);
1745 : 0 : return -EINVAL;
1746 : : }
1747 : : return 0;
1748 : : }
1749 : :
1750 : : static int
1751 : 0 : memif_set_zc(const char *key __rte_unused, const char *value, void *extra_args)
1752 : : {
1753 : : uint32_t *flags = (uint32_t *)extra_args;
1754 : :
1755 [ # # ]: 0 : if (strstr(value, "yes") != NULL) {
1756 [ # # ]: 0 : if (!rte_mcfg_get_single_file_segments()) {
1757 : 0 : MIF_LOG(ERR, "Zero-copy doesn't support multi-file segments.");
1758 : 0 : return -ENOTSUP;
1759 : : }
1760 : 0 : *flags |= ETH_MEMIF_FLAG_ZERO_COPY;
1761 [ # # ]: 0 : } else if (strstr(value, "no") != NULL) {
1762 : 0 : *flags &= ~ETH_MEMIF_FLAG_ZERO_COPY;
1763 : : } else {
1764 : 0 : MIF_LOG(ERR, "Failed to parse zero-copy param: %s.", value);
1765 : 0 : return -EINVAL;
1766 : : }
1767 : : return 0;
1768 : : }
1769 : :
1770 : : static int
1771 : 0 : memif_set_id(const char *key __rte_unused, const char *value, void *extra_args)
1772 : : {
1773 : : memif_interface_id_t *id = (memif_interface_id_t *)extra_args;
1774 : :
1775 : : /* even if parsing fails, 0 is a valid id */
1776 : 0 : *id = strtoul(value, NULL, 10);
1777 : 0 : return 0;
1778 : : }
1779 : :
1780 : : static int
1781 : 0 : memif_set_bs(const char *key __rte_unused, const char *value, void *extra_args)
1782 : : {
1783 : : unsigned long tmp;
1784 : : uint16_t *pkt_buffer_size = (uint16_t *)extra_args;
1785 : :
1786 : 0 : tmp = strtoul(value, NULL, 10);
1787 [ # # ]: 0 : if (tmp == 0 || tmp > 0xFFFF) {
1788 : 0 : MIF_LOG(ERR, "Invalid buffer size: %s.", value);
1789 : 0 : return -EINVAL;
1790 : : }
1791 : 0 : *pkt_buffer_size = tmp;
1792 : 0 : return 0;
1793 : : }
1794 : :
1795 : : static int
1796 : 0 : memif_set_rs(const char *key __rte_unused, const char *value, void *extra_args)
1797 : : {
1798 : : unsigned long tmp;
1799 : : memif_log2_ring_size_t *log2_ring_size =
1800 : : (memif_log2_ring_size_t *)extra_args;
1801 : :
1802 : 0 : tmp = strtoul(value, NULL, 10);
1803 [ # # ]: 0 : if (tmp == 0 || tmp > ETH_MEMIF_MAX_LOG2_RING_SIZE) {
1804 : 0 : MIF_LOG(ERR, "Invalid ring size: %s (max %u).",
1805 : : value, ETH_MEMIF_MAX_LOG2_RING_SIZE);
1806 : 0 : return -EINVAL;
1807 : : }
1808 : 0 : *log2_ring_size = tmp;
1809 : 0 : return 0;
1810 : : }
1811 : :
1812 : : /* check if directory exists and if we have permission to read/write */
1813 : : static int
1814 : 0 : memif_check_socket_filename(const char *filename)
1815 : : {
1816 : : char *dir = NULL, *tmp;
1817 : : uint32_t idx;
1818 : : int ret = 0;
1819 : :
1820 [ # # ]: 0 : if (strlen(filename) >= MEMIF_SOCKET_UN_SIZE) {
1821 : 0 : MIF_LOG(ERR, "Unix socket address too long (max 108).");
1822 : 0 : return -1;
1823 : : }
1824 : :
1825 : 0 : tmp = strrchr(filename, '/');
1826 [ # # ]: 0 : if (tmp != NULL) {
1827 : 0 : idx = tmp - filename;
1828 : 0 : dir = rte_zmalloc("memif_tmp", sizeof(char) * (idx + 1), 0);
1829 [ # # ]: 0 : if (dir == NULL) {
1830 : 0 : MIF_LOG(ERR, "Failed to allocate memory.");
1831 : 0 : return -1;
1832 : : }
1833 : : strlcpy(dir, filename, sizeof(char) * (idx + 1));
1834 : : }
1835 : :
1836 [ # # ]: 0 : if (dir == NULL || (faccessat(-1, dir, F_OK | R_OK |
1837 : : W_OK, AT_EACCESS) < 0)) {
1838 : 0 : MIF_LOG(ERR, "Invalid socket directory.");
1839 : : ret = -EINVAL;
1840 : : }
1841 : :
1842 : 0 : rte_free(dir);
1843 : :
1844 : 0 : return ret;
1845 : : }
1846 : :
1847 : : static int
1848 : 0 : memif_set_socket_filename(const char *key __rte_unused, const char *value,
1849 : : void *extra_args)
1850 : : {
1851 : : const char **socket_filename = (const char **)extra_args;
1852 : :
1853 : 0 : *socket_filename = value;
1854 : 0 : return 0;
1855 : : }
1856 : :
1857 : : static int
1858 : 0 : memif_set_is_socket_abstract(const char *key __rte_unused, const char *value, void *extra_args)
1859 : : {
1860 : : uint32_t *flags = (uint32_t *)extra_args;
1861 : :
1862 [ # # ]: 0 : if (strstr(value, "yes") != NULL) {
1863 : 0 : *flags |= ETH_MEMIF_FLAG_SOCKET_ABSTRACT;
1864 [ # # ]: 0 : } else if (strstr(value, "no") != NULL) {
1865 : 0 : *flags &= ~ETH_MEMIF_FLAG_SOCKET_ABSTRACT;
1866 : : } else {
1867 : 0 : MIF_LOG(ERR, "Failed to parse socket-abstract param: %s.", value);
1868 : 0 : return -EINVAL;
1869 : : }
1870 : : return 0;
1871 : : }
1872 : :
1873 : : static int
1874 : 0 : memif_set_owner(const char *key, const char *value, void *extra_args)
1875 : : {
1876 : : RTE_ASSERT(sizeof(uid_t) == sizeof(uint32_t));
1877 : : RTE_ASSERT(sizeof(gid_t) == sizeof(uint32_t));
1878 : :
1879 : : unsigned long val;
1880 : 0 : char *end = NULL;
1881 : : uint32_t *id = (uint32_t *)extra_args;
1882 : :
1883 : 0 : val = strtoul(value, &end, 10);
1884 [ # # # # ]: 0 : if (*value == '\0' || *end != '\0') {
1885 : 0 : MIF_LOG(ERR, "Failed to parse %s: %s.", key, value);
1886 : 0 : return -EINVAL;
1887 : : }
1888 [ # # ]: 0 : if (val >= UINT32_MAX) {
1889 : 0 : MIF_LOG(ERR, "Invalid %s: %s.", key, value);
1890 : 0 : return -ERANGE;
1891 : : }
1892 : :
1893 : 0 : *id = val;
1894 : 0 : return 0;
1895 : : }
1896 : :
1897 : : static int
1898 : 0 : memif_set_mac(const char *key __rte_unused, const char *value, void *extra_args)
1899 : : {
1900 : : struct rte_ether_addr *ether_addr = (struct rte_ether_addr *)extra_args;
1901 : :
1902 [ # # ]: 0 : if (rte_ether_unformat_addr(value, ether_addr) < 0)
1903 : 0 : MIF_LOG(WARNING, "Failed to parse mac '%s'.", value);
1904 : 0 : return 0;
1905 : : }
1906 : :
1907 : : static int
1908 : 0 : memif_set_secret(const char *key __rte_unused, const char *value, void *extra_args)
1909 : : {
1910 : : const char **secret = (const char **)extra_args;
1911 : :
1912 : 0 : *secret = value;
1913 : 0 : return 0;
1914 : : }
1915 : :
1916 : : static int
1917 [ # # ]: 0 : rte_pmd_memif_probe(struct rte_vdev_device *vdev)
1918 : : {
1919 : : RTE_BUILD_BUG_ON(sizeof(memif_msg_t) != 128);
1920 : : RTE_BUILD_BUG_ON(sizeof(memif_desc_t) != 16);
1921 : : int ret = 0;
1922 : : struct rte_kvargs *kvlist;
1923 : : const char *name = rte_vdev_device_name(vdev);
1924 : 0 : enum memif_role_t role = MEMIF_ROLE_CLIENT;
1925 : 0 : memif_interface_id_t id = 0;
1926 : 0 : uint16_t pkt_buffer_size = ETH_MEMIF_DEFAULT_PKT_BUFFER_SIZE;
1927 : 0 : memif_log2_ring_size_t log2_ring_size = ETH_MEMIF_DEFAULT_RING_SIZE;
1928 : 0 : const char *socket_filename = ETH_MEMIF_DEFAULT_SOCKET_FILENAME;
1929 : 0 : uid_t owner_uid = -1;
1930 : 0 : gid_t owner_gid = -1;
1931 : 0 : uint32_t flags = 0;
1932 : 0 : const char *secret = NULL;
1933 : 0 : struct rte_ether_addr *ether_addr = rte_zmalloc("",
1934 : : sizeof(struct rte_ether_addr), 0);
1935 : : struct rte_eth_dev *eth_dev;
1936 : :
1937 : 0 : rte_eth_random_addr(ether_addr->addr_bytes);
1938 : :
1939 : 0 : MIF_LOG(INFO, "Initialize MEMIF: %s.", name);
1940 : :
1941 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
1942 : 0 : eth_dev = rte_eth_dev_attach_secondary(name);
1943 [ # # ]: 0 : if (!eth_dev) {
1944 : 0 : MIF_LOG(ERR, "Failed to probe %s", name);
1945 : 0 : return -1;
1946 : : }
1947 : :
1948 : 0 : eth_dev->dev_ops = &ops;
1949 : 0 : eth_dev->device = &vdev->device;
1950 : 0 : eth_dev->rx_pkt_burst = eth_memif_rx;
1951 : 0 : eth_dev->tx_pkt_burst = eth_memif_tx;
1952 : :
1953 [ # # ]: 0 : if (!rte_eal_primary_proc_alive(NULL)) {
1954 : 0 : MIF_LOG(ERR, "Primary process is missing");
1955 : 0 : return -1;
1956 : : }
1957 : :
1958 : 0 : eth_dev->process_private = (struct pmd_process_private *)
1959 : 0 : rte_zmalloc(name,
1960 : : sizeof(struct pmd_process_private),
1961 : : RTE_CACHE_LINE_SIZE);
1962 [ # # ]: 0 : if (eth_dev->process_private == NULL) {
1963 : 0 : MIF_LOG(ERR,
1964 : : "Failed to alloc memory for process private");
1965 : 0 : return -1;
1966 : : }
1967 : :
1968 : 0 : rte_eth_dev_probing_finish(eth_dev);
1969 : :
1970 : 0 : return 0;
1971 : : }
1972 : :
1973 : 0 : ret = rte_mp_action_register(MEMIF_MP_SEND_REGION, memif_mp_send_region);
1974 : : /*
1975 : : * Primary process can continue probing, but secondary process won't
1976 : : * be able to get memory regions information
1977 : : */
1978 [ # # # # ]: 0 : if (ret < 0 && rte_errno != EEXIST)
1979 : 0 : MIF_LOG(WARNING, "Failed to register mp action callback: %s",
1980 : : strerror(rte_errno));
1981 : :
1982 : : /* use abstract address by default */
1983 [ # # ]: 0 : flags |= ETH_MEMIF_FLAG_SOCKET_ABSTRACT;
1984 : :
1985 : 0 : kvlist = rte_kvargs_parse(rte_vdev_device_args(vdev), valid_arguments);
1986 : :
1987 : : /* parse parameters */
1988 [ # # ]: 0 : if (kvlist != NULL) {
1989 : 0 : ret = rte_kvargs_process(kvlist, ETH_MEMIF_ROLE_ARG,
1990 : : &memif_set_role, &role);
1991 [ # # ]: 0 : if (ret < 0)
1992 : 0 : goto exit;
1993 : 0 : ret = rte_kvargs_process(kvlist, ETH_MEMIF_ID_ARG,
1994 : : &memif_set_id, &id);
1995 [ # # ]: 0 : if (ret < 0)
1996 : 0 : goto exit;
1997 : 0 : ret = rte_kvargs_process(kvlist, ETH_MEMIF_PKT_BUFFER_SIZE_ARG,
1998 : : &memif_set_bs, &pkt_buffer_size);
1999 [ # # ]: 0 : if (ret < 0)
2000 : 0 : goto exit;
2001 : 0 : ret = rte_kvargs_process(kvlist, ETH_MEMIF_RING_SIZE_ARG,
2002 : : &memif_set_rs, &log2_ring_size);
2003 [ # # ]: 0 : if (ret < 0)
2004 : 0 : goto exit;
2005 : 0 : ret = rte_kvargs_process(kvlist, ETH_MEMIF_SOCKET_ARG,
2006 : : &memif_set_socket_filename,
2007 : : (void *)(&socket_filename));
2008 [ # # ]: 0 : if (ret < 0)
2009 : 0 : goto exit;
2010 : 0 : ret = rte_kvargs_process(kvlist, ETH_MEMIF_SOCKET_ABSTRACT_ARG,
2011 : : &memif_set_is_socket_abstract, &flags);
2012 [ # # ]: 0 : if (ret < 0)
2013 : 0 : goto exit;
2014 : 0 : ret = rte_kvargs_process(kvlist, ETH_MEMIF_OWNER_UID_ARG,
2015 : : &memif_set_owner, &owner_uid);
2016 [ # # ]: 0 : if (ret < 0)
2017 : 0 : goto exit;
2018 : 0 : ret = rte_kvargs_process(kvlist, ETH_MEMIF_OWNER_GID_ARG,
2019 : : &memif_set_owner, &owner_gid);
2020 [ # # ]: 0 : if (ret < 0)
2021 : 0 : goto exit;
2022 : 0 : ret = rte_kvargs_process(kvlist, ETH_MEMIF_MAC_ARG,
2023 : : &memif_set_mac, ether_addr);
2024 [ # # ]: 0 : if (ret < 0)
2025 : 0 : goto exit;
2026 : 0 : ret = rte_kvargs_process(kvlist, ETH_MEMIF_ZC_ARG,
2027 : : &memif_set_zc, &flags);
2028 [ # # ]: 0 : if (ret < 0)
2029 : 0 : goto exit;
2030 : 0 : ret = rte_kvargs_process(kvlist, ETH_MEMIF_SECRET_ARG,
2031 : : &memif_set_secret, (void *)(&secret));
2032 [ # # ]: 0 : if (ret < 0)
2033 : 0 : goto exit;
2034 : : }
2035 : :
2036 [ # # ]: 0 : if (!(flags & ETH_MEMIF_FLAG_SOCKET_ABSTRACT)) {
2037 : 0 : ret = memif_check_socket_filename(socket_filename);
2038 [ # # ]: 0 : if (ret < 0)
2039 : 0 : goto exit;
2040 : : }
2041 : :
2042 : : /* create interface */
2043 : 0 : ret = memif_create(vdev, role, id, flags, socket_filename, owner_uid, owner_gid,
2044 : : log2_ring_size, pkt_buffer_size, secret, ether_addr);
2045 : :
2046 : 0 : exit:
2047 : 0 : rte_kvargs_free(kvlist);
2048 : 0 : return ret;
2049 : : }
2050 : :
2051 : : static int
2052 [ # # ]: 0 : rte_pmd_memif_remove(struct rte_vdev_device *vdev)
2053 : : {
2054 : : struct rte_eth_dev *eth_dev;
2055 : :
2056 : 0 : eth_dev = rte_eth_dev_allocated(rte_vdev_device_name(vdev));
2057 [ # # ]: 0 : if (eth_dev == NULL)
2058 : : return 0;
2059 : :
2060 : 0 : return rte_eth_dev_close(eth_dev->data->port_id);
2061 : : }
2062 : :
2063 : : static struct rte_vdev_driver pmd_memif_drv = {
2064 : : .probe = rte_pmd_memif_probe,
2065 : : .remove = rte_pmd_memif_remove,
2066 : : };
2067 : :
2068 : 238 : RTE_PMD_REGISTER_VDEV(net_memif, pmd_memif_drv);
2069 : :
2070 : : RTE_PMD_REGISTER_PARAM_STRING(net_memif,
2071 : : ETH_MEMIF_ID_ARG "=<int>"
2072 : : ETH_MEMIF_ROLE_ARG "=server|client"
2073 : : ETH_MEMIF_PKT_BUFFER_SIZE_ARG "=<int>"
2074 : : ETH_MEMIF_RING_SIZE_ARG "=<int>"
2075 : : ETH_MEMIF_SOCKET_ARG "=<string>"
2076 : : ETH_MEMIF_SOCKET_ABSTRACT_ARG "=yes|no"
2077 : : ETH_MEMIF_OWNER_UID_ARG "=<int>"
2078 : : ETH_MEMIF_OWNER_GID_ARG "=<int>"
2079 : : ETH_MEMIF_MAC_ARG "=xx:xx:xx:xx:xx:xx"
2080 : : ETH_MEMIF_ZC_ARG "=yes|no"
2081 : : ETH_MEMIF_SECRET_ARG "=<string>");
2082 : :
2083 [ - + ]: 238 : RTE_LOG_REGISTER_DEFAULT(memif_logtype, NOTICE);
|