lib/netdev-dpdk: make device name parsing more robust
[cascardo/ovs.git] / lib / netdev-dpdk.c
index 09ccc2c..f94e0d4 100644 (file)
@@ -33,6 +33,7 @@
 #include "dirs.h"
 #include "dp-packet.h"
 #include "dpif-netdev.h"
+#include "fatal-signal.h"
 #include "list.h"
 #include "netdev-dpdk.h"
 #include "netdev-provider.h"
@@ -187,7 +188,7 @@ struct dpdk_ring {
     /* For the client rings */
     struct rte_ring *cring_tx;
     struct rte_ring *cring_rx;
-    int user_port_id; /* User given port no, parsed from port name */
+    unsigned int user_port_id; /* User given port no, parsed from port name */
     int eth_port_id; /* ethernet device port id */
     struct ovs_list list_node OVS_GUARDED_BY(dpdk_mutex);
 };
@@ -613,6 +614,7 @@ netdev_dpdk_init(struct netdev *netdev_, unsigned int port_no,
 
     netdev_->n_txq = NR_QUEUE;
     netdev_->n_rxq = NR_QUEUE;
+    netdev_->requested_n_rxq = NR_QUEUE;
     netdev->real_n_txq = NR_QUEUE;
 
     if (type == DPDK_DEV_ETH) {
@@ -633,6 +635,8 @@ unlock:
     return err;
 }
 
+/* dev_name must be the prefix followed by a positive decimal number.
+ * (no leading + or - signs are allowed) */
 static int
 dpdk_dev_parse_name(const char dev_name[], const char prefix[],
                     unsigned int *port_no)
@@ -644,8 +648,12 @@ dpdk_dev_parse_name(const char dev_name[], const char prefix[],
     }
 
     cport = dev_name + strlen(prefix);
-    *port_no = strtol(cport, NULL, 0); /* string must be null terminated */
-    return 0;
+
+    if (str_to_uint(cport, 10, port_no)) {
+        return 0;
+    } else {
+        return ENODEV;
+    }
 }
 
 static int
@@ -687,9 +695,13 @@ netdev_dpdk_vhost_user_construct(struct netdev *netdev_)
     if (err) {
         VLOG_ERR("vhost-user socket device setup failure for socket %s\n",
                  netdev->vhost_id);
+    } else {
+        fatal_signal_add_file_to_unlink(netdev->vhost_id);
+        VLOG_INFO("Socket %s created for vhost-user port %s\n",
+                  netdev->vhost_id, netdev_->name);
+        err = vhost_construct_helper(netdev_);
     }
-    VLOG_INFO("Socket %s created for vhost-user port %s\n", netdev->vhost_id, netdev_->name);
-    err = vhost_construct_helper(netdev_);
+
     ovs_mutex_unlock(&dpdk_mutex);
     return err;
 }
@@ -745,6 +757,8 @@ netdev_dpdk_vhost_destruct(struct netdev *netdev_)
 
     if (rte_vhost_driver_unregister(dev->vhost_id)) {
         VLOG_ERR("Unable to remove vhost-user socket %s", dev->vhost_id);
+    } else {
+        fatal_signal_remove_file_to_unlink(dev->vhost_id);
     }
 
     ovs_mutex_lock(&dpdk_mutex);
@@ -762,20 +776,35 @@ netdev_dpdk_dealloc(struct netdev *netdev_)
 }
 
 static int
-netdev_dpdk_get_config(const struct netdev *netdev_, struct smap *args)
+netdev_dpdk_get_config(const struct netdev *netdev, struct smap *args)
 {
-    struct netdev_dpdk *dev = netdev_dpdk_cast(netdev_);
+    struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
 
     ovs_mutex_lock(&dev->mutex);
 
-    smap_add_format(args, "configured_rx_queues", "%d", netdev_->n_rxq);
-    smap_add_format(args, "requested_tx_queues", "%d", netdev_->n_txq);
+    smap_add_format(args, "requested_rx_queues", "%d", netdev->requested_n_rxq);
+    smap_add_format(args, "configured_rx_queues", "%d", netdev->n_rxq);
+    smap_add_format(args, "requested_tx_queues", "%d", netdev->n_txq);
     smap_add_format(args, "configured_tx_queues", "%d", dev->real_n_txq);
     ovs_mutex_unlock(&dev->mutex);
 
     return 0;
 }
 
