Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2010-2015 Intel Corporation
3 : : */
4 : :
5 : : #include <stdlib.h>
6 : :
7 : : #include <eal_export.h>
8 : : #include "rte_eth_ring.h"
9 : : #include <rte_mbuf.h>
10 : : #include <ethdev_driver.h>
11 : : #include <rte_malloc.h>
12 : : #include <rte_memcpy.h>
13 : : #include <rte_os_shim.h>
14 : : #include <rte_per_lcore.h>
15 : : #include <rte_string_fns.h>
16 : : #include <bus_vdev_driver.h>
17 : : #include <rte_kvargs.h>
18 : : #include <rte_errno.h>
19 : :
20 : : #define ETH_RING_NUMA_NODE_ACTION_ARG "nodeaction"
21 : : #define ETH_RING_ACTION_CREATE "CREATE"
22 : : #define ETH_RING_ACTION_ATTACH "ATTACH"
23 : : #define ETH_RING_ACTION_MAX_LEN 8 /* CREATE | ACTION */
24 : :
25 : : static const char *valid_arguments[] = {
26 : : ETH_RING_NUMA_NODE_ACTION_ARG,
27 : : NULL
28 : : };
29 : :
30 : : struct ring_internal_args {
31 : : struct rte_ring * const *rx_queues;
32 : : const unsigned int nb_rx_queues;
33 : : struct rte_ring * const *tx_queues;
34 : : const unsigned int nb_tx_queues;
35 : : const unsigned int numa_node;
36 : : };
37 : :
38 : : /* rte_eth_from_rings() stashes a pointer to its on-stack args here */
39 : : static RTE_DEFINE_PER_LCORE(struct ring_internal_args *, eth_ring_internal_args);
40 : :
41 : : enum dev_action {
42 : : DEV_CREATE,
43 : : DEV_ATTACH
44 : : };
45 : :
46 : : struct ring_queue {
47 : : struct rte_ring *rng;
48 : : uint16_t in_port;
49 : : RTE_ATOMIC(uint64_t) rx_pkts;
50 : : RTE_ATOMIC(uint64_t) tx_pkts;
51 : : };
52 : :
53 : : struct pmd_internals {
54 : : unsigned int max_rx_queues;
55 : : unsigned int max_tx_queues;
56 : :
57 : : struct ring_queue rx_ring_queues[RTE_PMD_RING_MAX_RX_RINGS];
58 : : struct ring_queue tx_ring_queues[RTE_PMD_RING_MAX_TX_RINGS];
59 : :
60 : : struct rte_ether_addr address;
61 : : enum dev_action action;
62 : : };
63 : :
64 : : static struct rte_eth_link pmd_link = {
65 : : .link_speed = RTE_ETH_SPEED_NUM_10G,
66 : : .link_duplex = RTE_ETH_LINK_FULL_DUPLEX,
67 : : .link_status = RTE_ETH_LINK_DOWN,
68 : : .link_autoneg = RTE_ETH_LINK_FIXED,
69 : : };
70 : :
71 [ - + ]: 302 : RTE_LOG_REGISTER_DEFAULT(eth_ring_logtype, NOTICE);
72 : : #define RTE_LOGTYPE_ETH_RING eth_ring_logtype
73 : :
74 : : #define PMD_LOG(level, ...) \
75 : : RTE_LOG_LINE_PREFIX(level, ETH_RING, "%s(): ", __func__, __VA_ARGS__)
76 : :
77 : : static uint16_t
78 : 7383469 : eth_ring_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
79 : : {
80 : : unsigned int i;
81 : : void **ptrs = (void *)&bufs[0];
82 : : struct ring_queue *r = q;
83 [ - + - - : 7383469 : const uint16_t nb_rx = (uint16_t)rte_ring_dequeue_burst(r->rng,
- ]
84 : : ptrs, nb_bufs, NULL);
85 [ + + ]: 39238319 : for (i = 0; i < nb_rx; i++)
86 : 31854850 : bufs[i]->port = r->in_port;
87 [ + - ]: 7383469 : if (r->rng->flags & RING_F_SC_DEQ)
88 : 7383469 : r->rx_pkts += nb_rx;
89 : : else
90 : 0 : rte_atomic_fetch_add_explicit(&r->rx_pkts, nb_rx, rte_memory_order_relaxed);
91 : 7383469 : return nb_rx;
92 : : }
93 : :
94 : : static uint16_t
95 : 3189165 : eth_ring_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
96 : : {
97 : : void **ptrs = (void *)&bufs[0];
98 : : struct ring_queue *r = q;
99 [ - + - - : 3189165 : const uint16_t nb_tx = (uint16_t)rte_ring_enqueue_burst(r->rng,
- ]
100 : : ptrs, nb_bufs, NULL);
101 [ + - ]: 3189165 : if (r->rng->flags & RING_F_SP_ENQ)
102 : 3189165 : r->tx_pkts += nb_tx;
103 : : else
104 : 0 : rte_atomic_fetch_add_explicit(&r->tx_pkts, nb_tx, rte_memory_order_relaxed);
105 : 3189165 : return nb_tx;
106 : : }
107 : :
108 : : static int
109 : 14 : eth_dev_configure(struct rte_eth_dev *dev __rte_unused) { return 0; }
110 : :
111 : : static int
112 : 10 : eth_dev_start(struct rte_eth_dev *dev)
113 : : {
114 : 10 : dev->data->dev_link.link_status = RTE_ETH_LINK_UP;
115 : 10 : return 0;
116 : : }
117 : :
118 : : static int
119 : 10 : eth_dev_stop(struct rte_eth_dev *dev)
120 : : {
121 : : uint16_t i;
122 : :
123 : 25 : dev->data->dev_started = 0;
124 : 25 : dev->data->dev_link.link_status = RTE_ETH_LINK_DOWN;
125 : :
126 [ + + + + ]: 172 : for (i = 0; i < dev->data->nb_rx_queues; i++)
127 : 147 : dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
128 [ + + + + ]: 174 : for (i = 0; i < dev->data->nb_tx_queues; i++)
129 : 149 : dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
130 : 10 : return 0;
131 : : }
132 : :
133 : : static int
134 : 0 : eth_dev_set_link_down(struct rte_eth_dev *dev)
135 : : {
136 : : uint16_t i;
137 : :
138 : 0 : dev->data->dev_link.link_status = RTE_ETH_LINK_DOWN;
139 : :
140 [ # # ]: 0 : for (i = 0; i < dev->data->nb_rx_queues; i++)
141 : 0 : dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
142 [ # # ]: 0 : for (i = 0; i < dev->data->nb_tx_queues; i++)
143 : 0 : dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
144 : :
145 : 0 : return 0;
146 : : }
147 : :
148 : : static int
149 : 0 : eth_dev_set_link_up(struct rte_eth_dev *dev)
150 : : {
151 : 0 : dev->data->dev_link.link_status = RTE_ETH_LINK_UP;
152 : 0 : return 0;
153 : : }
154 : :
155 : : static int
156 : 43 : eth_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id,
157 : : uint16_t nb_rx_desc __rte_unused,
158 : : unsigned int socket_id __rte_unused,
159 : : const struct rte_eth_rxconf *rx_conf __rte_unused,
160 : : struct rte_mempool *mb_pool __rte_unused)
161 : : {
162 : 43 : struct pmd_internals *internals = dev->data->dev_private;
163 : 43 : internals->rx_ring_queues[rx_queue_id].in_port = dev->data->port_id;
164 : 43 : dev->data->rx_queues[rx_queue_id] = &internals->rx_ring_queues[rx_queue_id];
165 : 43 : return 0;
166 : : }
167 : :
168 : : static int
169 : 45 : eth_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id,
170 : : uint16_t nb_tx_desc __rte_unused,
171 : : unsigned int socket_id __rte_unused,
172 : : const struct rte_eth_txconf *tx_conf __rte_unused)
173 : : {
174 : 45 : struct pmd_internals *internals = dev->data->dev_private;
175 : :
176 : 45 : dev->data->tx_queues[tx_queue_id] = &internals->tx_ring_queues[tx_queue_id];
177 : 45 : return 0;
178 : : }
179 : :
180 : :
181 : : static int
182 : 121 : eth_dev_info(struct rte_eth_dev *dev,
183 : : struct rte_eth_dev_info *dev_info)
184 : : {
185 : 121 : struct pmd_internals *internals = dev->data->dev_private;
186 : :
187 : 121 : dev_info->max_mac_addrs = 1;
188 : 121 : dev_info->max_rx_pktlen = (uint32_t)-1;
189 : 121 : dev_info->max_rx_queues = (uint16_t)internals->max_rx_queues;
190 : 121 : dev_info->rx_offload_capa = RTE_ETH_RX_OFFLOAD_SCATTER;
191 : 121 : dev_info->tx_offload_capa = RTE_ETH_TX_OFFLOAD_MULTI_SEGS;
192 : 121 : dev_info->max_tx_queues = (uint16_t)internals->max_tx_queues;
193 : 121 : dev_info->min_rx_bufsize = 0;
194 : :
195 : 121 : return 0;
196 : : }
197 : :
198 : : static int
199 : 17 : eth_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats,
200 : : struct eth_queue_stats *qstats)
201 : : {
202 : : unsigned int i;
203 : : unsigned long rx_total = 0, tx_total = 0;
204 : 17 : const struct pmd_internals *internal = dev->data->dev_private;
205 : :
206 [ + + ]: 36 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
207 [ + + ]: 19 : if (qstats != NULL)
208 : 3 : qstats[i].q_ipackets = internal->rx_ring_queues[i].rx_pkts;
209 : 19 : rx_total += internal->rx_ring_queues[i].rx_pkts;
210 : : }
211 : :
212 [ + + ]: 38 : for (i = 0; i < dev->data->nb_tx_queues; i++) {
213 [ + + ]: 21 : if (qstats != NULL)
214 : 5 : qstats[i].q_opackets = internal->tx_ring_queues[i].tx_pkts;
215 : 21 : tx_total += internal->tx_ring_queues[i].tx_pkts;
216 : : }
217 : :
218 : 17 : stats->ipackets = rx_total;
219 : 17 : stats->opackets = tx_total;
220 : :
221 : 17 : return 0;
222 : : }
223 : :
224 : : static int
225 : 4 : eth_stats_reset(struct rte_eth_dev *dev)
226 : : {
227 : : unsigned int i;
228 : 4 : struct pmd_internals *internal = dev->data->dev_private;
229 : :
230 [ + + ]: 8 : for (i = 0; i < dev->data->nb_rx_queues; i++)
231 : 4 : internal->rx_ring_queues[i].rx_pkts = 0;
232 [ + + ]: 8 : for (i = 0; i < dev->data->nb_tx_queues; i++)
233 : 4 : internal->tx_ring_queues[i].tx_pkts = 0;
234 : :
235 : 4 : return 0;
236 : : }
237 : :
238 : : static void
239 : 0 : eth_mac_addr_remove(struct rte_eth_dev *dev __rte_unused,
240 : : uint32_t index __rte_unused)
241 : : {
242 : 0 : }
243 : :
244 : : static int
245 : 10 : eth_mac_addr_add(struct rte_eth_dev *dev __rte_unused,
246 : : struct rte_ether_addr *mac_addr __rte_unused,
247 : : uint32_t index __rte_unused,
248 : : uint32_t vmdq __rte_unused)
249 : : {
250 : 10 : return 0;
251 : : }
252 : :
253 : : static int
254 : 10 : eth_promiscuous_enable(struct rte_eth_dev *dev __rte_unused)
255 : : {
256 : 10 : return 0;
257 : : }
258 : :
259 : : static int
260 : 0 : eth_promiscuous_disable(struct rte_eth_dev *dev __rte_unused)
261 : : {
262 : 0 : return 0;
263 : : }
264 : :
265 : : static int
266 : 10 : eth_allmulticast_enable(struct rte_eth_dev *dev __rte_unused)
267 : : {
268 : 10 : return 0;
269 : : }
270 : :
271 : : static int
272 : 0 : eth_allmulticast_disable(struct rte_eth_dev *dev __rte_unused)
273 : : {
274 : 0 : return 0;
275 : : }
276 : :
277 : : static int
278 : 13 : eth_link_update(struct rte_eth_dev *dev __rte_unused,
279 : 13 : int wait_to_complete __rte_unused) { return 0; }
280 : :
281 : : static int
282 : 15 : eth_dev_close(struct rte_eth_dev *dev)
283 : : {
284 : : struct pmd_internals *internals = NULL;
285 : : struct ring_queue *r = NULL;
286 : : uint16_t i;
287 : : int ret;
288 : :
289 [ + - ]: 15 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
290 : : return 0;
291 : :
292 : : ret = eth_dev_stop(dev);
293 : :
294 : 15 : internals = dev->data->dev_private;
295 [ + + ]: 15 : if (internals->action == DEV_CREATE) {
296 : : /*
297 : : * it is only necessary to delete the rings in rx_queues because
298 : : * they are the same used in tx_queues
299 : : */
300 [ + + ]: 68 : for (i = 0; i < dev->data->nb_rx_queues; i++) {
301 : 64 : r = dev->data->rx_queues[i];
302 : 64 : rte_ring_free(r->rng);
303 : : }
304 : : }
305 : :
306 : : /* mac_addrs must not be freed alone because part of dev_private */
307 : 15 : dev->data->mac_addrs = NULL;
308 : :
309 : 15 : return ret;
310 : : }
311 : :
312 : 0 : static int ring_monitor_callback(const uint64_t value,
313 : : const uint64_t arg[RTE_POWER_MONITOR_OPAQUE_SZ])
314 : : {
315 : : /* Check if the head pointer has changed */
316 : 0 : return value != arg[0];
317 : : }
318 : :
319 : : static int
320 : 0 : eth_get_monitor_addr(void *rx_queue, struct rte_power_monitor_cond *pmc)
321 : : {
322 : 0 : struct rte_ring *rng = ((struct ring_queue *)rx_queue)->rng;
323 : :
324 : : /*
325 : : * Monitor ring head since if head moves
326 : : * there are packets to transmit
327 : : */
328 : 0 : pmc->addr = &rng->prod.head;
329 : 0 : pmc->size = sizeof(rng->prod.head);
330 : 0 : pmc->opaque[0] = rng->prod.head;
331 : 0 : pmc->fn = ring_monitor_callback;
332 : 0 : return 0;
333 : : }
334 : :
335 : : static const struct eth_dev_ops ops = {
336 : : .dev_close = eth_dev_close,
337 : : .dev_start = eth_dev_start,
338 : : .dev_stop = eth_dev_stop,
339 : : .dev_set_link_up = eth_dev_set_link_up,
340 : : .dev_set_link_down = eth_dev_set_link_down,
341 : : .dev_configure = eth_dev_configure,
342 : : .dev_infos_get = eth_dev_info,
343 : : .rx_queue_setup = eth_rx_queue_setup,
344 : : .tx_queue_setup = eth_tx_queue_setup,
345 : : .link_update = eth_link_update,
346 : : .stats_get = eth_stats_get,
347 : : .stats_reset = eth_stats_reset,
348 : : .mac_addr_remove = eth_mac_addr_remove,
349 : : .mac_addr_add = eth_mac_addr_add,
350 : : .promiscuous_enable = eth_promiscuous_enable,
351 : : .promiscuous_disable = eth_promiscuous_disable,
352 : : .allmulticast_enable = eth_allmulticast_enable,
353 : : .allmulticast_disable = eth_allmulticast_disable,
354 : : .get_monitor_addr = eth_get_monitor_addr,
355 : : };
356 : :
357 : : static int
358 : 16 : do_eth_dev_ring_create(const char *name,
359 : : struct rte_vdev_device *vdev,
360 : : struct rte_ring * const rx_queues[],
361 : : const unsigned int nb_rx_queues,
362 : : struct rte_ring *const tx_queues[],
363 : : const unsigned int nb_tx_queues,
364 : : const unsigned int numa_node, enum dev_action action,
365 : : struct rte_eth_dev **eth_dev_p)
366 : : {
367 : : struct rte_eth_dev_data *data = NULL;
368 : : struct pmd_internals *internals = NULL;
369 : : struct rte_eth_dev *eth_dev = NULL;
370 : : void **rx_queues_local = NULL;
371 : : void **tx_queues_local = NULL;
372 : : unsigned int i;
373 : :
374 : 16 : PMD_LOG(INFO, "Creating rings-backed ethdev on numa socket %u",
375 : : numa_node);
376 : :
377 : 16 : rx_queues_local = rte_calloc_socket(name, nb_rx_queues,
378 : : sizeof(void *), 0, numa_node);
379 [ - + ]: 16 : if (rx_queues_local == NULL) {
380 : 0 : rte_errno = ENOMEM;
381 : 0 : goto error;
382 : : }
383 : :
384 : 16 : tx_queues_local = rte_calloc_socket(name, nb_tx_queues,
385 : : sizeof(void *), 0, numa_node);
386 [ - + ]: 16 : if (tx_queues_local == NULL) {
387 : 0 : rte_errno = ENOMEM;
388 : 0 : goto error;
389 : : }
390 : :
391 : 16 : internals = rte_zmalloc_socket(name, sizeof(*internals), 0, numa_node);
392 [ - + ]: 16 : if (internals == NULL) {
393 : 0 : rte_errno = ENOMEM;
394 : 0 : goto error;
395 : : }
396 : :
397 : : /* reserve an ethdev entry */
398 : 16 : eth_dev = rte_eth_dev_allocate(name);
399 [ - + ]: 16 : if (eth_dev == NULL) {
400 : 0 : rte_errno = ENOSPC;
401 : 0 : goto error;
402 : : }
403 : :
404 : : /* now put it all together
405 : : * - store EAL device in eth_dev,
406 : : * - store queue data in internals,
407 : : * - store numa_node info in eth_dev_data
408 : : * - point eth_dev_data to internals
409 : : * - and point eth_dev structure to new eth_dev_data structure
410 : : */
411 : :
412 : 16 : eth_dev->device = &vdev->device;
413 : :
414 : 16 : data = eth_dev->data;
415 : 16 : data->rx_queues = rx_queues_local;
416 : 16 : data->tx_queues = tx_queues_local;
417 : :
418 : 16 : internals->action = action;
419 : 16 : internals->max_rx_queues = nb_rx_queues;
420 : 16 : internals->max_tx_queues = nb_tx_queues;
421 [ + + ]: 144 : for (i = 0; i < nb_rx_queues; i++) {
422 : 128 : internals->rx_ring_queues[i].rng = rx_queues[i];
423 : 128 : internals->rx_ring_queues[i].in_port = -1;
424 : 128 : data->rx_queues[i] = &internals->rx_ring_queues[i];
425 : : }
426 [ + + ]: 146 : for (i = 0; i < nb_tx_queues; i++) {
427 : 130 : internals->tx_ring_queues[i].rng = tx_queues[i];
428 : 130 : internals->tx_ring_queues[i].in_port = -1;
429 : 130 : data->tx_queues[i] = &internals->tx_ring_queues[i];
430 : : }
431 : :
432 : 16 : data->dev_private = internals;
433 : 16 : data->nb_rx_queues = (uint16_t)nb_rx_queues;
434 : 16 : data->nb_tx_queues = (uint16_t)nb_tx_queues;
435 : 16 : data->dev_link = pmd_link;
436 : 16 : data->mac_addrs = &internals->address;
437 : 16 : data->promiscuous = 1;
438 : 16 : data->all_multicast = 1;
439 : 16 : data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS;
440 : :
441 : 16 : eth_dev->dev_ops = &ops;
442 : 16 : data->numa_node = numa_node;
443 : :
444 : : /* finally assign rx and tx ops */
445 : 16 : eth_dev->rx_pkt_burst = eth_ring_rx;
446 : 16 : eth_dev->tx_pkt_burst = eth_ring_tx;
447 : :
448 : 16 : rte_eth_dev_probing_finish(eth_dev);
449 : 16 : *eth_dev_p = eth_dev;
450 : :
451 : 16 : return data->port_id;
452 : :
453 : 0 : error:
454 : 0 : rte_free(rx_queues_local);
455 : 0 : rte_free(tx_queues_local);
456 : 0 : rte_free(internals);
457 : :
458 : 0 : return -1;
459 : : }
460 : :
461 : : RTE_EXPORT_SYMBOL(rte_eth_from_rings)
462 : : int
463 : 11 : rte_eth_from_rings(const char *name, struct rte_ring *const rx_queues[],
464 : : const unsigned int nb_rx_queues,
465 : : struct rte_ring *const tx_queues[],
466 : : const unsigned int nb_tx_queues,
467 : : const unsigned int numa_node)
468 : : {
469 : 11 : struct ring_internal_args args = {
470 : : .rx_queues = rx_queues,
471 : : .nb_rx_queues = nb_rx_queues,
472 : : .tx_queues = tx_queues,
473 : : .nb_tx_queues = nb_tx_queues,
474 : : .numa_node = numa_node,
475 : : };
476 : : char ring_name[RTE_RING_NAMESIZE];
477 : 11 : uint16_t port_id = RTE_MAX_ETHPORTS;
478 : : int ret;
479 : :
480 : : /* do some parameter checking */
481 [ - + ]: 11 : if (rx_queues == NULL && nb_rx_queues > 0) {
482 : 0 : rte_errno = EINVAL;
483 : 0 : return -1;
484 : : }
485 [ - + ]: 11 : if (tx_queues == NULL && nb_tx_queues > 0) {
486 : 0 : rte_errno = EINVAL;
487 : 0 : return -1;
488 : : }
489 [ - + ]: 11 : if (nb_rx_queues > RTE_PMD_RING_MAX_RX_RINGS) {
490 : 0 : rte_errno = EINVAL;
491 : 0 : return -1;
492 : : }
493 : :
494 : : ret = snprintf(ring_name, sizeof(ring_name), "net_ring_%s", name);
495 [ - + ]: 11 : if (ret >= (int)sizeof(ring_name)) {
496 : 0 : rte_errno = ENAMETOOLONG;
497 : 0 : return -1;
498 : : }
499 : :
500 : : /* mark this thread's pending request; consumed and cleared by probe */
501 : 11 : RTE_PER_LCORE(eth_ring_internal_args) = &args;
502 : 11 : ret = rte_vdev_init(ring_name, NULL);
503 : 11 : RTE_PER_LCORE(eth_ring_internal_args) = NULL;
504 [ - + ]: 11 : if (ret) {
505 : 0 : rte_errno = EINVAL;
506 : 0 : return -1;
507 : : }
508 : :
509 : 11 : ret = rte_eth_dev_get_port_by_name(ring_name, &port_id);
510 [ - + ]: 11 : if (ret) {
511 : 0 : rte_errno = ENODEV;
512 : 0 : return -1;
513 : : }
514 : :
515 : 11 : return port_id;
516 : : }
517 : :
518 : : RTE_EXPORT_SYMBOL(rte_eth_from_ring)
519 : : int
520 : 0 : rte_eth_from_ring(struct rte_ring *r)
521 : : {
522 : 0 : return rte_eth_from_rings(r->name, &r, 1, &r, 1,
523 [ # # ]: 0 : r->memzone ? r->memzone->socket_id : SOCKET_ID_ANY);
524 : : }
525 : :
526 : : static int
527 : 5 : eth_dev_ring_create(const char *name,
528 : : struct rte_vdev_device *vdev,
529 : : const unsigned int numa_node,
530 : : enum dev_action action, struct rte_eth_dev **eth_dev)
531 : : {
532 : : /* rx and tx are so-called from point of view of first port.
533 : : * They are inverted from the point of view of second port
534 : : */
535 : : struct rte_ring *rxtx[RTE_PMD_RING_MAX_RX_RINGS];
536 : : unsigned int i;
537 : : char rng_name[RTE_RING_NAMESIZE];
538 : : unsigned int num_rings = RTE_MIN(RTE_PMD_RING_MAX_RX_RINGS,
539 : : RTE_PMD_RING_MAX_TX_RINGS);
540 : :
541 [ + + ]: 85 : for (i = 0; i < num_rings; i++) {
542 : : int cc;
543 : :
544 : : cc = snprintf(rng_name, sizeof(rng_name),
545 : : "ETH_RXTX%u_%s", i, name);
546 [ - + ]: 80 : if (cc >= (int)sizeof(rng_name)) {
547 : 0 : rte_errno = ENAMETOOLONG;
548 : 0 : return -1;
549 : : }
550 : :
551 : 80 : rxtx[i] = (action == DEV_CREATE) ?
552 : 80 : rte_ring_create(rng_name, 1024, numa_node,
553 [ + - ]: 80 : RING_F_SP_ENQ|RING_F_SC_DEQ) :
554 : 0 : rte_ring_lookup(rng_name);
555 [ + - ]: 80 : if (rxtx[i] == NULL)
556 : : return -1;
557 : : }
558 : :
559 [ - + ]: 5 : if (do_eth_dev_ring_create(name, vdev, rxtx, num_rings, rxtx, num_rings,
560 : : numa_node, action, eth_dev) < 0)
561 : 0 : return -1;
562 : :
563 : : return 0;
564 : : }
565 : :
566 : : struct node_action_pair {
567 : : char name[ETH_RING_ACTION_MAX_LEN];
568 : : unsigned int node;
569 : : enum dev_action action;
570 : : };
571 : :
572 : : struct node_action_list {
573 : : unsigned int total;
574 : : unsigned int count;
575 : : struct node_action_pair *list;
576 : : };
577 : :
578 : 1 : static int parse_kvlist(const char *key __rte_unused,
579 : : const char *value, void *data)
580 : : {
581 : : struct node_action_list *info = data;
582 : : int ret;
583 : : char *name;
584 : : char *action;
585 : : char *node;
586 : : char *end;
587 : :
588 : 1 : name = strdup(value);
589 : :
590 : : ret = -EINVAL;
591 : :
592 [ - + ]: 1 : if (!name) {
593 : 0 : PMD_LOG(WARNING, "command line parameter is empty for ring pmd!");
594 : 0 : goto out;
595 : : }
596 : :
597 : 1 : node = strchr(name, ':');
598 [ - + ]: 1 : if (!node) {
599 : 0 : PMD_LOG(WARNING, "could not parse node value from %s",
600 : : name);
601 : 0 : goto out;
602 : : }
603 : :
604 : 1 : *node = '\0';
605 : 1 : node++;
606 : :
607 : 1 : action = strchr(node, ':');
608 [ - + ]: 1 : if (!action) {
609 : 0 : PMD_LOG(WARNING, "could not parse action value from %s",
610 : : node);
611 : 0 : goto out;
612 : : }
613 : :
614 : 1 : *action = '\0';
615 : 1 : action++;
616 : :
617 : : /*
618 : : * Need to do some sanity checking here
619 : : */
620 : :
621 [ - + ]: 1 : if (strcmp(action, ETH_RING_ACTION_ATTACH) == 0)
622 : 0 : info->list[info->count].action = DEV_ATTACH;
623 [ + - ]: 1 : else if (strcmp(action, ETH_RING_ACTION_CREATE) == 0)
624 : 1 : info->list[info->count].action = DEV_CREATE;
625 : : else
626 : 0 : goto out;
627 : :
628 : 1 : errno = 0;
629 : 1 : info->list[info->count].node = strtol(node, &end, 10);
630 : :
631 [ + - - + ]: 1 : if ((errno != 0) || (*end != '\0')) {
632 : 0 : PMD_LOG(WARNING,
633 : : "node value %s is unparseable as a number", node);
634 : 0 : goto out;
635 : : }
636 : :
637 : 1 : strlcpy(info->list[info->count].name, name,
638 : : sizeof(info->list[info->count].name));
639 : :
640 : 1 : info->count++;
641 : :
642 : : ret = 0;
643 : 1 : out:
644 : 1 : free(name);
645 : 1 : return ret;
646 : : }
647 : :
648 : : static int
649 : 16 : rte_pmd_ring_probe(struct rte_vdev_device *dev)
650 : : {
651 : : const char *name, *params;
652 : : struct rte_kvargs *kvlist = NULL;
653 : : int ret = 0;
654 : : struct node_action_list *info = NULL;
655 [ + - ]: 16 : struct rte_eth_dev *eth_dev = NULL;
656 : : struct ring_internal_args *internal_args;
657 : :
658 : : name = rte_vdev_device_name(dev);
659 : : params = rte_vdev_device_args(dev);
660 : :
661 : 16 : PMD_LOG(INFO, "Initializing pmd_ring for %s", name);
662 : :
663 [ - + ]: 16 : if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
664 : 0 : eth_dev = rte_eth_dev_attach_secondary(name);
665 [ # # ]: 0 : if (!eth_dev) {
666 : 0 : PMD_LOG(ERR, "Failed to probe %s", name);
667 : 0 : return -1;
668 : : }
669 : 0 : eth_dev->dev_ops = &ops;
670 : 0 : eth_dev->device = &dev->device;
671 : :
672 : 0 : eth_dev->rx_pkt_burst = eth_ring_rx;
673 : 0 : eth_dev->tx_pkt_burst = eth_ring_tx;
674 : :
675 : 0 : rte_eth_dev_probing_finish(eth_dev);
676 : :
677 : 0 : return 0;
678 : : }
679 : :
680 : : /* set only by rte_eth_from_rings() */
681 : 16 : internal_args = RTE_PER_LCORE(eth_ring_internal_args);
682 [ + + ]: 16 : if (internal_args != NULL) {
683 : 11 : RTE_PER_LCORE(eth_ring_internal_args) = NULL;
684 : 11 : ret = do_eth_dev_ring_create(name, dev,
685 : : internal_args->rx_queues,
686 : 11 : internal_args->nb_rx_queues,
687 : : internal_args->tx_queues,
688 : 11 : internal_args->nb_tx_queues,
689 : 11 : internal_args->numa_node,
690 : : DEV_ATTACH,
691 : : ð_dev);
692 : 11 : return ret >= 0 ? 0 : ret;
693 : : }
694 : :
695 [ + - + + ]: 5 : if (params == NULL || params[0] == '\0') {
696 : 3 : ret = eth_dev_ring_create(name, dev, rte_socket_id(), DEV_CREATE,
697 : : ð_dev);
698 [ - + ]: 3 : if (ret == -1) {
699 : 0 : PMD_LOG(INFO,
700 : : "Attach to pmd_ring for %s", name);
701 : 0 : ret = eth_dev_ring_create(name, dev, rte_socket_id(),
702 : : DEV_ATTACH, ð_dev);
703 : : }
704 : : } else {
705 : 2 : kvlist = rte_kvargs_parse(params, valid_arguments);
706 : :
707 [ + + ]: 2 : if (!kvlist) {
708 : 1 : PMD_LOG(INFO,
709 : : "Ignoring unsupported parameters when creating rings-backed ethernet device");
710 : 1 : ret = eth_dev_ring_create(name, dev, rte_socket_id(),
711 : : DEV_CREATE, ð_dev);
712 [ - + ]: 1 : if (ret == -1) {
713 : 0 : PMD_LOG(INFO,
714 : : "Attach to pmd_ring for %s",
715 : : name);
716 : 0 : ret = eth_dev_ring_create(name, dev, rte_socket_id(),
717 : : DEV_ATTACH, ð_dev);
718 : : }
719 : :
720 : 1 : return ret;
721 : : }
722 : :
723 : 1 : ret = rte_kvargs_count(kvlist, ETH_RING_NUMA_NODE_ACTION_ARG);
724 : 1 : info = rte_zmalloc("struct node_action_list",
725 : 1 : sizeof(struct node_action_list) +
726 : : (sizeof(struct node_action_pair) * ret),
727 : : 0);
728 [ - + ]: 1 : if (!info)
729 : 0 : goto out_free;
730 : :
731 : 1 : info->total = ret;
732 : 1 : info->list = (struct node_action_pair *)(info + 1);
733 : :
734 : 1 : ret = rte_kvargs_process(kvlist, ETH_RING_NUMA_NODE_ACTION_ARG,
735 : : parse_kvlist, info);
736 : :
737 [ - + ]: 1 : if (ret < 0)
738 : 0 : goto out_free;
739 : :
740 [ + + ]: 2 : for (info->count = 0; info->count < info->total; info->count++) {
741 : 1 : ret = eth_dev_ring_create(info->list[info->count].name,
742 : : dev,
743 : : info->list[info->count].node,
744 : 1 : info->list[info->count].action,
745 : : ð_dev);
746 [ - + - - ]: 1 : if (ret == -1 && info->list[info->count].action == DEV_CREATE) {
747 : 0 : PMD_LOG(INFO,
748 : : "Attach to pmd_ring for %s",
749 : : name);
750 : 0 : ret = eth_dev_ring_create(name, dev,
751 : 0 : info->list[info->count].node,
752 : : DEV_ATTACH,
753 : : ð_dev);
754 : : }
755 : : }
756 : : }
757 : :
758 : 1 : out_free:
759 : 4 : rte_kvargs_free(kvlist);
760 : 4 : rte_free(info);
761 : 4 : return ret;
762 : : }
763 : :
764 : : static int
765 [ + - ]: 16 : rte_pmd_ring_remove(struct rte_vdev_device *dev)
766 : : {
767 : : const char *name = rte_vdev_device_name(dev);
768 : : struct rte_eth_dev *eth_dev = NULL;
769 : :
770 : 16 : PMD_LOG(INFO, "Un-Initializing pmd_ring for %s", name);
771 : :
772 [ + - ]: 16 : if (name == NULL)
773 : : return -EINVAL;
774 : :
775 : : /* find an ethdev entry */
776 : 16 : eth_dev = rte_eth_dev_allocated(name);
777 [ + + ]: 16 : if (eth_dev == NULL)
778 : : return 0; /* port already released */
779 : :
780 : 14 : eth_dev_close(eth_dev);
781 : 14 : rte_eth_dev_release_port(eth_dev);
782 : 14 : return 0;
783 : : }
784 : :
785 : : static struct rte_vdev_driver pmd_ring_drv = {
786 : : .probe = rte_pmd_ring_probe,
787 : : .remove = rte_pmd_ring_remove,
788 : : };
789 : :
790 : 302 : RTE_PMD_REGISTER_VDEV(net_ring, pmd_ring_drv);
791 : : RTE_PMD_REGISTER_ALIAS(net_ring, eth_ring);
792 : : RTE_PMD_REGISTER_PARAM_STRING(net_ring,
793 : : ETH_RING_NUMA_NODE_ACTION_ARG "=name:node:action(ATTACH|CREATE)");
|