examples/vhost: support multiple socket files
[dpdk.git] / examples / vhost / main.c
index 3b98f42..71f6d92 100644 (file)
@@ -90,9 +90,6 @@
 /* Size of buffers used for snprintfs. */
 #define MAX_PRINT_BUFF 6072
 
-/* Maximum character device basename size. */
-#define MAX_BASENAME_SZ 10
-
 /* Maximum long option length for option parsing. */
 #define MAX_LONG_OPT_SZ 64
 
@@ -139,8 +136,9 @@ static uint32_t burst_rx_delay_time = BURST_RX_WAIT_US;
 /* Specify the number of retries on RX. */
 static uint32_t burst_rx_retry_num = BURST_RX_RETRIES;
 
-/* Character device basename. Can be set by user. */
-static char dev_basename[MAX_BASENAME_SZ] = "vhost-net";
+/* Socket file paths. Can be set by user */
+static char *socket_files;
+static int nb_sockets;
 
 /* empty vmdq configuration structure. Filled in programatically */
 static struct rte_eth_conf vmdq_conf_default = {
@@ -327,6 +325,8 @@ port_init(uint8_t port)
        if (enable_tso == 0) {
                rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_HOST_TSO4);
                rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_HOST_TSO6);
+               rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_GUEST_TSO4);
+               rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_GUEST_TSO6);
        }
 
        rx_rings = (uint16_t)dev_info.max_rx_queues;
@@ -390,17 +390,18 @@ port_init(uint8_t port)
 }
 
 /*
- * Set character device basename.
+ * Set socket file path.
  */
 static int
-us_vhost_parse_basename(const char *q_arg)
+us_vhost_parse_socket_path(const char *q_arg)
 {
        /* parse number string */
-
-       if (strnlen(q_arg, MAX_BASENAME_SZ) > MAX_BASENAME_SZ)
+       if (strnlen(q_arg, PATH_MAX) > PATH_MAX)
                return -1;
-       else
-               snprintf((char*)&dev_basename, MAX_BASENAME_SZ, "%s", q_arg);
+
+       socket_files = realloc(socket_files, PATH_MAX * (nb_sockets + 1));
+       snprintf(socket_files + nb_sockets * PATH_MAX, PATH_MAX, "%s", q_arg);
+       nb_sockets++;
 
        return 0;
 }
