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