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