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