@@ -460,7 +461,7 @@ us_vhost_usage(const char *prgname)
        RTE_LOG(INFO, VHOST_CONFIG, "%s [EAL options] -- -p PORTMASK\n"
        "               --vm2vm [0|1|2]\n"
        "               --rx_retry [0|1] --mergeable [0|1] --stats [0-N]\n"
-       "               --dev-basename <name>\n"
+       "               --socket-file <path>\n"
        "               --nb-devices ND\n"
        "               -p PORTMASK: Set mask for ports to be used by application\n"
        "               --vm2vm [0|1|2]: disable/software(default)/hardware vm2vm comms\n"
@@ -470,7 +471,7 @@ us_vhost_usage(const char *prgname)
        "               --mergeable [0|1]: disable(default)/enable RX mergeable buffers\n"
        "               --vlan-strip [0|1]: disable/enable(default) RX VLAN strip on host\n"
        "               --stats [0-N]: 0: Disable stats, N: Time in seconds to print stats\n"
-       "               --dev-basename: The basename to be used for the character device.\n"
+       "               --socket-file: The path of the socket file.\n"
        "               --tx-csum [0|1] disable/enable TX checksum offload.\n"
        "               --tso [0|1] disable/enable TCP segment offload.\n"
        "               --client register a vhost-user socket as client mode.\n",
@@ -495,7 +496,7 @@ us_vhost_parse_args(int argc, char **argv)
                {"mergeable", required_argument, NULL, 0},
                {"vlan-strip", required_argument, NULL, 0},
                {"stats", required_argument, NULL, 0},
-               {"dev-basename", required_argument, NULL, 0},
+               {"socket-file", required_argument, NULL, 0},
                {"tx-csum", required_argument, NULL, 0},
                {"tso", required_argument, NULL, 0},
                {"client", no_argument, &client_mode, 1},
@@ -636,7 +637,8 @@ us_vhost_parse_args(int argc, char **argv)
                        if (!strncmp(long_option[option_index].name, "stats", MAX_LONG_OPT_SZ)) {
                                ret = parse_num_opt(optarg, INT32_MAX);
                                if (ret == -1) {
-                                       RTE_LOG(INFO, VHOST_CONFIG, "Invalid argument for stats [0..N]\n");
+                                       RTE_LOG(INFO, VHOST_CONFIG,
+                                               "Invalid argument for stats [0..N]\n");
                                        us_vhost_usage(prgname);
                                        return -1;
                                } else {
@@ -644,10 +646,13 @@ us_vhost_parse_args(int argc, char **argv)
                                }
                        }
 
-                       /* Set character device basename. */
-                       if (!strncmp(long_option[option_index].name, "dev-basename", MAX_LONG_OPT_SZ)) {
-                               if (us_vhost_parse_basename(optarg) == -1) {
-                                       RTE_LOG(INFO, VHOST_CONFIG, "Invalid argument for character device basename (Max %d characters)\n", MAX_BASENAME_SZ);
+                       /* Set socket file path. */
+                       if (!strncmp(long_option[option_index].name,
+                                               "socket-file", MAX_LONG_OPT_SZ)) {
+                               if (us_vhost_parse_socket_path(optarg) == -1) {
+                                       RTE_LOG(INFO, VHOST_CONFIG,
+                                       "Invalid argument for socket name (Max %d characters)\n",
+                                       PATH_MAX);
                                        us_vhost_usage(prgname);
                                        return -1;
                                }
@@ -1338,14 +1343,27 @@ print_stats(void)
        }
 }
 
+static void
+unregister_drivers(int socket_num)
+{
+       int i, ret;
+
+       for (i = 0; i < socket_num; i++) {
+               ret = rte_vhost_driver_unregister(socket_files + i * PATH_MAX);
+               if (ret != 0)
+                       RTE_LOG(ERR, VHOST_CONFIG,
+                               "Fail to unregister vhost driver for %s.\n",
+                               socket_files + i * PATH_MAX);
+       }
+}
+
 /* When we receive a INT signal, unregister vhost driver */
 static void
 sigint_handler(__rte_unused int signum)
 {
        /* Unregister vhost driver. */
-       int ret = rte_vhost_driver_unregister((char *)&dev_basename);
-       if (ret != 0)
-               rte_exit(EXIT_FAILURE, "vhost driver unregister failure.\n");
+       unregister_drivers(nb_sockets);
+
        exit(0);
 }
 
@@ -1409,7 +1427,7 @@ main(int argc, char *argv[])
 {
        unsigned lcore_id, core_id = 0;
        unsigned nb_ports, valid_num_ports;
-       int ret;
+       int ret, i;
        uint8_t portid;
        static pthread_t tid;
        char thread_name[RTE_MAX_THREAD_NAME_LEN];
@@ -1507,10 +1525,16 @@ main(int argc, char *argv[])
        if (client_mode)
                flags |= RTE_VHOST_USER_CLIENT;
 
-       /* Register vhost(cuse or user) driver to handle vhost messages. */
-       ret = rte_vhost_driver_register(dev_basename, flags);
-       if (ret != 0)
-               rte_exit(EXIT_FAILURE, "vhost driver register failure.\n");
+       /* Register vhost user driver to handle vhost messages. */
+       for (i = 0; i < nb_sockets; i++) {
+               ret = rte_vhost_driver_register
+                               (socket_files + i * PATH_MAX, flags);
+               if (ret != 0) {
+                       unregister_drivers(i);
+                       rte_exit(EXIT_FAILURE,
+                               "vhost driver register failure.\n");
+               }
+       }
 
        rte_vhost_driver_callback_register(&virtio_net_device_ops);