+static int
+netdev_dpdk_set_config(struct netdev *netdev, const struct smap *args)
+{
+    struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
+
+    ovs_mutex_lock(&dev->mutex);
+    netdev->requested_n_rxq = MAX(smap_get_int(args, "n_rxq",
+                                               netdev->requested_n_rxq), 1);
+    netdev_change_seq_changed(netdev);
+    ovs_mutex_unlock(&dev->mutex);
+
+    return 0;
+}
+
 static int
 netdev_dpdk_get_numa_id(const struct netdev *netdev_)
 {
@@ -1881,6 +1910,7 @@ static void
 destroy_device(volatile struct virtio_net *dev)
 {
     struct netdev_dpdk *vhost_dev;
+    bool exists = false;
 
     ovs_mutex_lock(&dpdk_mutex);
     LIST_FOR_EACH (vhost_dev, list_node, &dpdk_list) {
@@ -1889,24 +1919,32 @@ destroy_device(volatile struct virtio_net *dev)
             ovs_mutex_lock(&vhost_dev->mutex);
             dev->flags &= ~VIRTIO_DEV_RUNNING;
             ovsrcu_set(&vhost_dev->virtio_dev, NULL);
+            exists = true;
             ovs_mutex_unlock(&vhost_dev->mutex);
-
-            /*
-             * Wait for other threads to quiesce before
-             * setting the virtio_dev to NULL.
-             */
-            ovsrcu_synchronize();
-            /*
-             * As call to ovsrcu_synchronize() will end the quiescent state,
-             * put thread back into quiescent state before returning.
-             */
-            ovsrcu_quiesce_start();
+            break;
         }
     }
+
     ovs_mutex_unlock(&dpdk_mutex);
 
-    VLOG_INFO("vHost Device '%s' %"PRIu64" has been removed", dev->ifname,
-              dev->device_fh);
+    if (exists == true) {
+        /*
+         * Wait for other threads to quiesce after setting the 'virtio_dev'
+         * to NULL, before returning.
+         */
+        ovsrcu_synchronize();
+        /*
+         * As call to ovsrcu_synchronize() will end the quiescent state,
+         * put thread back into quiescent state before returning.
+         */
+        ovsrcu_quiesce_start();
+        VLOG_INFO("vHost Device '%s' %"PRIu64" has been removed", dev->ifname,
+                  dev->device_fh);
+    } else {
+        VLOG_INFO("vHost Device '%s' %"PRIu64" not found", dev->ifname,
+                  dev->device_fh);
+    }
+
 }
 
 struct virtio_net *
@@ -1988,7 +2026,7 @@ dpdk_ring_create(const char dev_name[], unsigned int port_no,
                  unsigned int *eth_port_id)
 {
     struct dpdk_ring *ivshmem;
-    char ring_name[10];
+    char ring_name[RTE_RING_NAMESIZE];
     int err;
 
     ivshmem = dpdk_rte_mzalloc(sizeof *ivshmem);
@@ -1997,7 +2035,7 @@ dpdk_ring_create(const char dev_name[], unsigned int port_no,
     }
 
     /* XXX: Add support for multiquque ring. */
-    err = snprintf(ring_name, 10, "%s_tx", dev_name);
+    err = snprintf(ring_name, sizeof(ring_name), "%s_tx", dev_name);
     if (err < 0) {
         return -err;
     }
@@ -2010,7 +2048,7 @@ dpdk_ring_create(const char dev_name[], unsigned int port_no,
         return ENOMEM;
     }
 
-    err = snprintf(ring_name, 10, "%s_rx", dev_name);
+    err = snprintf(ring_name, sizeof(ring_name), "%s_rx", dev_name);
     if (err < 0) {
         return -err;
     }
@@ -2120,7 +2158,7 @@ unlock_dpdk:
     DESTRUCT,                                                 \
     netdev_dpdk_dealloc,                                      \
     netdev_dpdk_get_config,                                   \
-    NULL,                       /* netdev_dpdk_set_config */  \
+    netdev_dpdk_set_config,                                   \
     NULL,                       /* get_tunnel_config */       \
     NULL,                       /* build header */            \
     NULL,                       /* push header */             \