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