1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) IGEL Co.,Ltd. 3 * All rights reserved. 4 */ 5 6 #include <rte_mbuf.h> 7 #include <rte_ethdev_driver.h> 8 #include <rte_ethdev_vdev.h> 9 #include <rte_malloc.h> 10 #include <rte_memcpy.h> 11 #include <rte_bus_vdev.h> 12 #include <rte_kvargs.h> 13 #include <rte_spinlock.h> 14 15 #define ETH_NULL_PACKET_SIZE_ARG "size" 16 #define ETH_NULL_PACKET_COPY_ARG "copy" 17 #define ETH_NULL_PACKET_NO_RX_ARG "no-rx" 18 19 static unsigned int default_packet_size = 64; 20 static unsigned int default_packet_copy; 21 static unsigned int default_no_rx; 22 23 static const char *valid_arguments[] = { 24 ETH_NULL_PACKET_SIZE_ARG, 25 ETH_NULL_PACKET_COPY_ARG, 26 ETH_NULL_PACKET_NO_RX_ARG, 27 NULL 28 }; 29 30 struct pmd_internals; 31 32 struct null_queue { 33 struct pmd_internals *internals; 34 35 struct rte_mempool *mb_pool; 36 struct rte_mbuf *dummy_packet; 37 38 rte_atomic64_t rx_pkts; 39 rte_atomic64_t tx_pkts; 40 }; 41 42 struct pmd_options { 43 unsigned int packet_copy; 44 unsigned int packet_size; 45 unsigned int no_rx; 46 }; 47 48 struct pmd_internals { 49 unsigned int packet_size; 50 unsigned int packet_copy; 51 unsigned int no_rx; 52 uint16_t port_id; 53 54 struct null_queue rx_null_queues[RTE_MAX_QUEUES_PER_PORT]; 55 struct null_queue tx_null_queues[RTE_MAX_QUEUES_PER_PORT]; 56 57 struct rte_ether_addr eth_addr; 58 /** Bit mask of RSS offloads, the bit offset also means flow type */ 59 uint64_t flow_type_rss_offloads; 60 61 rte_spinlock_t rss_lock; 62 63 uint16_t reta_size; 64 struct rte_eth_rss_reta_entry64 reta_conf[ETH_RSS_RETA_SIZE_128 / 65 RTE_RETA_GROUP_SIZE]; 66 67 uint8_t rss_key[40]; /**< 40-byte hash key. */ 68 }; 69 static struct rte_eth_link pmd_link = { 70 .link_speed = ETH_SPEED_NUM_10G, 71 .link_duplex = ETH_LINK_FULL_DUPLEX, 72 .link_status = ETH_LINK_DOWN, 73 .link_autoneg = ETH_LINK_FIXED, 74 }; 75 76 static int eth_null_logtype; 77 78 #define PMD_LOG(level, fmt, args...) \ 79 rte_log(RTE_LOG_ ## level, eth_null_logtype, \ 80 "%s(): " fmt "\n", __func__, ##args) 81 82 static uint16_t 83 eth_null_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs) 84 { 85 int i; 86 struct null_queue *h = q; 87 unsigned int packet_size; 88 89 if ((q == NULL) || (bufs == NULL)) 90 return 0; 91 92 packet_size = h->internals->packet_size; 93 if (rte_pktmbuf_alloc_bulk(h->mb_pool, bufs, nb_bufs) != 0) 94 return 0; 95 96 for (i = 0; i < nb_bufs; i++) { 97 bufs[i]->data_len = (uint16_t)packet_size; 98 bufs[i]->pkt_len = packet_size; 99 bufs[i]->port = h->internals->port_id; 100 } 101 102 rte_atomic64_add(&(h->rx_pkts), i); 103 104 return i; 105 } 106 107 static uint16_t 108 eth_null_copy_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs) 109 { 110 int i; 111 struct null_queue *h = q; 112 unsigned int packet_size; 113 114 if ((q == NULL) || (bufs == NULL)) 115 return 0; 116 117 packet_size = h->internals->packet_size; 118 if (rte_pktmbuf_alloc_bulk(h->mb_pool, bufs, nb_bufs) != 0) 119 return 0; 120 121 for (i = 0; i < nb_bufs; i++) { 122 rte_memcpy(rte_pktmbuf_mtod(bufs[i], void *), h->dummy_packet, 123 packet_size); 124 bufs[i]->data_len = (uint16_t)packet_size; 125 bufs[i]->pkt_len = packet_size; 126 bufs[i]->port = h->internals->port_id; 127 } 128 129 rte_atomic64_add(&(h->rx_pkts), i); 130 131 return i; 132 } 133 134 static uint16_t 135 eth_null_no_rx(void *q __rte_unused, struct rte_mbuf **bufs __rte_unused, 136 uint16_t nb_bufs __rte_unused) 137 { 138 return 0; 139 } 140 141 static uint16_t 142 eth_null_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs) 143 { 144 int i; 145 struct null_queue *h = q; 146 147 if ((q == NULL) || (bufs == NULL)) 148 return 0; 149 150 for (i = 0; i < nb_bufs; i++) 151 rte_pktmbuf_free(bufs[i]); 152 153 rte_atomic64_add(&(h->tx_pkts), i); 154 155 return i; 156 } 157 158 static uint16_t 159 eth_null_copy_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs) 160 { 161 int i; 162 struct null_queue *h = q; 163 unsigned int packet_size; 164 165 if ((q == NULL) || (bufs == NULL)) 166 return 0; 167 168 packet_size = h->internals->packet_size; 169 for (i = 0; i < nb_bufs; i++) { 170 rte_memcpy(h->dummy_packet, rte_pktmbuf_mtod(bufs[i], void *), 171 packet_size); 172 rte_pktmbuf_free(bufs[i]); 173 } 174 175 rte_atomic64_add(&(h->tx_pkts), i); 176 177 return i; 178 } 179 180 static int 181 eth_dev_configure(struct rte_eth_dev *dev __rte_unused) 182 { 183 return 0; 184 } 185 186 static int 187 eth_dev_start(struct rte_eth_dev *dev) 188 { 189 if (dev == NULL) 190 return -EINVAL; 191 192 dev->data->dev_link.link_status = ETH_LINK_UP; 193 return 0; 194 } 195 196 static void 197 eth_dev_stop(struct rte_eth_dev *dev) 198 { 199 if (dev == NULL) 200 return; 201 202 dev->data->dev_link.link_status = ETH_LINK_DOWN; 203 } 204 205 static int 206 eth_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id, 207 uint16_t nb_rx_desc __rte_unused, 208 unsigned int socket_id __rte_unused, 209 const struct rte_eth_rxconf *rx_conf __rte_unused, 210 struct rte_mempool *mb_pool) 211 { 212 struct rte_mbuf *dummy_packet; 213 struct pmd_internals *internals; 214 unsigned int packet_size; 215 216 if ((dev == NULL) || (mb_pool == NULL)) 217 return -EINVAL; 218 219 internals = dev->data->dev_private; 220 221 if (rx_queue_id >= dev->data->nb_rx_queues) 222 return -ENODEV; 223 224 packet_size = internals->packet_size; 225 226 internals->rx_null_queues[rx_queue_id].mb_pool = mb_pool; 227 dev->data->rx_queues[rx_queue_id] = 228 &internals->rx_null_queues[rx_queue_id]; 229 dummy_packet = rte_zmalloc_socket(NULL, 230 packet_size, 0, dev->data->numa_node); 231 if (dummy_packet == NULL) 232 return -ENOMEM; 233 234 internals->rx_null_queues[rx_queue_id].internals = internals; 235 internals->rx_null_queues[rx_queue_id].dummy_packet = dummy_packet; 236 237 return 0; 238 } 239 240 static int 241 eth_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id, 242 uint16_t nb_tx_desc __rte_unused, 243 unsigned int socket_id __rte_unused, 244 const struct rte_eth_txconf *tx_conf __rte_unused) 245 { 246 struct rte_mbuf *dummy_packet; 247 struct pmd_internals *internals; 248 unsigned int packet_size; 249 250 if (dev == NULL) 251 return -EINVAL; 252 253 internals = dev->data->dev_private; 254 255 if (tx_queue_id >= dev->data->nb_tx_queues) 256 return -ENODEV; 257 258 packet_size = internals->packet_size; 259 260 dev->data->tx_queues[tx_queue_id] = 261 &internals->tx_null_queues[tx_queue_id]; 262 dummy_packet = rte_zmalloc_socket(NULL, 263 packet_size, 0, dev->data->numa_node); 264 if (dummy_packet == NULL) 265 return -ENOMEM; 266 267 internals->tx_null_queues[tx_queue_id].internals = internals; 268 internals->tx_null_queues[tx_queue_id].dummy_packet = dummy_packet; 269 270 return 0; 271 } 272 273 static int 274 eth_mtu_set(struct rte_eth_dev *dev __rte_unused, uint16_t mtu __rte_unused) 275 { 276 return 0; 277 } 278 279 static int 280 eth_dev_info(struct rte_eth_dev *dev, 281 struct rte_eth_dev_info *dev_info) 282 { 283 struct pmd_internals *internals; 284 285 if ((dev == NULL) || (dev_info == NULL)) 286 return -EINVAL; 287 288 internals = dev->data->dev_private; 289 dev_info->max_mac_addrs = 1; 290 dev_info->max_rx_pktlen = (uint32_t)-1; 291 dev_info->max_rx_queues = RTE_DIM(internals->rx_null_queues); 292 dev_info->max_tx_queues = RTE_DIM(internals->tx_null_queues); 293 dev_info->min_rx_bufsize = 0; 294 dev_info->reta_size = internals->reta_size; 295 dev_info->flow_type_rss_offloads = internals->flow_type_rss_offloads; 296 297 return 0; 298 } 299 300 static int 301 eth_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *igb_stats) 302 { 303 unsigned int i, num_stats; 304 unsigned long rx_total = 0, tx_total = 0; 305 const struct pmd_internals *internal; 306 307 if ((dev == NULL) || (igb_stats == NULL)) 308 return -EINVAL; 309 310 internal = dev->data->dev_private; 311 num_stats = RTE_MIN((unsigned int)RTE_ETHDEV_QUEUE_STAT_CNTRS, 312 RTE_MIN(dev->data->nb_rx_queues, 313 RTE_DIM(internal->rx_null_queues))); 314 for (i = 0; i < num_stats; i++) { 315 igb_stats->q_ipackets[i] = 316 internal->rx_null_queues[i].rx_pkts.cnt; 317 rx_total += igb_stats->q_ipackets[i]; 318 } 319 320 num_stats = RTE_MIN((unsigned int)RTE_ETHDEV_QUEUE_STAT_CNTRS, 321 RTE_MIN(dev->data->nb_tx_queues, 322 RTE_DIM(internal->tx_null_queues))); 323 for (i = 0; i < num_stats; i++) { 324 igb_stats->q_opackets[i] = 325 internal->tx_null_queues[i].tx_pkts.cnt; 326 tx_total += igb_stats->q_opackets[i]; 327 } 328 329 igb_stats->ipackets = rx_total; 330 igb_stats->opackets = tx_total; 331 332 return 0; 333 } 334 335 static int 336 eth_stats_reset(struct rte_eth_dev *dev) 337 { 338 unsigned int i; 339 struct pmd_internals *internal; 340 341 if (dev == NULL) 342 return -EINVAL; 343 344 internal = dev->data->dev_private; 345 for (i = 0; i < RTE_DIM(internal->rx_null_queues); i++) 346 internal->rx_null_queues[i].rx_pkts.cnt = 0; 347 for (i = 0; i < RTE_DIM(internal->tx_null_queues); i++) 348 internal->tx_null_queues[i].tx_pkts.cnt = 0; 349 350 return 0; 351 } 352 353 static void 354 eth_queue_release(void *q) 355 { 356 struct null_queue *nq; 357 358 if (q == NULL) 359 return; 360 361 nq = q; 362 rte_free(nq->dummy_packet); 363 } 364 365 static int 366 eth_link_update(struct rte_eth_dev *dev __rte_unused, 367 int wait_to_complete __rte_unused) { return 0; } 368 369 static int 370 eth_rss_reta_update(struct rte_eth_dev *dev, 371 struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size) 372 { 373 int i, j; 374 struct pmd_internals *internal = dev->data->dev_private; 375 376 if (reta_size != internal->reta_size) 377 return -EINVAL; 378 379 rte_spinlock_lock(&internal->rss_lock); 380 381 /* Copy RETA table */ 382 for (i = 0; i < (internal->reta_size / RTE_RETA_GROUP_SIZE); i++) { 383 internal->reta_conf[i].mask = reta_conf[i].mask; 384 for (j = 0; j < RTE_RETA_GROUP_SIZE; j++) 385 if ((reta_conf[i].mask >> j) & 0x01) 386 internal->reta_conf[i].reta[j] = reta_conf[i].reta[j]; 387 } 388 389 rte_spinlock_unlock(&internal->rss_lock); 390 391 return 0; 392 } 393 394 static int 395 eth_rss_reta_query(struct rte_eth_dev *dev, 396 struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size) 397 { 398 int i, j; 399 struct pmd_internals *internal = dev->data->dev_private; 400 401 if (reta_size != internal->reta_size) 402 return -EINVAL; 403 404 rte_spinlock_lock(&internal->rss_lock); 405 406 /* Copy RETA table */ 407 for (i = 0; i < (internal->reta_size / RTE_RETA_GROUP_SIZE); i++) { 408 for (j = 0; j < RTE_RETA_GROUP_SIZE; j++) 409 if ((reta_conf[i].mask >> j) & 0x01) 410 reta_conf[i].reta[j] = internal->reta_conf[i].reta[j]; 411 } 412 413 rte_spinlock_unlock(&internal->rss_lock); 414 415 return 0; 416 } 417 418 static int 419 eth_rss_hash_update(struct rte_eth_dev *dev, struct rte_eth_rss_conf *rss_conf) 420 { 421 struct pmd_internals *internal = dev->data->dev_private; 422 423 rte_spinlock_lock(&internal->rss_lock); 424 425 if ((rss_conf->rss_hf & internal->flow_type_rss_offloads) != 0) 426 dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf = 427 rss_conf->rss_hf & internal->flow_type_rss_offloads; 428 429 if (rss_conf->rss_key) 430 rte_memcpy(internal->rss_key, rss_conf->rss_key, 40); 431 432 rte_spinlock_unlock(&internal->rss_lock); 433 434 return 0; 435 } 436 437 static int 438 eth_rss_hash_conf_get(struct rte_eth_dev *dev, 439 struct rte_eth_rss_conf *rss_conf) 440 { 441 struct pmd_internals *internal = dev->data->dev_private; 442 443 rte_spinlock_lock(&internal->rss_lock); 444 445 rss_conf->rss_hf = dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf; 446 if (rss_conf->rss_key) 447 rte_memcpy(rss_conf->rss_key, internal->rss_key, 40); 448 449 rte_spinlock_unlock(&internal->rss_lock); 450 451 return 0; 452 } 453 454 static int 455 eth_mac_address_set(__rte_unused struct rte_eth_dev *dev, 456 __rte_unused struct rte_ether_addr *addr) 457 { 458 return 0; 459 } 460 461 static const struct eth_dev_ops ops = { 462 .dev_start = eth_dev_start, 463 .dev_stop = eth_dev_stop, 464 .dev_configure = eth_dev_configure, 465 .dev_infos_get = eth_dev_info, 466 .rx_queue_setup = eth_rx_queue_setup, 467 .tx_queue_setup = eth_tx_queue_setup, 468 .rx_queue_release = eth_queue_release, 469 .tx_queue_release = eth_queue_release, 470 .mtu_set = eth_mtu_set, 471 .link_update = eth_link_update, 472 .mac_addr_set = eth_mac_address_set, 473 .stats_get = eth_stats_get, 474 .stats_reset = eth_stats_reset, 475 .reta_update = eth_rss_reta_update, 476 .reta_query = eth_rss_reta_query, 477 .rss_hash_update = eth_rss_hash_update, 478 .rss_hash_conf_get = eth_rss_hash_conf_get 479 }; 480 481 static int 482 eth_dev_null_create(struct rte_vdev_device *dev, struct pmd_options *args) 483 { 484 const unsigned int nb_rx_queues = 1; 485 const unsigned int nb_tx_queues = 1; 486 struct rte_eth_dev_data *data; 487 struct pmd_internals *internals = NULL; 488 struct rte_eth_dev *eth_dev = NULL; 489 490 static const uint8_t default_rss_key[40] = { 491 0x6D, 0x5A, 0x56, 0xDA, 0x25, 0x5B, 0x0E, 0xC2, 0x41, 0x67, 0x25, 0x3D, 492 0x43, 0xA3, 0x8F, 0xB0, 0xD0, 0xCA, 0x2B, 0xCB, 0xAE, 0x7B, 0x30, 0xB4, 493 0x77, 0xCB, 0x2D, 0xA3, 0x80, 0x30, 0xF2, 0x0C, 0x6A, 0x42, 0xB7, 0x3B, 494 0xBE, 0xAC, 0x01, 0xFA 495 }; 496 497 if (dev->device.numa_node == SOCKET_ID_ANY) 498 dev->device.numa_node = rte_socket_id(); 499 500 PMD_LOG(INFO, "Creating null ethdev on numa socket %u", 501 dev->device.numa_node); 502 503 eth_dev = rte_eth_vdev_allocate(dev, sizeof(*internals)); 504 if (!eth_dev) 505 return -ENOMEM; 506 507 /* now put it all together 508 * - store queue data in internals, 509 * - store numa_node info in ethdev data 510 * - point eth_dev_data to internals 511 * - and point eth_dev structure to new eth_dev_data structure 512 */ 513 /* NOTE: we'll replace the data element, of originally allocated eth_dev 514 * so the nulls are local per-process */ 515 516 internals = eth_dev->data->dev_private; 517 internals->packet_size = args->packet_size; 518 internals->packet_copy = args->packet_copy; 519 internals->no_rx = args->no_rx; 520 internals->port_id = eth_dev->data->port_id; 521 rte_eth_random_addr(internals->eth_addr.addr_bytes); 522 523 internals->flow_type_rss_offloads = ETH_RSS_PROTO_MASK; 524 internals->reta_size = RTE_DIM(internals->reta_conf) * RTE_RETA_GROUP_SIZE; 525 526 rte_memcpy(internals->rss_key, default_rss_key, 40); 527 528 data = eth_dev->data; 529 data->nb_rx_queues = (uint16_t)nb_rx_queues; 530 data->nb_tx_queues = (uint16_t)nb_tx_queues; 531 data->dev_link = pmd_link; 532 data->mac_addrs = &internals->eth_addr; 533 data->promiscuous = 1; 534 data->all_multicast = 1; 535 536 eth_dev->dev_ops = &ops; 537 538 /* finally assign rx and tx ops */ 539 if (internals->packet_copy) { 540 eth_dev->rx_pkt_burst = eth_null_copy_rx; 541 eth_dev->tx_pkt_burst = eth_null_copy_tx; 542 } else if (internals->no_rx) { 543 eth_dev->rx_pkt_burst = eth_null_no_rx; 544 eth_dev->tx_pkt_burst = eth_null_tx; 545 } else { 546 eth_dev->rx_pkt_burst = eth_null_rx; 547 eth_dev->tx_pkt_burst = eth_null_tx; 548 } 549 550 rte_eth_dev_probing_finish(eth_dev); 551 return 0; 552 } 553 554 static inline int 555 get_packet_size_arg(const char *key __rte_unused, 556 const char *value, void *extra_args) 557 { 558 const char *a = value; 559 unsigned int *packet_size = extra_args; 560 561 if ((value == NULL) || (extra_args == NULL)) 562 return -EINVAL; 563 564 *packet_size = (unsigned int)strtoul(a, NULL, 0); 565 if (*packet_size == UINT_MAX) 566 return -1; 567 568 return 0; 569 } 570 571 static inline int 572 get_packet_copy_arg(const char *key __rte_unused, 573 const char *value, void *extra_args) 574 { 575 const char *a = value; 576 unsigned int *packet_copy = extra_args; 577 578 if ((value == NULL) || (extra_args == NULL)) 579 return -EINVAL; 580 581 *packet_copy = (unsigned int)strtoul(a, NULL, 0); 582 if (*packet_copy == UINT_MAX) 583 return -1; 584 585 return 0; 586 } 587 588 static int 589 get_packet_no_rx_arg(const char *key __rte_unused, 590 const char *value, void *extra_args) 591 { 592 const char *a = value; 593 unsigned int no_rx; 594 595 if (value == NULL || extra_args == NULL) 596 return -EINVAL; 597 598 no_rx = (unsigned int)strtoul(a, NULL, 0); 599 if (no_rx != 0 && no_rx != 1) 600 return -1; 601 602 *(unsigned int *)extra_args = no_rx; 603 return 0; 604 } 605 606 static int 607 rte_pmd_null_probe(struct rte_vdev_device *dev) 608 { 609 const char *name, *params; 610 struct pmd_options args = { 611 .packet_copy = default_packet_copy, 612 .packet_size = default_packet_size, 613 .no_rx = default_no_rx, 614 }; 615 struct rte_kvargs *kvlist = NULL; 616 struct rte_eth_dev *eth_dev; 617 int ret; 618 619 if (!dev) 620 return -EINVAL; 621 622 name = rte_vdev_device_name(dev); 623 params = rte_vdev_device_args(dev); 624 PMD_LOG(INFO, "Initializing pmd_null for %s", name); 625 626 if (rte_eal_process_type() == RTE_PROC_SECONDARY) { 627 struct pmd_internals *internals; 628 eth_dev = rte_eth_dev_attach_secondary(name); 629 if (!eth_dev) { 630 PMD_LOG(ERR, "Failed to probe %s", name); 631 return -1; 632 } 633 /* TODO: request info from primary to set up Rx and Tx */ 634 eth_dev->dev_ops = &ops; 635 eth_dev->device = &dev->device; 636 internals = eth_dev->data->dev_private; 637 if (internals->packet_copy) { 638 eth_dev->rx_pkt_burst = eth_null_copy_rx; 639 eth_dev->tx_pkt_burst = eth_null_copy_tx; 640 } else if (internals->no_rx) { 641 eth_dev->rx_pkt_burst = eth_null_no_rx; 642 eth_dev->tx_pkt_burst = eth_null_tx; 643 } else { 644 eth_dev->rx_pkt_burst = eth_null_rx; 645 eth_dev->tx_pkt_burst = eth_null_tx; 646 } 647 rte_eth_dev_probing_finish(eth_dev); 648 return 0; 649 } 650 651 if (params != NULL) { 652 kvlist = rte_kvargs_parse(params, valid_arguments); 653 if (kvlist == NULL) 654 return -1; 655 656 ret = rte_kvargs_process(kvlist, 657 ETH_NULL_PACKET_SIZE_ARG, 658 &get_packet_size_arg, &args.packet_size); 659 if (ret < 0) 660 goto free_kvlist; 661 662 663 ret = rte_kvargs_process(kvlist, 664 ETH_NULL_PACKET_COPY_ARG, 665 &get_packet_copy_arg, &args.packet_copy); 666 if (ret < 0) 667 goto free_kvlist; 668 669 ret = rte_kvargs_process(kvlist, 670 ETH_NULL_PACKET_NO_RX_ARG, 671 &get_packet_no_rx_arg, &args.no_rx); 672 if (ret < 0) 673 goto free_kvlist; 674 675 if (args.no_rx && args.packet_copy) { 676 PMD_LOG(ERR, 677 "Both %s and %s arguments at the same time not supported", 678 ETH_NULL_PACKET_COPY_ARG, 679 ETH_NULL_PACKET_NO_RX_ARG); 680 goto free_kvlist; 681 } 682 } 683 684 PMD_LOG(INFO, "Configure pmd_null: packet size is %d, " 685 "packet copy is %s", args.packet_size, 686 args.packet_copy ? "enabled" : "disabled"); 687 688 ret = eth_dev_null_create(dev, &args); 689 690 free_kvlist: 691 if (kvlist) 692 rte_kvargs_free(kvlist); 693 return ret; 694 } 695 696 static int 697 rte_pmd_null_remove(struct rte_vdev_device *dev) 698 { 699 struct rte_eth_dev *eth_dev = NULL; 700 701 if (!dev) 702 return -EINVAL; 703 704 PMD_LOG(INFO, "Closing null ethdev on numa socket %u", 705 rte_socket_id()); 706 707 /* find the ethdev entry */ 708 eth_dev = rte_eth_dev_allocated(rte_vdev_device_name(dev)); 709 if (eth_dev == NULL) 710 return -1; 711 712 if (rte_eal_process_type() == RTE_PROC_PRIMARY) 713 /* mac_addrs must not be freed alone because part of dev_private */ 714 eth_dev->data->mac_addrs = NULL; 715 716 rte_eth_dev_release_port(eth_dev); 717 718 return 0; 719 } 720 721 static struct rte_vdev_driver pmd_null_drv = { 722 .probe = rte_pmd_null_probe, 723 .remove = rte_pmd_null_remove, 724 }; 725 726 RTE_PMD_REGISTER_VDEV(net_null, pmd_null_drv); 727 RTE_PMD_REGISTER_ALIAS(net_null, eth_null); 728 RTE_PMD_REGISTER_PARAM_STRING(net_null, 729 "size=<int> " 730 "copy=<int> " 731 ETH_NULL_PACKET_NO_RX_ARG "=0|1"); 732 733 RTE_INIT(eth_null_init_log) 734 { 735 eth_null_logtype = rte_log_register("pmd.net.null"); 736 if (eth_null_logtype >= 0) 737 rte_log_set_level(eth_null_logtype, RTE_LOG_NOTICE); 738 } 739