examples/vhost: fix corrupted vdev tailq list
[dpdk.git] / examples / vhost / main.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2016 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_malloc.h>
52 #include <rte_virtio_net.h>
53 #include <rte_ip.h>
54 #include <rte_tcp.h>
55
56 #include "main.h"
57
58 #ifndef MAX_QUEUES
59 #define MAX_QUEUES 128
60 #endif
61
62 /* the maximum number of external ports supported */
63 #define MAX_SUP_PORTS 1
64
65 #define MBUF_CACHE_SIZE 128
66 #define MBUF_DATA_SIZE  RTE_MBUF_DEFAULT_BUF_SIZE
67
68 #define MAX_PKT_BURST 32                /* Max burst size for RX/TX */
69 #define BURST_TX_DRAIN_US 100   /* TX drain every ~100us */
70
71 #define BURST_RX_WAIT_US 15     /* Defines how long we wait between retries on RX */
72 #define BURST_RX_RETRIES 4              /* Number of retries on RX. */
73
74 #define JUMBO_FRAME_MAX_SIZE    0x2600
75
76 /* State of virtio device. */
77 #define DEVICE_MAC_LEARNING 0
78 #define DEVICE_RX                       1
79 #define DEVICE_SAFE_REMOVE      2
80
81 /* Configurable number of RX/TX ring descriptors */
82 #define RTE_TEST_RX_DESC_DEFAULT 1024
83 #define RTE_TEST_TX_DESC_DEFAULT 512
84
85 #define INVALID_PORT_ID 0xFF
86
87 /* Max number of devices. Limited by vmdq. */
88 #define MAX_DEVICES 64
89
90 /* Size of buffers used for snprintfs. */
91 #define MAX_PRINT_BUFF 6072
92
93 /* Maximum character device basename size. */
94 #define MAX_BASENAME_SZ 10
95
96 /* Maximum long option length for option parsing. */
97 #define MAX_LONG_OPT_SZ 64
98
99 /* mask of enabled ports */
100 static uint32_t enabled_port_mask = 0;
101
102 /* Promiscuous mode */
103 static uint32_t promiscuous;
104
105 /* number of devices/queues to support*/
106 static uint32_t num_queues = 0;
107 static uint32_t num_devices;
108
109 static struct rte_mempool *mbuf_pool;
110 static int mergeable;
111
112 /* Do vlan strip on host, enabled on default */
113 static uint32_t vlan_strip = 1;
114
115 /* Enable VM2VM communications. If this is disabled then the MAC address compare is skipped. */
116 typedef enum {
117         VM2VM_DISABLED = 0,
118         VM2VM_SOFTWARE = 1,
119         VM2VM_HARDWARE = 2,
120         VM2VM_LAST
121 } vm2vm_type;
122 static vm2vm_type vm2vm_mode = VM2VM_SOFTWARE;
123
124 /* Enable stats. */
125 static uint32_t enable_stats = 0;
126 /* Enable retries on RX. */
127 static uint32_t enable_retry = 1;
128
129 /* Disable TX checksum offload */
130 static uint32_t enable_tx_csum;
131
132 /* Disable TSO offload */
133 static uint32_t enable_tso;
134
135 /* Specify timeout (in useconds) between retries on RX. */
136 static uint32_t burst_rx_delay_time = BURST_RX_WAIT_US;
137 /* Specify the number of retries on RX. */
138 static uint32_t burst_rx_retry_num = BURST_RX_RETRIES;
139
140 /* Character device basename. Can be set by user. */
141 static char dev_basename[MAX_BASENAME_SZ] = "vhost-net";
142
143 /* empty vmdq configuration structure. Filled in programatically */
144 static struct rte_eth_conf vmdq_conf_default = {
145         .rxmode = {
146                 .mq_mode        = ETH_MQ_RX_VMDQ_ONLY,
147                 .split_hdr_size = 0,
148                 .header_split   = 0, /**< Header Split disabled */
149                 .hw_ip_checksum = 0, /**< IP checksum offload disabled */
150                 .hw_vlan_filter = 0, /**< VLAN filtering disabled */
151                 /*
152                  * It is necessary for 1G NIC such as I350,
153                  * this fixes bug of ipv4 forwarding in guest can't
154                  * forward pakets from one virtio dev to another virtio dev.
155                  */
156                 .hw_vlan_strip  = 1, /**< VLAN strip enabled. */
157                 .jumbo_frame    = 0, /**< Jumbo Frame Support disabled */
158                 .hw_strip_crc   = 0, /**< CRC stripped by hardware */
159         },
160
161         .txmode = {
162                 .mq_mode = ETH_MQ_TX_NONE,
163         },
164         .rx_adv_conf = {
165                 /*
166                  * should be overridden separately in code with
167                  * appropriate values
168                  */
169                 .vmdq_rx_conf = {
170                         .nb_queue_pools = ETH_8_POOLS,
171                         .enable_default_pool = 0,
172                         .default_pool = 0,
173                         .nb_pool_maps = 0,
174                         .pool_map = {{0, 0},},
175                 },
176         },
177 };
178
179 static unsigned lcore_ids[RTE_MAX_LCORE];
180 static uint8_t ports[RTE_MAX_ETHPORTS];
181 static unsigned num_ports = 0; /**< The number of ports specified in command line */
182 static uint16_t num_pf_queues, num_vmdq_queues;
183 static uint16_t vmdq_pool_base, vmdq_queue_base;
184 static uint16_t queues_per_pool;
185
186 const uint16_t vlan_tags[] = {
187         1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007,
188         1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015,
189         1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023,
190         1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031,
191         1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039,
192         1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047,
193         1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055,
194         1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063,
195 };
196
197 /* ethernet addresses of ports */
198 static struct ether_addr vmdq_ports_eth_addr[RTE_MAX_ETHPORTS];
199
200 static struct vhost_dev_tailq_list vhost_dev_list =
201         TAILQ_HEAD_INITIALIZER(vhost_dev_list);
202
203 static struct lcore_info lcore_info[RTE_MAX_LCORE];
204
205 /* Used for queueing bursts of TX packets. */
206 struct mbuf_table {
207         unsigned len;
208         unsigned txq_id;
209         struct rte_mbuf *m_table[MAX_PKT_BURST];
210 };
211
212 /* TX queue for each data core. */
213 struct mbuf_table lcore_tx_queue[RTE_MAX_LCORE];
214
215 #define MBUF_TABLE_DRAIN_TSC    ((rte_get_tsc_hz() + US_PER_S - 1) \
216                                  / US_PER_S * BURST_TX_DRAIN_US)
217 #define VLAN_HLEN       4
218
219 /*
220  * Builds up the correct configuration for VMDQ VLAN pool map
221  * according to the pool & queue limits.
222  */
223 static inline int
224 get_eth_conf(struct rte_eth_conf *eth_conf, uint32_t num_devices)
225 {
226         struct rte_eth_vmdq_rx_conf conf;
227         struct rte_eth_vmdq_rx_conf *def_conf =
228                 &vmdq_conf_default.rx_adv_conf.vmdq_rx_conf;
229         unsigned i;
230
231         memset(&conf, 0, sizeof(conf));
232         conf.nb_queue_pools = (enum rte_eth_nb_pools)num_devices;
233         conf.nb_pool_maps = num_devices;
234         conf.enable_loop_back = def_conf->enable_loop_back;
235         conf.rx_mode = def_conf->rx_mode;
236
237         for (i = 0; i < conf.nb_pool_maps; i++) {
238                 conf.pool_map[i].vlan_id = vlan_tags[ i ];
239                 conf.pool_map[i].pools = (1UL << i);
240         }
241
242         (void)(rte_memcpy(eth_conf, &vmdq_conf_default, sizeof(*eth_conf)));
243         (void)(rte_memcpy(&eth_conf->rx_adv_conf.vmdq_rx_conf, &conf,
244                    sizeof(eth_conf->rx_adv_conf.vmdq_rx_conf)));
245         return 0;
246 }
247
248 /*
249  * Validate the device number according to the max pool number gotten form
250  * dev_info. If the device number is invalid, give the error message and
251  * return -1. Each device must have its own pool.
252  */
253 static inline int
254 validate_num_devices(uint32_t max_nb_devices)
255 {
256         if (num_devices > max_nb_devices) {
257                 RTE_LOG(ERR, VHOST_PORT, "invalid number of devices\n");
258                 return -1;
259         }
260         return 0;
261 }
262
263 /*
264  * Initialises a given port using global settings and with the rx buffers
265  * coming from the mbuf_pool passed as parameter
266  */
267 static inline int
268 port_init(uint8_t port)
269 {
270         struct rte_eth_dev_info dev_info;
271         struct rte_eth_conf port_conf;
272         struct rte_eth_rxconf *rxconf;
273         struct rte_eth_txconf *txconf;
274         int16_t rx_rings, tx_rings;
275         uint16_t rx_ring_size, tx_ring_size;
276         int retval;
277         uint16_t q;
278
279         /* The max pool number from dev_info will be used to validate the pool number specified in cmd line */
280         rte_eth_dev_info_get (port, &dev_info);
281
282         if (dev_info.max_rx_queues > MAX_QUEUES) {
283                 rte_exit(EXIT_FAILURE,
284                         "please define MAX_QUEUES no less than %u in %s\n",
285                         dev_info.max_rx_queues, __FILE__);
286         }
287
288         rxconf = &dev_info.default_rxconf;
289         txconf = &dev_info.default_txconf;
290         rxconf->rx_drop_en = 1;
291
292         /* Enable vlan offload */
293         txconf->txq_flags &= ~ETH_TXQ_FLAGS_NOVLANOFFL;
294
295         /*configure the number of supported virtio devices based on VMDQ limits */
296         num_devices = dev_info.max_vmdq_pools;
297
298         rx_ring_size = RTE_TEST_RX_DESC_DEFAULT;
299         tx_ring_size = RTE_TEST_TX_DESC_DEFAULT;
300         tx_rings = (uint16_t)rte_lcore_count();
301
302         retval = validate_num_devices(MAX_DEVICES);
303         if (retval < 0)
304                 return retval;
305
306         /* Get port configuration. */
307         retval = get_eth_conf(&port_conf, num_devices);
308         if (retval < 0)
309                 return retval;
310         /* NIC queues are divided into pf queues and vmdq queues.  */
311         num_pf_queues = dev_info.max_rx_queues - dev_info.vmdq_queue_num;
312         queues_per_pool = dev_info.vmdq_queue_num / dev_info.max_vmdq_pools;
313         num_vmdq_queues = num_devices * queues_per_pool;
314         num_queues = num_pf_queues + num_vmdq_queues;
315         vmdq_queue_base = dev_info.vmdq_queue_base;
316         vmdq_pool_base  = dev_info.vmdq_pool_base;
317         printf("pf queue num: %u, configured vmdq pool num: %u, each vmdq pool has %u queues\n",
318                 num_pf_queues, num_devices, queues_per_pool);
319
320         if (port >= rte_eth_dev_count()) return -1;
321
322         if (enable_tx_csum == 0)
323                 rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_CSUM);
324
325         if (enable_tso == 0) {
326                 rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_HOST_TSO4);
327                 rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_HOST_TSO6);
328         }
329
330         rx_rings = (uint16_t)dev_info.max_rx_queues;
331         /* Configure ethernet device. */
332         retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf);
333         if (retval != 0)
334                 return retval;
335
336         /* Setup the queues. */
337         for (q = 0; q < rx_rings; q ++) {
338                 retval = rte_eth_rx_queue_setup(port, q, rx_ring_size,
339                                                 rte_eth_dev_socket_id(port),
340                                                 rxconf,
341                                                 mbuf_pool);
342                 if (retval < 0)
343                         return retval;
344         }
345         for (q = 0; q < tx_rings; q ++) {
346                 retval = rte_eth_tx_queue_setup(port, q, tx_ring_size,
347                                                 rte_eth_dev_socket_id(port),
348                                                 txconf);
349                 if (retval < 0)
350                         return retval;
351         }
352
353         /* Start the device. */
354         retval  = rte_eth_dev_start(port);
355         if (retval < 0) {
356                 RTE_LOG(ERR, VHOST_DATA, "Failed to start the device.\n");
357                 return retval;
358         }
359
360         if (promiscuous)
361                 rte_eth_promiscuous_enable(port);
362
363         rte_eth_macaddr_get(port, &vmdq_ports_eth_addr[port]);
364         RTE_LOG(INFO, VHOST_PORT, "Max virtio devices supported: %u\n", num_devices);
365         RTE_LOG(INFO, VHOST_PORT, "Port %u MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8
366                         " %02"PRIx8" %02"PRIx8" %02"PRIx8"\n",
367                         (unsigned)port,
368                         vmdq_ports_eth_addr[port].addr_bytes[0],
369                         vmdq_ports_eth_addr[port].addr_bytes[1],
370                         vmdq_ports_eth_addr[port].addr_bytes[2],
371                         vmdq_ports_eth_addr[port].addr_bytes[3],
372                         vmdq_ports_eth_addr[port].addr_bytes[4],
373                         vmdq_ports_eth_addr[port].addr_bytes[5]);
374
375         return 0;
376 }
377
378 /*
379  * Set character device basename.
380  */
381 static int
382 us_vhost_parse_basename(const char *q_arg)
383 {
384         /* parse number string */
385
386         if (strnlen(q_arg, MAX_BASENAME_SZ) > MAX_BASENAME_SZ)
387                 return -1;
388         else
389                 snprintf((char*)&dev_basename, MAX_BASENAME_SZ, "%s", q_arg);
390
391         return 0;
392 }
393
394 /*
395  * Parse the portmask provided at run time.
396  */
397 static int
398 parse_portmask(const char *portmask)
399 {
400         char *end = NULL;
401         unsigned long pm;
402
403         errno = 0;
404
405         /* parse hexadecimal string */
406         pm = strtoul(portmask, &end, 16);
407         if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0') || (errno != 0))
408                 return -1;
409
410         if (pm == 0)
411                 return -1;
412
413         return pm;
414
415 }
416
417 /*
418  * Parse num options at run time.
419  */
420 static int
421 parse_num_opt(const char *q_arg, uint32_t max_valid_value)
422 {
423         char *end = NULL;
424         unsigned long num;
425
426         errno = 0;
427
428         /* parse unsigned int string */
429         num = strtoul(q_arg, &end, 10);
430         if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0') || (errno != 0))
431                 return -1;
432
433         if (num > max_valid_value)
434                 return -1;
435
436         return num;
437
438 }
439
440 /*
441  * Display usage
442  */
443 static void
444 us_vhost_usage(const char *prgname)
445 {
446         RTE_LOG(INFO, VHOST_CONFIG, "%s [EAL options] -- -p PORTMASK\n"
447         "               --vm2vm [0|1|2]\n"
448         "               --rx_retry [0|1] --mergeable [0|1] --stats [0-N]\n"
449         "               --dev-basename <name>\n"
450         "               --nb-devices ND\n"
451         "               -p PORTMASK: Set mask for ports to be used by application\n"
452         "               --vm2vm [0|1|2]: disable/software(default)/hardware vm2vm comms\n"
453         "               --rx-retry [0|1]: disable/enable(default) retries on rx. Enable retry if destintation queue is full\n"
454         "               --rx-retry-delay [0-N]: timeout(in usecond) between retries on RX. This makes effect only if retries on rx enabled\n"
455         "               --rx-retry-num [0-N]: the number of retries on rx. This makes effect only if retries on rx enabled\n"
456         "               --mergeable [0|1]: disable(default)/enable RX mergeable buffers\n"
457         "               --vlan-strip [0|1]: disable/enable(default) RX VLAN strip on host\n"
458         "               --stats [0-N]: 0: Disable stats, N: Time in seconds to print stats\n"
459         "               --dev-basename: The basename to be used for the character device.\n"
460         "               --tx-csum [0|1] disable/enable TX checksum offload.\n"
461         "               --tso [0|1] disable/enable TCP segment offload.\n",
462                prgname);
463 }
464
465 /*
466  * Parse the arguments given in the command line of the application.
467  */
468 static int
469 us_vhost_parse_args(int argc, char **argv)
470 {
471         int opt, ret;
472         int option_index;
473         unsigned i;
474         const char *prgname = argv[0];
475         static struct option long_option[] = {
476                 {"vm2vm", required_argument, NULL, 0},
477                 {"rx-retry", required_argument, NULL, 0},
478                 {"rx-retry-delay", required_argument, NULL, 0},
479                 {"rx-retry-num", required_argument, NULL, 0},
480                 {"mergeable", required_argument, NULL, 0},
481                 {"vlan-strip", required_argument, NULL, 0},
482                 {"stats", required_argument, NULL, 0},
483                 {"dev-basename", required_argument, NULL, 0},
484                 {"tx-csum", required_argument, NULL, 0},
485                 {"tso", required_argument, NULL, 0},
486                 {NULL, 0, 0, 0},
487         };
488
489         /* Parse command line */
490         while ((opt = getopt_long(argc, argv, "p:P",
491                         long_option, &option_index)) != EOF) {
492                 switch (opt) {
493                 /* Portmask */
494                 case 'p':
495                         enabled_port_mask = parse_portmask(optarg);
496                         if (enabled_port_mask == 0) {
497                                 RTE_LOG(INFO, VHOST_CONFIG, "Invalid portmask\n");
498                                 us_vhost_usage(prgname);
499                                 return -1;
500                         }
501                         break;
502
503                 case 'P':
504                         promiscuous = 1;
505                         vmdq_conf_default.rx_adv_conf.vmdq_rx_conf.rx_mode =
506                                 ETH_VMDQ_ACCEPT_BROADCAST |
507                                 ETH_VMDQ_ACCEPT_MULTICAST;
508                         rte_vhost_feature_enable(1ULL << VIRTIO_NET_F_CTRL_RX);
509
510                         break;
511
512                 case 0:
513                         /* Enable/disable vm2vm comms. */
514                         if (!strncmp(long_option[option_index].name, "vm2vm",
515                                 MAX_LONG_OPT_SZ)) {
516                                 ret = parse_num_opt(optarg, (VM2VM_LAST - 1));
517                                 if (ret == -1) {
518                                         RTE_LOG(INFO, VHOST_CONFIG,
519                                                 "Invalid argument for "
520                                                 "vm2vm [0|1|2]\n");
521                                         us_vhost_usage(prgname);
522                                         return -1;
523                                 } else {
524                                         vm2vm_mode = (vm2vm_type)ret;
525                                 }
526                         }
527
528                         /* Enable/disable retries on RX. */
529                         if (!strncmp(long_option[option_index].name, "rx-retry", MAX_LONG_OPT_SZ)) {
530                                 ret = parse_num_opt(optarg, 1);
531                                 if (ret == -1) {
532                                         RTE_LOG(INFO, VHOST_CONFIG, "Invalid argument for rx-retry [0|1]\n");
533                                         us_vhost_usage(prgname);
534                                         return -1;
535                                 } else {
536                                         enable_retry = ret;
537                                 }
538                         }
539
540                         /* Enable/disable TX checksum offload. */
541                         if (!strncmp(long_option[option_index].name, "tx-csum", MAX_LONG_OPT_SZ)) {
542                                 ret = parse_num_opt(optarg, 1);
543                                 if (ret == -1) {
544                                         RTE_LOG(INFO, VHOST_CONFIG, "Invalid argument for tx-csum [0|1]\n");
545                                         us_vhost_usage(prgname);
546                                         return -1;
547                                 } else
548                                         enable_tx_csum = ret;
549                         }
550
551                         /* Enable/disable TSO offload. */
552                         if (!strncmp(long_option[option_index].name, "tso", MAX_LONG_OPT_SZ)) {
553                                 ret = parse_num_opt(optarg, 1);
554                                 if (ret == -1) {
555                                         RTE_LOG(INFO, VHOST_CONFIG, "Invalid argument for tso [0|1]\n");
556                                         us_vhost_usage(prgname);
557                                         return -1;
558                                 } else
559                                         enable_tso = ret;
560                         }
561
562                         /* Specify the retries delay time (in useconds) on RX. */
563                         if (!strncmp(long_option[option_index].name, "rx-retry-delay", MAX_LONG_OPT_SZ)) {
564                                 ret = parse_num_opt(optarg, INT32_MAX);
565                                 if (ret == -1) {
566                                         RTE_LOG(INFO, VHOST_CONFIG, "Invalid argument for rx-retry-delay [0-N]\n");
567                                         us_vhost_usage(prgname);
568                                         return -1;
569                                 } else {
570                                         burst_rx_delay_time = ret;
571                                 }
572                         }
573
574                         /* Specify the retries number on RX. */
575                         if (!strncmp(long_option[option_index].name, "rx-retry-num", MAX_LONG_OPT_SZ)) {
576                                 ret = parse_num_opt(optarg, INT32_MAX);
577                                 if (ret == -1) {
578                                         RTE_LOG(INFO, VHOST_CONFIG, "Invalid argument for rx-retry-num [0-N]\n");
579                                         us_vhost_usage(prgname);
580                                         return -1;
581                                 } else {
582                                         burst_rx_retry_num = ret;
583                                 }
584                         }
585
586                         /* Enable/disable RX mergeable buffers. */
587                         if (!strncmp(long_option[option_index].name, "mergeable", MAX_LONG_OPT_SZ)) {
588                                 ret = parse_num_opt(optarg, 1);
589                                 if (ret == -1) {
590                                         RTE_LOG(INFO, VHOST_CONFIG, "Invalid argument for mergeable [0|1]\n");
591                                         us_vhost_usage(prgname);
592                                         return -1;
593                                 } else {
594                                         mergeable = !!ret;
595                                         if (ret) {
596                                                 vmdq_conf_default.rxmode.jumbo_frame = 1;
597                                                 vmdq_conf_default.rxmode.max_rx_pkt_len
598                                                         = JUMBO_FRAME_MAX_SIZE;
599                                         }
600                                 }
601                         }
602
603                         /* Enable/disable RX VLAN strip on host. */
604                         if (!strncmp(long_option[option_index].name,
605                                 "vlan-strip", MAX_LONG_OPT_SZ)) {
606                                 ret = parse_num_opt(optarg, 1);
607                                 if (ret == -1) {
608                                         RTE_LOG(INFO, VHOST_CONFIG,
609                                                 "Invalid argument for VLAN strip [0|1]\n");
610                                         us_vhost_usage(prgname);
611                                         return -1;
612                                 } else {
613                                         vlan_strip = !!ret;
614                                         vmdq_conf_default.rxmode.hw_vlan_strip =
615                                                 vlan_strip;
616                                 }
617                         }
618
619                         /* Enable/disable stats. */
620                         if (!strncmp(long_option[option_index].name, "stats", MAX_LONG_OPT_SZ)) {
621                                 ret = parse_num_opt(optarg, INT32_MAX);
622                                 if (ret == -1) {
623                                         RTE_LOG(INFO, VHOST_CONFIG, "Invalid argument for stats [0..N]\n");
624                                         us_vhost_usage(prgname);
625                                         return -1;
626                                 } else {
627                                         enable_stats = ret;
628                                 }
629                         }
630
631                         /* Set character device basename. */
632                         if (!strncmp(long_option[option_index].name, "dev-basename", MAX_LONG_OPT_SZ)) {
633                                 if (us_vhost_parse_basename(optarg) == -1) {
634                                         RTE_LOG(INFO, VHOST_CONFIG, "Invalid argument for character device basename (Max %d characters)\n", MAX_BASENAME_SZ);
635                                         us_vhost_usage(prgname);
636                                         return -1;
637                                 }
638                         }
639
640                         break;
641
642                         /* Invalid option - print options. */
643                 default:
644                         us_vhost_usage(prgname);
645                         return -1;
646                 }
647         }
648
649         for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
650                 if (enabled_port_mask & (1 << i))
651                         ports[num_ports++] = (uint8_t)i;
652         }
653
654         if ((num_ports ==  0) || (num_ports > MAX_SUP_PORTS)) {
655                 RTE_LOG(INFO, VHOST_PORT, "Current enabled port number is %u,"
656                         "but only %u port can be enabled\n",num_ports, MAX_SUP_PORTS);
657                 return -1;
658         }
659
660         return 0;
661 }
662
663 /*
664  * Update the global var NUM_PORTS and array PORTS according to system ports number
665  * and return valid ports number
666  */
667 static unsigned check_ports_num(unsigned nb_ports)
668 {
669         unsigned valid_num_ports = num_ports;
670         unsigned portid;
671
672         if (num_ports > nb_ports) {
673                 RTE_LOG(INFO, VHOST_PORT, "\nSpecified port number(%u) exceeds total system port number(%u)\n",
674                         num_ports, nb_ports);
675                 num_ports = nb_ports;
676         }
677
678         for (portid = 0; portid < num_ports; portid ++) {
679                 if (ports[portid] >= nb_ports) {
680                         RTE_LOG(INFO, VHOST_PORT, "\nSpecified port ID(%u) exceeds max system port ID(%u)\n",
681                                 ports[portid], (nb_ports - 1));
682                         ports[portid] = INVALID_PORT_ID;
683                         valid_num_ports--;
684                 }
685         }
686         return valid_num_ports;
687 }
688
689 static inline struct vhost_dev *__attribute__((always_inline))
690 find_vhost_dev(struct ether_addr *mac)
691 {
692         struct vhost_dev *vdev;
693
694         TAILQ_FOREACH(vdev, &vhost_dev_list, global_vdev_entry) {
695                 if (vdev->ready == DEVICE_RX &&
696                     is_same_ether_addr(mac, &vdev->mac_address))
697                         return vdev;
698         }
699
700         return NULL;
701 }
702
703 /*
704  * This function learns the MAC address of the device and registers this along with a
705  * vlan tag to a VMDQ.
706  */
707 static int
708 link_vmdq(struct vhost_dev *vdev, struct rte_mbuf *m)
709 {
710         struct ether_hdr *pkt_hdr;
711         struct virtio_net *dev = vdev->dev;
712         int i, ret;
713
714         /* Learn MAC address of guest device from packet */
715         pkt_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *);
716
717         if (find_vhost_dev(&pkt_hdr->s_addr)) {
718                 RTE_LOG(ERR, VHOST_DATA,
719                         "Device (%" PRIu64 ") is using a registered MAC!\n",
720                         dev->device_fh);
721                 return -1;
722         }
723
724         for (i = 0; i < ETHER_ADDR_LEN; i++)
725                 vdev->mac_address.addr_bytes[i] = pkt_hdr->s_addr.addr_bytes[i];
726
727         /* vlan_tag currently uses the device_id. */
728         vdev->vlan_tag = vlan_tags[dev->device_fh];
729
730         /* Print out VMDQ registration info. */
731         RTE_LOG(INFO, VHOST_DATA, "(%"PRIu64") MAC_ADDRESS %02x:%02x:%02x:%02x:%02x:%02x and VLAN_TAG %d registered\n",
732                 dev->device_fh,
733                 vdev->mac_address.addr_bytes[0], vdev->mac_address.addr_bytes[1],
734                 vdev->mac_address.addr_bytes[2], vdev->mac_address.addr_bytes[3],
735                 vdev->mac_address.addr_bytes[4], vdev->mac_address.addr_bytes[5],
736                 vdev->vlan_tag);
737
738         /* Register the MAC address. */
739         ret = rte_eth_dev_mac_addr_add(ports[0], &vdev->mac_address,
740                                 (uint32_t)dev->device_fh + vmdq_pool_base);
741         if (ret)
742                 RTE_LOG(ERR, VHOST_DATA, "(%"PRIu64") Failed to add device MAC address to VMDQ\n",
743                                         dev->device_fh);
744
745         /* Enable stripping of the vlan tag as we handle routing. */
746         if (vlan_strip)
747                 rte_eth_dev_set_vlan_strip_on_queue(ports[0],
748                         (uint16_t)vdev->vmdq_rx_q, 1);
749
750         /* Set device as ready for RX. */
751         vdev->ready = DEVICE_RX;
752
753         return 0;
754 }
755
756 /*
757  * Removes MAC address and vlan tag from VMDQ. Ensures that nothing is adding buffers to the RX
758  * queue before disabling RX on the device.
759  */
760 static inline void
761 unlink_vmdq(struct vhost_dev *vdev)
762 {
763         unsigned i = 0;
764         unsigned rx_count;
765         struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
766
767         if (vdev->ready == DEVICE_RX) {
768                 /*clear MAC and VLAN settings*/
769                 rte_eth_dev_mac_addr_remove(ports[0], &vdev->mac_address);
770                 for (i = 0; i < 6; i++)
771                         vdev->mac_address.addr_bytes[i] = 0;
772
773                 vdev->vlan_tag = 0;
774
775                 /*Clear out the receive buffers*/
776                 rx_count = rte_eth_rx_burst(ports[0],
777                                         (uint16_t)vdev->vmdq_rx_q, pkts_burst, MAX_PKT_BURST);
778
779                 while (rx_count) {
780                         for (i = 0; i < rx_count; i++)
781                                 rte_pktmbuf_free(pkts_burst[i]);
782
783                         rx_count = rte_eth_rx_burst(ports[0],
784                                         (uint16_t)vdev->vmdq_rx_q, pkts_burst, MAX_PKT_BURST);
785                 }
786
787                 vdev->ready = DEVICE_MAC_LEARNING;
788         }
789 }
790
791 static inline void __attribute__((always_inline))
792 virtio_xmit(struct vhost_dev *dst_vdev, struct vhost_dev *src_vdev,
793             struct rte_mbuf *m)
794 {
795         uint16_t ret;
796
797         ret = rte_vhost_enqueue_burst(dst_vdev->dev, VIRTIO_RXQ, &m, 1);
798         if (enable_stats) {
799                 rte_atomic64_inc(&dst_vdev->stats.rx_total_atomic);
800                 rte_atomic64_add(&dst_vdev->stats.rx_atomic, ret);
801                 src_vdev->stats.tx_total++;
802                 src_vdev->stats.tx += ret;
803         }
804 }
805
806 /*
807  * Check if the packet destination MAC address is for a local device. If so then put
808  * the packet on that devices RX queue. If not then return.
809  */
810 static inline int __attribute__((always_inline))
811 virtio_tx_local(struct vhost_dev *vdev, struct rte_mbuf *m)
812 {
813         struct ether_hdr *pkt_hdr;
814         struct vhost_dev *dst_vdev;
815         uint64_t fh;
816
817         pkt_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *);
818
819         dst_vdev = find_vhost_dev(&pkt_hdr->d_addr);
820         if (!dst_vdev)
821                 return -1;
822
823         fh = dst_vdev->dev->device_fh;
824         if (fh == vdev->dev->device_fh) {
825                 RTE_LOG(DEBUG, VHOST_DATA,
826                         "(%" PRIu64 ") TX: src and dst MAC is same. "
827                         "Dropping packet.\n", fh);
828                 return 0;
829         }
830
831         RTE_LOG(DEBUG, VHOST_DATA,
832                 "(%" PRIu64 ") TX: MAC address is local\n", fh);
833
834         if (unlikely(dst_vdev->remove)) {
835                 RTE_LOG(DEBUG, VHOST_DATA, "(%" PRIu64 ") "
836                         "Device is marked for removal\n", fh);
837                 return 0;
838         }
839
840         virtio_xmit(dst_vdev, vdev, m);
841         return 0;
842 }
843
844 /*
845  * Check if the destination MAC of a packet is one local VM,
846  * and get its vlan tag, and offset if it is.
847  */
848 static inline int __attribute__((always_inline))
849 find_local_dest(struct virtio_net *dev, struct rte_mbuf *m,
850         uint32_t *offset, uint16_t *vlan_tag)
851 {
852         struct vhost_dev *dst_vdev;
853         struct ether_hdr *pkt_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *);
854
855         dst_vdev = find_vhost_dev(&pkt_hdr->d_addr);
856         if (!dst_vdev)
857                 return 0;
858
859         if (dst_vdev->dev->device_fh == dev->device_fh) {
860                 RTE_LOG(DEBUG, VHOST_DATA,
861                         "(%" PRIu64 ") TX: src and dst MAC is same. "
862                         " Dropping packet.\n", dst_vdev->dev->device_fh);
863                 return -1;
864         }
865
866         /*
867          * HW vlan strip will reduce the packet length
868          * by minus length of vlan tag, so need restore
869          * the packet length by plus it.
870          */
871         *offset  = VLAN_HLEN;
872         *vlan_tag = vlan_tags[(uint16_t)dst_vdev->dev->device_fh];
873
874         RTE_LOG(DEBUG, VHOST_DATA,
875                 "(%" PRIu64 ") TX: pkt to local VM device id: (%" PRIu64 ") "
876                 "vlan tag: %u.\n",
877                 dev->device_fh, dst_vdev->dev->device_fh, *vlan_tag);
878
879         return 0;
880 }
881
882 static uint16_t
883 get_psd_sum(void *l3_hdr, uint64_t ol_flags)
884 {
885         if (ol_flags & PKT_TX_IPV4)
886                 return rte_ipv4_phdr_cksum(l3_hdr, ol_flags);
887         else /* assume ethertype == ETHER_TYPE_IPv6 */
888                 return rte_ipv6_phdr_cksum(l3_hdr, ol_flags);
889 }
890
891 static void virtio_tx_offload(struct rte_mbuf *m)
892 {
893         void *l3_hdr;
894         struct ipv4_hdr *ipv4_hdr = NULL;
895         struct tcp_hdr *tcp_hdr = NULL;
896         struct ether_hdr *eth_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *);
897
898         l3_hdr = (char *)eth_hdr + m->l2_len;
899
900         if (m->ol_flags & PKT_TX_IPV4) {
901                 ipv4_hdr = l3_hdr;
902                 ipv4_hdr->hdr_checksum = 0;
903                 m->ol_flags |= PKT_TX_IP_CKSUM;
904         }
905
906         tcp_hdr = (struct tcp_hdr *)((char *)l3_hdr + m->l3_len);
907         tcp_hdr->cksum = get_psd_sum(l3_hdr, m->ol_flags);
908 }
909
910 static inline void
911 free_pkts(struct rte_mbuf **pkts, uint16_t n)
912 {
913         while (n--)
914                 rte_pktmbuf_free(pkts[n]);
915 }
916
917 static inline void __attribute__((always_inline))
918 do_drain_mbuf_table(struct mbuf_table *tx_q)
919 {
920         uint16_t count;
921
922         count = rte_eth_tx_burst(ports[0], tx_q->txq_id,
923                                  tx_q->m_table, tx_q->len);
924         if (unlikely(count < tx_q->len))
925                 free_pkts(&tx_q->m_table[count], tx_q->len - count);
926
927         tx_q->len = 0;
928 }
929
930 /*
931  * This function routes the TX packet to the correct interface. This
932  * may be a local device or the physical port.
933  */
934 static inline void __attribute__((always_inline))
935 virtio_tx_route(struct vhost_dev *vdev, struct rte_mbuf *m, uint16_t vlan_tag)
936 {
937         struct mbuf_table *tx_q;
938         unsigned offset = 0;
939         const uint16_t lcore_id = rte_lcore_id();
940         struct virtio_net *dev = vdev->dev;
941         struct ether_hdr *nh;
942
943
944         nh = rte_pktmbuf_mtod(m, struct ether_hdr *);
945         if (unlikely(is_broadcast_ether_addr(&nh->d_addr))) {
946                 struct vhost_dev *vdev2;
947
948                 TAILQ_FOREACH(vdev2, &vhost_dev_list, global_vdev_entry) {
949                         virtio_xmit(vdev2, vdev, m);
950                 }
951                 goto queue2nic;
952         }
953
954         /*check if destination is local VM*/
955         if ((vm2vm_mode == VM2VM_SOFTWARE) && (virtio_tx_local(vdev, m) == 0)) {
956                 rte_pktmbuf_free(m);
957                 return;
958         }
959
960         if (unlikely(vm2vm_mode == VM2VM_HARDWARE)) {
961                 if (unlikely(find_local_dest(dev, m, &offset, &vlan_tag) != 0)) {
962                         rte_pktmbuf_free(m);
963                         return;
964                 }
965         }
966
967         RTE_LOG(DEBUG, VHOST_DATA, "(%" PRIu64 ") TX: "
968                 "MAC address is external\n", dev->device_fh);
969
970 queue2nic:
971
972         /*Add packet to the port tx queue*/
973         tx_q = &lcore_tx_queue[lcore_id];
974
975         nh = rte_pktmbuf_mtod(m, struct ether_hdr *);
976         if (unlikely(nh->ether_type == rte_cpu_to_be_16(ETHER_TYPE_VLAN))) {
977                 /* Guest has inserted the vlan tag. */
978                 struct vlan_hdr *vh = (struct vlan_hdr *) (nh + 1);
979                 uint16_t vlan_tag_be = rte_cpu_to_be_16(vlan_tag);
980                 if ((vm2vm_mode == VM2VM_HARDWARE) &&
981                         (vh->vlan_tci != vlan_tag_be))
982                         vh->vlan_tci = vlan_tag_be;
983         } else {
984                 m->ol_flags |= PKT_TX_VLAN_PKT;
985
986                 /*
987                  * Find the right seg to adjust the data len when offset is
988                  * bigger than tail room size.
989                  */
990                 if (unlikely(vm2vm_mode == VM2VM_HARDWARE)) {
991                         if (likely(offset <= rte_pktmbuf_tailroom(m)))
992                                 m->data_len += offset;
993                         else {
994                                 struct rte_mbuf *seg = m;
995
996                                 while ((seg->next != NULL) &&
997                                         (offset > rte_pktmbuf_tailroom(seg)))
998                                         seg = seg->next;
999
1000                                 seg->data_len += offset;
1001                         }
1002                         m->pkt_len += offset;
1003                 }
1004
1005                 m->vlan_tci = vlan_tag;
1006         }
1007
1008         if (m->ol_flags & PKT_TX_TCP_SEG)
1009                 virtio_tx_offload(m);
1010
1011         tx_q->m_table[tx_q->len++] = m;
1012         if (enable_stats) {
1013                 vdev->stats.tx_total++;
1014                 vdev->stats.tx++;
1015         }
1016
1017         if (unlikely(tx_q->len == MAX_PKT_BURST))
1018                 do_drain_mbuf_table(tx_q);
1019 }
1020
1021
1022 static inline void __attribute__((always_inline))
1023 drain_mbuf_table(struct mbuf_table *tx_q)
1024 {
1025         static uint64_t prev_tsc;
1026         uint64_t cur_tsc;
1027
1028         if (tx_q->len == 0)
1029                 return;
1030
1031         cur_tsc = rte_rdtsc();
1032         if (unlikely(cur_tsc - prev_tsc > MBUF_TABLE_DRAIN_TSC)) {
1033                 prev_tsc = cur_tsc;
1034
1035                 RTE_LOG(DEBUG, VHOST_DATA,
1036                         "TX queue drained after timeout with burst size %u\n",
1037                         tx_q->len);
1038                 do_drain_mbuf_table(tx_q);
1039         }
1040 }
1041
1042 static inline void __attribute__((always_inline))
1043 drain_eth_rx(struct vhost_dev *vdev)
1044 {
1045         uint16_t rx_count, enqueue_count;
1046         struct virtio_net *dev = vdev->dev;
1047         struct rte_mbuf *pkts[MAX_PKT_BURST];
1048
1049         rx_count = rte_eth_rx_burst(ports[0], vdev->vmdq_rx_q,
1050                                     pkts, MAX_PKT_BURST);
1051         if (!rx_count)
1052                 return;
1053
1054         /*
1055          * When "enable_retry" is set, here we wait and retry when there
1056          * is no enough free slots in the queue to hold @rx_count packets,
1057          * to diminish packet loss.
1058          */
1059         if (enable_retry &&
1060             unlikely(rx_count > rte_vring_available_entries(dev,
1061                         VIRTIO_RXQ))) {
1062                 uint32_t retry;
1063
1064                 for (retry = 0; retry < burst_rx_retry_num; retry++) {
1065                         rte_delay_us(burst_rx_delay_time);
1066                         if (rx_count <= rte_vring_available_entries(dev,
1067                                         VIRTIO_RXQ))
1068                                 break;
1069                 }
1070         }
1071
1072         enqueue_count = rte_vhost_enqueue_burst(dev, VIRTIO_RXQ,
1073                                                 pkts, rx_count);
1074         if (enable_stats) {
1075                 rte_atomic64_add(&vdev->stats.rx_total_atomic, rx_count);
1076                 rte_atomic64_add(&vdev->stats.rx_atomic, enqueue_count);
1077         }
1078
1079         free_pkts(pkts, rx_count);
1080 }
1081
1082 static inline void __attribute__((always_inline))
1083 drain_virtio_tx(struct vhost_dev *vdev)
1084 {
1085         struct rte_mbuf *pkts[MAX_PKT_BURST];
1086         uint16_t count;
1087         uint16_t i;
1088
1089         count = rte_vhost_dequeue_burst(vdev->dev, VIRTIO_TXQ, mbuf_pool,
1090                                         pkts, MAX_PKT_BURST);
1091
1092         /* setup VMDq for the first packet */
1093         if (unlikely(vdev->ready == DEVICE_MAC_LEARNING) && count) {
1094                 if (vdev->remove || link_vmdq(vdev, pkts[0]) == -1)
1095                         free_pkts(pkts, count);
1096         }
1097
1098         for (i = 0; i < count; ++i) {
1099                 virtio_tx_route(vdev, pkts[i],
1100                         vlan_tags[(uint16_t)vdev->dev->device_fh]);
1101         }
1102 }
1103
1104 /*
1105  * Main function of vhost-switch. It basically does:
1106  *
1107  * for each vhost device {
1108  *    - drain_eth_rx()
1109  *
1110  *      Which drains the host eth Rx queue linked to the vhost device,
1111  *      and deliver all of them to guest virito Rx ring associated with
1112  *      this vhost device.
1113  *
1114  *    - drain_virtio_tx()
1115  *
1116  *      Which drains the guest virtio Tx queue and deliver all of them
1117  *      to the target, which could be another vhost device, or the
1118  *      physical eth dev. The route is done in function "virtio_tx_route".
1119  * }
1120  */
1121 static int
1122 switch_worker(void *arg __rte_unused)
1123 {
1124         unsigned i;
1125         unsigned lcore_id = rte_lcore_id();
1126         struct vhost_dev *vdev;
1127         struct mbuf_table *tx_q;
1128
1129         RTE_LOG(INFO, VHOST_DATA, "Procesing on Core %u started\n", lcore_id);
1130
1131         tx_q = &lcore_tx_queue[lcore_id];
1132         for (i = 0; i < rte_lcore_count(); i++) {
1133                 if (lcore_ids[i] == lcore_id) {
1134                         tx_q->txq_id = i;
1135                         break;
1136                 }
1137         }
1138
1139         while(1) {
1140                 drain_mbuf_table(tx_q);
1141
1142                 /*
1143                  * Inform the configuration core that we have exited the
1144                  * linked list and that no devices are in use if requested.
1145                  */
1146                 if (lcore_info[lcore_id].dev_removal_flag == REQUEST_DEV_REMOVAL)
1147                         lcore_info[lcore_id].dev_removal_flag = ACK_DEV_REMOVAL;
1148
1149                 /*
1150                  * Process vhost devices
1151                  */
1152                 TAILQ_FOREACH(vdev, &lcore_info[lcore_id].vdev_list,
1153                               lcore_vdev_entry) {
1154                         if (unlikely(vdev->remove)) {
1155                                 unlink_vmdq(vdev);
1156                                 vdev->ready = DEVICE_SAFE_REMOVE;
1157                                 continue;
1158                         }
1159
1160                         if (likely(vdev->ready == DEVICE_RX))
1161                                 drain_eth_rx(vdev);
1162
1163                         if (likely(!vdev->remove))
1164                                 drain_virtio_tx(vdev);
1165                 }
1166         }
1167
1168         return 0;
1169 }
1170
1171 /*
1172  * Remove a device from the specific data core linked list and from the
1173  * main linked list. Synchonization  occurs through the use of the
1174  * lcore dev_removal_flag. Device is made volatile here to avoid re-ordering
1175  * of dev->remove=1 which can cause an infinite loop in the rte_pause loop.
1176  */
1177 static void
1178 destroy_device (volatile struct virtio_net *dev)
1179 {
1180         struct vhost_dev *vdev;
1181         int lcore;
1182
1183         dev->flags &= ~VIRTIO_DEV_RUNNING;
1184
1185         vdev = (struct vhost_dev *)dev->priv;
1186         /*set the remove flag. */
1187         vdev->remove = 1;
1188         while(vdev->ready != DEVICE_SAFE_REMOVE) {
1189                 rte_pause();
1190         }
1191
1192         TAILQ_REMOVE(&lcore_info[vdev->coreid].vdev_list, vdev,
1193                      lcore_vdev_entry);
1194         TAILQ_REMOVE(&vhost_dev_list, vdev, global_vdev_entry);
1195
1196
1197         /* Set the dev_removal_flag on each lcore. */
1198         RTE_LCORE_FOREACH_SLAVE(lcore)
1199                 lcore_info[lcore].dev_removal_flag = REQUEST_DEV_REMOVAL;
1200
1201         /*
1202          * Once each core has set the dev_removal_flag to ACK_DEV_REMOVAL
1203          * we can be sure that they can no longer access the device removed
1204          * from the linked lists and that the devices are no longer in use.
1205          */
1206         RTE_LCORE_FOREACH_SLAVE(lcore) {
1207                 while (lcore_info[lcore].dev_removal_flag != ACK_DEV_REMOVAL)
1208                         rte_pause();
1209         }
1210
1211         lcore_info[vdev->coreid].device_num--;
1212
1213         RTE_LOG(INFO, VHOST_DATA,
1214                 "(%" PRIu64 ") Device has been removed from data core\n",
1215                 dev->device_fh);
1216
1217         rte_free(vdev);
1218 }
1219
1220 /*
1221  * A new device is added to a data core. First the device is added to the main linked list
1222  * and the allocated to a specific data core.
1223  */
1224 static int
1225 new_device (struct virtio_net *dev)
1226 {
1227         int lcore, core_add = 0;
1228         uint32_t device_num_min = num_devices;
1229         struct vhost_dev *vdev;
1230
1231         vdev = rte_zmalloc("vhost device", sizeof(*vdev), RTE_CACHE_LINE_SIZE);
1232         if (vdev == NULL) {
1233                 RTE_LOG(INFO, VHOST_DATA, "(%"PRIu64") Couldn't allocate memory for vhost dev\n",
1234                         dev->device_fh);
1235                 return -1;
1236         }
1237         vdev->dev = dev;
1238         dev->priv = vdev;
1239
1240         TAILQ_INSERT_TAIL(&vhost_dev_list, vdev, global_vdev_entry);
1241         vdev->vmdq_rx_q
1242                 = dev->device_fh * queues_per_pool + vmdq_queue_base;
1243
1244         /*reset ready flag*/
1245         vdev->ready = DEVICE_MAC_LEARNING;
1246         vdev->remove = 0;
1247
1248         /* Find a suitable lcore to add the device. */
1249         RTE_LCORE_FOREACH_SLAVE(lcore) {
1250                 if (lcore_info[lcore].device_num < device_num_min) {
1251                         device_num_min = lcore_info[lcore].device_num;
1252                         core_add = lcore;
1253                 }
1254         }
1255         vdev->coreid = core_add;
1256
1257         TAILQ_INSERT_TAIL(&lcore_info[vdev->coreid].vdev_list, vdev,
1258                           lcore_vdev_entry);
1259         lcore_info[vdev->coreid].device_num++;
1260
1261         /* Disable notifications. */
1262         rte_vhost_enable_guest_notification(dev, VIRTIO_RXQ, 0);
1263         rte_vhost_enable_guest_notification(dev, VIRTIO_TXQ, 0);
1264         dev->flags |= VIRTIO_DEV_RUNNING;
1265
1266         RTE_LOG(INFO, VHOST_DATA, "(%"PRIu64") Device has been added to data core %d\n", dev->device_fh, vdev->coreid);
1267
1268         return 0;
1269 }
1270
1271 /*
1272  * These callback allow devices to be added to the data core when configuration
1273  * has been fully complete.
1274  */
1275 static const struct virtio_net_device_ops virtio_net_device_ops =
1276 {
1277         .new_device =  new_device,
1278         .destroy_device = destroy_device,
1279 };
1280
1281 /*
1282  * This is a thread will wake up after a period to print stats if the user has
1283  * enabled them.
1284  */
1285 static void
1286 print_stats(void)
1287 {
1288         struct vhost_dev *vdev;
1289         uint64_t tx_dropped, rx_dropped;
1290         uint64_t tx, tx_total, rx, rx_total;
1291         const char clr[] = { 27, '[', '2', 'J', '\0' };
1292         const char top_left[] = { 27, '[', '1', ';', '1', 'H','\0' };
1293
1294         while(1) {
1295                 sleep(enable_stats);
1296
1297                 /* Clear screen and move to top left */
1298                 printf("%s%s\n", clr, top_left);
1299                 printf("Device statistics =================================\n");
1300
1301                 TAILQ_FOREACH(vdev, &vhost_dev_list, global_vdev_entry) {
1302                         tx_total   = vdev->stats.tx_total;
1303                         tx         = vdev->stats.tx;
1304                         tx_dropped = tx_total - tx;
1305
1306                         rx_total   = rte_atomic64_read(&vdev->stats.rx_total_atomic);
1307                         rx         = rte_atomic64_read(&vdev->stats.rx_atomic);
1308                         rx_dropped = rx_total - rx;
1309
1310                         printf("Statistics for device %" PRIu64 "\n"
1311                                 "-----------------------\n"
1312                                 "TX total:              %" PRIu64 "\n"
1313                                 "TX dropped:            %" PRIu64 "\n"
1314                                 "TX successful:         %" PRIu64 "\n"
1315                                 "RX total:              %" PRIu64 "\n"
1316                                 "RX dropped:            %" PRIu64 "\n"
1317                                 "RX successful:         %" PRIu64 "\n",
1318                                 vdev->dev->device_fh,
1319                                 tx_total, tx_dropped, tx,
1320                                 rx_total, rx_dropped, rx);
1321                 }
1322
1323                 printf("===================================================\n");
1324         }
1325 }
1326
1327 /* When we receive a INT signal, unregister vhost driver */
1328 static void
1329 sigint_handler(__rte_unused int signum)
1330 {
1331         /* Unregister vhost driver. */
1332         int ret = rte_vhost_driver_unregister((char *)&dev_basename);
1333         if (ret != 0)
1334                 rte_exit(EXIT_FAILURE, "vhost driver unregister failure.\n");
1335         exit(0);
1336 }
1337
1338 /*
1339  * While creating an mbuf pool, one key thing is to figure out how
1340  * many mbuf entries is enough for our use. FYI, here are some
1341  * guidelines:
1342  *
1343  * - Each rx queue would reserve @nr_rx_desc mbufs at queue setup stage
1344  *
1345  * - For each switch core (A CPU core does the packet switch), we need
1346  *   also make some reservation for receiving the packets from virtio
1347  *   Tx queue. How many is enough depends on the usage. It's normally
1348  *   a simple calculation like following:
1349  *
1350  *       MAX_PKT_BURST * max packet size / mbuf size
1351  *
1352  *   So, we definitely need allocate more mbufs when TSO is enabled.
1353  *
1354  * - Similarly, for each switching core, we should serve @nr_rx_desc
1355  *   mbufs for receiving the packets from physical NIC device.
1356  *
1357  * - We also need make sure, for each switch core, we have allocated
1358  *   enough mbufs to fill up the mbuf cache.
1359  */
1360 static void
1361 create_mbuf_pool(uint16_t nr_port, uint32_t nr_switch_core, uint32_t mbuf_size,
1362         uint32_t nr_queues, uint32_t nr_rx_desc, uint32_t nr_mbuf_cache)
1363 {
1364         uint32_t nr_mbufs;
1365         uint32_t nr_mbufs_per_core;
1366         uint32_t mtu = 1500;
1367
1368         if (mergeable)
1369                 mtu = 9000;
1370         if (enable_tso)
1371                 mtu = 64 * 1024;
1372
1373         nr_mbufs_per_core  = (mtu + mbuf_size) * MAX_PKT_BURST /
1374                         (mbuf_size - RTE_PKTMBUF_HEADROOM) * MAX_PKT_BURST;
1375         nr_mbufs_per_core += nr_rx_desc;
1376         nr_mbufs_per_core  = RTE_MAX(nr_mbufs_per_core, nr_mbuf_cache);
1377
1378         nr_mbufs  = nr_queues * nr_rx_desc;
1379         nr_mbufs += nr_mbufs_per_core * nr_switch_core;
1380         nr_mbufs *= nr_port;
1381
1382         mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", nr_mbufs,
1383                                             nr_mbuf_cache, 0, mbuf_size,
1384                                             rte_socket_id());
1385         if (mbuf_pool == NULL)
1386                 rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n");
1387 }
1388
1389 /*
1390  * Main function, does initialisation and calls the per-lcore functions. The CUSE
1391  * device is also registered here to handle the IOCTLs.
1392  */
1393 int
1394 main(int argc, char *argv[])
1395 {
1396         unsigned lcore_id, core_id = 0;
1397         unsigned nb_ports, valid_num_ports;
1398         int ret;
1399         uint8_t portid;
1400         static pthread_t tid;
1401         char thread_name[RTE_MAX_THREAD_NAME_LEN];
1402
1403         signal(SIGINT, sigint_handler);
1404
1405         /* init EAL */
1406         ret = rte_eal_init(argc, argv);
1407         if (ret < 0)
1408                 rte_exit(EXIT_FAILURE, "Error with EAL initialization\n");
1409         argc -= ret;
1410         argv += ret;
1411
1412         /* parse app arguments */
1413         ret = us_vhost_parse_args(argc, argv);
1414         if (ret < 0)
1415                 rte_exit(EXIT_FAILURE, "Invalid argument\n");
1416
1417         for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id ++)
1418                 TAILQ_INIT(&lcore_info[lcore_id].vdev_list);
1419
1420                 if (rte_lcore_is_enabled(lcore_id))
1421                         lcore_ids[core_id ++] = lcore_id;
1422
1423         if (rte_lcore_count() > RTE_MAX_LCORE)
1424                 rte_exit(EXIT_FAILURE,"Not enough cores\n");
1425
1426         /* Get the number of physical ports. */
1427         nb_ports = rte_eth_dev_count();
1428
1429         /*
1430          * Update the global var NUM_PORTS and global array PORTS
1431          * and get value of var VALID_NUM_PORTS according to system ports number
1432          */
1433         valid_num_ports = check_ports_num(nb_ports);
1434
1435         if ((valid_num_ports ==  0) || (valid_num_ports > MAX_SUP_PORTS)) {
1436                 RTE_LOG(INFO, VHOST_PORT, "Current enabled port number is %u,"
1437                         "but only %u port can be enabled\n",num_ports, MAX_SUP_PORTS);
1438                 return -1;
1439         }
1440
1441         /*
1442          * FIXME: here we are trying to allocate mbufs big enough for
1443          * @MAX_QUEUES, but the truth is we're never going to use that
1444          * many queues here. We probably should only do allocation for
1445          * those queues we are going to use.
1446          */
1447         create_mbuf_pool(valid_num_ports, rte_lcore_count() - 1, MBUF_DATA_SIZE,
1448                          MAX_QUEUES, RTE_TEST_RX_DESC_DEFAULT, MBUF_CACHE_SIZE);
1449
1450         if (vm2vm_mode == VM2VM_HARDWARE) {
1451                 /* Enable VT loop back to let L2 switch to do it. */
1452                 vmdq_conf_default.rx_adv_conf.vmdq_rx_conf.enable_loop_back = 1;
1453                 RTE_LOG(DEBUG, VHOST_CONFIG,
1454                         "Enable loop back for L2 switch in vmdq.\n");
1455         }
1456
1457         /* initialize all ports */
1458         for (portid = 0; portid < nb_ports; portid++) {
1459                 /* skip ports that are not enabled */
1460                 if ((enabled_port_mask & (1 << portid)) == 0) {
1461                         RTE_LOG(INFO, VHOST_PORT,
1462                                 "Skipping disabled port %d\n", portid);
1463                         continue;
1464                 }
1465                 if (port_init(portid) != 0)
1466                         rte_exit(EXIT_FAILURE,
1467                                 "Cannot initialize network ports\n");
1468         }
1469
1470         /* Enable stats if the user option is set. */
1471         if (enable_stats) {
1472                 ret = pthread_create(&tid, NULL, (void *)print_stats, NULL);
1473                 if (ret != 0)
1474                         rte_exit(EXIT_FAILURE,
1475                                 "Cannot create print-stats thread\n");
1476
1477                 /* Set thread_name for aid in debugging.  */
1478                 snprintf(thread_name, RTE_MAX_THREAD_NAME_LEN, "print-stats");
1479                 ret = rte_thread_setname(tid, thread_name);
1480                 if (ret != 0)
1481                         RTE_LOG(DEBUG, VHOST_CONFIG,
1482                                 "Cannot set print-stats name\n");
1483         }
1484
1485         /* Launch all data cores. */
1486         RTE_LCORE_FOREACH_SLAVE(lcore_id)
1487                 rte_eal_remote_launch(switch_worker, NULL, lcore_id);
1488
1489         if (mergeable == 0)
1490                 rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_MRG_RXBUF);
1491
1492         /* Register vhost(cuse or user) driver to handle vhost messages. */
1493         ret = rte_vhost_driver_register((char *)&dev_basename);
1494         if (ret != 0)
1495                 rte_exit(EXIT_FAILURE, "vhost driver register failure.\n");
1496
1497         rte_vhost_driver_callback_register(&virtio_net_device_ops);
1498
1499         /* Start CUSE session. */
1500         rte_vhost_driver_session_start();
1501         return 0;
1502
1503 }