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