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