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