1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright (C) IGEL Co.,Ltd.
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>
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"
19 static unsigned int default_packet_size = 64;
20 static unsigned int default_packet_copy;
21 static unsigned int default_no_rx;
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,
33 struct pmd_internals *internals;
35 struct rte_mempool *mb_pool;
36 struct rte_mbuf *dummy_packet;
38 rte_atomic64_t rx_pkts;
39 rte_atomic64_t tx_pkts;
43 unsigned int packet_copy;
44 unsigned int packet_size;
48 struct pmd_internals {
49 unsigned int packet_size;
50 unsigned int packet_copy;
54 struct null_queue rx_null_queues[RTE_MAX_QUEUES_PER_PORT];
55 struct null_queue tx_null_queues[RTE_MAX_QUEUES_PER_PORT];
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;
61 rte_spinlock_t rss_lock;
64 struct rte_eth_rss_reta_entry64 reta_conf[ETH_RSS_RETA_SIZE_128 /
67 uint8_t rss_key[40]; /**< 40-byte hash key. */
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,
76 RTE_LOG_REGISTER(eth_null_logtype, pmd.net.null, NOTICE);
78 #define PMD_LOG(level, fmt, args...) \
79 rte_log(RTE_LOG_ ## level, eth_null_logtype, \
80 "%s(): " fmt "\n", __func__, ##args)
83 eth_null_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
86 struct null_queue *h = q;
87 unsigned int packet_size;
89 if ((q == NULL) || (bufs == NULL))
92 packet_size = h->internals->packet_size;
93 if (rte_pktmbuf_alloc_bulk(h->mb_pool, bufs, nb_bufs) != 0)
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;
102 rte_atomic64_add(&(h->rx_pkts), i);
108 eth_null_copy_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
111 struct null_queue *h = q;
112 unsigned int packet_size;
114 if ((q == NULL) || (bufs == NULL))
117 packet_size = h->internals->packet_size;
118 if (rte_pktmbuf_alloc_bulk(h->mb_pool, bufs, nb_bufs) != 0)
121 for (i = 0; i < nb_bufs; i++) {
122 rte_memcpy(rte_pktmbuf_mtod(bufs[i], void *), h->dummy_packet,
124 bufs[i]->data_len = (uint16_t)packet_size;
125 bufs[i]->pkt_len = packet_size;
126 bufs[i]->port = h->internals->port_id;
129 rte_atomic64_add(&(h->rx_pkts), i);
135 eth_null_no_rx(void *q __rte_unused, struct rte_mbuf **bufs __rte_unused,
136 uint16_t nb_bufs __rte_unused)
142 eth_null_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
145 struct null_queue *h = q;
147 if ((q == NULL) || (bufs == NULL))
150 for (i = 0; i < nb_bufs; i++)
151 rte_pktmbuf_free(bufs[i]);
153 rte_atomic64_add(&(h->tx_pkts), i);
159 eth_null_copy_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
162 struct null_queue *h = q;
163 unsigned int packet_size;
165 if ((q == NULL) || (bufs == NULL))
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 *),
172 rte_pktmbuf_free(bufs[i]);
175 rte_atomic64_add(&(h->tx_pkts), i);
181 eth_dev_configure(struct rte_eth_dev *dev __rte_unused)
187 eth_dev_start(struct rte_eth_dev *dev)
192 dev->data->dev_link.link_status = ETH_LINK_UP;
197 eth_dev_stop(struct rte_eth_dev *dev)
202 dev->data->dev_link.link_status = ETH_LINK_DOWN;
208 eth_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id,
209 uint16_t nb_rx_desc __rte_unused,
210 unsigned int socket_id __rte_unused,
211 const struct rte_eth_rxconf *rx_conf __rte_unused,
212 struct rte_mempool *mb_pool)
214 struct rte_mbuf *dummy_packet;
215 struct pmd_internals *internals;
216 unsigned int packet_size;
218 if ((dev == NULL) || (mb_pool == NULL))
221 internals = dev->data->dev_private;
223 if (rx_queue_id >= dev->data->nb_rx_queues)
226 packet_size = internals->packet_size;
228 internals->rx_null_queues[rx_queue_id].mb_pool = mb_pool;
229 dev->data->rx_queues[rx_queue_id] =
230 &internals->rx_null_queues[rx_queue_id];
231 dummy_packet = rte_zmalloc_socket(NULL,
232 packet_size, 0, dev->data->numa_node);
233 if (dummy_packet == NULL)
236 internals->rx_null_queues[rx_queue_id].internals = internals;
237 internals->rx_null_queues[rx_queue_id].dummy_packet = dummy_packet;
243 eth_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id,
244 uint16_t nb_tx_desc __rte_unused,
245 unsigned int socket_id __rte_unused,
246 const struct rte_eth_txconf *tx_conf __rte_unused)
248 struct rte_mbuf *dummy_packet;
249 struct pmd_internals *internals;
250 unsigned int packet_size;
255 internals = dev->data->dev_private;
257 if (tx_queue_id >= dev->data->nb_tx_queues)
260 packet_size = internals->packet_size;
262 dev->data->tx_queues[tx_queue_id] =
263 &internals->tx_null_queues[tx_queue_id];
264 dummy_packet = rte_zmalloc_socket(NULL,
265 packet_size, 0, dev->data->numa_node);
266 if (dummy_packet == NULL)
269 internals->tx_null_queues[tx_queue_id].internals = internals;
270 internals->tx_null_queues[tx_queue_id].dummy_packet = dummy_packet;
276 eth_mtu_set(struct rte_eth_dev *dev __rte_unused, uint16_t mtu __rte_unused)
282 eth_dev_info(struct rte_eth_dev *dev,
283 struct rte_eth_dev_info *dev_info)
285 struct pmd_internals *internals;
287 if ((dev == NULL) || (dev_info == NULL))
290 internals = dev->data->dev_private;
291 dev_info->max_mac_addrs = 1;
292 dev_info->max_rx_pktlen = (uint32_t)-1;
293 dev_info->max_rx_queues = RTE_DIM(internals->rx_null_queues);
294 dev_info->max_tx_queues = RTE_DIM(internals->tx_null_queues);
295 dev_info->min_rx_bufsize = 0;
296 dev_info->reta_size = internals->reta_size;
297 dev_info->flow_type_rss_offloads = internals->flow_type_rss_offloads;
303 eth_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *igb_stats)
305 unsigned int i, num_stats;
306 unsigned long rx_total = 0, tx_total = 0;
307 const struct pmd_internals *internal;
309 if ((dev == NULL) || (igb_stats == NULL))
312 internal = dev->data->dev_private;
313 num_stats = RTE_MIN((unsigned int)RTE_ETHDEV_QUEUE_STAT_CNTRS,
314 RTE_MIN(dev->data->nb_rx_queues,
315 RTE_DIM(internal->rx_null_queues)));
316 for (i = 0; i < num_stats; i++) {
317 igb_stats->q_ipackets[i] =
318 internal->rx_null_queues[i].rx_pkts.cnt;
319 rx_total += igb_stats->q_ipackets[i];
322 num_stats = RTE_MIN((unsigned int)RTE_ETHDEV_QUEUE_STAT_CNTRS,
323 RTE_MIN(dev->data->nb_tx_queues,
324 RTE_DIM(internal->tx_null_queues)));
325 for (i = 0; i < num_stats; i++) {
326 igb_stats->q_opackets[i] =
327 internal->tx_null_queues[i].tx_pkts.cnt;
328 tx_total += igb_stats->q_opackets[i];
331 igb_stats->ipackets = rx_total;
332 igb_stats->opackets = tx_total;
338 eth_stats_reset(struct rte_eth_dev *dev)
341 struct pmd_internals *internal;
346 internal = dev->data->dev_private;
347 for (i = 0; i < RTE_DIM(internal->rx_null_queues); i++)
348 internal->rx_null_queues[i].rx_pkts.cnt = 0;
349 for (i = 0; i < RTE_DIM(internal->tx_null_queues); i++)
350 internal->tx_null_queues[i].tx_pkts.cnt = 0;
356 eth_queue_release(void *q)
358 struct null_queue *nq;
364 rte_free(nq->dummy_packet);
368 eth_link_update(struct rte_eth_dev *dev __rte_unused,
369 int wait_to_complete __rte_unused) { return 0; }
372 eth_rss_reta_update(struct rte_eth_dev *dev,
373 struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size)
376 struct pmd_internals *internal = dev->data->dev_private;
378 if (reta_size != internal->reta_size)
381 rte_spinlock_lock(&internal->rss_lock);
383 /* Copy RETA table */
384 for (i = 0; i < (internal->reta_size / RTE_RETA_GROUP_SIZE); i++) {
385 internal->reta_conf[i].mask = reta_conf[i].mask;
386 for (j = 0; j < RTE_RETA_GROUP_SIZE; j++)
387 if ((reta_conf[i].mask >> j) & 0x01)
388 internal->reta_conf[i].reta[j] = reta_conf[i].reta[j];
391 rte_spinlock_unlock(&internal->rss_lock);
397 eth_rss_reta_query(struct rte_eth_dev *dev,
398 struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size)
401 struct pmd_internals *internal = dev->data->dev_private;
403 if (reta_size != internal->reta_size)
406 rte_spinlock_lock(&internal->rss_lock);
408 /* Copy RETA table */
409 for (i = 0; i < (internal->reta_size / RTE_RETA_GROUP_SIZE); i++) {
410 for (j = 0; j < RTE_RETA_GROUP_SIZE; j++)
411 if ((reta_conf[i].mask >> j) & 0x01)
412 reta_conf[i].reta[j] = internal->reta_conf[i].reta[j];
415 rte_spinlock_unlock(&internal->rss_lock);
421 eth_rss_hash_update(struct rte_eth_dev *dev, struct rte_eth_rss_conf *rss_conf)
423 struct pmd_internals *internal = dev->data->dev_private;
425 rte_spinlock_lock(&internal->rss_lock);
427 if ((rss_conf->rss_hf & internal->flow_type_rss_offloads) != 0)
428 dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf =
429 rss_conf->rss_hf & internal->flow_type_rss_offloads;
431 if (rss_conf->rss_key)
432 rte_memcpy(internal->rss_key, rss_conf->rss_key, 40);
434 rte_spinlock_unlock(&internal->rss_lock);
440 eth_rss_hash_conf_get(struct rte_eth_dev *dev,
441 struct rte_eth_rss_conf *rss_conf)
443 struct pmd_internals *internal = dev->data->dev_private;
445 rte_spinlock_lock(&internal->rss_lock);
447 rss_conf->rss_hf = dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf;
448 if (rss_conf->rss_key)
449 rte_memcpy(rss_conf->rss_key, internal->rss_key, 40);
451 rte_spinlock_unlock(&internal->rss_lock);
457 eth_mac_address_set(__rte_unused struct rte_eth_dev *dev,
458 __rte_unused struct rte_ether_addr *addr)
464 eth_dev_close(struct rte_eth_dev *dev)
466 PMD_LOG(INFO, "Closing null ethdev on NUMA socket %u",
469 if (rte_eal_process_type() != RTE_PROC_PRIMARY)
472 /* mac_addrs must not be freed alone because part of dev_private */
473 dev->data->mac_addrs = NULL;
478 static const struct eth_dev_ops ops = {
479 .dev_close = eth_dev_close,
480 .dev_start = eth_dev_start,
481 .dev_stop = eth_dev_stop,
482 .dev_configure = eth_dev_configure,
483 .dev_infos_get = eth_dev_info,
484 .rx_queue_setup = eth_rx_queue_setup,
485 .tx_queue_setup = eth_tx_queue_setup,
486 .rx_queue_release = eth_queue_release,
487 .tx_queue_release = eth_queue_release,
488 .mtu_set = eth_mtu_set,
489 .link_update = eth_link_update,
490 .mac_addr_set = eth_mac_address_set,
491 .stats_get = eth_stats_get,
492 .stats_reset = eth_stats_reset,
493 .reta_update = eth_rss_reta_update,
494 .reta_query = eth_rss_reta_query,
495 .rss_hash_update = eth_rss_hash_update,
496 .rss_hash_conf_get = eth_rss_hash_conf_get
500 eth_dev_null_create(struct rte_vdev_device *dev, struct pmd_options *args)
502 const unsigned int nb_rx_queues = 1;
503 const unsigned int nb_tx_queues = 1;
504 struct rte_eth_dev_data *data;
505 struct pmd_internals *internals = NULL;
506 struct rte_eth_dev *eth_dev = NULL;
508 static const uint8_t default_rss_key[40] = {
509 0x6D, 0x5A, 0x56, 0xDA, 0x25, 0x5B, 0x0E, 0xC2, 0x41, 0x67, 0x25, 0x3D,
510 0x43, 0xA3, 0x8F, 0xB0, 0xD0, 0xCA, 0x2B, 0xCB, 0xAE, 0x7B, 0x30, 0xB4,
511 0x77, 0xCB, 0x2D, 0xA3, 0x80, 0x30, 0xF2, 0x0C, 0x6A, 0x42, 0xB7, 0x3B,
512 0xBE, 0xAC, 0x01, 0xFA
515 if (dev->device.numa_node == SOCKET_ID_ANY)
516 dev->device.numa_node = rte_socket_id();
518 PMD_LOG(INFO, "Creating null ethdev on numa socket %u",
519 dev->device.numa_node);
521 eth_dev = rte_eth_vdev_allocate(dev, sizeof(*internals));
525 /* now put it all together
526 * - store queue data in internals,
527 * - store numa_node info in ethdev data
528 * - point eth_dev_data to internals
529 * - and point eth_dev structure to new eth_dev_data structure
531 /* NOTE: we'll replace the data element, of originally allocated eth_dev
532 * so the nulls are local per-process */
534 internals = eth_dev->data->dev_private;
535 internals->packet_size = args->packet_size;
536 internals->packet_copy = args->packet_copy;
537 internals->no_rx = args->no_rx;
538 internals->port_id = eth_dev->data->port_id;
539 rte_eth_random_addr(internals->eth_addr.addr_bytes);
541 internals->flow_type_rss_offloads = ETH_RSS_PROTO_MASK;
542 internals->reta_size = RTE_DIM(internals->reta_conf) * RTE_RETA_GROUP_SIZE;
544 rte_memcpy(internals->rss_key, default_rss_key, 40);
546 data = eth_dev->data;
547 data->nb_rx_queues = (uint16_t)nb_rx_queues;
548 data->nb_tx_queues = (uint16_t)nb_tx_queues;
549 data->dev_link = pmd_link;
550 data->mac_addrs = &internals->eth_addr;
551 data->promiscuous = 1;
552 data->all_multicast = 1;
553 data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS;
555 eth_dev->dev_ops = &ops;
557 /* finally assign rx and tx ops */
558 if (internals->packet_copy) {
559 eth_dev->rx_pkt_burst = eth_null_copy_rx;
560 eth_dev->tx_pkt_burst = eth_null_copy_tx;
561 } else if (internals->no_rx) {
562 eth_dev->rx_pkt_burst = eth_null_no_rx;
563 eth_dev->tx_pkt_burst = eth_null_tx;
565 eth_dev->rx_pkt_burst = eth_null_rx;
566 eth_dev->tx_pkt_burst = eth_null_tx;
569 rte_eth_dev_probing_finish(eth_dev);
574 get_packet_size_arg(const char *key __rte_unused,
575 const char *value, void *extra_args)
577 const char *a = value;
578 unsigned int *packet_size = extra_args;
580 if ((value == NULL) || (extra_args == NULL))
583 *packet_size = (unsigned int)strtoul(a, NULL, 0);
584 if (*packet_size == UINT_MAX)
591 get_packet_copy_arg(const char *key __rte_unused,
592 const char *value, void *extra_args)
594 const char *a = value;
595 unsigned int *packet_copy = extra_args;
597 if ((value == NULL) || (extra_args == NULL))
600 *packet_copy = (unsigned int)strtoul(a, NULL, 0);
601 if (*packet_copy == UINT_MAX)
608 get_packet_no_rx_arg(const char *key __rte_unused,
609 const char *value, void *extra_args)
611 const char *a = value;
614 if (value == NULL || extra_args == NULL)
617 no_rx = (unsigned int)strtoul(a, NULL, 0);
618 if (no_rx != 0 && no_rx != 1)
621 *(unsigned int *)extra_args = no_rx;
626 rte_pmd_null_probe(struct rte_vdev_device *dev)
628 const char *name, *params;
629 struct pmd_options args = {
630 .packet_copy = default_packet_copy,
631 .packet_size = default_packet_size,
632 .no_rx = default_no_rx,
634 struct rte_kvargs *kvlist = NULL;
635 struct rte_eth_dev *eth_dev;
641 name = rte_vdev_device_name(dev);
642 params = rte_vdev_device_args(dev);
643 PMD_LOG(INFO, "Initializing pmd_null for %s", name);
645 if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
646 struct pmd_internals *internals;
647 eth_dev = rte_eth_dev_attach_secondary(name);
649 PMD_LOG(ERR, "Failed to probe %s", name);
652 /* TODO: request info from primary to set up Rx and Tx */
653 eth_dev->dev_ops = &ops;
654 eth_dev->device = &dev->device;
655 internals = eth_dev->data->dev_private;
656 if (internals->packet_copy) {
657 eth_dev->rx_pkt_burst = eth_null_copy_rx;
658 eth_dev->tx_pkt_burst = eth_null_copy_tx;
659 } else if (internals->no_rx) {
660 eth_dev->rx_pkt_burst = eth_null_no_rx;
661 eth_dev->tx_pkt_burst = eth_null_tx;
663 eth_dev->rx_pkt_burst = eth_null_rx;
664 eth_dev->tx_pkt_burst = eth_null_tx;
666 rte_eth_dev_probing_finish(eth_dev);
670 if (params != NULL) {
671 kvlist = rte_kvargs_parse(params, valid_arguments);
675 ret = rte_kvargs_process(kvlist,
676 ETH_NULL_PACKET_SIZE_ARG,
677 &get_packet_size_arg, &args.packet_size);
682 ret = rte_kvargs_process(kvlist,
683 ETH_NULL_PACKET_COPY_ARG,
684 &get_packet_copy_arg, &args.packet_copy);
688 ret = rte_kvargs_process(kvlist,
689 ETH_NULL_PACKET_NO_RX_ARG,
690 &get_packet_no_rx_arg, &args.no_rx);
694 if (args.no_rx && args.packet_copy) {
696 "Both %s and %s arguments at the same time not supported",
697 ETH_NULL_PACKET_COPY_ARG,
698 ETH_NULL_PACKET_NO_RX_ARG);
703 PMD_LOG(INFO, "Configure pmd_null: packet size is %d, "
704 "packet copy is %s", args.packet_size,
705 args.packet_copy ? "enabled" : "disabled");
707 ret = eth_dev_null_create(dev, &args);
711 rte_kvargs_free(kvlist);
716 rte_pmd_null_remove(struct rte_vdev_device *dev)
718 struct rte_eth_dev *eth_dev = NULL;
723 /* find the ethdev entry */
724 eth_dev = rte_eth_dev_allocated(rte_vdev_device_name(dev));
726 return 0; /* port already released */
728 eth_dev_close(eth_dev);
729 rte_eth_dev_release_port(eth_dev);
734 static struct rte_vdev_driver pmd_null_drv = {
735 .probe = rte_pmd_null_probe,
736 .remove = rte_pmd_null_remove,
739 RTE_PMD_REGISTER_VDEV(net_null, pmd_null_drv);
740 RTE_PMD_REGISTER_ALIAS(net_null, eth_null);
741 RTE_PMD_REGISTER_PARAM_STRING(net_null,
744 ETH_NULL_PACKET_NO_RX_ARG "=0|1");