14418919fSjohnjiang /* SPDX-License-Identifier: BSD-3-Clause
24418919fSjohnjiang * Copyright(c) 2010-2014 Intel Corporation
34418919fSjohnjiang */
44418919fSjohnjiang
54418919fSjohnjiang #include <rte_mbuf.h>
64418919fSjohnjiang #include <rte_ethdev.h>
74418919fSjohnjiang #include <rte_ethdev_driver.h>
84418919fSjohnjiang #include <rte_pci.h>
94418919fSjohnjiang #include <rte_bus_pci.h>
104418919fSjohnjiang #include <rte_malloc.h>
114418919fSjohnjiang #include <rte_memcpy.h>
124418919fSjohnjiang #include <rte_memory.h>
134418919fSjohnjiang #include <rte_ring.h>
144418919fSjohnjiang
154418919fSjohnjiang #include "virtual_pmd.h"
164418919fSjohnjiang
174418919fSjohnjiang #define MAX_PKT_BURST 512
184418919fSjohnjiang
194418919fSjohnjiang static const char *virtual_ethdev_driver_name = "Virtual PMD";
204418919fSjohnjiang
214418919fSjohnjiang struct virtual_ethdev_private {
224418919fSjohnjiang struct eth_dev_ops dev_ops;
234418919fSjohnjiang struct rte_eth_stats eth_stats;
244418919fSjohnjiang
254418919fSjohnjiang struct rte_ring *rx_queue;
264418919fSjohnjiang struct rte_ring *tx_queue;
274418919fSjohnjiang
284418919fSjohnjiang int tx_burst_fail_count;
294418919fSjohnjiang };
304418919fSjohnjiang
314418919fSjohnjiang struct virtual_ethdev_queue {
324418919fSjohnjiang int port_id;
334418919fSjohnjiang int queue_id;
344418919fSjohnjiang };
354418919fSjohnjiang
364418919fSjohnjiang static int
virtual_ethdev_start_success(struct rte_eth_dev * eth_dev __rte_unused)374418919fSjohnjiang virtual_ethdev_start_success(struct rte_eth_dev *eth_dev __rte_unused)
384418919fSjohnjiang {
394418919fSjohnjiang eth_dev->data->dev_started = 1;
404418919fSjohnjiang
414418919fSjohnjiang return 0;
424418919fSjohnjiang }
434418919fSjohnjiang
444418919fSjohnjiang static int
virtual_ethdev_start_fail(struct rte_eth_dev * eth_dev __rte_unused)454418919fSjohnjiang virtual_ethdev_start_fail(struct rte_eth_dev *eth_dev __rte_unused)
464418919fSjohnjiang {
474418919fSjohnjiang eth_dev->data->dev_started = 0;
484418919fSjohnjiang
494418919fSjohnjiang return -1;
504418919fSjohnjiang }
virtual_ethdev_stop(struct rte_eth_dev * eth_dev __rte_unused)51*2d9fd380Sjfb8856606 static int virtual_ethdev_stop(struct rte_eth_dev *eth_dev __rte_unused)
524418919fSjohnjiang {
534418919fSjohnjiang void *pkt = NULL;
544418919fSjohnjiang struct virtual_ethdev_private *prv = eth_dev->data->dev_private;
554418919fSjohnjiang
564418919fSjohnjiang eth_dev->data->dev_link.link_status = ETH_LINK_DOWN;
574418919fSjohnjiang eth_dev->data->dev_started = 0;
584418919fSjohnjiang while (rte_ring_dequeue(prv->rx_queue, &pkt) != -ENOENT)
594418919fSjohnjiang rte_pktmbuf_free(pkt);
604418919fSjohnjiang
614418919fSjohnjiang while (rte_ring_dequeue(prv->tx_queue, &pkt) != -ENOENT)
624418919fSjohnjiang rte_pktmbuf_free(pkt);
63*2d9fd380Sjfb8856606
64*2d9fd380Sjfb8856606 return 0;
654418919fSjohnjiang }
664418919fSjohnjiang
67*2d9fd380Sjfb8856606 static int
virtual_ethdev_close(struct rte_eth_dev * dev __rte_unused)684418919fSjohnjiang virtual_ethdev_close(struct rte_eth_dev *dev __rte_unused)
69*2d9fd380Sjfb8856606 {
70*2d9fd380Sjfb8856606 return 0;
71*2d9fd380Sjfb8856606 }
724418919fSjohnjiang
734418919fSjohnjiang static int
virtual_ethdev_configure_success(struct rte_eth_dev * dev __rte_unused)744418919fSjohnjiang virtual_ethdev_configure_success(struct rte_eth_dev *dev __rte_unused)
754418919fSjohnjiang {
764418919fSjohnjiang return 0;
774418919fSjohnjiang }
784418919fSjohnjiang
794418919fSjohnjiang static int
virtual_ethdev_configure_fail(struct rte_eth_dev * dev __rte_unused)804418919fSjohnjiang virtual_ethdev_configure_fail(struct rte_eth_dev *dev __rte_unused)
814418919fSjohnjiang {
824418919fSjohnjiang return -1;
834418919fSjohnjiang }
844418919fSjohnjiang
854418919fSjohnjiang static int
virtual_ethdev_info_get(struct rte_eth_dev * dev __rte_unused,struct rte_eth_dev_info * dev_info)864418919fSjohnjiang virtual_ethdev_info_get(struct rte_eth_dev *dev __rte_unused,
874418919fSjohnjiang struct rte_eth_dev_info *dev_info)
884418919fSjohnjiang {
894418919fSjohnjiang dev_info->driver_name = virtual_ethdev_driver_name;
904418919fSjohnjiang dev_info->max_mac_addrs = 1;
914418919fSjohnjiang
924418919fSjohnjiang dev_info->max_rx_pktlen = (uint32_t)2048;
934418919fSjohnjiang
944418919fSjohnjiang dev_info->max_rx_queues = (uint16_t)128;
954418919fSjohnjiang dev_info->max_tx_queues = (uint16_t)512;
964418919fSjohnjiang
974418919fSjohnjiang dev_info->min_rx_bufsize = 0;
984418919fSjohnjiang
994418919fSjohnjiang return 0;
1004418919fSjohnjiang }
1014418919fSjohnjiang
1024418919fSjohnjiang static int
virtual_ethdev_rx_queue_setup_success(struct rte_eth_dev * dev,uint16_t rx_queue_id,uint16_t nb_rx_desc __rte_unused,unsigned int socket_id,const struct rte_eth_rxconf * rx_conf __rte_unused,struct rte_mempool * mb_pool __rte_unused)1034418919fSjohnjiang virtual_ethdev_rx_queue_setup_success(struct rte_eth_dev *dev,
1044418919fSjohnjiang uint16_t rx_queue_id, uint16_t nb_rx_desc __rte_unused,
1054418919fSjohnjiang unsigned int socket_id,
1064418919fSjohnjiang const struct rte_eth_rxconf *rx_conf __rte_unused,
1074418919fSjohnjiang struct rte_mempool *mb_pool __rte_unused)
1084418919fSjohnjiang {
1094418919fSjohnjiang struct virtual_ethdev_queue *rx_q;
1104418919fSjohnjiang
1114418919fSjohnjiang rx_q = (struct virtual_ethdev_queue *)rte_zmalloc_socket(NULL,
1124418919fSjohnjiang sizeof(struct virtual_ethdev_queue), 0, socket_id);
1134418919fSjohnjiang
1144418919fSjohnjiang if (rx_q == NULL)
1154418919fSjohnjiang return -1;
1164418919fSjohnjiang
1174418919fSjohnjiang rx_q->port_id = dev->data->port_id;
1184418919fSjohnjiang rx_q->queue_id = rx_queue_id;
1194418919fSjohnjiang
1204418919fSjohnjiang dev->data->rx_queues[rx_queue_id] = rx_q;
1214418919fSjohnjiang
1224418919fSjohnjiang return 0;
1234418919fSjohnjiang }
1244418919fSjohnjiang
1254418919fSjohnjiang static int
virtual_ethdev_rx_queue_setup_fail(struct rte_eth_dev * dev __rte_unused,uint16_t rx_queue_id __rte_unused,uint16_t nb_rx_desc __rte_unused,unsigned int socket_id __rte_unused,const struct rte_eth_rxconf * rx_conf __rte_unused,struct rte_mempool * mb_pool __rte_unused)1264418919fSjohnjiang virtual_ethdev_rx_queue_setup_fail(struct rte_eth_dev *dev __rte_unused,
1274418919fSjohnjiang uint16_t rx_queue_id __rte_unused, uint16_t nb_rx_desc __rte_unused,
1284418919fSjohnjiang unsigned int socket_id __rte_unused,
1294418919fSjohnjiang const struct rte_eth_rxconf *rx_conf __rte_unused,
1304418919fSjohnjiang struct rte_mempool *mb_pool __rte_unused)
1314418919fSjohnjiang {
1324418919fSjohnjiang return -1;
1334418919fSjohnjiang }
1344418919fSjohnjiang
1354418919fSjohnjiang static int
virtual_ethdev_tx_queue_setup_success(struct rte_eth_dev * dev,uint16_t tx_queue_id,uint16_t nb_tx_desc __rte_unused,unsigned int socket_id,const struct rte_eth_txconf * tx_conf __rte_unused)1364418919fSjohnjiang virtual_ethdev_tx_queue_setup_success(struct rte_eth_dev *dev,
1374418919fSjohnjiang uint16_t tx_queue_id, uint16_t nb_tx_desc __rte_unused,
1384418919fSjohnjiang unsigned int socket_id,
1394418919fSjohnjiang const struct rte_eth_txconf *tx_conf __rte_unused)
1404418919fSjohnjiang {
1414418919fSjohnjiang struct virtual_ethdev_queue *tx_q;
1424418919fSjohnjiang
1434418919fSjohnjiang tx_q = (struct virtual_ethdev_queue *)rte_zmalloc_socket(NULL,
1444418919fSjohnjiang sizeof(struct virtual_ethdev_queue), 0, socket_id);
1454418919fSjohnjiang
1464418919fSjohnjiang if (tx_q == NULL)
1474418919fSjohnjiang return -1;
1484418919fSjohnjiang
1494418919fSjohnjiang tx_q->port_id = dev->data->port_id;
1504418919fSjohnjiang tx_q->queue_id = tx_queue_id;
1514418919fSjohnjiang
1524418919fSjohnjiang dev->data->tx_queues[tx_queue_id] = tx_q;
1534418919fSjohnjiang
1544418919fSjohnjiang return 0;
1554418919fSjohnjiang }
1564418919fSjohnjiang
1574418919fSjohnjiang static int
virtual_ethdev_tx_queue_setup_fail(struct rte_eth_dev * dev __rte_unused,uint16_t tx_queue_id __rte_unused,uint16_t nb_tx_desc __rte_unused,unsigned int socket_id __rte_unused,const struct rte_eth_txconf * tx_conf __rte_unused)1584418919fSjohnjiang virtual_ethdev_tx_queue_setup_fail(struct rte_eth_dev *dev __rte_unused,
1594418919fSjohnjiang uint16_t tx_queue_id __rte_unused, uint16_t nb_tx_desc __rte_unused,
1604418919fSjohnjiang unsigned int socket_id __rte_unused,
1614418919fSjohnjiang const struct rte_eth_txconf *tx_conf __rte_unused)
1624418919fSjohnjiang {
1634418919fSjohnjiang return -1;
1644418919fSjohnjiang }
1654418919fSjohnjiang
1664418919fSjohnjiang static void
virtual_ethdev_rx_queue_release(void * q __rte_unused)1674418919fSjohnjiang virtual_ethdev_rx_queue_release(void *q __rte_unused)
1684418919fSjohnjiang {
1694418919fSjohnjiang }
1704418919fSjohnjiang
1714418919fSjohnjiang static void
virtual_ethdev_tx_queue_release(void * q __rte_unused)1724418919fSjohnjiang virtual_ethdev_tx_queue_release(void *q __rte_unused)
1734418919fSjohnjiang {
1744418919fSjohnjiang }
1754418919fSjohnjiang
1764418919fSjohnjiang static int
virtual_ethdev_link_update_success(struct rte_eth_dev * bonded_eth_dev,int wait_to_complete __rte_unused)1774418919fSjohnjiang virtual_ethdev_link_update_success(struct rte_eth_dev *bonded_eth_dev,
1784418919fSjohnjiang int wait_to_complete __rte_unused)
1794418919fSjohnjiang {
1804418919fSjohnjiang if (!bonded_eth_dev->data->dev_started)
1814418919fSjohnjiang bonded_eth_dev->data->dev_link.link_status = ETH_LINK_DOWN;
1824418919fSjohnjiang
1834418919fSjohnjiang return 0;
1844418919fSjohnjiang }
1854418919fSjohnjiang
1864418919fSjohnjiang static int
virtual_ethdev_link_update_fail(struct rte_eth_dev * bonded_eth_dev __rte_unused,int wait_to_complete __rte_unused)1874418919fSjohnjiang virtual_ethdev_link_update_fail(struct rte_eth_dev *bonded_eth_dev __rte_unused,
1884418919fSjohnjiang int wait_to_complete __rte_unused)
1894418919fSjohnjiang {
1904418919fSjohnjiang return -1;
1914418919fSjohnjiang }
1924418919fSjohnjiang
1934418919fSjohnjiang static int
virtual_ethdev_stats_get(struct rte_eth_dev * dev,struct rte_eth_stats * stats)1944418919fSjohnjiang virtual_ethdev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
1954418919fSjohnjiang {
1964418919fSjohnjiang struct virtual_ethdev_private *dev_private = dev->data->dev_private;
1974418919fSjohnjiang
1984418919fSjohnjiang if (stats)
1994418919fSjohnjiang rte_memcpy(stats, &dev_private->eth_stats, sizeof(*stats));
2004418919fSjohnjiang
2014418919fSjohnjiang return 0;
2024418919fSjohnjiang }
2034418919fSjohnjiang
2044418919fSjohnjiang static int
virtual_ethdev_stats_reset(struct rte_eth_dev * dev)2054418919fSjohnjiang virtual_ethdev_stats_reset(struct rte_eth_dev *dev)
2064418919fSjohnjiang {
2074418919fSjohnjiang struct virtual_ethdev_private *dev_private = dev->data->dev_private;
2084418919fSjohnjiang void *pkt = NULL;
2094418919fSjohnjiang
2104418919fSjohnjiang while (rte_ring_dequeue(dev_private->tx_queue, &pkt) == -ENOBUFS)
2114418919fSjohnjiang rte_pktmbuf_free(pkt);
2124418919fSjohnjiang
2134418919fSjohnjiang /* Reset internal statistics */
2144418919fSjohnjiang memset(&dev_private->eth_stats, 0, sizeof(dev_private->eth_stats));
2154418919fSjohnjiang
2164418919fSjohnjiang return 0;
2174418919fSjohnjiang }
2184418919fSjohnjiang
2194418919fSjohnjiang static int
virtual_ethdev_promiscuous_mode_enable(struct rte_eth_dev * dev __rte_unused)2204418919fSjohnjiang virtual_ethdev_promiscuous_mode_enable(struct rte_eth_dev *dev __rte_unused)
2214418919fSjohnjiang {
2224418919fSjohnjiang return 0;
2234418919fSjohnjiang }
2244418919fSjohnjiang
2254418919fSjohnjiang static int
virtual_ethdev_promiscuous_mode_disable(struct rte_eth_dev * dev __rte_unused)2264418919fSjohnjiang virtual_ethdev_promiscuous_mode_disable(struct rte_eth_dev *dev __rte_unused)
2274418919fSjohnjiang {
2284418919fSjohnjiang return 0;
2294418919fSjohnjiang }
2304418919fSjohnjiang
2314418919fSjohnjiang static int
virtual_ethdev_mac_address_set(__rte_unused struct rte_eth_dev * dev,__rte_unused struct rte_ether_addr * addr)2324418919fSjohnjiang virtual_ethdev_mac_address_set(__rte_unused struct rte_eth_dev *dev,
2334418919fSjohnjiang __rte_unused struct rte_ether_addr *addr)
2344418919fSjohnjiang {
2354418919fSjohnjiang return 0;
2364418919fSjohnjiang }
2374418919fSjohnjiang
2384418919fSjohnjiang static const struct eth_dev_ops virtual_ethdev_default_dev_ops = {
2394418919fSjohnjiang .dev_configure = virtual_ethdev_configure_success,
2404418919fSjohnjiang .dev_start = virtual_ethdev_start_success,
2414418919fSjohnjiang .dev_stop = virtual_ethdev_stop,
2424418919fSjohnjiang .dev_close = virtual_ethdev_close,
2434418919fSjohnjiang .dev_infos_get = virtual_ethdev_info_get,
2444418919fSjohnjiang .rx_queue_setup = virtual_ethdev_rx_queue_setup_success,
2454418919fSjohnjiang .tx_queue_setup = virtual_ethdev_tx_queue_setup_success,
2464418919fSjohnjiang .rx_queue_release = virtual_ethdev_rx_queue_release,
2474418919fSjohnjiang .tx_queue_release = virtual_ethdev_tx_queue_release,
2484418919fSjohnjiang .link_update = virtual_ethdev_link_update_success,
2494418919fSjohnjiang .mac_addr_set = virtual_ethdev_mac_address_set,
2504418919fSjohnjiang .stats_get = virtual_ethdev_stats_get,
2514418919fSjohnjiang .stats_reset = virtual_ethdev_stats_reset,
2524418919fSjohnjiang .promiscuous_enable = virtual_ethdev_promiscuous_mode_enable,
2534418919fSjohnjiang .promiscuous_disable = virtual_ethdev_promiscuous_mode_disable
2544418919fSjohnjiang };
2554418919fSjohnjiang
2564418919fSjohnjiang void
virtual_ethdev_start_fn_set_success(uint16_t port_id,uint8_t success)2574418919fSjohnjiang virtual_ethdev_start_fn_set_success(uint16_t port_id, uint8_t success)
2584418919fSjohnjiang {
2594418919fSjohnjiang struct rte_eth_dev *dev = &rte_eth_devices[port_id];
2604418919fSjohnjiang struct virtual_ethdev_private *dev_private = dev->data->dev_private;
2614418919fSjohnjiang struct eth_dev_ops *dev_ops = &dev_private->dev_ops;
2624418919fSjohnjiang
2634418919fSjohnjiang if (success)
2644418919fSjohnjiang dev_ops->dev_start = virtual_ethdev_start_success;
2654418919fSjohnjiang else
2664418919fSjohnjiang dev_ops->dev_start = virtual_ethdev_start_fail;
2674418919fSjohnjiang
2684418919fSjohnjiang }
2694418919fSjohnjiang
2704418919fSjohnjiang void
virtual_ethdev_configure_fn_set_success(uint16_t port_id,uint8_t success)2714418919fSjohnjiang virtual_ethdev_configure_fn_set_success(uint16_t port_id, uint8_t success)
2724418919fSjohnjiang {
2734418919fSjohnjiang struct rte_eth_dev *dev = &rte_eth_devices[port_id];
2744418919fSjohnjiang struct virtual_ethdev_private *dev_private = dev->data->dev_private;
2754418919fSjohnjiang struct eth_dev_ops *dev_ops = &dev_private->dev_ops;
2764418919fSjohnjiang
2774418919fSjohnjiang if (success)
2784418919fSjohnjiang dev_ops->dev_configure = virtual_ethdev_configure_success;
2794418919fSjohnjiang else
2804418919fSjohnjiang dev_ops->dev_configure = virtual_ethdev_configure_fail;
2814418919fSjohnjiang }
2824418919fSjohnjiang
2834418919fSjohnjiang void
virtual_ethdev_rx_queue_setup_fn_set_success(uint16_t port_id,uint8_t success)2844418919fSjohnjiang virtual_ethdev_rx_queue_setup_fn_set_success(uint16_t port_id, uint8_t success)
2854418919fSjohnjiang {
2864418919fSjohnjiang struct rte_eth_dev *dev = &rte_eth_devices[port_id];
2874418919fSjohnjiang struct virtual_ethdev_private *dev_private = dev->data->dev_private;
2884418919fSjohnjiang struct eth_dev_ops *dev_ops = &dev_private->dev_ops;
2894418919fSjohnjiang
2904418919fSjohnjiang if (success)
2914418919fSjohnjiang dev_ops->rx_queue_setup = virtual_ethdev_rx_queue_setup_success;
2924418919fSjohnjiang else
2934418919fSjohnjiang dev_ops->rx_queue_setup = virtual_ethdev_rx_queue_setup_fail;
2944418919fSjohnjiang }
2954418919fSjohnjiang
2964418919fSjohnjiang void
virtual_ethdev_tx_queue_setup_fn_set_success(uint16_t port_id,uint8_t success)2974418919fSjohnjiang virtual_ethdev_tx_queue_setup_fn_set_success(uint16_t port_id, uint8_t success)
2984418919fSjohnjiang {
2994418919fSjohnjiang struct rte_eth_dev *dev = &rte_eth_devices[port_id];
3004418919fSjohnjiang struct virtual_ethdev_private *dev_private = dev->data->dev_private;
3014418919fSjohnjiang struct eth_dev_ops *dev_ops = &dev_private->dev_ops;
3024418919fSjohnjiang
3034418919fSjohnjiang if (success)
3044418919fSjohnjiang dev_ops->tx_queue_setup = virtual_ethdev_tx_queue_setup_success;
3054418919fSjohnjiang else
3064418919fSjohnjiang dev_ops->tx_queue_setup = virtual_ethdev_tx_queue_setup_fail;
3074418919fSjohnjiang }
3084418919fSjohnjiang
3094418919fSjohnjiang void
virtual_ethdev_link_update_fn_set_success(uint16_t port_id,uint8_t success)3104418919fSjohnjiang virtual_ethdev_link_update_fn_set_success(uint16_t port_id, uint8_t success)
3114418919fSjohnjiang {
3124418919fSjohnjiang struct rte_eth_dev *dev = &rte_eth_devices[port_id];
3134418919fSjohnjiang struct virtual_ethdev_private *dev_private = dev->data->dev_private;
3144418919fSjohnjiang struct eth_dev_ops *dev_ops = &dev_private->dev_ops;
3154418919fSjohnjiang
3164418919fSjohnjiang if (success)
3174418919fSjohnjiang dev_ops->link_update = virtual_ethdev_link_update_success;
3184418919fSjohnjiang else
3194418919fSjohnjiang dev_ops->link_update = virtual_ethdev_link_update_fail;
3204418919fSjohnjiang }
3214418919fSjohnjiang
3224418919fSjohnjiang
3234418919fSjohnjiang static uint16_t
virtual_ethdev_rx_burst_success(void * queue __rte_unused,struct rte_mbuf ** bufs,uint16_t nb_pkts)3244418919fSjohnjiang virtual_ethdev_rx_burst_success(void *queue __rte_unused,
3254418919fSjohnjiang struct rte_mbuf **bufs,
3264418919fSjohnjiang uint16_t nb_pkts)
3274418919fSjohnjiang {
3284418919fSjohnjiang struct rte_eth_dev *vrtl_eth_dev;
3294418919fSjohnjiang struct virtual_ethdev_queue *pq_map;
3304418919fSjohnjiang struct virtual_ethdev_private *dev_private;
3314418919fSjohnjiang
3324418919fSjohnjiang int rx_count, i;
3334418919fSjohnjiang
3344418919fSjohnjiang pq_map = (struct virtual_ethdev_queue *)queue;
3354418919fSjohnjiang vrtl_eth_dev = &rte_eth_devices[pq_map->port_id];
3364418919fSjohnjiang dev_private = vrtl_eth_dev->data->dev_private;
3374418919fSjohnjiang
3384418919fSjohnjiang rx_count = rte_ring_dequeue_burst(dev_private->rx_queue, (void **) bufs,
3394418919fSjohnjiang nb_pkts, NULL);
3404418919fSjohnjiang
3414418919fSjohnjiang /* increments ipackets count */
3424418919fSjohnjiang dev_private->eth_stats.ipackets += rx_count;
3434418919fSjohnjiang
3444418919fSjohnjiang /* increments ibytes count */
3454418919fSjohnjiang for (i = 0; i < rx_count; i++)
3464418919fSjohnjiang dev_private->eth_stats.ibytes += rte_pktmbuf_pkt_len(bufs[i]);
3474418919fSjohnjiang
3484418919fSjohnjiang return rx_count;
3494418919fSjohnjiang }
3504418919fSjohnjiang
3514418919fSjohnjiang static uint16_t
virtual_ethdev_rx_burst_fail(void * queue __rte_unused,struct rte_mbuf ** bufs __rte_unused,uint16_t nb_pkts __rte_unused)3524418919fSjohnjiang virtual_ethdev_rx_burst_fail(void *queue __rte_unused,
3534418919fSjohnjiang struct rte_mbuf **bufs __rte_unused,
3544418919fSjohnjiang uint16_t nb_pkts __rte_unused)
3554418919fSjohnjiang {
3564418919fSjohnjiang return 0;
3574418919fSjohnjiang }
3584418919fSjohnjiang
3594418919fSjohnjiang static uint16_t
virtual_ethdev_tx_burst_success(void * queue,struct rte_mbuf ** bufs,uint16_t nb_pkts)3604418919fSjohnjiang virtual_ethdev_tx_burst_success(void *queue, struct rte_mbuf **bufs,
3614418919fSjohnjiang uint16_t nb_pkts)
3624418919fSjohnjiang {
3634418919fSjohnjiang struct virtual_ethdev_queue *tx_q = queue;
3644418919fSjohnjiang
3654418919fSjohnjiang struct rte_eth_dev *vrtl_eth_dev;
3664418919fSjohnjiang struct virtual_ethdev_private *dev_private;
3674418919fSjohnjiang
3684418919fSjohnjiang int i;
3694418919fSjohnjiang
3704418919fSjohnjiang vrtl_eth_dev = &rte_eth_devices[tx_q->port_id];
3714418919fSjohnjiang dev_private = vrtl_eth_dev->data->dev_private;
3724418919fSjohnjiang
3734418919fSjohnjiang if (!vrtl_eth_dev->data->dev_link.link_status)
3744418919fSjohnjiang nb_pkts = 0;
3754418919fSjohnjiang else
3764418919fSjohnjiang nb_pkts = rte_ring_enqueue_burst(dev_private->tx_queue, (void **)bufs,
3774418919fSjohnjiang nb_pkts, NULL);
3784418919fSjohnjiang
3794418919fSjohnjiang /* increment opacket count */
3804418919fSjohnjiang dev_private->eth_stats.opackets += nb_pkts;
3814418919fSjohnjiang
3824418919fSjohnjiang /* increment obytes count */
3834418919fSjohnjiang for (i = 0; i < nb_pkts; i++)
3844418919fSjohnjiang dev_private->eth_stats.obytes += rte_pktmbuf_pkt_len(bufs[i]);
3854418919fSjohnjiang
3864418919fSjohnjiang return nb_pkts;
3874418919fSjohnjiang }
3884418919fSjohnjiang
3894418919fSjohnjiang static uint16_t
virtual_ethdev_tx_burst_fail(void * queue,struct rte_mbuf ** bufs,uint16_t nb_pkts)3904418919fSjohnjiang virtual_ethdev_tx_burst_fail(void *queue, struct rte_mbuf **bufs,
3914418919fSjohnjiang uint16_t nb_pkts)
3924418919fSjohnjiang {
3934418919fSjohnjiang struct rte_eth_dev *vrtl_eth_dev = NULL;
3944418919fSjohnjiang struct virtual_ethdev_queue *tx_q = NULL;
3954418919fSjohnjiang struct virtual_ethdev_private *dev_private = NULL;
3964418919fSjohnjiang
3974418919fSjohnjiang int i;
3984418919fSjohnjiang
3994418919fSjohnjiang tx_q = queue;
4004418919fSjohnjiang vrtl_eth_dev = &rte_eth_devices[tx_q->port_id];
4014418919fSjohnjiang dev_private = vrtl_eth_dev->data->dev_private;
4024418919fSjohnjiang
4034418919fSjohnjiang if (dev_private->tx_burst_fail_count < nb_pkts) {
4044418919fSjohnjiang int successfully_txd = nb_pkts - dev_private->tx_burst_fail_count;
4054418919fSjohnjiang
4064418919fSjohnjiang /* increment opacket count */
4074418919fSjohnjiang dev_private->eth_stats.opackets += successfully_txd;
4084418919fSjohnjiang
4094418919fSjohnjiang /* free packets in burst */
4104418919fSjohnjiang for (i = 0; i < successfully_txd; i++) {
4114418919fSjohnjiang /* free packets in burst */
4124418919fSjohnjiang if (bufs[i] != NULL)
4134418919fSjohnjiang rte_pktmbuf_free(bufs[i]);
4144418919fSjohnjiang
4154418919fSjohnjiang bufs[i] = NULL;
4164418919fSjohnjiang }
4174418919fSjohnjiang
4184418919fSjohnjiang return successfully_txd;
4194418919fSjohnjiang }
4204418919fSjohnjiang
4214418919fSjohnjiang return 0;
4224418919fSjohnjiang }
4234418919fSjohnjiang
4244418919fSjohnjiang
4254418919fSjohnjiang void
virtual_ethdev_rx_burst_fn_set_success(uint16_t port_id,uint8_t success)4264418919fSjohnjiang virtual_ethdev_rx_burst_fn_set_success(uint16_t port_id, uint8_t success)
4274418919fSjohnjiang {
4284418919fSjohnjiang struct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id];
4294418919fSjohnjiang
4304418919fSjohnjiang if (success)
4314418919fSjohnjiang vrtl_eth_dev->rx_pkt_burst = virtual_ethdev_rx_burst_success;
4324418919fSjohnjiang else
4334418919fSjohnjiang vrtl_eth_dev->rx_pkt_burst = virtual_ethdev_rx_burst_fail;
4344418919fSjohnjiang }
4354418919fSjohnjiang
4364418919fSjohnjiang
4374418919fSjohnjiang void
virtual_ethdev_tx_burst_fn_set_success(uint16_t port_id,uint8_t success)4384418919fSjohnjiang virtual_ethdev_tx_burst_fn_set_success(uint16_t port_id, uint8_t success)
4394418919fSjohnjiang {
4404418919fSjohnjiang struct virtual_ethdev_private *dev_private = NULL;
4414418919fSjohnjiang struct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id];
4424418919fSjohnjiang
4434418919fSjohnjiang dev_private = vrtl_eth_dev->data->dev_private;
4444418919fSjohnjiang
4454418919fSjohnjiang if (success)
4464418919fSjohnjiang vrtl_eth_dev->tx_pkt_burst = virtual_ethdev_tx_burst_success;
4474418919fSjohnjiang else
4484418919fSjohnjiang vrtl_eth_dev->tx_pkt_burst = virtual_ethdev_tx_burst_fail;
4494418919fSjohnjiang
4504418919fSjohnjiang dev_private->tx_burst_fail_count = 0;
4514418919fSjohnjiang }
4524418919fSjohnjiang
4534418919fSjohnjiang void
virtual_ethdev_tx_burst_fn_set_tx_pkt_fail_count(uint16_t port_id,uint8_t packet_fail_count)4544418919fSjohnjiang virtual_ethdev_tx_burst_fn_set_tx_pkt_fail_count(uint16_t port_id,
4554418919fSjohnjiang uint8_t packet_fail_count)
4564418919fSjohnjiang {
4574418919fSjohnjiang struct virtual_ethdev_private *dev_private = NULL;
4584418919fSjohnjiang struct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id];
4594418919fSjohnjiang
4604418919fSjohnjiang
4614418919fSjohnjiang dev_private = vrtl_eth_dev->data->dev_private;
4624418919fSjohnjiang dev_private->tx_burst_fail_count = packet_fail_count;
4634418919fSjohnjiang }
4644418919fSjohnjiang
4654418919fSjohnjiang void
virtual_ethdev_set_link_status(uint16_t port_id,uint8_t link_status)4664418919fSjohnjiang virtual_ethdev_set_link_status(uint16_t port_id, uint8_t link_status)
4674418919fSjohnjiang {
4684418919fSjohnjiang struct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id];
4694418919fSjohnjiang
4704418919fSjohnjiang vrtl_eth_dev->data->dev_link.link_status = link_status;
4714418919fSjohnjiang }
4724418919fSjohnjiang
4734418919fSjohnjiang void
virtual_ethdev_simulate_link_status_interrupt(uint16_t port_id,uint8_t link_status)4744418919fSjohnjiang virtual_ethdev_simulate_link_status_interrupt(uint16_t port_id,
4754418919fSjohnjiang uint8_t link_status)
4764418919fSjohnjiang {
4774418919fSjohnjiang struct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id];
4784418919fSjohnjiang
4794418919fSjohnjiang vrtl_eth_dev->data->dev_link.link_status = link_status;
4804418919fSjohnjiang
481*2d9fd380Sjfb8856606 rte_eth_dev_callback_process(vrtl_eth_dev, RTE_ETH_EVENT_INTR_LSC,
4824418919fSjohnjiang NULL);
4834418919fSjohnjiang }
4844418919fSjohnjiang
4854418919fSjohnjiang int
virtual_ethdev_add_mbufs_to_rx_queue(uint16_t port_id,struct rte_mbuf ** pkt_burst,int burst_length)4864418919fSjohnjiang virtual_ethdev_add_mbufs_to_rx_queue(uint16_t port_id,
4874418919fSjohnjiang struct rte_mbuf **pkt_burst, int burst_length)
4884418919fSjohnjiang {
4894418919fSjohnjiang struct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id];
4904418919fSjohnjiang struct virtual_ethdev_private *dev_private =
4914418919fSjohnjiang vrtl_eth_dev->data->dev_private;
4924418919fSjohnjiang
4934418919fSjohnjiang return rte_ring_enqueue_burst(dev_private->rx_queue, (void **)pkt_burst,
4944418919fSjohnjiang burst_length, NULL);
4954418919fSjohnjiang }
4964418919fSjohnjiang
4974418919fSjohnjiang int
virtual_ethdev_get_mbufs_from_tx_queue(uint16_t port_id,struct rte_mbuf ** pkt_burst,int burst_length)4984418919fSjohnjiang virtual_ethdev_get_mbufs_from_tx_queue(uint16_t port_id,
4994418919fSjohnjiang struct rte_mbuf **pkt_burst, int burst_length)
5004418919fSjohnjiang {
5014418919fSjohnjiang struct virtual_ethdev_private *dev_private;
5024418919fSjohnjiang struct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id];
5034418919fSjohnjiang
5044418919fSjohnjiang dev_private = vrtl_eth_dev->data->dev_private;
5054418919fSjohnjiang return rte_ring_dequeue_burst(dev_private->tx_queue, (void **)pkt_burst,
5064418919fSjohnjiang burst_length, NULL);
5074418919fSjohnjiang }
5084418919fSjohnjiang
5094418919fSjohnjiang
5104418919fSjohnjiang int
virtual_ethdev_create(const char * name,struct rte_ether_addr * mac_addr,uint8_t socket_id,uint8_t isr_support)5114418919fSjohnjiang virtual_ethdev_create(const char *name, struct rte_ether_addr *mac_addr,
5124418919fSjohnjiang uint8_t socket_id, uint8_t isr_support)
5134418919fSjohnjiang {
5144418919fSjohnjiang struct rte_pci_device *pci_dev = NULL;
5154418919fSjohnjiang struct rte_eth_dev *eth_dev = NULL;
5164418919fSjohnjiang struct rte_pci_driver *pci_drv = NULL;
5174418919fSjohnjiang struct rte_pci_id *id_table = NULL;
5184418919fSjohnjiang struct virtual_ethdev_private *dev_private = NULL;
5194418919fSjohnjiang char name_buf[RTE_RING_NAMESIZE];
5204418919fSjohnjiang
5214418919fSjohnjiang
5224418919fSjohnjiang /* now do all data allocation - for eth_dev structure, dummy pci driver
5234418919fSjohnjiang * and internal (dev_private) data
5244418919fSjohnjiang */
5254418919fSjohnjiang
5264418919fSjohnjiang pci_dev = rte_zmalloc_socket(name, sizeof(*pci_dev), 0, socket_id);
5274418919fSjohnjiang if (pci_dev == NULL)
5284418919fSjohnjiang goto err;
5294418919fSjohnjiang
5304418919fSjohnjiang pci_drv = rte_zmalloc_socket(name, sizeof(*pci_drv), 0, socket_id);
5314418919fSjohnjiang if (pci_drv == NULL)
5324418919fSjohnjiang goto err;
5334418919fSjohnjiang
5344418919fSjohnjiang id_table = rte_zmalloc_socket(name, sizeof(*id_table), 0, socket_id);
5354418919fSjohnjiang if (id_table == NULL)
5364418919fSjohnjiang goto err;
5374418919fSjohnjiang id_table->device_id = 0xBEEF;
5384418919fSjohnjiang
5394418919fSjohnjiang dev_private = rte_zmalloc_socket(name, sizeof(*dev_private), 0, socket_id);
5404418919fSjohnjiang if (dev_private == NULL)
5414418919fSjohnjiang goto err;
5424418919fSjohnjiang
5434418919fSjohnjiang snprintf(name_buf, sizeof(name_buf), "%s_rxQ", name);
5444418919fSjohnjiang dev_private->rx_queue = rte_ring_create(name_buf, MAX_PKT_BURST, socket_id,
5454418919fSjohnjiang 0);
5464418919fSjohnjiang if (dev_private->rx_queue == NULL)
5474418919fSjohnjiang goto err;
5484418919fSjohnjiang
5494418919fSjohnjiang snprintf(name_buf, sizeof(name_buf), "%s_txQ", name);
5504418919fSjohnjiang dev_private->tx_queue = rte_ring_create(name_buf, MAX_PKT_BURST, socket_id,
5514418919fSjohnjiang 0);
5524418919fSjohnjiang if (dev_private->tx_queue == NULL)
5534418919fSjohnjiang goto err;
5544418919fSjohnjiang
5554418919fSjohnjiang /* reserve an ethdev entry */
5564418919fSjohnjiang eth_dev = rte_eth_dev_allocate(name);
5574418919fSjohnjiang if (eth_dev == NULL)
5584418919fSjohnjiang goto err;
5594418919fSjohnjiang
5604418919fSjohnjiang pci_dev->device.numa_node = socket_id;
5614418919fSjohnjiang pci_dev->device.name = eth_dev->data->name;
5624418919fSjohnjiang pci_drv->driver.name = virtual_ethdev_driver_name;
5634418919fSjohnjiang pci_drv->id_table = id_table;
5644418919fSjohnjiang
5654418919fSjohnjiang if (isr_support)
5664418919fSjohnjiang pci_drv->drv_flags |= RTE_PCI_DRV_INTR_LSC;
5674418919fSjohnjiang else
5684418919fSjohnjiang pci_drv->drv_flags &= ~RTE_PCI_DRV_INTR_LSC;
5694418919fSjohnjiang
5704418919fSjohnjiang
5714418919fSjohnjiang eth_dev->device = &pci_dev->device;
5724418919fSjohnjiang eth_dev->device->driver = &pci_drv->driver;
5734418919fSjohnjiang
5744418919fSjohnjiang eth_dev->data->nb_rx_queues = (uint16_t)1;
5754418919fSjohnjiang eth_dev->data->nb_tx_queues = (uint16_t)1;
5764418919fSjohnjiang
5774418919fSjohnjiang eth_dev->data->dev_link.link_status = ETH_LINK_DOWN;
5784418919fSjohnjiang eth_dev->data->dev_link.link_speed = ETH_SPEED_NUM_10G;
5794418919fSjohnjiang eth_dev->data->dev_link.link_duplex = ETH_LINK_FULL_DUPLEX;
5804418919fSjohnjiang
5814418919fSjohnjiang eth_dev->data->mac_addrs = rte_zmalloc(name, RTE_ETHER_ADDR_LEN, 0);
5824418919fSjohnjiang if (eth_dev->data->mac_addrs == NULL)
5834418919fSjohnjiang goto err;
5844418919fSjohnjiang
5854418919fSjohnjiang memcpy(eth_dev->data->mac_addrs, mac_addr,
5864418919fSjohnjiang sizeof(*eth_dev->data->mac_addrs));
5874418919fSjohnjiang
5884418919fSjohnjiang eth_dev->data->dev_started = 0;
5894418919fSjohnjiang eth_dev->data->promiscuous = 0;
5904418919fSjohnjiang eth_dev->data->scattered_rx = 0;
5914418919fSjohnjiang eth_dev->data->all_multicast = 0;
5924418919fSjohnjiang
5934418919fSjohnjiang eth_dev->data->dev_private = dev_private;
5944418919fSjohnjiang
5954418919fSjohnjiang /* Copy default device operation functions */
5964418919fSjohnjiang dev_private->dev_ops = virtual_ethdev_default_dev_ops;
5974418919fSjohnjiang eth_dev->dev_ops = &dev_private->dev_ops;
5984418919fSjohnjiang
5994418919fSjohnjiang pci_dev->device.driver = &pci_drv->driver;
6004418919fSjohnjiang eth_dev->device = &pci_dev->device;
6014418919fSjohnjiang
6024418919fSjohnjiang eth_dev->rx_pkt_burst = virtual_ethdev_rx_burst_success;
6034418919fSjohnjiang eth_dev->tx_pkt_burst = virtual_ethdev_tx_burst_success;
6044418919fSjohnjiang
6054418919fSjohnjiang rte_eth_dev_probing_finish(eth_dev);
6064418919fSjohnjiang
6074418919fSjohnjiang return eth_dev->data->port_id;
6084418919fSjohnjiang
6094418919fSjohnjiang err:
6104418919fSjohnjiang rte_free(pci_dev);
6114418919fSjohnjiang rte_free(pci_drv);
6124418919fSjohnjiang rte_free(id_table);
6134418919fSjohnjiang rte_free(dev_private);
6144418919fSjohnjiang
6154418919fSjohnjiang return -1;
6164418919fSjohnjiang }
617