eba4d35aa2d7ba512039ee404e28130c617b929d
[deb_dpdk.git] / examples / vhost_xen / main.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #include <arpa/inet.h>
35 #include <getopt.h>
36 #include <linux/if_ether.h>
37 #include <linux/if_vlan.h>
38 #include <linux/virtio_net.h>
39 #include <linux/virtio_ring.h>
40 #include <signal.h>
41 #include <stdint.h>
42 #include <sys/eventfd.h>
43 #include <sys/param.h>
44 #include <unistd.h>
45
46 #include <rte_atomic.h>
47 #include <rte_cycles.h>
48 #include <rte_ethdev.h>
49 #include <rte_log.h>
50 #include <rte_string_fns.h>
51 #include <rte_pause.h>
52
53 #include "main.h"
54 #include "virtio-net.h"
55 #include "xen_vhost.h"
56
57 #define MAX_QUEUES 128
58
59 /* the maximum number of external ports supported */
60 #define MAX_SUP_PORTS 1
61
62 /*
63  * Calculate the number of buffers needed per port
64  */
65 #define NUM_MBUFS_PER_PORT ((MAX_QUEUES*RTE_TEST_RX_DESC_DEFAULT) +             \
66                                                         (num_switching_cores*MAX_PKT_BURST) +                   \
67                                                         (num_switching_cores*RTE_TEST_TX_DESC_DEFAULT) +\
68                                                         (num_switching_cores*MBUF_CACHE_SIZE))
69
70 #define MBUF_CACHE_SIZE 64
71
72 /*
73  * RX and TX Prefetch, Host, and Write-back threshold values should be
74  * carefully set for optimal performance. Consult the network
75  * controller's datasheet and supporting DPDK documentation for guidance
76  * on how these parameters should be set.
77  */
78 #define RX_PTHRESH 8 /* Default values of RX prefetch threshold reg. */
79 #define RX_HTHRESH 8 /* Default values of RX host threshold reg. */
80 #define RX_WTHRESH 4 /* Default values of RX write-back threshold reg. */
81
82 /*
83  * These default values are optimized for use with the Intel(R) 82599 10 GbE
84  * Controller and the DPDK ixgbe PMD. Consider using other values for other
85  * network controllers and/or network drivers.
86  */
87 #define TX_PTHRESH 36 /* Default values of TX prefetch threshold reg. */
88 #define TX_HTHRESH 0  /* Default values of TX host threshold reg. */
89 #define TX_WTHRESH 0  /* Default values of TX write-back threshold reg. */
90
91 #define MAX_PKT_BURST 32                /* Max burst size for RX/TX */
92 #define MAX_MRG_PKT_BURST 16    /* Max burst for merge buffers. Set to 1 due to performance issue. */
93 #define BURST_TX_DRAIN_US 100   /* TX drain every ~100us */
94
95 /* State of virtio device. */
96 #define DEVICE_NOT_READY     0
97 #define DEVICE_READY         1
98 #define DEVICE_SAFE_REMOVE   2
99
100 /* Config_core_flag status definitions. */
101 #define REQUEST_DEV_REMOVAL 1
102 #define ACK_DEV_REMOVAL 0
103
104 /* Configurable number of RX/TX ring descriptors */
105 #define RTE_TEST_RX_DESC_DEFAULT 128
106 #define RTE_TEST_TX_DESC_DEFAULT 512
107
108 #define INVALID_PORT_ID 0xFF
109
110 /* Max number of devices. Limited by vmdq. */
111 #define MAX_DEVICES 64
112
113 /* Size of buffers used for snprintfs. */
114 #define MAX_PRINT_BUFF 6072
115
116
117 /* Maximum long option length for option parsing. */
118 #define MAX_LONG_OPT_SZ 64
119
120 /* Used to compare MAC addresses. */
121 #define MAC_ADDR_CMP 0xFFFFFFFFFFFF
122
123 /* mask of enabled ports */
124 static uint32_t enabled_port_mask = 0;
125
126 /*Number of switching cores enabled*/
127 static uint32_t num_switching_cores = 0;
128
129 /* number of devices/queues to support*/
130 static uint32_t num_queues = 0;
131 uint32_t num_devices = 0;
132
133 /* Enable VM2VM communications. If this is disabled then the MAC address compare is skipped. */
134 static uint32_t enable_vm2vm = 1;
135 /* Enable stats. */
136 static uint32_t enable_stats = 0;
137
138 /* empty vmdq configuration structure. Filled in programatically */
139 static const struct rte_eth_conf vmdq_conf_default = {
140         .rxmode = {
141                 .mq_mode        = ETH_MQ_RX_VMDQ_ONLY,
142                 .split_hdr_size = 0,
143                 .header_split   = 0, /**< Header Split disabled */
144                 .hw_ip_checksum = 0, /**< IP checksum offload disabled */
145                 .hw_vlan_filter = 0, /**< VLAN filtering disabled */
146                 /*
147                  * It is necessary for 1G NIC such as I350,
148                  * this fixes bug of ipv4 forwarding in guest can't
149                  * forward pakets from one virtio dev to another virtio dev.
150                  */
151                 .hw_vlan_strip  = 1, /**< VLAN strip enabled. */
152                 .jumbo_frame    = 0, /**< Jumbo Frame Support disabled */
153                 .hw_strip_crc   = 1, /**< CRC stripped by hardware */
154         },
155
156         .txmode = {
157                 .mq_mode = ETH_MQ_TX_NONE,
158         },
159         .rx_adv_conf = {
160                 /*
161                  * should be overridden separately in code with
162                  * appropriate values
163                  */
164                 .vmdq_rx_conf = {
165                         .nb_queue_pools = ETH_8_POOLS,
166                         .enable_default_pool = 0,
167                         .default_pool = 0,
168                         .nb_pool_maps = 0,
169                         .pool_map = {{0, 0},},
170                 },
171         },
172 };
173
174 static unsigned lcore_ids[RTE_MAX_LCORE];
175 static uint8_t ports[RTE_MAX_ETHPORTS];
176 static unsigned num_ports = 0; /**< The number of ports specified in command line */
177
178 const uint16_t vlan_tags[] = {
179         1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007,
180         1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015,
181         1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023,
182         1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031,
183         1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039,
184         1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047,
185         1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055,
186         1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063,
187 };
188
189 /* ethernet addresses of ports */
190 static struct ether_addr vmdq_ports_eth_addr[RTE_MAX_ETHPORTS];
191
192 /* heads for the main used and free linked lists for the data path. */
193 static struct virtio_net_data_ll *ll_root_used = NULL;
194 static struct virtio_net_data_ll *ll_root_free = NULL;
195
196 /* Array of data core structures containing information on individual core linked lists. */
197 static struct lcore_info lcore_info[RTE_MAX_LCORE];
198
199 /* Used for queueing bursts of TX packets. */
200 struct mbuf_table {
201         unsigned len;
202         unsigned txq_id;
203         struct rte_mbuf *m_table[MAX_PKT_BURST];
204 };
205
206 /* TX queue for each data core. */
207 struct mbuf_table lcore_tx_queue[RTE_MAX_LCORE];
208
209 /* Vlan header struct used to insert vlan tags on TX. */
210 struct vlan_ethhdr {
211         unsigned char   h_dest[ETH_ALEN];
212         unsigned char   h_source[ETH_ALEN];
213         __be16          h_vlan_proto;
214         __be16          h_vlan_TCI;
215         __be16          h_vlan_encapsulated_proto;
216 };
217
218 /* Header lengths. */
219 #define VLAN_HLEN       4
220 #define VLAN_ETH_HLEN   18
221
222 /* Per-device statistics struct */
223 struct device_statistics {
224         uint64_t tx_total;
225         rte_atomic64_t rx_total;
226         uint64_t tx;
227         rte_atomic64_t rx;
228 } __rte_cache_aligned;
229 struct device_statistics dev_statistics[MAX_DEVICES];
230
231 /*
232  * Builds up the correct configuration for VMDQ VLAN pool map
233  * according to the pool & queue limits.
234  */
235 static inline int
236 get_eth_conf(struct rte_eth_conf *eth_conf, uint32_t num_devices)
237 {
238         struct rte_eth_vmdq_rx_conf conf;
239         unsigned i;
240
241         memset(&conf, 0, sizeof(conf));
242         conf.nb_queue_pools = (enum rte_eth_nb_pools)num_devices;
243         conf.nb_pool_maps = num_devices;
244
245         for (i = 0; i < conf.nb_pool_maps; i++) {
246                 conf.pool_map[i].vlan_id = vlan_tags[ i ];
247                 conf.pool_map[i].pools = (1UL << i);
248         }
249
250         (void)(rte_memcpy(eth_conf, &vmdq_conf_default, sizeof(*eth_conf)));
251         (void)(rte_memcpy(&eth_conf->rx_adv_conf.vmdq_rx_conf, &conf,
252                    sizeof(eth_conf->rx_adv_conf.vmdq_rx_conf)));
253         return 0;
254 }
255
256 /*
257  * Validate the device number according to the max pool number gotten form dev_info
258  * If the device number is invalid, give the error message and return -1.
259  * Each device must have its own pool.
260  */
261 static inline int
262 validate_num_devices(uint32_t max_nb_devices)
263 {
264         if (num_devices > max_nb_devices) {
265                 RTE_LOG(ERR, VHOST_PORT, "invalid number of devices\n");
266                 return -1;
267         }
268         return 0;
269 }
270
271 /*
272  * Initialises a given port using global settings and with the rx buffers
273  * coming from the mbuf_pool passed as parameter
274  */
275 static inline int
276 port_init(uint8_t port, struct rte_mempool *mbuf_pool)
277 {
278         struct rte_eth_dev_info dev_info;
279         struct rte_eth_rxconf *rxconf;
280         struct rte_eth_conf port_conf;
281         uint16_t rx_rings, tx_rings = (uint16_t)rte_lcore_count();
282         uint16_t rx_ring_size = RTE_TEST_RX_DESC_DEFAULT;
283         uint16_t tx_ring_size = RTE_TEST_TX_DESC_DEFAULT;
284         int retval;
285         uint16_t q;
286
287         /* The max pool number from dev_info will be used to validate the pool number specified in cmd line */
288         rte_eth_dev_info_get (port, &dev_info);
289
290         /*configure the number of supported virtio devices based on VMDQ limits */
291         num_devices = dev_info.max_vmdq_pools;
292         num_queues = dev_info.max_rx_queues;
293
294         retval = validate_num_devices(MAX_DEVICES);
295         if (retval < 0)
296                 return retval;
297
298         /* Get port configuration. */
299         retval = get_eth_conf(&port_conf, num_devices);
300         if (retval < 0)
301                 return retval;
302
303         if (port >= rte_eth_dev_count()) return -1;
304
305         rx_rings = (uint16_t)num_queues,
306         /* Configure ethernet device. */
307         retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf);
308         if (retval != 0)
309                 return retval;
310
311         retval = rte_eth_dev_adjust_nb_rx_tx_desc(port, &rx_ring_size,
312                 &tx_ring_size);
313         if (retval != 0)
314                 return retval;
315         if (rx_ring_size > RTE_TEST_RX_DESC_DEFAULT ||
316                 tx_ring_size > RTE_TEST_TX_DESC_DEFAULT) {
317                 RTE_LOG(ERR, VHOST_PORT, "Mbuf pool has an insufficient size for "
318                         "port %u.\n", port);
319                 return -1;
320         }
321
322         rte_eth_dev_info_get(port, &dev_info);
323         rxconf = &dev_info.default_rxconf;
324         rxconf->rx_drop_en = 1;
325         /* Setup the queues. */
326         for (q = 0; q < rx_rings; q ++) {
327                 retval = rte_eth_rx_queue_setup(port, q, rx_ring_size,
328                                                 rte_eth_dev_socket_id(port), rxconf,
329                                                 mbuf_pool);
330                 if (retval < 0)
331                         return retval;
332         }
333         for (q = 0; q < tx_rings; q ++) {
334                 retval = rte_eth_tx_queue_setup(port, q, tx_ring_size,
335                                                 rte_eth_dev_socket_id(port),
336                                                 NULL);
337                 if (retval < 0)
338                         return retval;
339         }
340
341         /* Start the device. */
342         retval  = rte_eth_dev_start(port);
343         if (retval < 0)
344                 return retval;
345
346         rte_eth_macaddr_get(port, &vmdq_ports_eth_addr[port]);
347         RTE_LOG(INFO, VHOST_PORT, "Max virtio devices supported: %u\n", num_devices);
348         RTE_LOG(INFO, VHOST_PORT, "Port %u MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8
349                         " %02"PRIx8" %02"PRIx8" %02"PRIx8"\n",
350                         (unsigned)port,
351                         vmdq_ports_eth_addr[port].addr_bytes[0],
352                         vmdq_ports_eth_addr[port].addr_bytes[1],
353                         vmdq_ports_eth_addr[port].addr_bytes[2],
354                         vmdq_ports_eth_addr[port].addr_bytes[3],
355                         vmdq_ports_eth_addr[port].addr_bytes[4],
356                         vmdq_ports_eth_addr[port].addr_bytes[5]);
357
358         return 0;
359 }
360
361 /*
362  * Parse the portmask provided at run time.
363  */
364 static int
365 parse_portmask(const char *portmask)
366 {
367         char *end = NULL;
368         unsigned long pm;
369
370         errno = 0;
371
372         /* parse hexadecimal string */
373         pm = strtoul(portmask, &end, 16);
374         if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0') || (errno != 0))
375                 return -1;
376
377         if (pm == 0)
378                 return -1;
379
380         return pm;
381
382 }
383
384 /*
385  * Parse num options at run time.
386  */
387 static int
388 parse_num_opt(const char *q_arg, uint32_t max_valid_value)
389 {
390         char *end = NULL;
391         unsigned long num;
392
393         errno = 0;
394
395         /* parse unsigned int string */
396         num = strtoul(q_arg, &end, 10);
397         if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0') || (errno != 0))
398                 return -1;
399
400         if (num > max_valid_value)
401                 return -1;
402
403         return num;
404
405 }
406
407 /*
408  * Display usage
409  */
410 static void
411 us_vhost_usage(const char *prgname)
412 {
413         RTE_LOG(INFO, VHOST_CONFIG, "%s [EAL options] -- -p PORTMASK --vm2vm [0|1] --stats [0-N] --nb-devices ND\n"
414         "               -p PORTMASK: Set mask for ports to be used by application\n"
415         "               --vm2vm [0|1]: disable/enable(default) vm2vm comms\n"
416         "               --stats [0-N]: 0: Disable stats, N: Time in seconds to print stats\n",
417                prgname);
418 }
419
420 /*
421  * Parse the arguments given in the command line of the application.
422  */
423 static int
424 us_vhost_parse_args(int argc, char **argv)
425 {
426         int opt, ret;
427         int option_index;
428         unsigned i;
429         const char *prgname = argv[0];
430         static struct option long_option[] = {
431                 {"vm2vm", required_argument, NULL, 0},
432                 {"stats", required_argument, NULL, 0},
433                 {NULL, 0, 0, 0}
434         };
435
436         /* Parse command line */
437         while ((opt = getopt_long(argc, argv, "p:",long_option, &option_index)) != EOF) {
438                 switch (opt) {
439                 /* Portmask */
440                 case 'p':
441                         enabled_port_mask = parse_portmask(optarg);
442                         if (enabled_port_mask == 0) {
443                                 RTE_LOG(INFO, VHOST_CONFIG, "Invalid portmask\n");
444                                 us_vhost_usage(prgname);
445                                 return -1;
446                         }
447                         break;
448
449                 case 0:
450                         /* Enable/disable vm2vm comms. */
451                         if (!strncmp(long_option[option_index].name, "vm2vm", MAX_LONG_OPT_SZ)) {
452                                 ret = parse_num_opt(optarg, 1);
453                                 if (ret == -1) {
454                                         RTE_LOG(INFO, VHOST_CONFIG, "Invalid argument for vm2vm [0|1]\n");
455                                         us_vhost_usage(prgname);
456                                         return -1;
457                                 } else {
458                                         enable_vm2vm = ret;
459                                 }
460                         }
461
462                         /* Enable/disable stats. */
463                         if (!strncmp(long_option[option_index].name, "stats", MAX_LONG_OPT_SZ)) {
464                                 ret = parse_num_opt(optarg, INT32_MAX);
465                                 if (ret == -1) {
466                                         RTE_LOG(INFO, VHOST_CONFIG, "Invalid argument for stats [0..N]\n");
467                                         us_vhost_usage(prgname);
468                                         return -1;
469                                 } else {
470                                         enable_stats = ret;
471                                 }
472                         }
473                         break;
474
475                         /* Invalid option - print options. */
476                 default:
477                         us_vhost_usage(prgname);
478                         return -1;
479                 }
480         }
481
482         for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
483                 if (enabled_port_mask & (1 << i))
484                         ports[num_ports++] = (uint8_t)i;
485         }
486
487         if ((num_ports ==  0) || (num_ports > MAX_SUP_PORTS)) {
488                 RTE_LOG(INFO, VHOST_PORT, "Current enabled port number is %u,"
489                         "but only %u port can be enabled\n",num_ports, MAX_SUP_PORTS);
490                 return -1;
491         }
492
493         return 0;
494 }
495
496 /*
497  * Update the global var NUM_PORTS and array PORTS according to system ports number
498  * and return valid ports number
499  */
500 static unsigned check_ports_num(unsigned nb_ports)
501 {
502         unsigned valid_num_ports = num_ports;
503         unsigned portid;
504
505         if (num_ports > nb_ports) {
506                 RTE_LOG(INFO, VHOST_PORT, "\nSpecified port number(%u) exceeds total system port number(%u)\n",
507                         num_ports, nb_ports);
508                 num_ports = nb_ports;
509         }
510
511         for (portid = 0; portid < num_ports; portid ++) {
512                 if (ports[portid] >= nb_ports) {
513                         RTE_LOG(INFO, VHOST_PORT, "\nSpecified port ID(%u) exceeds max system port ID(%u)\n",
514                                 ports[portid], (nb_ports - 1));
515                         ports[portid] = INVALID_PORT_ID;
516                         valid_num_ports--;
517                 }
518         }
519         return valid_num_ports;
520 }
521
522 /*
523  * Function to convert guest physical addresses to vhost virtual addresses. This
524  * is used to convert virtio buffer addresses.
525  */
526 static __rte_always_inline uint64_t
527 gpa_to_vva(struct virtio_net *dev, uint64_t guest_pa)
528 {
529         struct virtio_memory_regions *region;
530         uint32_t regionidx;
531         uint64_t vhost_va = 0;
532
533         for (regionidx = 0; regionidx < dev->mem->nregions; regionidx++) {
534                 region = &dev->mem->regions[regionidx];
535                 if ((guest_pa >= region->guest_phys_address) &&
536                         (guest_pa <= region->guest_phys_address_end)) {
537                         vhost_va = region->address_offset + guest_pa;
538                         break;
539                 }
540         }
541         RTE_LOG_DP(DEBUG, VHOST_DATA, "(%" PRIu64 ") GPA %p| VVA %p\n",
542                 dev->device_fh, (void*)(uintptr_t)guest_pa, (void*)(uintptr_t)vhost_va);
543
544         return vhost_va;
545 }
546
547 /*
548  * This function adds buffers to the virtio devices RX virtqueue. Buffers can
549  * be received from the physical port or from another virtio device. A packet
550  * count is returned to indicate the number of packets that were successfully
551  * added to the RX queue.
552  */
553 static __rte_always_inline uint32_t
554 virtio_dev_rx(struct virtio_net *dev, struct rte_mbuf **pkts, uint32_t count)
555 {
556         struct vhost_virtqueue *vq;
557         struct vring_desc *desc;
558         struct rte_mbuf *buff;
559         /* The virtio_hdr is initialised to 0. */
560         struct virtio_net_hdr_mrg_rxbuf virtio_hdr = {{0,0,0,0,0,0},0};
561         uint64_t buff_addr = 0;
562         uint64_t buff_hdr_addr = 0;
563         uint32_t head[MAX_PKT_BURST], packet_len = 0;
564         uint32_t head_idx, packet_success = 0;
565         uint16_t avail_idx, res_cur_idx;
566         uint16_t res_base_idx, res_end_idx;
567         uint16_t free_entries;
568         uint8_t success = 0;
569         void *userdata;
570
571         RTE_LOG_DP(DEBUG, VHOST_DATA, "(%" PRIu64 ") virtio_dev_rx()\n", dev->device_fh);
572         vq = dev->virtqueue_rx;
573         count = (count > MAX_PKT_BURST) ? MAX_PKT_BURST : count;
574         /* As many data cores may want access to available buffers, they need to be reserved. */
575         do {
576
577                 res_base_idx = vq->last_used_idx_res;
578
579                 avail_idx = *((volatile uint16_t *)&vq->avail->idx);
580
581                 free_entries = (avail_idx - res_base_idx);
582
583                 /*check that we have enough buffers*/
584                 if (unlikely(count > free_entries))
585                         count = free_entries;
586
587                 if (count == 0)
588                         return 0;
589
590                 res_end_idx = res_base_idx + count;
591                 /* vq->last_used_idx_res is atomically updated. */
592                 success = rte_atomic16_cmpset(&vq->last_used_idx_res, res_base_idx,
593                                                                         res_end_idx);
594         } while (unlikely(success == 0));
595         res_cur_idx = res_base_idx;
596         RTE_LOG_DP(DEBUG, VHOST_DATA, "(%" PRIu64 ") Current Index %d| End Index %d\n",
597                 dev->device_fh, res_cur_idx, res_end_idx);
598
599         /* Prefetch available ring to retrieve indexes. */
600         rte_prefetch0(&vq->avail->ring[res_cur_idx & (vq->size - 1)]);
601
602         /* Retrieve all of the head indexes first to avoid caching issues. */
603         for (head_idx = 0; head_idx < count; head_idx++)
604                 head[head_idx] = vq->avail->ring[(res_cur_idx + head_idx) & (vq->size - 1)];
605
606         /*Prefetch descriptor index. */
607         rte_prefetch0(&vq->desc[head[packet_success]]);
608
609         while (res_cur_idx != res_end_idx) {
610                 /* Get descriptor from available ring */
611                 desc = &vq->desc[head[packet_success]];
612                 /* Prefetch descriptor address. */
613                 rte_prefetch0(desc);
614
615                 buff = pkts[packet_success];
616
617                 /* Convert from gpa to vva (guest physical addr -> vhost virtual addr) */
618                 buff_addr = gpa_to_vva(dev, desc->addr);
619                 /* Prefetch buffer address. */
620                 rte_prefetch0((void*)(uintptr_t)buff_addr);
621
622                 {
623                         /* Copy virtio_hdr to packet and increment buffer address */
624                         buff_hdr_addr = buff_addr;
625                         packet_len = rte_pktmbuf_data_len(buff) + vq->vhost_hlen;
626
627                         /*
628                          * If the descriptors are chained the header and data are placed in
629                          * separate buffers.
630                          */
631                         if (desc->flags & VRING_DESC_F_NEXT) {
632                                 desc->len = vq->vhost_hlen;
633                                 desc = &vq->desc[desc->next];
634                                 /* Buffer address translation. */
635                                 buff_addr = gpa_to_vva(dev, desc->addr);
636                                 desc->len = rte_pktmbuf_data_len(buff);
637                         } else {
638                                 buff_addr += vq->vhost_hlen;
639                                 desc->len = packet_len;
640                         }
641                 }
642
643                 /* Update used ring with desc information */
644                 vq->used->ring[res_cur_idx & (vq->size - 1)].id = head[packet_success];
645                 vq->used->ring[res_cur_idx & (vq->size - 1)].len = packet_len;
646
647                 /* Copy mbuf data to buffer */
648                 userdata = rte_pktmbuf_mtod(buff, void *);
649                 rte_memcpy((void *)(uintptr_t)buff_addr, userdata, rte_pktmbuf_data_len(buff));
650
651                 res_cur_idx++;
652                 packet_success++;
653
654                 /* mergeable is disabled then a header is required per buffer. */
655                 rte_memcpy((void *)(uintptr_t)buff_hdr_addr, (const void *)&virtio_hdr, vq->vhost_hlen);
656                 if (res_cur_idx < res_end_idx) {
657                         /* Prefetch descriptor index. */
658                         rte_prefetch0(&vq->desc[head[packet_success]]);
659                 }
660         }
661
662         rte_compiler_barrier();
663
664         /* Wait until it's our turn to add our buffer to the used ring. */
665         while (unlikely(vq->last_used_idx != res_base_idx))
666                 rte_pause();
667
668         *(volatile uint16_t *)&vq->used->idx += count;
669
670         vq->last_used_idx = res_end_idx;
671
672         return count;
673 }
674
675 /*
676  * Compares a packet destination MAC address to a device MAC address.
677  */
678 static __rte_always_inline int
679 ether_addr_cmp(struct ether_addr *ea, struct ether_addr *eb)
680 {
681         return ((*(uint64_t *)ea ^ *(uint64_t *)eb) & MAC_ADDR_CMP) == 0;
682 }
683
684 /*
685  * This function registers mac along with a
686  * vlan tag to a VMDQ.
687  */
688 static int
689 link_vmdq(struct virtio_net *dev)
690 {
691         int ret;
692         struct virtio_net_data_ll *dev_ll;
693
694         dev_ll = ll_root_used;
695
696         while (dev_ll != NULL) {
697                 if ((dev != dev_ll->dev) && ether_addr_cmp(&dev->mac_address, &dev_ll->dev->mac_address)) {
698                         RTE_LOG(INFO, VHOST_DATA, "(%"PRIu64") WARNING: This device is using an existing MAC address and has not been registered.\n", dev->device_fh);
699                         return -1;
700                 }
701                 dev_ll = dev_ll->next;
702         }
703
704         /* vlan_tag currently uses the device_id. */
705         dev->vlan_tag = vlan_tags[dev->device_fh];
706         dev->vmdq_rx_q = dev->device_fh * (num_queues/num_devices);
707
708         /* Print out VMDQ registration info. */
709         RTE_LOG(INFO, VHOST_DATA, "(%"PRIu64") MAC_ADDRESS %02x:%02x:%02x:%02x:%02x:%02x and VLAN_TAG %d registered\n",
710                 dev->device_fh,
711                 dev->mac_address.addr_bytes[0], dev->mac_address.addr_bytes[1],
712                 dev->mac_address.addr_bytes[2], dev->mac_address.addr_bytes[3],
713                 dev->mac_address.addr_bytes[4], dev->mac_address.addr_bytes[5],
714                 dev->vlan_tag);
715
716         /* Register the MAC address. */
717         ret = rte_eth_dev_mac_addr_add(ports[0], &dev->mac_address, (uint32_t)dev->device_fh);
718         if (ret) {
719                 RTE_LOG(ERR, VHOST_DATA, "(%"PRIu64") Failed to add device MAC address to VMDQ\n",
720                                                                                 dev->device_fh);
721                 return -1;
722         }
723
724         /* Enable stripping of the vlan tag as we handle routing. */
725         rte_eth_dev_set_vlan_strip_on_queue(ports[0], dev->vmdq_rx_q, 1);
726
727         rte_compiler_barrier();
728         /* Set device as ready for RX. */
729         dev->ready = DEVICE_READY;
730
731         return 0;
732 }
733
734 /*
735  * Removes MAC address and vlan tag from VMDQ. Ensures that nothing is adding buffers to the RX
736  * queue before disabling RX on the device.
737  */
738 static inline void
739 unlink_vmdq(struct virtio_net *dev)
740 {
741         unsigned i = 0;
742         unsigned rx_count;
743         struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
744
745         if (dev->ready == DEVICE_READY) {
746                 /*clear MAC and VLAN settings*/
747                 rte_eth_dev_mac_addr_remove(ports[0], &dev->mac_address);
748                 for (i = 0; i < 6; i++)
749                         dev->mac_address.addr_bytes[i] = 0;
750
751                 dev->vlan_tag = 0;
752
753                 /*Clear out the receive buffers*/
754                 rx_count = rte_eth_rx_burst(ports[0],
755                                         (uint16_t)dev->vmdq_rx_q, pkts_burst, MAX_PKT_BURST);
756
757                 while (rx_count) {
758                         for (i = 0; i < rx_count; i++)
759                                 rte_pktmbuf_free(pkts_burst[i]);
760
761                         rx_count = rte_eth_rx_burst(ports[0],
762                                         (uint16_t)dev->vmdq_rx_q, pkts_burst, MAX_PKT_BURST);
763                 }
764
765                 dev->ready = DEVICE_NOT_READY;
766         }
767 }
768
769 /*
770  * Check if the packet destination MAC address is for a local device. If so then put
771  * the packet on that devices RX queue. If not then return.
772  */
773 static __rte_always_inline unsigned
774 virtio_tx_local(struct virtio_net *dev, struct rte_mbuf *m)
775 {
776         struct virtio_net_data_ll *dev_ll;
777         struct ether_hdr *pkt_hdr;
778         uint64_t ret = 0;
779
780         pkt_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *);
781
782         /*get the used devices list*/
783         dev_ll = ll_root_used;
784
785         while (dev_ll != NULL) {
786                 if (likely(dev_ll->dev->ready == DEVICE_READY) && ether_addr_cmp(&(pkt_hdr->d_addr),
787                                           &dev_ll->dev->mac_address)) {
788
789                         /* Drop the packet if the TX packet is destined for the TX device. */
790                         if (dev_ll->dev->device_fh == dev->device_fh) {
791                                 RTE_LOG_DP(DEBUG, VHOST_DATA, "(%" PRIu64 ") TX: "
792                                         "Source and destination MAC addresses are the same. "
793                                         "Dropping packet.\n",
794                                         dev_ll->dev->device_fh);
795                                 return 0;
796                         }
797
798
799                         RTE_LOG_DP(DEBUG, VHOST_DATA, "(%" PRIu64 ") TX: "
800                                 "MAC address is local\n", dev_ll->dev->device_fh);
801
802                         if (dev_ll->dev->remove) {
803                                 /*drop the packet if the device is marked for removal*/
804                                 RTE_LOG_DP(DEBUG, VHOST_DATA, "(%" PRIu64 ") "
805                                         "Device is marked for removal\n",
806                                         dev_ll->dev->device_fh);
807                         } else {
808                                 /*send the packet to the local virtio device*/
809                                 ret = virtio_dev_rx(dev_ll->dev, &m, 1);
810                                 if (enable_stats) {
811                                         rte_atomic64_add(&dev_statistics[dev_ll->dev->device_fh].rx_total, 1);
812                                         rte_atomic64_add(&dev_statistics[dev_ll->dev->device_fh].rx, ret);
813                                         dev_statistics[dev->device_fh].tx_total++;
814                                         dev_statistics[dev->device_fh].tx += ret;
815                                 }
816                         }
817
818                         return 0;
819                 }
820                 dev_ll = dev_ll->next;
821         }
822
823         return -1;
824 }
825
826 /*
827  * This function routes the TX packet to the correct interface. This may be a local device
828  * or the physical port.
829  */
830 static __rte_always_inline void
831 virtio_tx_route(struct virtio_net* dev, struct rte_mbuf *m, struct rte_mempool *mbuf_pool, uint16_t vlan_tag)
832 {
833         struct mbuf_table *tx_q;
834         struct vlan_ethhdr *vlan_hdr;
835         struct rte_mbuf **m_table;
836         struct rte_mbuf *mbuf;
837         unsigned len, ret;
838         const uint16_t lcore_id = rte_lcore_id();
839
840         /*check if destination is local VM*/
841         if (enable_vm2vm && (virtio_tx_local(dev, m) == 0)) {
842                 return;
843         }
844
845         RTE_LOG_DP(DEBUG, VHOST_DATA, "(%" PRIu64 ") TX: "
846                 "MAC address is external\n", dev->device_fh);
847
848         /*Add packet to the port tx queue*/
849         tx_q = &lcore_tx_queue[lcore_id];
850         len = tx_q->len;
851
852         /* Allocate an mbuf and populate the structure. */
853         mbuf = rte_pktmbuf_alloc(mbuf_pool);
854         if(!mbuf)
855                 return;
856
857         mbuf->data_len = m->data_len + VLAN_HLEN;
858         mbuf->pkt_len = mbuf->data_len;
859
860         /* Copy ethernet header to mbuf. */
861         rte_memcpy(rte_pktmbuf_mtod(mbuf, void*),
862                         rte_pktmbuf_mtod(m, const void*), ETH_HLEN);
863
864
865         /* Setup vlan header. Bytes need to be re-ordered for network with htons()*/
866         vlan_hdr = rte_pktmbuf_mtod(mbuf, struct vlan_ethhdr *);
867         vlan_hdr->h_vlan_encapsulated_proto = vlan_hdr->h_vlan_proto;
868         vlan_hdr->h_vlan_proto = htons(ETH_P_8021Q);
869         vlan_hdr->h_vlan_TCI = htons(vlan_tag);
870
871         /* Copy the remaining packet contents to the mbuf. */
872         rte_memcpy(rte_pktmbuf_mtod_offset(mbuf, void *, VLAN_ETH_HLEN),
873                 rte_pktmbuf_mtod_offset(m, const void *, ETH_HLEN),
874                 (m->data_len - ETH_HLEN));
875         tx_q->m_table[len] = mbuf;
876         len++;
877         if (enable_stats) {
878                 dev_statistics[dev->device_fh].tx_total++;
879                 dev_statistics[dev->device_fh].tx++;
880         }
881
882         if (unlikely(len == MAX_PKT_BURST)) {
883                 m_table = (struct rte_mbuf **)tx_q->m_table;
884                 ret = rte_eth_tx_burst(ports[0], (uint16_t)tx_q->txq_id, m_table, (uint16_t) len);
885                 /* Free any buffers not handled by TX and update the port stats. */
886                 if (unlikely(ret < len)) {
887                         do {
888                                 rte_pktmbuf_free(m_table[ret]);
889                         } while (++ret < len);
890                 }
891
892                 len = 0;
893         }
894
895         tx_q->len = len;
896         return;
897 }
898
899 static __rte_always_inline void
900 virtio_dev_tx(struct virtio_net* dev, struct rte_mempool *mbuf_pool)
901 {
902         struct rte_mbuf m;
903         struct vhost_virtqueue *vq;
904         struct vring_desc *desc;
905         uint64_t buff_addr = 0;
906         uint32_t head[MAX_PKT_BURST];
907         uint32_t used_idx;
908         uint32_t i;
909         uint16_t free_entries, packet_success = 0;
910         uint16_t avail_idx;
911
912         vq = dev->virtqueue_tx;
913         avail_idx = *((volatile uint16_t *)&vq->avail->idx);
914
915         /* If there are no available buffers then return. */
916         if (vq->last_used_idx == avail_idx)
917                 return;
918
919         RTE_LOG_DP(DEBUG, VHOST_DATA, "(%" PRIu64 ") virtio_dev_tx()\n",
920                 dev->device_fh);
921
922         /* Prefetch available ring to retrieve head indexes. */
923         rte_prefetch0(&vq->avail->ring[vq->last_used_idx & (vq->size - 1)]);
924
925         /*get the number of free entries in the ring*/
926         free_entries = avail_idx - vq->last_used_idx;
927         free_entries = unlikely(free_entries < MAX_PKT_BURST) ? free_entries : MAX_PKT_BURST;
928
929         RTE_LOG_DP(DEBUG, VHOST_DATA, "(%" PRIu64 ") Buffers available %d\n",
930                 dev->device_fh, free_entries);
931         /* Retrieve all of the head indexes first to avoid caching issues. */
932         for (i = 0; i < free_entries; i++)
933                 head[i] = vq->avail->ring[(vq->last_used_idx + i) & (vq->size - 1)];
934
935         /* Prefetch descriptor index. */
936         rte_prefetch0(&vq->desc[head[packet_success]]);
937
938         while (packet_success < free_entries) {
939                 desc = &vq->desc[head[packet_success]];
940                 /* Prefetch descriptor address. */
941                 rte_prefetch0(desc);
942
943                 if (packet_success < (free_entries - 1)) {
944                         /* Prefetch descriptor index. */
945                         rte_prefetch0(&vq->desc[head[packet_success+1]]);
946                 }
947
948                 /* Update used index buffer information. */
949                 used_idx = vq->last_used_idx & (vq->size - 1);
950                 vq->used->ring[used_idx].id = head[packet_success];
951                 vq->used->ring[used_idx].len = 0;
952
953                 /* Discard first buffer as it is the virtio header */
954                 desc = &vq->desc[desc->next];
955
956                 /* Buffer address translation. */
957                 buff_addr = gpa_to_vva(dev, desc->addr);
958                 /* Prefetch buffer address. */
959                 rte_prefetch0((void*)(uintptr_t)buff_addr);
960
961                 /* Setup dummy mbuf. This is copied to a real mbuf if transmitted out the physical port. */
962                 m.data_len = desc->len;
963                 m.data_off = 0;
964                 m.nb_segs = 1;
965
966                 virtio_tx_route(dev, &m, mbuf_pool, 0);
967
968                 vq->last_used_idx++;
969                 packet_success++;
970         }
971
972         rte_compiler_barrier();
973         vq->used->idx += packet_success;
974         /* Kick guest if required. */
975 }
976
977 /*
978  * This function is called by each data core. It handles all RX/TX registered with the
979  * core. For TX the specific lcore linked list is used. For RX, MAC addresses are compared
980  * with all devices in the main linked list.
981  */
982 static int
983 switch_worker(__attribute__((unused)) void *arg)
984 {
985         struct rte_mempool *mbuf_pool = arg;
986         struct virtio_net *dev = NULL;
987         struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
988         struct virtio_net_data_ll *dev_ll;
989         struct mbuf_table *tx_q;
990         volatile struct lcore_ll_info *lcore_ll;
991         const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * BURST_TX_DRAIN_US;
992         uint64_t prev_tsc, diff_tsc, cur_tsc, ret_count = 0;
993         unsigned ret, i;
994         const uint16_t lcore_id = rte_lcore_id();
995         const uint16_t num_cores = (uint16_t)rte_lcore_count();
996         uint16_t rx_count = 0;
997
998         RTE_LOG(INFO, VHOST_DATA, "Procesing on Core %u started \n", lcore_id);
999         lcore_ll = lcore_info[lcore_id].lcore_ll;
1000         prev_tsc = 0;
1001
1002         tx_q = &lcore_tx_queue[lcore_id];
1003         for (i = 0; i < num_cores; i ++) {
1004                 if (lcore_ids[i] == lcore_id) {
1005                         tx_q->txq_id = i;
1006                         break;
1007                 }
1008         }
1009
1010         while(1) {
1011                 cur_tsc = rte_rdtsc();
1012                 /*
1013                  * TX burst queue drain
1014                  */
1015                 diff_tsc = cur_tsc - prev_tsc;
1016                 if (unlikely(diff_tsc > drain_tsc)) {
1017
1018                         if (tx_q->len) {
1019                                 RTE_LOG_DP(DEBUG, VHOST_DATA,
1020                                         "TX queue drained after timeout with burst size %u\n",
1021                                         tx_q->len);
1022
1023                                 /*Tx any packets in the queue*/
1024                                 ret = rte_eth_tx_burst(ports[0], (uint16_t)tx_q->txq_id,
1025                                                                            (struct rte_mbuf **)tx_q->m_table,
1026                                                                            (uint16_t)tx_q->len);
1027                                 if (unlikely(ret < tx_q->len)) {
1028                                         do {
1029                                                 rte_pktmbuf_free(tx_q->m_table[ret]);
1030                                         } while (++ret < tx_q->len);
1031                                 }
1032
1033                                 tx_q->len = 0;
1034                         }
1035
1036                         prev_tsc = cur_tsc;
1037
1038                 }
1039
1040                 /*
1041                  * Inform the configuration core that we have exited the linked list and that no devices are
1042                  * in use if requested.
1043                  */
1044                 if (lcore_ll->dev_removal_flag == REQUEST_DEV_REMOVAL)
1045                         lcore_ll->dev_removal_flag = ACK_DEV_REMOVAL;
1046
1047                 /*
1048                  * Process devices
1049                  */
1050                 dev_ll = lcore_ll->ll_root_used;
1051
1052                 while (dev_ll != NULL) {
1053                         /*get virtio device ID*/
1054                         dev = dev_ll->dev;
1055
1056                         if (unlikely(dev->remove)) {
1057                                 dev_ll = dev_ll->next;
1058                                 unlink_vmdq(dev);
1059                                 dev->ready = DEVICE_SAFE_REMOVE;
1060                                 continue;
1061                         }
1062                         if (likely(dev->ready == DEVICE_READY)) {
1063                                 /*Handle guest RX*/
1064                                 rx_count = rte_eth_rx_burst(ports[0],
1065                                         (uint16_t)dev->vmdq_rx_q, pkts_burst, MAX_PKT_BURST);
1066
1067                                 if (rx_count) {
1068                                         ret_count = virtio_dev_rx(dev, pkts_burst, rx_count);
1069                                         if (enable_stats) {
1070                                                 rte_atomic64_add(&dev_statistics[dev_ll->dev->device_fh].rx_total, rx_count);
1071                                                 rte_atomic64_add(&dev_statistics[dev_ll->dev->device_fh].rx, ret_count);
1072                                         }
1073                                         while (likely(rx_count)) {
1074                                                 rx_count--;
1075                                                 rte_pktmbuf_free_seg(pkts_burst[rx_count]);
1076                                         }
1077
1078                                 }
1079                         }
1080
1081                         if (likely(!dev->remove))
1082                                 /*Handle guest TX*/
1083                                 virtio_dev_tx(dev, mbuf_pool);
1084
1085                         /*move to the next device in the list*/
1086                         dev_ll = dev_ll->next;
1087                 }
1088         }
1089
1090         return 0;
1091 }
1092
1093 /*
1094  * Add an entry to a used linked list. A free entry must first be found in the free linked list
1095  * using get_data_ll_free_entry();
1096  */
1097 static void
1098 add_data_ll_entry(struct virtio_net_data_ll **ll_root_addr, struct virtio_net_data_ll *ll_dev)
1099 {
1100         struct virtio_net_data_ll *ll = *ll_root_addr;
1101
1102         /* Set next as NULL and use a compiler barrier to avoid reordering. */
1103         ll_dev->next = NULL;
1104         rte_compiler_barrier();
1105
1106         /* If ll == NULL then this is the first device. */
1107         if (ll) {
1108                 /* Increment to the tail of the linked list. */
1109                 while ((ll->next != NULL) )
1110                         ll = ll->next;
1111
1112                 ll->next = ll_dev;
1113         } else {
1114                 *ll_root_addr = ll_dev;
1115         }
1116 }
1117
1118 /*
1119  * Remove an entry from a used linked list. The entry must then be added to the free linked list
1120  * using put_data_ll_free_entry().
1121  */
1122 static void
1123 rm_data_ll_entry(struct virtio_net_data_ll **ll_root_addr, struct virtio_net_data_ll *ll_dev, struct virtio_net_data_ll *ll_dev_last)
1124 {
1125         struct virtio_net_data_ll *ll = *ll_root_addr;
1126
1127         if (ll_dev == ll)
1128                 *ll_root_addr = ll_dev->next;
1129         else
1130                 ll_dev_last->next = ll_dev->next;
1131 }
1132
1133 /*
1134  * Find and return an entry from the free linked list.
1135  */
1136 static struct virtio_net_data_ll *
1137 get_data_ll_free_entry(struct virtio_net_data_ll **ll_root_addr)
1138 {
1139         struct virtio_net_data_ll *ll_free = *ll_root_addr;
1140         struct virtio_net_data_ll *ll_dev;
1141
1142         if (ll_free == NULL)
1143                 return NULL;
1144
1145         ll_dev = ll_free;
1146         *ll_root_addr = ll_free->next;
1147
1148         return ll_dev;
1149 }
1150
1151 /*
1152  * Place an entry back on to the free linked list.
1153  */
1154 static void
1155 put_data_ll_free_entry(struct virtio_net_data_ll **ll_root_addr, struct virtio_net_data_ll *ll_dev)
1156 {
1157         struct virtio_net_data_ll *ll_free = *ll_root_addr;
1158
1159         ll_dev->next = ll_free;
1160         *ll_root_addr = ll_dev;
1161 }
1162
1163 /*
1164  * Creates a linked list of a given size.
1165  */
1166 static struct virtio_net_data_ll *
1167 alloc_data_ll(uint32_t size)
1168 {
1169         struct virtio_net_data_ll *ll_new;
1170         uint32_t i;
1171
1172         /* Malloc and then chain the linked list. */
1173         ll_new = malloc(size * sizeof(struct virtio_net_data_ll));
1174         if (ll_new == NULL) {
1175                 RTE_LOG(ERR, VHOST_CONFIG, "Failed to allocate memory for ll_new.\n");
1176                 return NULL;
1177         }
1178
1179         for (i = 0; i < size - 1; i++) {
1180                 ll_new[i].dev = NULL;
1181                 ll_new[i].next = &ll_new[i+1];
1182         }
1183         ll_new[i].next = NULL;
1184
1185         return ll_new;
1186 }
1187
1188 /*
1189  * Create the main linked list along with each individual cores linked list. A used and a free list
1190  * are created to manage entries.
1191  */
1192 static int
1193 init_data_ll (void)
1194 {
1195         int lcore;
1196
1197         RTE_LCORE_FOREACH_SLAVE(lcore) {
1198                 lcore_info[lcore].lcore_ll = malloc(sizeof(struct lcore_ll_info));
1199                 if (lcore_info[lcore].lcore_ll == NULL) {
1200                         RTE_LOG(ERR, VHOST_CONFIG, "Failed to allocate memory for lcore_ll.\n");
1201                         return -1;
1202                 }
1203
1204                 lcore_info[lcore].lcore_ll->device_num = 0;
1205                 lcore_info[lcore].lcore_ll->dev_removal_flag = ACK_DEV_REMOVAL;
1206                 lcore_info[lcore].lcore_ll->ll_root_used = NULL;
1207                 if (num_devices % num_switching_cores)
1208                         lcore_info[lcore].lcore_ll->ll_root_free = alloc_data_ll((num_devices / num_switching_cores) + 1);
1209                 else
1210                         lcore_info[lcore].lcore_ll->ll_root_free = alloc_data_ll(num_devices / num_switching_cores);
1211         }
1212
1213         /* Allocate devices up to a maximum of MAX_DEVICES. */
1214         ll_root_free = alloc_data_ll(MIN((num_devices), MAX_DEVICES));
1215
1216         return 0;
1217 }
1218 /*
1219  * Remove a device from the specific data core linked list and from the main linked list. The
1220  * rx/tx thread must be set the flag to indicate that it is safe to remove the device.
1221  * used.
1222  */
1223 static void
1224 destroy_device (volatile struct virtio_net *dev)
1225 {
1226         struct virtio_net_data_ll *ll_lcore_dev_cur;
1227         struct virtio_net_data_ll *ll_main_dev_cur;
1228         struct virtio_net_data_ll *ll_lcore_dev_last = NULL;
1229         struct virtio_net_data_ll *ll_main_dev_last = NULL;
1230         int lcore;
1231
1232         dev->flags &= ~VIRTIO_DEV_RUNNING;
1233
1234         /*set the remove flag. */
1235         dev->remove = 1;
1236
1237         while(dev->ready != DEVICE_SAFE_REMOVE) {
1238                 rte_pause();
1239         }
1240
1241         /* Search for entry to be removed from lcore ll */
1242         ll_lcore_dev_cur = lcore_info[dev->coreid].lcore_ll->ll_root_used;
1243         while (ll_lcore_dev_cur != NULL) {
1244                 if (ll_lcore_dev_cur->dev == dev) {
1245                         break;
1246                 } else {
1247                         ll_lcore_dev_last = ll_lcore_dev_cur;
1248                         ll_lcore_dev_cur = ll_lcore_dev_cur->next;
1249                 }
1250         }
1251
1252         /* Search for entry to be removed from main ll */
1253         ll_main_dev_cur = ll_root_used;
1254         ll_main_dev_last = NULL;
1255         while (ll_main_dev_cur != NULL) {
1256                 if (ll_main_dev_cur->dev == dev) {
1257                         break;
1258                 } else {
1259                         ll_main_dev_last = ll_main_dev_cur;
1260                         ll_main_dev_cur = ll_main_dev_cur->next;
1261                 }
1262         }
1263
1264         if (ll_lcore_dev_cur == NULL || ll_main_dev_cur == NULL) {
1265                 RTE_LOG(ERR, XENHOST, "%s: could find device in per_cpu list or main_list\n", __func__);
1266                 return;
1267         }
1268
1269         /* Remove entries from the lcore and main ll. */
1270         rm_data_ll_entry(&lcore_info[ll_lcore_dev_cur->dev->coreid].lcore_ll->ll_root_used, ll_lcore_dev_cur, ll_lcore_dev_last);
1271         rm_data_ll_entry(&ll_root_used, ll_main_dev_cur, ll_main_dev_last);
1272
1273         /* Set the dev_removal_flag on each lcore. */
1274         RTE_LCORE_FOREACH_SLAVE(lcore) {
1275                 lcore_info[lcore].lcore_ll->dev_removal_flag = REQUEST_DEV_REMOVAL;
1276         }
1277
1278         /*
1279          * Once each core has set the dev_removal_flag to ACK_DEV_REMOVAL we can be sure that
1280          * they can no longer access the device removed from the linked lists and that the devices
1281          * are no longer in use.
1282          */
1283         RTE_LCORE_FOREACH_SLAVE(lcore) {
1284                 while (lcore_info[lcore].lcore_ll->dev_removal_flag != ACK_DEV_REMOVAL) {
1285                         rte_pause();
1286                 }
1287         }
1288
1289         /* Add the entries back to the lcore and main free ll.*/
1290         put_data_ll_free_entry(&lcore_info[ll_lcore_dev_cur->dev->coreid].lcore_ll->ll_root_free, ll_lcore_dev_cur);
1291         put_data_ll_free_entry(&ll_root_free, ll_main_dev_cur);
1292
1293         /* Decrement number of device on the lcore. */
1294         lcore_info[ll_lcore_dev_cur->dev->coreid].lcore_ll->device_num--;
1295
1296         RTE_LOG(INFO, VHOST_DATA, "  #####(%"PRIu64") Device has been removed from data core\n", dev->device_fh);
1297 }
1298
1299 /*
1300  * A new device is added to a data core. First the device is added to the main linked list
1301  * and the allocated to a specific data core.
1302  */
1303 static int
1304 new_device (struct virtio_net *dev)
1305 {
1306         struct virtio_net_data_ll *ll_dev;
1307         int lcore, core_add = 0;
1308         uint32_t device_num_min = num_devices;
1309
1310         /* Add device to main ll */
1311         ll_dev = get_data_ll_free_entry(&ll_root_free);
1312         if (ll_dev == NULL) {
1313                 RTE_LOG(INFO, VHOST_DATA, "(%"PRIu64") No free entry found in linked list. Device limit "
1314                         "of %d devices per core has been reached\n",
1315                         dev->device_fh, num_devices);
1316                 return -1;
1317         }
1318         ll_dev->dev = dev;
1319         add_data_ll_entry(&ll_root_used, ll_dev);
1320
1321         /*reset ready flag*/
1322         dev->ready = DEVICE_NOT_READY;
1323         dev->remove = 0;
1324
1325         /* Find a suitable lcore to add the device. */
1326         RTE_LCORE_FOREACH_SLAVE(lcore) {
1327                 if (lcore_info[lcore].lcore_ll->device_num < device_num_min) {
1328                         device_num_min = lcore_info[lcore].lcore_ll->device_num;
1329                         core_add = lcore;
1330                 }
1331         }
1332         /* Add device to lcore ll */
1333         ll_dev->dev->coreid = core_add;
1334         ll_dev = get_data_ll_free_entry(&lcore_info[ll_dev->dev->coreid].lcore_ll->ll_root_free);
1335         if (ll_dev == NULL) {
1336                 RTE_LOG(INFO, VHOST_DATA, "(%"PRIu64") Failed to add device to data core\n", dev->device_fh);
1337                 destroy_device(dev);
1338                 return -1;
1339         }
1340         ll_dev->dev = dev;
1341         add_data_ll_entry(&lcore_info[ll_dev->dev->coreid].lcore_ll->ll_root_used, ll_dev);
1342
1343         /* Initialize device stats */
1344         memset(&dev_statistics[dev->device_fh], 0, sizeof(struct device_statistics));
1345
1346         lcore_info[ll_dev->dev->coreid].lcore_ll->device_num++;
1347         dev->flags |= VIRTIO_DEV_RUNNING;
1348
1349         RTE_LOG(INFO, VHOST_DATA, "(%"PRIu64") Device has been added to data core %d\n", dev->device_fh, dev->coreid);
1350
1351         link_vmdq(dev);
1352
1353         return 0;
1354 }
1355
1356 /*
1357  * These callback allow devices to be added to the data core when configuration
1358  * has been fully complete.
1359  */
1360 static const struct virtio_net_device_ops virtio_net_device_ops =
1361 {
1362         .new_device =  new_device,
1363         .destroy_device = destroy_device,
1364 };
1365
1366 /*
1367  * This is a thread will wake up after a period to print stats if the user has
1368  * enabled them.
1369  */
1370 static void
1371 print_stats(void)
1372 {
1373         struct virtio_net_data_ll *dev_ll;
1374         uint64_t tx_dropped, rx_dropped;
1375         uint64_t tx, tx_total, rx, rx_total;
1376         uint32_t device_fh;
1377         const char clr[] = { 27, '[', '2', 'J', '\0' };
1378         const char top_left[] = { 27, '[', '1', ';', '1', 'H','\0' };
1379
1380         while(1) {
1381                 sleep(enable_stats);
1382
1383                 /* Clear screen and move to top left */
1384                 printf("%s%s", clr, top_left);
1385
1386                 printf("\nDevice statistics ====================================");
1387
1388                 dev_ll = ll_root_used;
1389                 while (dev_ll != NULL) {
1390                         device_fh = (uint32_t)dev_ll->dev->device_fh;
1391                         tx_total = dev_statistics[device_fh].tx_total;
1392                         tx = dev_statistics[device_fh].tx;
1393                         tx_dropped = tx_total - tx;
1394                         rx_total = rte_atomic64_read(&dev_statistics[device_fh].rx_total);
1395                         rx = rte_atomic64_read(&dev_statistics[device_fh].rx);
1396                         rx_dropped = rx_total - rx;
1397
1398                         printf("\nStatistics for device %"PRIu32" ------------------------------"
1399                                         "\nTX total:            %"PRIu64""
1400                                         "\nTX dropped:          %"PRIu64""
1401                                         "\nTX successful:               %"PRIu64""
1402                                         "\nRX total:            %"PRIu64""
1403                                         "\nRX dropped:          %"PRIu64""
1404                                         "\nRX successful:               %"PRIu64"",
1405                                         device_fh,
1406                                         tx_total,
1407                                         tx_dropped,
1408                                         tx,
1409                                         rx_total,
1410                                         rx_dropped,
1411                                         rx);
1412
1413                         dev_ll = dev_ll->next;
1414                 }
1415                 printf("\n======================================================\n");
1416         }
1417 }
1418
1419
1420 int init_virtio_net(struct virtio_net_device_ops const * const ops);
1421
1422 /*
1423  * Main function, does initialisation and calls the per-lcore functions.
1424  */
1425 int
1426 main(int argc, char *argv[])
1427 {
1428         struct rte_mempool *mbuf_pool;
1429         unsigned lcore_id, core_id = 0;
1430         unsigned nb_ports, valid_num_ports;
1431         int ret;
1432         uint8_t portid;
1433         static pthread_t tid;
1434         char thread_name[RTE_MAX_THREAD_NAME_LEN];
1435
1436         /* init EAL */
1437         ret = rte_eal_init(argc, argv);
1438         if (ret < 0)
1439                 rte_exit(EXIT_FAILURE, "Error with EAL initialization\n");
1440         argc -= ret;
1441         argv += ret;
1442
1443         /* parse app arguments */
1444         ret = us_vhost_parse_args(argc, argv);
1445         if (ret < 0)
1446                 rte_exit(EXIT_FAILURE, "Invalid argument\n");
1447
1448         for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id ++)
1449                 if (rte_lcore_is_enabled(lcore_id))
1450                         lcore_ids[core_id ++] = lcore_id;
1451
1452         if (rte_lcore_count() > RTE_MAX_LCORE)
1453                 rte_exit(EXIT_FAILURE,"Not enough cores\n");
1454
1455         /*set the number of swithcing cores available*/
1456         num_switching_cores = rte_lcore_count()-1;
1457
1458         /* Get the number of physical ports. */
1459         nb_ports = rte_eth_dev_count();
1460
1461         /*
1462          * Update the global var NUM_PORTS and global array PORTS
1463          * and get value of var VALID_NUM_PORTS according to system ports number
1464          */
1465         valid_num_ports = check_ports_num(nb_ports);
1466
1467         if ((valid_num_ports ==  0) || (valid_num_ports > MAX_SUP_PORTS)) {
1468                 RTE_LOG(INFO, VHOST_PORT, "Current enabled port number is %u,"
1469                         "but only %u port can be enabled\n",num_ports, MAX_SUP_PORTS);
1470                 return -1;
1471         }
1472
1473         /* Create the mbuf pool. */
1474         mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL",
1475                 NUM_MBUFS_PER_PORT * valid_num_ports, MBUF_CACHE_SIZE, 0,
1476                 RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
1477         if (mbuf_pool == NULL)
1478                 rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n");
1479
1480         /* initialize all ports */
1481         for (portid = 0; portid < nb_ports; portid++) {
1482                 /* skip ports that are not enabled */
1483                 if ((enabled_port_mask & (1 << portid)) == 0) {
1484                         RTE_LOG(INFO, VHOST_PORT, "Skipping disabled port %d\n", portid);
1485                         continue;
1486                 }
1487                 if (port_init(portid, mbuf_pool) != 0)
1488                         rte_exit(EXIT_FAILURE, "Cannot initialize network ports\n");
1489         }
1490
1491         /* Initialise all linked lists. */
1492         if (init_data_ll() == -1)
1493                 rte_exit(EXIT_FAILURE, "Failed to initialize linked list\n");
1494
1495         /* Initialize device stats */
1496         memset(&dev_statistics, 0, sizeof(dev_statistics));
1497
1498         /* Enable stats if the user option is set. */
1499         if (enable_stats) {
1500                 ret = pthread_create(&tid, NULL, (void *)print_stats, NULL);
1501                 if (ret != 0)
1502                         rte_exit(EXIT_FAILURE,
1503                                 "Cannot create print-stats thread\n");
1504
1505                 /* Set thread_name for aid in debugging. */
1506                 snprintf(thread_name, RTE_MAX_THREAD_NAME_LEN, "print-xen-stats");
1507                 ret = rte_thread_setname(tid, thread_name);
1508                 if (ret != 0)
1509                         RTE_LOG(DEBUG, VHOST_CONFIG,
1510                                 "Cannot set print-stats name\n");
1511         }
1512
1513         /* Launch all data cores. */
1514         RTE_LCORE_FOREACH_SLAVE(lcore_id) {
1515                 rte_eal_remote_launch(switch_worker, mbuf_pool, lcore_id);
1516         }
1517
1518         init_virtio_xen(&virtio_net_device_ops);
1519
1520         virtio_monitor_loop();
1521         return 0;
1522 }