1b3b413f7SBruce Richardson /*- 2b3b413f7SBruce Richardson * BSD LICENSE 3b3b413f7SBruce Richardson * 4b3b413f7SBruce Richardson * Copyright (C) IGEL Co.,Ltd. 5b3b413f7SBruce Richardson * All rights reserved. 6b3b413f7SBruce Richardson * 7b3b413f7SBruce Richardson * Redistribution and use in source and binary forms, with or without 8b3b413f7SBruce Richardson * modification, are permitted provided that the following conditions 9b3b413f7SBruce Richardson * are met: 10b3b413f7SBruce Richardson * 11b3b413f7SBruce Richardson * * Redistributions of source code must retain the above copyright 12b3b413f7SBruce Richardson * notice, this list of conditions and the following disclaimer. 13b3b413f7SBruce Richardson * * Redistributions in binary form must reproduce the above copyright 14b3b413f7SBruce Richardson * notice, this list of conditions and the following disclaimer in 15b3b413f7SBruce Richardson * the documentation and/or other materials provided with the 16b3b413f7SBruce Richardson * distribution. 17b3b413f7SBruce Richardson * * Neither the name of IGEL Co.,Ltd. nor the names of its 18b3b413f7SBruce Richardson * contributors may be used to endorse or promote products derived 19b3b413f7SBruce Richardson * from this software without specific prior written permission. 20b3b413f7SBruce Richardson * 21b3b413f7SBruce Richardson * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22b3b413f7SBruce Richardson * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23b3b413f7SBruce Richardson * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24b3b413f7SBruce Richardson * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25b3b413f7SBruce Richardson * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26b3b413f7SBruce Richardson * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27b3b413f7SBruce Richardson * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28b3b413f7SBruce Richardson * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29b3b413f7SBruce Richardson * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30b3b413f7SBruce Richardson * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31b3b413f7SBruce Richardson * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32b3b413f7SBruce Richardson */ 33b3b413f7SBruce Richardson 34b3b413f7SBruce Richardson #include <rte_mbuf.h> 35ffc905f3SFerruh Yigit #include <rte_ethdev_driver.h> 36050fe6e9SJan Blunck #include <rte_ethdev_vdev.h> 37b3b413f7SBruce Richardson #include <rte_malloc.h> 38b3b413f7SBruce Richardson #include <rte_memcpy.h> 39d4a586d2SJianfeng Tan #include <rte_bus_vdev.h> 40b3b413f7SBruce Richardson #include <rte_kvargs.h> 411ccec0a8STomasz Kulasek #include <rte_spinlock.h> 42b3b413f7SBruce Richardson 43b3b413f7SBruce Richardson #define ETH_NULL_PACKET_SIZE_ARG "size" 44b3b413f7SBruce Richardson #define ETH_NULL_PACKET_COPY_ARG "copy" 45b3b413f7SBruce Richardson 46b3b413f7SBruce Richardson static unsigned default_packet_size = 64; 47b3b413f7SBruce Richardson static unsigned default_packet_copy; 48b3b413f7SBruce Richardson 49b3b413f7SBruce Richardson static const char *valid_arguments[] = { 50b3b413f7SBruce Richardson ETH_NULL_PACKET_SIZE_ARG, 51b3b413f7SBruce Richardson ETH_NULL_PACKET_COPY_ARG, 52b3b413f7SBruce Richardson NULL 53b3b413f7SBruce Richardson }; 54b3b413f7SBruce Richardson 55b3b413f7SBruce Richardson struct pmd_internals; 56b3b413f7SBruce Richardson 57b3b413f7SBruce Richardson struct null_queue { 58b3b413f7SBruce Richardson struct pmd_internals *internals; 59b3b413f7SBruce Richardson 60b3b413f7SBruce Richardson struct rte_mempool *mb_pool; 61b3b413f7SBruce Richardson struct rte_mbuf *dummy_packet; 62b3b413f7SBruce Richardson 63b3b413f7SBruce Richardson rte_atomic64_t rx_pkts; 64b3b413f7SBruce Richardson rte_atomic64_t tx_pkts; 65b3b413f7SBruce Richardson rte_atomic64_t err_pkts; 66b3b413f7SBruce Richardson }; 67b3b413f7SBruce Richardson 68b3b413f7SBruce Richardson struct pmd_internals { 69b3b413f7SBruce Richardson unsigned packet_size; 70b3b413f7SBruce Richardson unsigned packet_copy; 71f8244c63SZhiyong Yang uint16_t port_id; 72b3b413f7SBruce Richardson 73dd7c54a6STomasz Kulasek struct null_queue rx_null_queues[RTE_MAX_QUEUES_PER_PORT]; 74dd7c54a6STomasz Kulasek struct null_queue tx_null_queues[RTE_MAX_QUEUES_PER_PORT]; 751ccec0a8STomasz Kulasek 761ccec0a8STomasz Kulasek /** Bit mask of RSS offloads, the bit offset also means flow type */ 771ccec0a8STomasz Kulasek uint64_t flow_type_rss_offloads; 781ccec0a8STomasz Kulasek 791ccec0a8STomasz Kulasek rte_spinlock_t rss_lock; 801ccec0a8STomasz Kulasek 811ccec0a8STomasz Kulasek uint16_t reta_size; 821ccec0a8STomasz Kulasek struct rte_eth_rss_reta_entry64 reta_conf[ETH_RSS_RETA_SIZE_128 / 831ccec0a8STomasz Kulasek RTE_RETA_GROUP_SIZE]; 841ccec0a8STomasz Kulasek 851ccec0a8STomasz Kulasek uint8_t rss_key[40]; /**< 40-byte hash key. */ 86b3b413f7SBruce Richardson }; 87b3b413f7SBruce Richardson 88b3b413f7SBruce Richardson 89b3b413f7SBruce Richardson static struct ether_addr eth_addr = { .addr_bytes = {0} }; 90b3b413f7SBruce Richardson static struct rte_eth_link pmd_link = { 9139fd068aSMarc Sune .link_speed = ETH_SPEED_NUM_10G, 92b3b413f7SBruce Richardson .link_duplex = ETH_LINK_FULL_DUPLEX, 9309419f23SThomas Monjalon .link_status = ETH_LINK_DOWN, 941e3a958fSThomas Monjalon .link_autoneg = ETH_LINK_AUTONEG, 95b3b413f7SBruce Richardson }; 96b3b413f7SBruce Richardson 97b3b413f7SBruce Richardson static uint16_t 98b3b413f7SBruce Richardson eth_null_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs) 99b3b413f7SBruce Richardson { 100b3b413f7SBruce Richardson int i; 101b3b413f7SBruce Richardson struct null_queue *h = q; 102b3b413f7SBruce Richardson unsigned packet_size; 103b3b413f7SBruce Richardson 104b3b413f7SBruce Richardson if ((q == NULL) || (bufs == NULL)) 105b3b413f7SBruce Richardson return 0; 106b3b413f7SBruce Richardson 107b3b413f7SBruce Richardson packet_size = h->internals->packet_size; 108b3b413f7SBruce Richardson for (i = 0; i < nb_bufs; i++) { 109b3b413f7SBruce Richardson bufs[i] = rte_pktmbuf_alloc(h->mb_pool); 110b3b413f7SBruce Richardson if (!bufs[i]) 111b3b413f7SBruce Richardson break; 112b3b413f7SBruce Richardson bufs[i]->data_len = (uint16_t)packet_size; 113b3b413f7SBruce Richardson bufs[i]->pkt_len = packet_size; 1145cf86418SSean Harte bufs[i]->port = h->internals->port_id; 115b3b413f7SBruce Richardson } 116b3b413f7SBruce Richardson 117b3b413f7SBruce Richardson rte_atomic64_add(&(h->rx_pkts), i); 118b3b413f7SBruce Richardson 119b3b413f7SBruce Richardson return i; 120b3b413f7SBruce Richardson } 121b3b413f7SBruce Richardson 122b3b413f7SBruce Richardson static uint16_t 123b3b413f7SBruce Richardson eth_null_copy_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs) 124b3b413f7SBruce Richardson { 125b3b413f7SBruce Richardson int i; 126b3b413f7SBruce Richardson struct null_queue *h = q; 127b3b413f7SBruce Richardson unsigned packet_size; 128b3b413f7SBruce Richardson 129b3b413f7SBruce Richardson if ((q == NULL) || (bufs == NULL)) 130b3b413f7SBruce Richardson return 0; 131b3b413f7SBruce Richardson 132b3b413f7SBruce Richardson packet_size = h->internals->packet_size; 133b3b413f7SBruce Richardson for (i = 0; i < nb_bufs; i++) { 134b3b413f7SBruce Richardson bufs[i] = rte_pktmbuf_alloc(h->mb_pool); 135b3b413f7SBruce Richardson if (!bufs[i]) 136b3b413f7SBruce Richardson break; 137b3b413f7SBruce Richardson rte_memcpy(rte_pktmbuf_mtod(bufs[i], void *), h->dummy_packet, 138b3b413f7SBruce Richardson packet_size); 139b3b413f7SBruce Richardson bufs[i]->data_len = (uint16_t)packet_size; 140b3b413f7SBruce Richardson bufs[i]->pkt_len = packet_size; 1415cf86418SSean Harte bufs[i]->port = h->internals->port_id; 142b3b413f7SBruce Richardson } 143b3b413f7SBruce Richardson 144b3b413f7SBruce Richardson rte_atomic64_add(&(h->rx_pkts), i); 145b3b413f7SBruce Richardson 146b3b413f7SBruce Richardson return i; 147b3b413f7SBruce Richardson } 148b3b413f7SBruce Richardson 149b3b413f7SBruce Richardson static uint16_t 150b3b413f7SBruce Richardson eth_null_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs) 151b3b413f7SBruce Richardson { 152b3b413f7SBruce Richardson int i; 153b3b413f7SBruce Richardson struct null_queue *h = q; 154b3b413f7SBruce Richardson 155b3b413f7SBruce Richardson if ((q == NULL) || (bufs == NULL)) 156b3b413f7SBruce Richardson return 0; 157b3b413f7SBruce Richardson 158b3b413f7SBruce Richardson for (i = 0; i < nb_bufs; i++) 159b3b413f7SBruce Richardson rte_pktmbuf_free(bufs[i]); 160b3b413f7SBruce Richardson 161b3b413f7SBruce Richardson rte_atomic64_add(&(h->tx_pkts), i); 162b3b413f7SBruce Richardson 163b3b413f7SBruce Richardson return i; 164b3b413f7SBruce Richardson } 165b3b413f7SBruce Richardson 166b3b413f7SBruce Richardson static uint16_t 167b3b413f7SBruce Richardson eth_null_copy_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs) 168b3b413f7SBruce Richardson { 169b3b413f7SBruce Richardson int i; 170b3b413f7SBruce Richardson struct null_queue *h = q; 171b3b413f7SBruce Richardson unsigned packet_size; 172b3b413f7SBruce Richardson 173b3b413f7SBruce Richardson if ((q == NULL) || (bufs == NULL)) 174b3b413f7SBruce Richardson return 0; 175b3b413f7SBruce Richardson 176b3b413f7SBruce Richardson packet_size = h->internals->packet_size; 177b3b413f7SBruce Richardson for (i = 0; i < nb_bufs; i++) { 178b3b413f7SBruce Richardson rte_memcpy(h->dummy_packet, rte_pktmbuf_mtod(bufs[i], void *), 179b3b413f7SBruce Richardson packet_size); 180b3b413f7SBruce Richardson rte_pktmbuf_free(bufs[i]); 181b3b413f7SBruce Richardson } 182b3b413f7SBruce Richardson 183b3b413f7SBruce Richardson rte_atomic64_add(&(h->tx_pkts), i); 184b3b413f7SBruce Richardson 185b3b413f7SBruce Richardson return i; 186b3b413f7SBruce Richardson } 187b3b413f7SBruce Richardson 188b3b413f7SBruce Richardson static int 189c9634e44SFerruh Yigit eth_dev_configure(struct rte_eth_dev *dev __rte_unused) 190c9634e44SFerruh Yigit { 191dd7c54a6STomasz Kulasek return 0; 192dd7c54a6STomasz Kulasek } 193b3b413f7SBruce Richardson 194b3b413f7SBruce Richardson static int 195b3b413f7SBruce Richardson eth_dev_start(struct rte_eth_dev *dev) 196b3b413f7SBruce Richardson { 197b3b413f7SBruce Richardson if (dev == NULL) 198b3b413f7SBruce Richardson return -EINVAL; 199b3b413f7SBruce Richardson 20009419f23SThomas Monjalon dev->data->dev_link.link_status = ETH_LINK_UP; 201b3b413f7SBruce Richardson return 0; 202b3b413f7SBruce Richardson } 203b3b413f7SBruce Richardson 204b3b413f7SBruce Richardson static void 205b3b413f7SBruce Richardson eth_dev_stop(struct rte_eth_dev *dev) 206b3b413f7SBruce Richardson { 207b3b413f7SBruce Richardson if (dev == NULL) 208b3b413f7SBruce Richardson return; 209b3b413f7SBruce Richardson 21009419f23SThomas Monjalon dev->data->dev_link.link_status = ETH_LINK_DOWN; 211b3b413f7SBruce Richardson } 212b3b413f7SBruce Richardson 213b3b413f7SBruce Richardson static int 214b3b413f7SBruce Richardson eth_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id, 215b3b413f7SBruce Richardson uint16_t nb_rx_desc __rte_unused, 216b3b413f7SBruce Richardson unsigned int socket_id __rte_unused, 217b3b413f7SBruce Richardson const struct rte_eth_rxconf *rx_conf __rte_unused, 218b3b413f7SBruce Richardson struct rte_mempool *mb_pool) 219b3b413f7SBruce Richardson { 220b3b413f7SBruce Richardson struct rte_mbuf *dummy_packet; 221b3b413f7SBruce Richardson struct pmd_internals *internals; 222b3b413f7SBruce Richardson unsigned packet_size; 223b3b413f7SBruce Richardson 224b3b413f7SBruce Richardson if ((dev == NULL) || (mb_pool == NULL)) 225b3b413f7SBruce Richardson return -EINVAL; 226b3b413f7SBruce Richardson 227dd7c54a6STomasz Kulasek internals = dev->data->dev_private; 228dd7c54a6STomasz Kulasek 229c9634e44SFerruh Yigit if (rx_queue_id >= dev->data->nb_rx_queues) 230b3b413f7SBruce Richardson return -ENODEV; 231b3b413f7SBruce Richardson 232b3b413f7SBruce Richardson packet_size = internals->packet_size; 233b3b413f7SBruce Richardson 234b3b413f7SBruce Richardson internals->rx_null_queues[rx_queue_id].mb_pool = mb_pool; 235b3b413f7SBruce Richardson dev->data->rx_queues[rx_queue_id] = 236b3b413f7SBruce Richardson &internals->rx_null_queues[rx_queue_id]; 237b3b413f7SBruce Richardson dummy_packet = rte_zmalloc_socket(NULL, 238c9634e44SFerruh Yigit packet_size, 0, dev->data->numa_node); 239b3b413f7SBruce Richardson if (dummy_packet == NULL) 240b3b413f7SBruce Richardson return -ENOMEM; 241b3b413f7SBruce Richardson 242b3b413f7SBruce Richardson internals->rx_null_queues[rx_queue_id].internals = internals; 243b3b413f7SBruce Richardson internals->rx_null_queues[rx_queue_id].dummy_packet = dummy_packet; 244b3b413f7SBruce Richardson 245b3b413f7SBruce Richardson return 0; 246b3b413f7SBruce Richardson } 247b3b413f7SBruce Richardson 248b3b413f7SBruce Richardson static int 249b3b413f7SBruce Richardson eth_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id, 250b3b413f7SBruce Richardson uint16_t nb_tx_desc __rte_unused, 251b3b413f7SBruce Richardson unsigned int socket_id __rte_unused, 252b3b413f7SBruce Richardson const struct rte_eth_txconf *tx_conf __rte_unused) 253b3b413f7SBruce Richardson { 254b3b413f7SBruce Richardson struct rte_mbuf *dummy_packet; 255b3b413f7SBruce Richardson struct pmd_internals *internals; 256b3b413f7SBruce Richardson unsigned packet_size; 257b3b413f7SBruce Richardson 258b3b413f7SBruce Richardson if (dev == NULL) 259b3b413f7SBruce Richardson return -EINVAL; 260b3b413f7SBruce Richardson 261dd7c54a6STomasz Kulasek internals = dev->data->dev_private; 262dd7c54a6STomasz Kulasek 263c9634e44SFerruh Yigit if (tx_queue_id >= dev->data->nb_tx_queues) 264b3b413f7SBruce Richardson return -ENODEV; 265b3b413f7SBruce Richardson 266b3b413f7SBruce Richardson packet_size = internals->packet_size; 267b3b413f7SBruce Richardson 268b3b413f7SBruce Richardson dev->data->tx_queues[tx_queue_id] = 269b3b413f7SBruce Richardson &internals->tx_null_queues[tx_queue_id]; 270b3b413f7SBruce Richardson dummy_packet = rte_zmalloc_socket(NULL, 271c9634e44SFerruh Yigit packet_size, 0, dev->data->numa_node); 272b3b413f7SBruce Richardson if (dummy_packet == NULL) 273b3b413f7SBruce Richardson return -ENOMEM; 274b3b413f7SBruce Richardson 275b3b413f7SBruce Richardson internals->tx_null_queues[tx_queue_id].internals = internals; 276b3b413f7SBruce Richardson internals->tx_null_queues[tx_queue_id].dummy_packet = dummy_packet; 277b3b413f7SBruce Richardson 278b3b413f7SBruce Richardson return 0; 279b3b413f7SBruce Richardson } 280b3b413f7SBruce Richardson 281e6acdc77SMallesh Koujalagi static int 282e6acdc77SMallesh Koujalagi eth_mtu_set(struct rte_eth_dev *dev __rte_unused, uint16_t mtu __rte_unused) 283e6acdc77SMallesh Koujalagi { 284e6acdc77SMallesh Koujalagi return 0; 285e6acdc77SMallesh Koujalagi } 286b3b413f7SBruce Richardson 287b3b413f7SBruce Richardson static void 288b3b413f7SBruce Richardson eth_dev_info(struct rte_eth_dev *dev, 289b3b413f7SBruce Richardson struct rte_eth_dev_info *dev_info) 290b3b413f7SBruce Richardson { 291b3b413f7SBruce Richardson struct pmd_internals *internals; 292b3b413f7SBruce Richardson 293b3b413f7SBruce Richardson if ((dev == NULL) || (dev_info == NULL)) 294b3b413f7SBruce Richardson return; 295b3b413f7SBruce Richardson 296b3b413f7SBruce Richardson internals = dev->data->dev_private; 297b3b413f7SBruce Richardson dev_info->max_mac_addrs = 1; 298b3b413f7SBruce Richardson dev_info->max_rx_pktlen = (uint32_t)-1; 299dd7c54a6STomasz Kulasek dev_info->max_rx_queues = RTE_DIM(internals->rx_null_queues); 300dd7c54a6STomasz Kulasek dev_info->max_tx_queues = RTE_DIM(internals->tx_null_queues); 301b3b413f7SBruce Richardson dev_info->min_rx_bufsize = 0; 3021ccec0a8STomasz Kulasek dev_info->reta_size = internals->reta_size; 3031ccec0a8STomasz Kulasek dev_info->flow_type_rss_offloads = internals->flow_type_rss_offloads; 304b3b413f7SBruce Richardson } 305b3b413f7SBruce Richardson 306d5b0924bSMatan Azrad static int 307b3b413f7SBruce Richardson eth_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *igb_stats) 308b3b413f7SBruce Richardson { 309b3b413f7SBruce Richardson unsigned i, num_stats; 310b3b413f7SBruce Richardson unsigned long rx_total = 0, tx_total = 0, tx_err_total = 0; 311b3b413f7SBruce Richardson const struct pmd_internals *internal; 312b3b413f7SBruce Richardson 313b3b413f7SBruce Richardson if ((dev == NULL) || (igb_stats == NULL)) 314d5b0924bSMatan Azrad return -EINVAL; 315b3b413f7SBruce Richardson 316b3b413f7SBruce Richardson internal = dev->data->dev_private; 317b3b413f7SBruce Richardson num_stats = RTE_MIN((unsigned)RTE_ETHDEV_QUEUE_STAT_CNTRS, 318c9634e44SFerruh Yigit RTE_MIN(dev->data->nb_rx_queues, 319b34141b2SBruce Richardson RTE_DIM(internal->rx_null_queues))); 320b3b413f7SBruce Richardson for (i = 0; i < num_stats; i++) { 321b3b413f7SBruce Richardson igb_stats->q_ipackets[i] = 322b3b413f7SBruce Richardson internal->rx_null_queues[i].rx_pkts.cnt; 323b3b413f7SBruce Richardson rx_total += igb_stats->q_ipackets[i]; 324b3b413f7SBruce Richardson } 325b3b413f7SBruce Richardson 326b3b413f7SBruce Richardson num_stats = RTE_MIN((unsigned)RTE_ETHDEV_QUEUE_STAT_CNTRS, 327c9634e44SFerruh Yigit RTE_MIN(dev->data->nb_tx_queues, 328b34141b2SBruce Richardson RTE_DIM(internal->tx_null_queues))); 329b3b413f7SBruce Richardson for (i = 0; i < num_stats; i++) { 330b3b413f7SBruce Richardson igb_stats->q_opackets[i] = 331b3b413f7SBruce Richardson internal->tx_null_queues[i].tx_pkts.cnt; 332b3b413f7SBruce Richardson igb_stats->q_errors[i] = 333b3b413f7SBruce Richardson internal->tx_null_queues[i].err_pkts.cnt; 334b3b413f7SBruce Richardson tx_total += igb_stats->q_opackets[i]; 335b3b413f7SBruce Richardson tx_err_total += igb_stats->q_errors[i]; 336b3b413f7SBruce Richardson } 337b3b413f7SBruce Richardson 338b3b413f7SBruce Richardson igb_stats->ipackets = rx_total; 339b3b413f7SBruce Richardson igb_stats->opackets = tx_total; 340b3b413f7SBruce Richardson igb_stats->oerrors = tx_err_total; 341d5b0924bSMatan Azrad 342d5b0924bSMatan Azrad return 0; 343b3b413f7SBruce Richardson } 344b3b413f7SBruce Richardson 345b3b413f7SBruce Richardson static void 346b3b413f7SBruce Richardson eth_stats_reset(struct rte_eth_dev *dev) 347b3b413f7SBruce Richardson { 348b3b413f7SBruce Richardson unsigned i; 349b3b413f7SBruce Richardson struct pmd_internals *internal; 350b3b413f7SBruce Richardson 351b3b413f7SBruce Richardson if (dev == NULL) 352b3b413f7SBruce Richardson return; 353b3b413f7SBruce Richardson 354b3b413f7SBruce Richardson internal = dev->data->dev_private; 355b34141b2SBruce Richardson for (i = 0; i < RTE_DIM(internal->rx_null_queues); i++) 356b3b413f7SBruce Richardson internal->rx_null_queues[i].rx_pkts.cnt = 0; 357b34141b2SBruce Richardson for (i = 0; i < RTE_DIM(internal->tx_null_queues); i++) { 358b3b413f7SBruce Richardson internal->tx_null_queues[i].tx_pkts.cnt = 0; 359b3b413f7SBruce Richardson internal->tx_null_queues[i].err_pkts.cnt = 0; 360b3b413f7SBruce Richardson } 361b3b413f7SBruce Richardson } 362b3b413f7SBruce Richardson 363b3b413f7SBruce Richardson static void 364b3b413f7SBruce Richardson eth_queue_release(void *q) 365b3b413f7SBruce Richardson { 366b3b413f7SBruce Richardson struct null_queue *nq; 367b3b413f7SBruce Richardson 368b3b413f7SBruce Richardson if (q == NULL) 369b3b413f7SBruce Richardson return; 370b3b413f7SBruce Richardson 371b3b413f7SBruce Richardson nq = q; 372b3b413f7SBruce Richardson rte_free(nq->dummy_packet); 373b3b413f7SBruce Richardson } 374b3b413f7SBruce Richardson 375b3b413f7SBruce Richardson static int 376b3b413f7SBruce Richardson eth_link_update(struct rte_eth_dev *dev __rte_unused, 377b3b413f7SBruce Richardson int wait_to_complete __rte_unused) { return 0; } 378b3b413f7SBruce Richardson 3791ccec0a8STomasz Kulasek static int 3801ccec0a8STomasz Kulasek eth_rss_reta_update(struct rte_eth_dev *dev, 3811ccec0a8STomasz Kulasek struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size) 3821ccec0a8STomasz Kulasek { 3831ccec0a8STomasz Kulasek int i, j; 3841ccec0a8STomasz Kulasek struct pmd_internals *internal = dev->data->dev_private; 3851ccec0a8STomasz Kulasek 3861ccec0a8STomasz Kulasek if (reta_size != internal->reta_size) 3871ccec0a8STomasz Kulasek return -EINVAL; 3881ccec0a8STomasz Kulasek 3891ccec0a8STomasz Kulasek rte_spinlock_lock(&internal->rss_lock); 3901ccec0a8STomasz Kulasek 3911ccec0a8STomasz Kulasek /* Copy RETA table */ 3921ccec0a8STomasz Kulasek for (i = 0; i < (internal->reta_size / RTE_RETA_GROUP_SIZE); i++) { 3931ccec0a8STomasz Kulasek internal->reta_conf[i].mask = reta_conf[i].mask; 3941ccec0a8STomasz Kulasek for (j = 0; j < RTE_RETA_GROUP_SIZE; j++) 3951ccec0a8STomasz Kulasek if ((reta_conf[i].mask >> j) & 0x01) 3961ccec0a8STomasz Kulasek internal->reta_conf[i].reta[j] = reta_conf[i].reta[j]; 3971ccec0a8STomasz Kulasek } 3981ccec0a8STomasz Kulasek 3991ccec0a8STomasz Kulasek rte_spinlock_unlock(&internal->rss_lock); 4001ccec0a8STomasz Kulasek 4011ccec0a8STomasz Kulasek return 0; 4021ccec0a8STomasz Kulasek } 4031ccec0a8STomasz Kulasek 4041ccec0a8STomasz Kulasek static int 4051ccec0a8STomasz Kulasek eth_rss_reta_query(struct rte_eth_dev *dev, 4061ccec0a8STomasz Kulasek struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size) 4071ccec0a8STomasz Kulasek { 4081ccec0a8STomasz Kulasek int i, j; 4091ccec0a8STomasz Kulasek struct pmd_internals *internal = dev->data->dev_private; 4101ccec0a8STomasz Kulasek 4111ccec0a8STomasz Kulasek if (reta_size != internal->reta_size) 4121ccec0a8STomasz Kulasek return -EINVAL; 4131ccec0a8STomasz Kulasek 4141ccec0a8STomasz Kulasek rte_spinlock_lock(&internal->rss_lock); 4151ccec0a8STomasz Kulasek 4161ccec0a8STomasz Kulasek /* Copy RETA table */ 4171ccec0a8STomasz Kulasek for (i = 0; i < (internal->reta_size / RTE_RETA_GROUP_SIZE); i++) { 4181ccec0a8STomasz Kulasek for (j = 0; j < RTE_RETA_GROUP_SIZE; j++) 4191ccec0a8STomasz Kulasek if ((reta_conf[i].mask >> j) & 0x01) 4201ccec0a8STomasz Kulasek reta_conf[i].reta[j] = internal->reta_conf[i].reta[j]; 4211ccec0a8STomasz Kulasek } 4221ccec0a8STomasz Kulasek 4231ccec0a8STomasz Kulasek rte_spinlock_unlock(&internal->rss_lock); 4241ccec0a8STomasz Kulasek 4251ccec0a8STomasz Kulasek return 0; 4261ccec0a8STomasz Kulasek } 4271ccec0a8STomasz Kulasek 4281ccec0a8STomasz Kulasek static int 4291ccec0a8STomasz Kulasek eth_rss_hash_update(struct rte_eth_dev *dev, struct rte_eth_rss_conf *rss_conf) 4301ccec0a8STomasz Kulasek { 4311ccec0a8STomasz Kulasek struct pmd_internals *internal = dev->data->dev_private; 4321ccec0a8STomasz Kulasek 4331ccec0a8STomasz Kulasek rte_spinlock_lock(&internal->rss_lock); 4341ccec0a8STomasz Kulasek 4351ccec0a8STomasz Kulasek if ((rss_conf->rss_hf & internal->flow_type_rss_offloads) != 0) 4361ccec0a8STomasz Kulasek dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf = 4371ccec0a8STomasz Kulasek rss_conf->rss_hf & internal->flow_type_rss_offloads; 4381ccec0a8STomasz Kulasek 4391ccec0a8STomasz Kulasek if (rss_conf->rss_key) 4401ccec0a8STomasz Kulasek rte_memcpy(internal->rss_key, rss_conf->rss_key, 40); 4411ccec0a8STomasz Kulasek 4421ccec0a8STomasz Kulasek rte_spinlock_unlock(&internal->rss_lock); 4431ccec0a8STomasz Kulasek 4441ccec0a8STomasz Kulasek return 0; 4451ccec0a8STomasz Kulasek } 4461ccec0a8STomasz Kulasek 4471ccec0a8STomasz Kulasek static int 4481ccec0a8STomasz Kulasek eth_rss_hash_conf_get(struct rte_eth_dev *dev, 4491ccec0a8STomasz Kulasek struct rte_eth_rss_conf *rss_conf) 4501ccec0a8STomasz Kulasek { 4511ccec0a8STomasz Kulasek struct pmd_internals *internal = dev->data->dev_private; 4521ccec0a8STomasz Kulasek 4531ccec0a8STomasz Kulasek rte_spinlock_lock(&internal->rss_lock); 4541ccec0a8STomasz Kulasek 4551ccec0a8STomasz Kulasek rss_conf->rss_hf = dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf; 4561ccec0a8STomasz Kulasek if (rss_conf->rss_key) 4571ccec0a8STomasz Kulasek rte_memcpy(rss_conf->rss_key, internal->rss_key, 40); 4581ccec0a8STomasz Kulasek 4591ccec0a8STomasz Kulasek rte_spinlock_unlock(&internal->rss_lock); 4601ccec0a8STomasz Kulasek 4611ccec0a8STomasz Kulasek return 0; 4621ccec0a8STomasz Kulasek } 4631ccec0a8STomasz Kulasek 464*c5ac7748SRadu Nicolau static void 465*c5ac7748SRadu Nicolau eth_mac_address_set(__rte_unused struct rte_eth_dev *dev, 466*c5ac7748SRadu Nicolau __rte_unused struct ether_addr *addr) 467*c5ac7748SRadu Nicolau { 468*c5ac7748SRadu Nicolau } 469*c5ac7748SRadu Nicolau 470b3b413f7SBruce Richardson static const struct eth_dev_ops ops = { 471b3b413f7SBruce Richardson .dev_start = eth_dev_start, 472b3b413f7SBruce Richardson .dev_stop = eth_dev_stop, 473b3b413f7SBruce Richardson .dev_configure = eth_dev_configure, 474b3b413f7SBruce Richardson .dev_infos_get = eth_dev_info, 475b3b413f7SBruce Richardson .rx_queue_setup = eth_rx_queue_setup, 476b3b413f7SBruce Richardson .tx_queue_setup = eth_tx_queue_setup, 477b3b413f7SBruce Richardson .rx_queue_release = eth_queue_release, 478b3b413f7SBruce Richardson .tx_queue_release = eth_queue_release, 479e6acdc77SMallesh Koujalagi .mtu_set = eth_mtu_set, 480b3b413f7SBruce Richardson .link_update = eth_link_update, 481*c5ac7748SRadu Nicolau .mac_addr_set = eth_mac_address_set, 482b3b413f7SBruce Richardson .stats_get = eth_stats_get, 483b3b413f7SBruce Richardson .stats_reset = eth_stats_reset, 4841ccec0a8STomasz Kulasek .reta_update = eth_rss_reta_update, 4851ccec0a8STomasz Kulasek .reta_query = eth_rss_reta_query, 4861ccec0a8STomasz Kulasek .rss_hash_update = eth_rss_hash_update, 4871ccec0a8STomasz Kulasek .rss_hash_conf_get = eth_rss_hash_conf_get 488b3b413f7SBruce Richardson }; 489b3b413f7SBruce Richardson 49073db5badSDavid Marchand static struct rte_vdev_driver pmd_null_drv; 49173db5badSDavid Marchand 492c3b047beSJan Blunck static int 493050fe6e9SJan Blunck eth_dev_null_create(struct rte_vdev_device *dev, 494b3b413f7SBruce Richardson unsigned packet_size, 495b3b413f7SBruce Richardson unsigned packet_copy) 496b3b413f7SBruce Richardson { 497b3b413f7SBruce Richardson const unsigned nb_rx_queues = 1; 498b3b413f7SBruce Richardson const unsigned nb_tx_queues = 1; 499b3b413f7SBruce Richardson struct rte_eth_dev_data *data = NULL; 500b3b413f7SBruce Richardson struct pmd_internals *internals = NULL; 501b3b413f7SBruce Richardson struct rte_eth_dev *eth_dev = NULL; 502b3b413f7SBruce Richardson 5031ccec0a8STomasz Kulasek static const uint8_t default_rss_key[40] = { 5041ccec0a8STomasz Kulasek 0x6D, 0x5A, 0x56, 0xDA, 0x25, 0x5B, 0x0E, 0xC2, 0x41, 0x67, 0x25, 0x3D, 5051ccec0a8STomasz Kulasek 0x43, 0xA3, 0x8F, 0xB0, 0xD0, 0xCA, 0x2B, 0xCB, 0xAE, 0x7B, 0x30, 0xB4, 5061ccec0a8STomasz Kulasek 0x77, 0xCB, 0x2D, 0xA3, 0x80, 0x30, 0xF2, 0x0C, 0x6A, 0x42, 0xB7, 0x3B, 5071ccec0a8STomasz Kulasek 0xBE, 0xAC, 0x01, 0xFA 5081ccec0a8STomasz Kulasek }; 5091ccec0a8STomasz Kulasek 510050fe6e9SJan Blunck if (dev->device.numa_node == SOCKET_ID_ANY) 511050fe6e9SJan Blunck dev->device.numa_node = rte_socket_id(); 512b3b413f7SBruce Richardson 513b3b413f7SBruce Richardson RTE_LOG(INFO, PMD, "Creating null ethdev on numa socket %u\n", 514050fe6e9SJan Blunck dev->device.numa_node); 515b3b413f7SBruce Richardson 516b3b413f7SBruce Richardson /* now do all data allocation - for eth_dev structure, dummy pci driver 517b3b413f7SBruce Richardson * and internal (private) data 518b3b413f7SBruce Richardson */ 519050fe6e9SJan Blunck data = rte_zmalloc_socket(rte_vdev_device_name(dev), sizeof(*data), 0, 520050fe6e9SJan Blunck dev->device.numa_node); 521050fe6e9SJan Blunck if (!data) 522050fe6e9SJan Blunck return -ENOMEM; 523b3b413f7SBruce Richardson 524050fe6e9SJan Blunck eth_dev = rte_eth_vdev_allocate(dev, sizeof(*internals)); 525050fe6e9SJan Blunck if (!eth_dev) { 526050fe6e9SJan Blunck rte_free(data); 527050fe6e9SJan Blunck return -ENOMEM; 528050fe6e9SJan Blunck } 529b3b413f7SBruce Richardson 530b3b413f7SBruce Richardson /* now put it all together 531b3b413f7SBruce Richardson * - store queue data in internals, 5328fb9e2bbSBernard Iremonger * - store numa_node info in ethdev data 5338fb9e2bbSBernard Iremonger * - point eth_dev_data to internals 534b3b413f7SBruce Richardson * - and point eth_dev structure to new eth_dev_data structure 535b3b413f7SBruce Richardson */ 536b3b413f7SBruce Richardson /* NOTE: we'll replace the data element, of originally allocated eth_dev 537b3b413f7SBruce Richardson * so the nulls are local per-process */ 538b3b413f7SBruce Richardson 539050fe6e9SJan Blunck internals = eth_dev->data->dev_private; 540b3b413f7SBruce Richardson internals->packet_size = packet_size; 541b3b413f7SBruce Richardson internals->packet_copy = packet_copy; 5425cf86418SSean Harte internals->port_id = eth_dev->data->port_id; 543b3b413f7SBruce Richardson 5441ccec0a8STomasz Kulasek internals->flow_type_rss_offloads = ETH_RSS_PROTO_MASK; 5451ccec0a8STomasz Kulasek internals->reta_size = RTE_DIM(internals->reta_conf) * RTE_RETA_GROUP_SIZE; 5461ccec0a8STomasz Kulasek 5471ccec0a8STomasz Kulasek rte_memcpy(internals->rss_key, default_rss_key, 40); 5481ccec0a8STomasz Kulasek 549050fe6e9SJan Blunck rte_memcpy(data, eth_dev->data, sizeof(*data)); 550b3b413f7SBruce Richardson data->nb_rx_queues = (uint16_t)nb_rx_queues; 551b3b413f7SBruce Richardson data->nb_tx_queues = (uint16_t)nb_tx_queues; 552b3b413f7SBruce Richardson data->dev_link = pmd_link; 553b3b413f7SBruce Richardson data->mac_addrs = ð_addr; 554b3b413f7SBruce Richardson 555b3b413f7SBruce Richardson eth_dev->data = data; 556b3b413f7SBruce Richardson eth_dev->dev_ops = &ops; 5576799cfe4SBernard Iremonger 558b3b413f7SBruce Richardson /* finally assign rx and tx ops */ 559b3b413f7SBruce Richardson if (packet_copy) { 560b3b413f7SBruce Richardson eth_dev->rx_pkt_burst = eth_null_copy_rx; 561b3b413f7SBruce Richardson eth_dev->tx_pkt_burst = eth_null_copy_tx; 562b3b413f7SBruce Richardson } else { 563b3b413f7SBruce Richardson eth_dev->rx_pkt_burst = eth_null_rx; 564b3b413f7SBruce Richardson eth_dev->tx_pkt_burst = eth_null_tx; 565b3b413f7SBruce Richardson } 566b3b413f7SBruce Richardson 567b3b413f7SBruce Richardson return 0; 568b3b413f7SBruce Richardson } 569b3b413f7SBruce Richardson 570b3b413f7SBruce Richardson static inline int 571b3b413f7SBruce Richardson get_packet_size_arg(const char *key __rte_unused, 572b3b413f7SBruce Richardson const char *value, void *extra_args) 573b3b413f7SBruce Richardson { 574b3b413f7SBruce Richardson const char *a = value; 575b3b413f7SBruce Richardson unsigned *packet_size = extra_args; 576b3b413f7SBruce Richardson 577b3b413f7SBruce Richardson if ((value == NULL) || (extra_args == NULL)) 578b3b413f7SBruce Richardson return -EINVAL; 579b3b413f7SBruce Richardson 580b3b413f7SBruce Richardson *packet_size = (unsigned)strtoul(a, NULL, 0); 581b3b413f7SBruce Richardson if (*packet_size == UINT_MAX) 582b3b413f7SBruce Richardson return -1; 583b3b413f7SBruce Richardson 584b3b413f7SBruce Richardson return 0; 585b3b413f7SBruce Richardson } 586b3b413f7SBruce Richardson 587b3b413f7SBruce Richardson static inline int 588b3b413f7SBruce Richardson get_packet_copy_arg(const char *key __rte_unused, 589b3b413f7SBruce Richardson const char *value, void *extra_args) 590b3b413f7SBruce Richardson { 591b3b413f7SBruce Richardson const char *a = value; 592b3b413f7SBruce Richardson unsigned *packet_copy = extra_args; 593b3b413f7SBruce Richardson 594b3b413f7SBruce Richardson if ((value == NULL) || (extra_args == NULL)) 595b3b413f7SBruce Richardson return -EINVAL; 596b3b413f7SBruce Richardson 597b3b413f7SBruce Richardson *packet_copy = (unsigned)strtoul(a, NULL, 0); 598b3b413f7SBruce Richardson if (*packet_copy == UINT_MAX) 599b3b413f7SBruce Richardson return -1; 600b3b413f7SBruce Richardson 601b3b413f7SBruce Richardson return 0; 602b3b413f7SBruce Richardson } 603b3b413f7SBruce Richardson 604b3b413f7SBruce Richardson static int 6055d2aa461SJan Blunck rte_pmd_null_probe(struct rte_vdev_device *dev) 606b3b413f7SBruce Richardson { 6075d2aa461SJan Blunck const char *name, *params; 608b3b413f7SBruce Richardson unsigned packet_size = default_packet_size; 609b3b413f7SBruce Richardson unsigned packet_copy = default_packet_copy; 610b3b413f7SBruce Richardson struct rte_kvargs *kvlist = NULL; 611b3b413f7SBruce Richardson int ret; 612b3b413f7SBruce Richardson 6135d2aa461SJan Blunck if (!dev) 614b3b413f7SBruce Richardson return -EINVAL; 615b3b413f7SBruce Richardson 6165d2aa461SJan Blunck name = rte_vdev_device_name(dev); 6175d2aa461SJan Blunck params = rte_vdev_device_args(dev); 618b3b413f7SBruce Richardson RTE_LOG(INFO, PMD, "Initializing pmd_null for %s\n", name); 619b3b413f7SBruce Richardson 620b3b413f7SBruce Richardson if (params != NULL) { 621b3b413f7SBruce Richardson kvlist = rte_kvargs_parse(params, valid_arguments); 622b3b413f7SBruce Richardson if (kvlist == NULL) 623b3b413f7SBruce Richardson return -1; 624b3b413f7SBruce Richardson 625b3b413f7SBruce Richardson if (rte_kvargs_count(kvlist, ETH_NULL_PACKET_SIZE_ARG) == 1) { 626b3b413f7SBruce Richardson 627b3b413f7SBruce Richardson ret = rte_kvargs_process(kvlist, 628b3b413f7SBruce Richardson ETH_NULL_PACKET_SIZE_ARG, 629b3b413f7SBruce Richardson &get_packet_size_arg, &packet_size); 630b3b413f7SBruce Richardson if (ret < 0) 631b3b413f7SBruce Richardson goto free_kvlist; 632b3b413f7SBruce Richardson } 633b3b413f7SBruce Richardson 634b3b413f7SBruce Richardson if (rte_kvargs_count(kvlist, ETH_NULL_PACKET_COPY_ARG) == 1) { 635b3b413f7SBruce Richardson 636b3b413f7SBruce Richardson ret = rte_kvargs_process(kvlist, 637b3b413f7SBruce Richardson ETH_NULL_PACKET_COPY_ARG, 638b3b413f7SBruce Richardson &get_packet_copy_arg, &packet_copy); 639b3b413f7SBruce Richardson if (ret < 0) 640b3b413f7SBruce Richardson goto free_kvlist; 641b3b413f7SBruce Richardson } 642b3b413f7SBruce Richardson } 643b3b413f7SBruce Richardson 644b3b413f7SBruce Richardson RTE_LOG(INFO, PMD, "Configure pmd_null: packet size is %d, " 645b3b413f7SBruce Richardson "packet copy is %s\n", packet_size, 646b3b413f7SBruce Richardson packet_copy ? "enabled" : "disabled"); 647b3b413f7SBruce Richardson 648050fe6e9SJan Blunck ret = eth_dev_null_create(dev, packet_size, packet_copy); 649b3b413f7SBruce Richardson 650b3b413f7SBruce Richardson free_kvlist: 651b3b413f7SBruce Richardson if (kvlist) 652b3b413f7SBruce Richardson rte_kvargs_free(kvlist); 653b3b413f7SBruce Richardson return ret; 654b3b413f7SBruce Richardson } 655b3b413f7SBruce Richardson 656b3b413f7SBruce Richardson static int 6575d2aa461SJan Blunck rte_pmd_null_remove(struct rte_vdev_device *dev) 658b3b413f7SBruce Richardson { 659b3b413f7SBruce Richardson struct rte_eth_dev *eth_dev = NULL; 660b3b413f7SBruce Richardson 6615d2aa461SJan Blunck if (!dev) 662b3b413f7SBruce Richardson return -EINVAL; 663b3b413f7SBruce Richardson 664b3b413f7SBruce Richardson RTE_LOG(INFO, PMD, "Closing null ethdev on numa socket %u\n", 665b3b413f7SBruce Richardson rte_socket_id()); 666b3b413f7SBruce Richardson 6676799cfe4SBernard Iremonger /* find the ethdev entry */ 6685d2aa461SJan Blunck eth_dev = rte_eth_dev_allocated(rte_vdev_device_name(dev)); 669b3b413f7SBruce Richardson if (eth_dev == NULL) 670b3b413f7SBruce Richardson return -1; 671b3b413f7SBruce Richardson 672b3b413f7SBruce Richardson rte_free(eth_dev->data->dev_private); 673b3b413f7SBruce Richardson rte_free(eth_dev->data); 674b3b413f7SBruce Richardson 675b3b413f7SBruce Richardson rte_eth_dev_release_port(eth_dev); 676b3b413f7SBruce Richardson 677b3b413f7SBruce Richardson return 0; 678b3b413f7SBruce Richardson } 679b3b413f7SBruce Richardson 680fe363dd4SJan Viktorin static struct rte_vdev_driver pmd_null_drv = { 68150a3345fSShreyansh Jain .probe = rte_pmd_null_probe, 68250a3345fSShreyansh Jain .remove = rte_pmd_null_remove, 683b3b413f7SBruce Richardson }; 684b3b413f7SBruce Richardson 68501f19227SShreyansh Jain RTE_PMD_REGISTER_VDEV(net_null, pmd_null_drv); 6869fa80cb2SJan Blunck RTE_PMD_REGISTER_ALIAS(net_null, eth_null); 68701f19227SShreyansh Jain RTE_PMD_REGISTER_PARAM_STRING(net_null, 68865eca099SPablo de Lara "size=<int> " 68965eca099SPablo de Lara "copy=<int>"); 690