xref: /dpdk/app/test/virtual_pmd.c (revision 4f84008676739874712cb95f3c3df62198b80dc8)
1a9de470cSBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
2a9de470cSBruce Richardson  * Copyright(c) 2010-2014 Intel Corporation
3a9de470cSBruce Richardson  */
4a9de470cSBruce Richardson 
5a9de470cSBruce Richardson #include <rte_mbuf.h>
6a9de470cSBruce Richardson #include <rte_ethdev.h>
7df96fd0dSBruce Richardson #include <ethdev_driver.h>
8a9de470cSBruce Richardson #include <rte_pci.h>
91f37cb2bSDavid Marchand #include <bus_pci_driver.h>
10a9de470cSBruce Richardson #include <rte_malloc.h>
11a9de470cSBruce Richardson #include <rte_memcpy.h>
12a9de470cSBruce Richardson #include <rte_memory.h>
13a9de470cSBruce Richardson #include <rte_ring.h>
14a9de470cSBruce Richardson 
15a9de470cSBruce Richardson #include "virtual_pmd.h"
16a9de470cSBruce Richardson 
17a9de470cSBruce Richardson #define MAX_PKT_BURST 512
18a9de470cSBruce Richardson 
19a9de470cSBruce Richardson static const char *virtual_ethdev_driver_name = "Virtual PMD";
20a9de470cSBruce Richardson 
21a9de470cSBruce Richardson struct virtual_ethdev_private {
22a9de470cSBruce Richardson 	struct eth_dev_ops dev_ops;
23a9de470cSBruce Richardson 	struct rte_eth_stats eth_stats;
24a9de470cSBruce Richardson 
25a9de470cSBruce Richardson 	struct rte_ring *rx_queue;
26a9de470cSBruce Richardson 	struct rte_ring *tx_queue;
27a9de470cSBruce Richardson 
28a9de470cSBruce Richardson 	int tx_burst_fail_count;
29a9de470cSBruce Richardson };
30a9de470cSBruce Richardson 
31a9de470cSBruce Richardson struct virtual_ethdev_queue {
32a9de470cSBruce Richardson 	int port_id;
33a9de470cSBruce Richardson 	int queue_id;
34a9de470cSBruce Richardson };
35a9de470cSBruce Richardson 
36a9de470cSBruce Richardson static int
virtual_ethdev_start_success(struct rte_eth_dev * eth_dev __rte_unused)37a9de470cSBruce Richardson virtual_ethdev_start_success(struct rte_eth_dev *eth_dev __rte_unused)
38a9de470cSBruce Richardson {
39a9de470cSBruce Richardson 	eth_dev->data->dev_started = 1;
40a9de470cSBruce Richardson 
41a9de470cSBruce Richardson 	return 0;
42a9de470cSBruce Richardson }
43a9de470cSBruce Richardson 
44a9de470cSBruce Richardson static int
virtual_ethdev_start_fail(struct rte_eth_dev * eth_dev __rte_unused)45a9de470cSBruce Richardson virtual_ethdev_start_fail(struct rte_eth_dev *eth_dev __rte_unused)
46a9de470cSBruce Richardson {
47a9de470cSBruce Richardson 	eth_dev->data->dev_started = 0;
48a9de470cSBruce Richardson 
49a9de470cSBruce Richardson 	return -1;
50a9de470cSBruce Richardson }
virtual_ethdev_stop(struct rte_eth_dev * eth_dev __rte_unused)5162024eb8SIvan Ilchenko static int  virtual_ethdev_stop(struct rte_eth_dev *eth_dev __rte_unused)
52a9de470cSBruce Richardson {
53a9de470cSBruce Richardson 	void *pkt = NULL;
54a9de470cSBruce Richardson 	struct virtual_ethdev_private *prv = eth_dev->data->dev_private;
55a9de470cSBruce Richardson 
56295968d1SFerruh Yigit 	eth_dev->data->dev_link.link_status = RTE_ETH_LINK_DOWN;
57a9de470cSBruce Richardson 	eth_dev->data->dev_started = 0;
58a9de470cSBruce Richardson 	while (rte_ring_dequeue(prv->rx_queue, &pkt) != -ENOENT)
59a9de470cSBruce Richardson 		rte_pktmbuf_free(pkt);
60a9de470cSBruce Richardson 
61a9de470cSBruce Richardson 	while (rte_ring_dequeue(prv->tx_queue, &pkt) != -ENOENT)
62a9de470cSBruce Richardson 		rte_pktmbuf_free(pkt);
6362024eb8SIvan Ilchenko 
6462024eb8SIvan Ilchenko 	return 0;
65a9de470cSBruce Richardson }
66a9de470cSBruce Richardson 
67b142387bSThomas Monjalon static int
virtual_ethdev_close(struct rte_eth_dev * dev __rte_unused)68a9de470cSBruce Richardson virtual_ethdev_close(struct rte_eth_dev *dev __rte_unused)
69b142387bSThomas Monjalon {
70b142387bSThomas Monjalon 	return 0;
71b142387bSThomas Monjalon }
72a9de470cSBruce Richardson 
73a9de470cSBruce Richardson static int
virtual_ethdev_configure_success(struct rte_eth_dev * dev __rte_unused)74a9de470cSBruce Richardson virtual_ethdev_configure_success(struct rte_eth_dev *dev __rte_unused)
75a9de470cSBruce Richardson {
76a9de470cSBruce Richardson 	return 0;
77a9de470cSBruce Richardson }
78a9de470cSBruce Richardson 
79a9de470cSBruce Richardson static int
virtual_ethdev_configure_fail(struct rte_eth_dev * dev __rte_unused)80a9de470cSBruce Richardson virtual_ethdev_configure_fail(struct rte_eth_dev *dev __rte_unused)
81a9de470cSBruce Richardson {
82a9de470cSBruce Richardson 	return -1;
83a9de470cSBruce Richardson }
84a9de470cSBruce Richardson 
85bdad90d1SIvan Ilchenko static int
virtual_ethdev_info_get(struct rte_eth_dev * dev __rte_unused,struct rte_eth_dev_info * dev_info)86a9de470cSBruce Richardson virtual_ethdev_info_get(struct rte_eth_dev *dev __rte_unused,
87a9de470cSBruce Richardson 		struct rte_eth_dev_info *dev_info)
88a9de470cSBruce Richardson {
89a9de470cSBruce Richardson 	dev_info->driver_name = virtual_ethdev_driver_name;
90a9de470cSBruce Richardson 	dev_info->max_mac_addrs = 1;
91a9de470cSBruce Richardson 
92a9de470cSBruce Richardson 	dev_info->max_rx_pktlen = (uint32_t)2048;
93a9de470cSBruce Richardson 
94a9de470cSBruce Richardson 	dev_info->max_rx_queues = (uint16_t)128;
95a9de470cSBruce Richardson 	dev_info->max_tx_queues = (uint16_t)512;
96a9de470cSBruce Richardson 
97a9de470cSBruce Richardson 	dev_info->min_rx_bufsize = 0;
98bdad90d1SIvan Ilchenko 
99bdad90d1SIvan Ilchenko 	return 0;
100a9de470cSBruce Richardson }
101a9de470cSBruce Richardson 
102a9de470cSBruce Richardson 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)103a9de470cSBruce Richardson virtual_ethdev_rx_queue_setup_success(struct rte_eth_dev *dev,
104a9de470cSBruce Richardson 		uint16_t rx_queue_id, uint16_t nb_rx_desc __rte_unused,
105a9de470cSBruce Richardson 		unsigned int socket_id,
106a9de470cSBruce Richardson 		const struct rte_eth_rxconf *rx_conf __rte_unused,
107a9de470cSBruce Richardson 		struct rte_mempool *mb_pool __rte_unused)
108a9de470cSBruce Richardson {
109a9de470cSBruce Richardson 	struct virtual_ethdev_queue *rx_q;
110a9de470cSBruce Richardson 
111a9de470cSBruce Richardson 	rx_q = (struct virtual_ethdev_queue *)rte_zmalloc_socket(NULL,
112a9de470cSBruce Richardson 			sizeof(struct virtual_ethdev_queue), 0, socket_id);
113a9de470cSBruce Richardson 
114a9de470cSBruce Richardson 	if (rx_q == NULL)
115a9de470cSBruce Richardson 		return -1;
116a9de470cSBruce Richardson 
117a9de470cSBruce Richardson 	rx_q->port_id = dev->data->port_id;
118a9de470cSBruce Richardson 	rx_q->queue_id = rx_queue_id;
119a9de470cSBruce Richardson 
120a9de470cSBruce Richardson 	dev->data->rx_queues[rx_queue_id] = rx_q;
121a9de470cSBruce Richardson 
122a9de470cSBruce Richardson 	return 0;
123a9de470cSBruce Richardson }
124a9de470cSBruce Richardson 
125a9de470cSBruce Richardson 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)126a9de470cSBruce Richardson virtual_ethdev_rx_queue_setup_fail(struct rte_eth_dev *dev __rte_unused,
127a9de470cSBruce Richardson 		uint16_t rx_queue_id __rte_unused, uint16_t nb_rx_desc __rte_unused,
128a9de470cSBruce Richardson 		unsigned int socket_id __rte_unused,
129a9de470cSBruce Richardson 		const struct rte_eth_rxconf *rx_conf __rte_unused,
130a9de470cSBruce Richardson 		struct rte_mempool *mb_pool __rte_unused)
131a9de470cSBruce Richardson {
132a9de470cSBruce Richardson 	return -1;
133a9de470cSBruce Richardson }
134a9de470cSBruce Richardson 
135a9de470cSBruce Richardson 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)136a9de470cSBruce Richardson virtual_ethdev_tx_queue_setup_success(struct rte_eth_dev *dev,
137a9de470cSBruce Richardson 		uint16_t tx_queue_id, uint16_t nb_tx_desc __rte_unused,
138a9de470cSBruce Richardson 		unsigned int socket_id,
139a9de470cSBruce Richardson 		const struct rte_eth_txconf *tx_conf __rte_unused)
140a9de470cSBruce Richardson {
141a9de470cSBruce Richardson 	struct virtual_ethdev_queue *tx_q;
142a9de470cSBruce Richardson 
143a9de470cSBruce Richardson 	tx_q = (struct virtual_ethdev_queue *)rte_zmalloc_socket(NULL,
144a9de470cSBruce Richardson 			sizeof(struct virtual_ethdev_queue), 0, socket_id);
145a9de470cSBruce Richardson 
146a9de470cSBruce Richardson 	if (tx_q == NULL)
147a9de470cSBruce Richardson 		return -1;
148a9de470cSBruce Richardson 
149a9de470cSBruce Richardson 	tx_q->port_id = dev->data->port_id;
150a9de470cSBruce Richardson 	tx_q->queue_id = tx_queue_id;
151a9de470cSBruce Richardson 
152a9de470cSBruce Richardson 	dev->data->tx_queues[tx_queue_id] = tx_q;
153a9de470cSBruce Richardson 
154a9de470cSBruce Richardson 	return 0;
155a9de470cSBruce Richardson }
156a9de470cSBruce Richardson 
157a9de470cSBruce Richardson 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)158a9de470cSBruce Richardson virtual_ethdev_tx_queue_setup_fail(struct rte_eth_dev *dev __rte_unused,
159a9de470cSBruce Richardson 		uint16_t tx_queue_id __rte_unused, uint16_t nb_tx_desc __rte_unused,
160a9de470cSBruce Richardson 		unsigned int socket_id __rte_unused,
161a9de470cSBruce Richardson 		const struct rte_eth_txconf *tx_conf __rte_unused)
162a9de470cSBruce Richardson {
163a9de470cSBruce Richardson 	return -1;
164a9de470cSBruce Richardson }
165a9de470cSBruce Richardson 
166a9de470cSBruce Richardson static int
virtual_ethdev_link_update_success(struct rte_eth_dev * bonding_eth_dev,int wait_to_complete __rte_unused)167*4f840086SLong Wu virtual_ethdev_link_update_success(struct rte_eth_dev *bonding_eth_dev,
168a9de470cSBruce Richardson 		int wait_to_complete __rte_unused)
169a9de470cSBruce Richardson {
170*4f840086SLong Wu 	if (!bonding_eth_dev->data->dev_started)
171*4f840086SLong Wu 		bonding_eth_dev->data->dev_link.link_status = RTE_ETH_LINK_DOWN;
172a9de470cSBruce Richardson 
173a9de470cSBruce Richardson 	return 0;
174a9de470cSBruce Richardson }
175a9de470cSBruce Richardson 
176a9de470cSBruce Richardson static int
virtual_ethdev_link_update_fail(struct rte_eth_dev * bonding_eth_dev __rte_unused,int wait_to_complete __rte_unused)177*4f840086SLong Wu virtual_ethdev_link_update_fail(struct rte_eth_dev *bonding_eth_dev __rte_unused,
178a9de470cSBruce Richardson 		int wait_to_complete __rte_unused)
179a9de470cSBruce Richardson {
180a9de470cSBruce Richardson 	return -1;
181a9de470cSBruce Richardson }
182a9de470cSBruce Richardson 
183a9de470cSBruce Richardson static int
virtual_ethdev_stats_get(struct rte_eth_dev * dev,struct rte_eth_stats * stats)184a9de470cSBruce Richardson virtual_ethdev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
185a9de470cSBruce Richardson {
186a9de470cSBruce Richardson 	struct virtual_ethdev_private *dev_private = dev->data->dev_private;
187a9de470cSBruce Richardson 
188a9de470cSBruce Richardson 	if (stats)
189a9de470cSBruce Richardson 		rte_memcpy(stats, &dev_private->eth_stats, sizeof(*stats));
190a9de470cSBruce Richardson 
191a9de470cSBruce Richardson 	return 0;
192a9de470cSBruce Richardson }
193a9de470cSBruce Richardson 
1949970a9adSIgor Romanov static int
virtual_ethdev_stats_reset(struct rte_eth_dev * dev)195a9de470cSBruce Richardson virtual_ethdev_stats_reset(struct rte_eth_dev *dev)
196a9de470cSBruce Richardson {
197a9de470cSBruce Richardson 	struct virtual_ethdev_private *dev_private = dev->data->dev_private;
198a9de470cSBruce Richardson 	void *pkt = NULL;
199a9de470cSBruce Richardson 
200a9de470cSBruce Richardson 	while (rte_ring_dequeue(dev_private->tx_queue, &pkt) == -ENOBUFS)
201a9de470cSBruce Richardson 			rte_pktmbuf_free(pkt);
202a9de470cSBruce Richardson 
203a9de470cSBruce Richardson 	/* Reset internal statistics */
204a9de470cSBruce Richardson 	memset(&dev_private->eth_stats, 0, sizeof(dev_private->eth_stats));
2059970a9adSIgor Romanov 
2069970a9adSIgor Romanov 	return 0;
207a9de470cSBruce Richardson }
208a9de470cSBruce Richardson 
2099039c812SAndrew Rybchenko static int
virtual_ethdev_promiscuous_mode_enable(struct rte_eth_dev * dev __rte_unused)210a9de470cSBruce Richardson virtual_ethdev_promiscuous_mode_enable(struct rte_eth_dev *dev __rte_unused)
2119039c812SAndrew Rybchenko {
2129039c812SAndrew Rybchenko 	return 0;
2139039c812SAndrew Rybchenko }
214a9de470cSBruce Richardson 
2159039c812SAndrew Rybchenko static int
virtual_ethdev_promiscuous_mode_disable(struct rte_eth_dev * dev __rte_unused)216a9de470cSBruce Richardson virtual_ethdev_promiscuous_mode_disable(struct rte_eth_dev *dev __rte_unused)
2179039c812SAndrew Rybchenko {
2189039c812SAndrew Rybchenko 	return 0;
2199039c812SAndrew Rybchenko }
220a9de470cSBruce Richardson 
221a9de470cSBruce Richardson static int
virtual_ethdev_mac_address_set(__rte_unused struct rte_eth_dev * dev,__rte_unused struct rte_ether_addr * addr)222a9de470cSBruce Richardson virtual_ethdev_mac_address_set(__rte_unused struct rte_eth_dev *dev,
2236d13ea8eSOlivier Matz 			       __rte_unused struct rte_ether_addr *addr)
224a9de470cSBruce Richardson {
225a9de470cSBruce Richardson 	return 0;
226a9de470cSBruce Richardson }
227a9de470cSBruce Richardson 
228a9de470cSBruce Richardson static const struct eth_dev_ops virtual_ethdev_default_dev_ops = {
229a9de470cSBruce Richardson 	.dev_configure = virtual_ethdev_configure_success,
230a9de470cSBruce Richardson 	.dev_start = virtual_ethdev_start_success,
231a9de470cSBruce Richardson 	.dev_stop = virtual_ethdev_stop,
232a9de470cSBruce Richardson 	.dev_close = virtual_ethdev_close,
233a9de470cSBruce Richardson 	.dev_infos_get = virtual_ethdev_info_get,
234a9de470cSBruce Richardson 	.rx_queue_setup = virtual_ethdev_rx_queue_setup_success,
235a9de470cSBruce Richardson 	.tx_queue_setup = virtual_ethdev_tx_queue_setup_success,
236a9de470cSBruce Richardson 	.link_update = virtual_ethdev_link_update_success,
237a9de470cSBruce Richardson 	.mac_addr_set = virtual_ethdev_mac_address_set,
238a9de470cSBruce Richardson 	.stats_get = virtual_ethdev_stats_get,
239a9de470cSBruce Richardson 	.stats_reset = virtual_ethdev_stats_reset,
240a9de470cSBruce Richardson 	.promiscuous_enable = virtual_ethdev_promiscuous_mode_enable,
241a9de470cSBruce Richardson 	.promiscuous_disable = virtual_ethdev_promiscuous_mode_disable
242a9de470cSBruce Richardson };
243a9de470cSBruce Richardson 
244a9de470cSBruce Richardson void
virtual_ethdev_start_fn_set_success(uint16_t port_id,uint8_t success)245a9de470cSBruce Richardson virtual_ethdev_start_fn_set_success(uint16_t port_id, uint8_t success)
246a9de470cSBruce Richardson {
247a9de470cSBruce Richardson 	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
248a9de470cSBruce Richardson 	struct virtual_ethdev_private *dev_private = dev->data->dev_private;
249a9de470cSBruce Richardson 	struct eth_dev_ops *dev_ops = &dev_private->dev_ops;
250a9de470cSBruce Richardson 
251a9de470cSBruce Richardson 	if (success)
252a9de470cSBruce Richardson 		dev_ops->dev_start = virtual_ethdev_start_success;
253a9de470cSBruce Richardson 	else
254a9de470cSBruce Richardson 		dev_ops->dev_start = virtual_ethdev_start_fail;
255a9de470cSBruce Richardson 
256a9de470cSBruce Richardson }
257a9de470cSBruce Richardson 
258a9de470cSBruce Richardson void
virtual_ethdev_configure_fn_set_success(uint16_t port_id,uint8_t success)259a9de470cSBruce Richardson virtual_ethdev_configure_fn_set_success(uint16_t port_id, uint8_t success)
260a9de470cSBruce Richardson {
261a9de470cSBruce Richardson 	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
262a9de470cSBruce Richardson 	struct virtual_ethdev_private *dev_private = dev->data->dev_private;
263a9de470cSBruce Richardson 	struct eth_dev_ops *dev_ops = &dev_private->dev_ops;
264a9de470cSBruce Richardson 
265a9de470cSBruce Richardson 	if (success)
266a9de470cSBruce Richardson 		dev_ops->dev_configure = virtual_ethdev_configure_success;
267a9de470cSBruce Richardson 	else
268a9de470cSBruce Richardson 		dev_ops->dev_configure = virtual_ethdev_configure_fail;
269a9de470cSBruce Richardson }
270a9de470cSBruce Richardson 
271a9de470cSBruce Richardson void
virtual_ethdev_rx_queue_setup_fn_set_success(uint16_t port_id,uint8_t success)272a9de470cSBruce Richardson virtual_ethdev_rx_queue_setup_fn_set_success(uint16_t port_id, uint8_t success)
273a9de470cSBruce Richardson {
274a9de470cSBruce Richardson 	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
275a9de470cSBruce Richardson 	struct virtual_ethdev_private *dev_private = dev->data->dev_private;
276a9de470cSBruce Richardson 	struct eth_dev_ops *dev_ops = &dev_private->dev_ops;
277a9de470cSBruce Richardson 
278a9de470cSBruce Richardson 	if (success)
279a9de470cSBruce Richardson 		dev_ops->rx_queue_setup = virtual_ethdev_rx_queue_setup_success;
280a9de470cSBruce Richardson 	else
281a9de470cSBruce Richardson 		dev_ops->rx_queue_setup = virtual_ethdev_rx_queue_setup_fail;
282a9de470cSBruce Richardson }
283a9de470cSBruce Richardson 
284a9de470cSBruce Richardson void
virtual_ethdev_tx_queue_setup_fn_set_success(uint16_t port_id,uint8_t success)285a9de470cSBruce Richardson virtual_ethdev_tx_queue_setup_fn_set_success(uint16_t port_id, uint8_t success)
286a9de470cSBruce Richardson {
287a9de470cSBruce Richardson 	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
288a9de470cSBruce Richardson 	struct virtual_ethdev_private *dev_private = dev->data->dev_private;
289a9de470cSBruce Richardson 	struct eth_dev_ops *dev_ops = &dev_private->dev_ops;
290a9de470cSBruce Richardson 
291a9de470cSBruce Richardson 	if (success)
292a9de470cSBruce Richardson 		dev_ops->tx_queue_setup = virtual_ethdev_tx_queue_setup_success;
293a9de470cSBruce Richardson 	else
294a9de470cSBruce Richardson 		dev_ops->tx_queue_setup = virtual_ethdev_tx_queue_setup_fail;
295a9de470cSBruce Richardson }
296a9de470cSBruce Richardson 
297a9de470cSBruce Richardson void
virtual_ethdev_link_update_fn_set_success(uint16_t port_id,uint8_t success)298a9de470cSBruce Richardson virtual_ethdev_link_update_fn_set_success(uint16_t port_id, uint8_t success)
299a9de470cSBruce Richardson {
300a9de470cSBruce Richardson 	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
301a9de470cSBruce Richardson 	struct virtual_ethdev_private *dev_private = dev->data->dev_private;
302a9de470cSBruce Richardson 	struct eth_dev_ops *dev_ops = &dev_private->dev_ops;
303a9de470cSBruce Richardson 
304a9de470cSBruce Richardson 	if (success)
305a9de470cSBruce Richardson 		dev_ops->link_update = virtual_ethdev_link_update_success;
306a9de470cSBruce Richardson 	else
307a9de470cSBruce Richardson 		dev_ops->link_update = virtual_ethdev_link_update_fail;
308a9de470cSBruce Richardson }
309a9de470cSBruce Richardson 
310a9de470cSBruce Richardson 
311a9de470cSBruce Richardson static uint16_t
virtual_ethdev_rx_burst_success(void * queue __rte_unused,struct rte_mbuf ** bufs,uint16_t nb_pkts)312a9de470cSBruce Richardson virtual_ethdev_rx_burst_success(void *queue __rte_unused,
313a9de470cSBruce Richardson 							 struct rte_mbuf **bufs,
314a9de470cSBruce Richardson 							 uint16_t nb_pkts)
315a9de470cSBruce Richardson {
316a9de470cSBruce Richardson 	struct rte_eth_dev *vrtl_eth_dev;
317a9de470cSBruce Richardson 	struct virtual_ethdev_queue *pq_map;
318a9de470cSBruce Richardson 	struct virtual_ethdev_private *dev_private;
319a9de470cSBruce Richardson 
320a9de470cSBruce Richardson 	int rx_count, i;
321a9de470cSBruce Richardson 
322a9de470cSBruce Richardson 	pq_map = (struct virtual_ethdev_queue *)queue;
323a9de470cSBruce Richardson 	vrtl_eth_dev = &rte_eth_devices[pq_map->port_id];
324a9de470cSBruce Richardson 	dev_private = vrtl_eth_dev->data->dev_private;
325a9de470cSBruce Richardson 
326a9de470cSBruce Richardson 	rx_count = rte_ring_dequeue_burst(dev_private->rx_queue, (void **) bufs,
327a9de470cSBruce Richardson 			nb_pkts, NULL);
328a9de470cSBruce Richardson 
329a9de470cSBruce Richardson 	/* increments ipackets count */
330a9de470cSBruce Richardson 	dev_private->eth_stats.ipackets += rx_count;
331a9de470cSBruce Richardson 
332a9de470cSBruce Richardson 	/* increments ibytes count */
333a9de470cSBruce Richardson 	for (i = 0; i < rx_count; i++)
334a9de470cSBruce Richardson 		dev_private->eth_stats.ibytes += rte_pktmbuf_pkt_len(bufs[i]);
335a9de470cSBruce Richardson 
336a9de470cSBruce Richardson 	return rx_count;
337a9de470cSBruce Richardson }
338a9de470cSBruce Richardson 
339a9de470cSBruce Richardson static uint16_t
virtual_ethdev_rx_burst_fail(void * queue __rte_unused,struct rte_mbuf ** bufs __rte_unused,uint16_t nb_pkts __rte_unused)340a9de470cSBruce Richardson virtual_ethdev_rx_burst_fail(void *queue __rte_unused,
341a9de470cSBruce Richardson 							 struct rte_mbuf **bufs __rte_unused,
342a9de470cSBruce Richardson 							 uint16_t nb_pkts __rte_unused)
343a9de470cSBruce Richardson {
344a9de470cSBruce Richardson 	return 0;
345a9de470cSBruce Richardson }
346a9de470cSBruce Richardson 
347a9de470cSBruce Richardson static uint16_t
virtual_ethdev_tx_burst_success(void * queue,struct rte_mbuf ** bufs,uint16_t nb_pkts)348a9de470cSBruce Richardson virtual_ethdev_tx_burst_success(void *queue, struct rte_mbuf **bufs,
349a9de470cSBruce Richardson 		uint16_t nb_pkts)
350a9de470cSBruce Richardson {
351a9de470cSBruce Richardson 	struct virtual_ethdev_queue *tx_q = queue;
352a9de470cSBruce Richardson 
353a9de470cSBruce Richardson 	struct rte_eth_dev *vrtl_eth_dev;
354a9de470cSBruce Richardson 	struct virtual_ethdev_private *dev_private;
355a9de470cSBruce Richardson 
356a9de470cSBruce Richardson 	int i;
357a9de470cSBruce Richardson 
358a9de470cSBruce Richardson 	vrtl_eth_dev = &rte_eth_devices[tx_q->port_id];
359a9de470cSBruce Richardson 	dev_private = vrtl_eth_dev->data->dev_private;
360a9de470cSBruce Richardson 
361a9de470cSBruce Richardson 	if (!vrtl_eth_dev->data->dev_link.link_status)
362a9de470cSBruce Richardson 		nb_pkts = 0;
363a9de470cSBruce Richardson 	else
364a9de470cSBruce Richardson 		nb_pkts = rte_ring_enqueue_burst(dev_private->tx_queue, (void **)bufs,
365a9de470cSBruce Richardson 				nb_pkts, NULL);
366a9de470cSBruce Richardson 
367a9de470cSBruce Richardson 	/* increment opacket count */
368a9de470cSBruce Richardson 	dev_private->eth_stats.opackets += nb_pkts;
369a9de470cSBruce Richardson 
370a9de470cSBruce Richardson 	/* increment obytes count */
371a9de470cSBruce Richardson 	for (i = 0; i < nb_pkts; i++)
372a9de470cSBruce Richardson 		dev_private->eth_stats.obytes += rte_pktmbuf_pkt_len(bufs[i]);
373a9de470cSBruce Richardson 
374a9de470cSBruce Richardson 	return nb_pkts;
375a9de470cSBruce Richardson }
376a9de470cSBruce Richardson 
377a9de470cSBruce Richardson static uint16_t
virtual_ethdev_tx_burst_fail(void * queue,struct rte_mbuf ** bufs,uint16_t nb_pkts)378a9de470cSBruce Richardson virtual_ethdev_tx_burst_fail(void *queue, struct rte_mbuf **bufs,
379a9de470cSBruce Richardson 		uint16_t nb_pkts)
380a9de470cSBruce Richardson {
381a9de470cSBruce Richardson 	struct rte_eth_dev *vrtl_eth_dev = NULL;
382a9de470cSBruce Richardson 	struct virtual_ethdev_queue *tx_q = NULL;
383a9de470cSBruce Richardson 	struct virtual_ethdev_private *dev_private = NULL;
384a9de470cSBruce Richardson 
385a9de470cSBruce Richardson 	int i;
386a9de470cSBruce Richardson 
387a9de470cSBruce Richardson 	tx_q = queue;
388a9de470cSBruce Richardson 	vrtl_eth_dev = &rte_eth_devices[tx_q->port_id];
389a9de470cSBruce Richardson 	dev_private = vrtl_eth_dev->data->dev_private;
390a9de470cSBruce Richardson 
391a9de470cSBruce Richardson 	if (dev_private->tx_burst_fail_count < nb_pkts) {
392a9de470cSBruce Richardson 		int successfully_txd = nb_pkts - dev_private->tx_burst_fail_count;
393a9de470cSBruce Richardson 
394a9de470cSBruce Richardson 		/* increment opacket count */
395a9de470cSBruce Richardson 		dev_private->eth_stats.opackets += successfully_txd;
396a9de470cSBruce Richardson 
397a9de470cSBruce Richardson 		/* free packets in burst */
398a9de470cSBruce Richardson 		for (i = 0; i < successfully_txd; i++) {
399a9de470cSBruce Richardson 			/* free packets in burst */
400a9de470cSBruce Richardson 			rte_pktmbuf_free(bufs[i]);
401a9de470cSBruce Richardson 
402a9de470cSBruce Richardson 			bufs[i] = NULL;
403a9de470cSBruce Richardson 		}
404a9de470cSBruce Richardson 
405a9de470cSBruce Richardson 		return successfully_txd;
406a9de470cSBruce Richardson 	}
407a9de470cSBruce Richardson 
408a9de470cSBruce Richardson 	return 0;
409a9de470cSBruce Richardson }
410a9de470cSBruce Richardson 
411a9de470cSBruce Richardson 
412a9de470cSBruce Richardson void
virtual_ethdev_rx_burst_fn_set_success(uint16_t port_id,uint8_t success)413a9de470cSBruce Richardson virtual_ethdev_rx_burst_fn_set_success(uint16_t port_id, uint8_t success)
414a9de470cSBruce Richardson {
415a9de470cSBruce Richardson 	struct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id];
416a9de470cSBruce Richardson 
417a136b08cSKonstantin Ananyev 	rte_eth_dev_stop(port_id);
418a136b08cSKonstantin Ananyev 
419a9de470cSBruce Richardson 	if (success)
420a9de470cSBruce Richardson 		vrtl_eth_dev->rx_pkt_burst = virtual_ethdev_rx_burst_success;
421a9de470cSBruce Richardson 	else
422a9de470cSBruce Richardson 		vrtl_eth_dev->rx_pkt_burst = virtual_ethdev_rx_burst_fail;
423a136b08cSKonstantin Ananyev 
424a136b08cSKonstantin Ananyev 	rte_eth_dev_start(port_id);
425a9de470cSBruce Richardson }
426a9de470cSBruce Richardson 
427a9de470cSBruce Richardson 
428a9de470cSBruce Richardson void
virtual_ethdev_tx_burst_fn_set_success(uint16_t port_id,uint8_t success)429a9de470cSBruce Richardson virtual_ethdev_tx_burst_fn_set_success(uint16_t port_id, uint8_t success)
430a9de470cSBruce Richardson {
431a9de470cSBruce Richardson 	struct virtual_ethdev_private *dev_private = NULL;
432a9de470cSBruce Richardson 	struct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id];
433a9de470cSBruce Richardson 
434a136b08cSKonstantin Ananyev 	rte_eth_dev_stop(port_id);
435a9de470cSBruce Richardson 	dev_private = vrtl_eth_dev->data->dev_private;
436a9de470cSBruce Richardson 
437a9de470cSBruce Richardson 	if (success)
438a9de470cSBruce Richardson 		vrtl_eth_dev->tx_pkt_burst = virtual_ethdev_tx_burst_success;
439a9de470cSBruce Richardson 	else
440a9de470cSBruce Richardson 		vrtl_eth_dev->tx_pkt_burst = virtual_ethdev_tx_burst_fail;
441a9de470cSBruce Richardson 
442a9de470cSBruce Richardson 	dev_private->tx_burst_fail_count = 0;
443a136b08cSKonstantin Ananyev 	rte_eth_dev_start(port_id);
444a9de470cSBruce Richardson }
445a9de470cSBruce Richardson 
446a9de470cSBruce Richardson void
virtual_ethdev_tx_burst_fn_set_tx_pkt_fail_count(uint16_t port_id,uint8_t packet_fail_count)447a9de470cSBruce Richardson virtual_ethdev_tx_burst_fn_set_tx_pkt_fail_count(uint16_t port_id,
448a9de470cSBruce Richardson 		uint8_t packet_fail_count)
449a9de470cSBruce Richardson {
450a9de470cSBruce Richardson 	struct virtual_ethdev_private *dev_private = NULL;
451a9de470cSBruce Richardson 	struct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id];
452a9de470cSBruce Richardson 
453a9de470cSBruce Richardson 	dev_private = vrtl_eth_dev->data->dev_private;
454a9de470cSBruce Richardson 	dev_private->tx_burst_fail_count = packet_fail_count;
455a9de470cSBruce Richardson }
456a9de470cSBruce Richardson 
457a9de470cSBruce Richardson void
virtual_ethdev_set_link_status(uint16_t port_id,uint8_t link_status)458a9de470cSBruce Richardson virtual_ethdev_set_link_status(uint16_t port_id, uint8_t link_status)
459a9de470cSBruce Richardson {
460a9de470cSBruce Richardson 	struct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id];
461a9de470cSBruce Richardson 
462a9de470cSBruce Richardson 	vrtl_eth_dev->data->dev_link.link_status = link_status;
463a9de470cSBruce Richardson }
464a9de470cSBruce Richardson 
465a9de470cSBruce Richardson void
virtual_ethdev_simulate_link_status_interrupt(uint16_t port_id,uint8_t link_status)466a9de470cSBruce Richardson virtual_ethdev_simulate_link_status_interrupt(uint16_t port_id,
467a9de470cSBruce Richardson 		uint8_t link_status)
468a9de470cSBruce Richardson {
469a9de470cSBruce Richardson 	struct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id];
470a9de470cSBruce Richardson 
471a9de470cSBruce Richardson 	vrtl_eth_dev->data->dev_link.link_status = link_status;
472a9de470cSBruce Richardson 
4735723fbedSFerruh Yigit 	rte_eth_dev_callback_process(vrtl_eth_dev, RTE_ETH_EVENT_INTR_LSC,
474a9de470cSBruce Richardson 				     NULL);
475a9de470cSBruce Richardson }
476a9de470cSBruce Richardson 
477a9de470cSBruce Richardson int
virtual_ethdev_add_mbufs_to_rx_queue(uint16_t port_id,struct rte_mbuf ** pkt_burst,int burst_length)478a9de470cSBruce Richardson virtual_ethdev_add_mbufs_to_rx_queue(uint16_t port_id,
479a9de470cSBruce Richardson 		struct rte_mbuf **pkt_burst, int burst_length)
480a9de470cSBruce Richardson {
481a9de470cSBruce Richardson 	struct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id];
482a9de470cSBruce Richardson 	struct virtual_ethdev_private *dev_private =
483a9de470cSBruce Richardson 			vrtl_eth_dev->data->dev_private;
484a9de470cSBruce Richardson 
485a9de470cSBruce Richardson 	return rte_ring_enqueue_burst(dev_private->rx_queue, (void **)pkt_burst,
486a9de470cSBruce Richardson 			burst_length, NULL);
487a9de470cSBruce Richardson }
488a9de470cSBruce Richardson 
489a9de470cSBruce Richardson int
virtual_ethdev_get_mbufs_from_tx_queue(uint16_t port_id,struct rte_mbuf ** pkt_burst,int burst_length)490a9de470cSBruce Richardson virtual_ethdev_get_mbufs_from_tx_queue(uint16_t port_id,
491a9de470cSBruce Richardson 		struct rte_mbuf **pkt_burst, int burst_length)
492a9de470cSBruce Richardson {
493a9de470cSBruce Richardson 	struct virtual_ethdev_private *dev_private;
494a9de470cSBruce Richardson 	struct rte_eth_dev *vrtl_eth_dev = &rte_eth_devices[port_id];
495a9de470cSBruce Richardson 
496a9de470cSBruce Richardson 	dev_private = vrtl_eth_dev->data->dev_private;
497a9de470cSBruce Richardson 	return rte_ring_dequeue_burst(dev_private->tx_queue, (void **)pkt_burst,
498a9de470cSBruce Richardson 		burst_length, NULL);
499a9de470cSBruce Richardson }
500a9de470cSBruce Richardson 
501a9de470cSBruce Richardson 
502a9de470cSBruce Richardson int
virtual_ethdev_create(const char * name,struct rte_ether_addr * mac_addr,uint8_t socket_id,uint8_t isr_support)5036d13ea8eSOlivier Matz virtual_ethdev_create(const char *name, struct rte_ether_addr *mac_addr,
504a9de470cSBruce Richardson 		uint8_t socket_id, uint8_t isr_support)
505a9de470cSBruce Richardson {
506a9de470cSBruce Richardson 	struct rte_pci_device *pci_dev = NULL;
507a9de470cSBruce Richardson 	struct rte_eth_dev *eth_dev = NULL;
508a9de470cSBruce Richardson 	struct rte_pci_driver *pci_drv = NULL;
509a9de470cSBruce Richardson 	struct rte_pci_id *id_table = NULL;
510a9de470cSBruce Richardson 	struct virtual_ethdev_private *dev_private = NULL;
511a9de470cSBruce Richardson 	char name_buf[RTE_RING_NAMESIZE];
512a9de470cSBruce Richardson 
513a9de470cSBruce Richardson 
514a9de470cSBruce Richardson 	/* now do all data allocation - for eth_dev structure, dummy pci driver
515a9de470cSBruce Richardson 	 * and internal (dev_private) data
516a9de470cSBruce Richardson 	 */
517a9de470cSBruce Richardson 
518a9de470cSBruce Richardson 	pci_dev = rte_zmalloc_socket(name, sizeof(*pci_dev), 0, socket_id);
519a9de470cSBruce Richardson 	if (pci_dev == NULL)
520a9de470cSBruce Richardson 		goto err;
521a9de470cSBruce Richardson 
522a9de470cSBruce Richardson 	pci_drv = rte_zmalloc_socket(name, sizeof(*pci_drv), 0, socket_id);
523a9de470cSBruce Richardson 	if (pci_drv == NULL)
524a9de470cSBruce Richardson 		goto err;
525a9de470cSBruce Richardson 
526a9de470cSBruce Richardson 	id_table = rte_zmalloc_socket(name, sizeof(*id_table), 0, socket_id);
527a9de470cSBruce Richardson 	if (id_table == NULL)
528a9de470cSBruce Richardson 		goto err;
529a9de470cSBruce Richardson 	id_table->device_id = 0xBEEF;
530a9de470cSBruce Richardson 
531a9de470cSBruce Richardson 	dev_private = rte_zmalloc_socket(name, sizeof(*dev_private), 0, socket_id);
532a9de470cSBruce Richardson 	if (dev_private == NULL)
533a9de470cSBruce Richardson 		goto err;
534a9de470cSBruce Richardson 
535a9de470cSBruce Richardson 	snprintf(name_buf, sizeof(name_buf), "%s_rxQ", name);
536a9de470cSBruce Richardson 	dev_private->rx_queue = rte_ring_create(name_buf, MAX_PKT_BURST, socket_id,
537a9de470cSBruce Richardson 			0);
538a9de470cSBruce Richardson 	if (dev_private->rx_queue == NULL)
539a9de470cSBruce Richardson 		goto err;
540a9de470cSBruce Richardson 
541a9de470cSBruce Richardson 	snprintf(name_buf, sizeof(name_buf), "%s_txQ", name);
542a9de470cSBruce Richardson 	dev_private->tx_queue = rte_ring_create(name_buf, MAX_PKT_BURST, socket_id,
543a9de470cSBruce Richardson 			0);
544a9de470cSBruce Richardson 	if (dev_private->tx_queue == NULL)
545a9de470cSBruce Richardson 		goto err;
546a9de470cSBruce Richardson 
547a9de470cSBruce Richardson 	/* reserve an ethdev entry */
548a9de470cSBruce Richardson 	eth_dev = rte_eth_dev_allocate(name);
549a9de470cSBruce Richardson 	if (eth_dev == NULL)
550a9de470cSBruce Richardson 		goto err;
551a9de470cSBruce Richardson 
552a9de470cSBruce Richardson 	pci_dev->device.numa_node = socket_id;
553a9de470cSBruce Richardson 	pci_dev->device.name = eth_dev->data->name;
554a9de470cSBruce Richardson 	pci_drv->driver.name = virtual_ethdev_driver_name;
555a9de470cSBruce Richardson 	pci_drv->id_table = id_table;
556a9de470cSBruce Richardson 
557a9de470cSBruce Richardson 	if (isr_support)
558a9de470cSBruce Richardson 		pci_drv->drv_flags |= RTE_PCI_DRV_INTR_LSC;
559a9de470cSBruce Richardson 	else
560a9de470cSBruce Richardson 		pci_drv->drv_flags &= ~RTE_PCI_DRV_INTR_LSC;
561a9de470cSBruce Richardson 
562a9de470cSBruce Richardson 
563a9de470cSBruce Richardson 	eth_dev->device = &pci_dev->device;
564a9de470cSBruce Richardson 	eth_dev->device->driver = &pci_drv->driver;
565a9de470cSBruce Richardson 
566a9de470cSBruce Richardson 	eth_dev->data->nb_rx_queues = (uint16_t)1;
567a9de470cSBruce Richardson 	eth_dev->data->nb_tx_queues = (uint16_t)1;
568a9de470cSBruce Richardson 
569295968d1SFerruh Yigit 	eth_dev->data->dev_link.link_status = RTE_ETH_LINK_DOWN;
570295968d1SFerruh Yigit 	eth_dev->data->dev_link.link_speed = RTE_ETH_SPEED_NUM_10G;
571295968d1SFerruh Yigit 	eth_dev->data->dev_link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
572a9de470cSBruce Richardson 
57335b2d13fSOlivier Matz 	eth_dev->data->mac_addrs = rte_zmalloc(name, RTE_ETHER_ADDR_LEN, 0);
574a9de470cSBruce Richardson 	if (eth_dev->data->mac_addrs == NULL)
575a9de470cSBruce Richardson 		goto err;
576a9de470cSBruce Richardson 
577a9de470cSBruce Richardson 	memcpy(eth_dev->data->mac_addrs, mac_addr,
578a9de470cSBruce Richardson 			sizeof(*eth_dev->data->mac_addrs));
579a9de470cSBruce Richardson 
580a9de470cSBruce Richardson 	eth_dev->data->dev_started = 0;
581a9de470cSBruce Richardson 	eth_dev->data->promiscuous = 0;
582a9de470cSBruce Richardson 	eth_dev->data->scattered_rx = 0;
583a9de470cSBruce Richardson 	eth_dev->data->all_multicast = 0;
584a9de470cSBruce Richardson 
585a9de470cSBruce Richardson 	eth_dev->data->dev_private = dev_private;
586a9de470cSBruce Richardson 
587a9de470cSBruce Richardson 	/* Copy default device operation functions */
588a9de470cSBruce Richardson 	dev_private->dev_ops = virtual_ethdev_default_dev_ops;
589a9de470cSBruce Richardson 	eth_dev->dev_ops = &dev_private->dev_ops;
590a9de470cSBruce Richardson 
591a9de470cSBruce Richardson 	pci_dev->device.driver = &pci_drv->driver;
592a9de470cSBruce Richardson 	eth_dev->device = &pci_dev->device;
593a9de470cSBruce Richardson 
594a9de470cSBruce Richardson 	eth_dev->rx_pkt_burst = virtual_ethdev_rx_burst_success;
595a9de470cSBruce Richardson 	eth_dev->tx_pkt_burst = virtual_ethdev_tx_burst_success;
596a9de470cSBruce Richardson 
597a9de470cSBruce Richardson 	rte_eth_dev_probing_finish(eth_dev);
598a9de470cSBruce Richardson 
599a9de470cSBruce Richardson 	return eth_dev->data->port_id;
600a9de470cSBruce Richardson 
601a9de470cSBruce Richardson err:
602a9de470cSBruce Richardson 	rte_free(pci_dev);
603a9de470cSBruce Richardson 	rte_free(pci_drv);
604a9de470cSBruce Richardson 	rte_free(id_table);
605a9de470cSBruce Richardson 	rte_free(dev_private);
606a9de470cSBruce Richardson 
607a9de470cSBruce Richardson 	return -1;
608a9de470cSBruce Richardson }
609