[ovs-dev] [PATCH RFC v4 2/3] netdev-dpdk: Arbitrary 'dpdk' port naming

Ciara Loftus ciara.loftus at intel.com
Fri Oct 28 14:45:57 UTC 2016


'dpdk' ports no longer have naming restrictions. Now, instead
of specifying the dpdk port ID as part of the name, the PCI
address of the device must be specified via the 'dpdk-devargs'
option. eg.

ovs-vsctl add-port br0 my-port
ovs-vsctl set Interface my-port type=dpdk
ovs-vsctl set Interface my-port options:dpdk-devargs=0000:06:00.3

The user must no longer hotplug DPDK ports by issuing specific
ovs-appctl commands. The hotplug is now automatically invoked when a
valid PCI address is set in the dpdk-devargs.

Signed-off-by: Ciara Loftus <ciara.loftus at intel.com>
---
 INSTALL.DPDK-ADVANCED.md |   9 +--
 INSTALL.DPDK.rst         |  14 +++--
 NEWS                     |   2 +
 lib/netdev-dpdk.c        | 153 ++++++++++++++++++-----------------------------
 vswitchd/vswitch.xml     |   8 +++
 5 files changed, 77 insertions(+), 109 deletions(-)

diff --git a/INSTALL.DPDK-ADVANCED.md b/INSTALL.DPDK-ADVANCED.md
index 7d90219..577e412 100644
--- a/INSTALL.DPDK-ADVANCED.md
+++ b/INSTALL.DPDK-ADVANCED.md
@@ -892,14 +892,7 @@ dpdk_nic_bind.py script:
 
 Then it can be attached to OVS:
 
-`ovs-appctl netdev-dpdk/port-attach 0000:01:00.0`
-
-At this point, the user can create a ovs port using the add-port command.
-
-It is also possible to detach a port from ovs, the user has to remove the
-port using the del-port command, then it can be detached using:
-
-`ovs-appctl netdev-dpdk/port-detach dpdk0`
+`ovs-vsctl add-port br0 dpdk0 -- set Interface dpdk0 type=dpdk options:dpdk-devargs=0000:01:00.0`
 
 This feature is not supported with VFIO and could not work with some NICs,
 please refer to the [DPDK Port Hotplug Framework] in order to get more
diff --git a/INSTALL.DPDK.rst b/INSTALL.DPDK.rst
index b917828..2f41f40 100644
--- a/INSTALL.DPDK.rst
+++ b/INSTALL.DPDK.rst
@@ -249,12 +249,14 @@ Bridges should be created with a ``datapath_type=netdev``:::
 
     $ ovs-vsctl add-br br0 -- set bridge br0 datapath_type=netdev
 
-Now you can add DPDK devices. OVS expects DPDK device names to start with
-``dpdk`` and end with a portid. ovs-vswitchd should print the number of dpdk
-devices found in the log file:::
-
-    $ ovs-vsctl add-port br0 dpdk0 -- set Interface dpdk0 type=dpdk
-    $ ovs-vsctl add-port br0 dpdk1 -- set Interface dpdk1 type=dpdk
+Now you can add dpdk devices. The PCI address of the device needs to be
+set using the 'dpdk-devargs' option. vswitchd should print (in the log file)
+the PCI addresses of dpdk devices found during initialisation.
+
+```
+ovs-vsctl add-port br0 dpdk0 -- set Interface dpdk0 type=dpdk options:dpdk-devargs=0000:06:00.0
+ovs-vsctl add-port br0 dpdk1 -- set Interface dpdk1 type=dpdk options:dpdk-devargs=0000:06:00.1
+```
 
 After the DPDK ports get added to switch, a polling thread continuously polls
 DPDK devices and consumes 100% of the core, as can be checked from 'top' and
diff --git a/NEWS b/NEWS
index c335547..4e3df06 100644
--- a/NEWS
+++ b/NEWS
@@ -34,6 +34,8 @@ Post-v2.6.0
      * New option 'n_rxq_desc' and 'n_txq_desc' fields for DPDK interfaces
        which set the number of rx and tx descriptors to use for the given port.
      * Port Hotplug is now supported.
+     * DPDK physical ports can now have arbitrary names. The PCI address of
+       the device must be set using the 'dpdk-devargs' option.
    - Fedora packaging:
      * A package upgrade does not automatically restart OVS service.
 
diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c
index c102506..816e0a6 100644
--- a/lib/netdev-dpdk.c
+++ b/lib/netdev-dpdk.c
@@ -811,7 +811,7 @@ netdev_dpdk_init(struct netdev *netdev, unsigned int port_no,
     /* If the 'sid' is negative, it means that the kernel fails
      * to obtain the pci numa info.  In that situation, always
      * use 'SOCKET0'. */
-    if (type == DPDK_DEV_ETH) {
+    if (type == DPDK_DEV_ETH && rte_eth_dev_is_valid_port(dev->port_id)) {
         sid = rte_eth_dev_socket_id(port_no);
     } else {
         sid = rte_lcore_to_socket_id(rte_get_master_lcore());
@@ -850,9 +850,11 @@ netdev_dpdk_init(struct netdev *netdev, unsigned int port_no,
     /* Initialize the flow control to NULL */
     memset(&dev->fc_conf, 0, sizeof dev->fc_conf);
     if (type == DPDK_DEV_ETH) {
-        err = dpdk_eth_dev_init(dev);
-        if (err) {
-            goto unlock;
+        if (rte_eth_dev_is_valid_port(dev->port_id)) {
+            err = dpdk_eth_dev_init(dev);
+            if (err) {
+                goto unlock;
+            }
         }
         dev->tx_q = netdev_dpdk_alloc_txq(netdev->n_txq);
     } else {
@@ -948,17 +950,10 @@ netdev_dpdk_vhost_client_construct(struct netdev *netdev)
 static int
 netdev_dpdk_construct(struct netdev *netdev)
 {
-    unsigned int port_no;
     int err;
 
-    /* Names always start with "dpdk" */
-    err = dpdk_dev_parse_name(netdev->name, "dpdk", &port_no);
-    if (err) {
-        return err;
-    }
-
     ovs_mutex_lock(&dpdk_mutex);
-    err = netdev_dpdk_init(netdev, port_no, DPDK_DEV_ETH);
+    err = netdev_dpdk_init(netdev, -1, DPDK_DEV_ETH);
     ovs_mutex_unlock(&dpdk_mutex);
     return err;
 }
@@ -1067,6 +1062,49 @@ netdev_dpdk_get_config(const struct netdev *netdev, struct smap *args)
 }
 
 static void
+netdev_dpdk_process_devargs(struct netdev_dpdk *dev, const char *devargs)
+{
+    int i = 0;
+    struct rte_eth_dev_info info;
+    struct rte_pci_addr addr;
+
+    if (eal_parse_pci_DomBDF(devargs, &addr)) {
+        return;
+    }
+
+    /* Search for PCI device in DPDK */
+    for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
+        if (!rte_eth_dev_is_valid_port(i)) {
+            continue;
+        }
+        rte_eth_dev_info_get(i, &info);
+        if (!rte_eal_compare_pci_addr(&info.pci_dev->addr, &addr)) {
+            dev->port_id = i;
+            break;
+        }
+    }
+
+    if (!rte_eth_dev_is_valid_port(dev->port_id)) {
+        /* PCI device not found in DPDK, attempt to attach it */
+        uint8_t port_id;
+
+        if (!rte_eth_dev_attach(devargs, &port_id)) {
+            /* Attach successful */
+            VLOG_INFO("Device "PCI_PRI_FMT" has been attached to DPDK",
+                    addr.domain, addr.bus, addr.devid, addr.function);
+            dev->port_id = port_id;
+        } else {
+            /* Attach unsuccessful */
+            return;
+        }
+    }
+
+    rte_eth_dev_stop(dev->port_id);
+    dev->socket_id = rte_eth_dev_socket_id(dev->port_id);
+    dpdk_eth_dev_init(dev);
+}
+
+static void
 dpdk_set_rxq_config(struct netdev_dpdk *dev, const struct smap *args)
     OVS_REQUIRES(dev->mutex)
 {
@@ -1106,6 +1144,7 @@ netdev_dpdk_set_config(struct netdev *netdev, const struct smap *args)
         {RTE_FC_NONE,     RTE_FC_TX_PAUSE},
         {RTE_FC_RX_PAUSE, RTE_FC_FULL    }
     };
+    const char *new_devargs;
 
     ovs_mutex_lock(&dev->mutex);
 
@@ -1129,6 +1168,13 @@ netdev_dpdk_set_config(struct netdev *netdev, const struct smap *args)
         dpdk_eth_flow_ctrl_setup(dev);
     }
 
+    if (!rte_eth_dev_is_valid_port(dev->port_id)) {
+        new_devargs = smap_get(args, "dpdk-devargs");
+        if (new_devargs && strlen(new_devargs)) {
+            netdev_dpdk_process_devargs(dev, new_devargs);
+        }
+    }
+
     ovs_mutex_unlock(&dev->mutex);
 
     return 0;
@@ -2291,83 +2337,6 @@ netdev_dpdk_set_admin_state(struct unixctl_conn *conn, int argc,
     unixctl_command_reply(conn, "OK");
 }
 
-static void
-netdev_dpdk_port_attach(struct unixctl_conn *conn, int argc OVS_UNUSED,
-                        const char *argv[], void *aux OVS_UNUSED)
-{
-    int ret;
-    char response[128];
-    uint8_t port_id;
-
-    ovs_mutex_lock(&dpdk_mutex);
-
-    ret = rte_eth_dev_attach(argv[1], &port_id);
-    if (ret < 0) {
-        snprintf(response, sizeof(response),
-                 "Error attaching device '%s'", argv[1]);
-        ovs_mutex_unlock(&dpdk_mutex);
-        unixctl_command_reply_error(conn, response);
-        return;
-    }
-
-    snprintf(response, sizeof(response),
-             "Device '%s' has been attached as 'dpdk%d'", argv[1], port_id);
-
-    ovs_mutex_unlock(&dpdk_mutex);
-    unixctl_command_reply(conn, response);
-}
-
-static void
-netdev_dpdk_port_detach(struct unixctl_conn *conn, int argc OVS_UNUSED,
-                        const char *argv[], void *aux OVS_UNUSED)
-{
-    int ret;
-    char response[128];
-    unsigned int parsed_port;
-    uint8_t port_id;
-    char devname[RTE_ETH_NAME_MAX_LEN];
-
-    ovs_mutex_lock(&dpdk_mutex);
-
-    ret = dpdk_dev_parse_name(argv[1], "dpdk", &parsed_port);
-    if (ret) {
-        snprintf(response, sizeof(response),
-                 "'%s' is not a valid port", argv[1]);
-        goto error;
-    }
-
-    port_id = parsed_port;
-
-    struct netdev *netdev = netdev_from_name(argv[1]);
-    if (netdev) {
-        netdev_close(netdev);
-        snprintf(response, sizeof(response),
-                 "Port '%s' is being used. Remove it before detaching",
-                 argv[1]);
-        goto error;
-    }
-
-    rte_eth_dev_close(port_id);
-
-    ret = rte_eth_dev_detach(port_id, devname);
-    if (ret < 0) {
-        snprintf(response, sizeof(response),
-                 "Port '%s' can not be detached", argv[1]);
-        goto error;
-    }
-
-    snprintf(response, sizeof(response),
-             "Port '%s' has been detached", argv[1]);
-
-    ovs_mutex_unlock(&dpdk_mutex);
-    unixctl_command_reply(conn, response);
-    return;
-
-error:
-    ovs_mutex_unlock(&dpdk_mutex);
-    unixctl_command_reply_error(conn, response);
-}
-
 /*
  * Set virtqueue flags so that we do not receive interrupts.
  */
@@ -2643,12 +2612,6 @@ netdev_dpdk_class_init(void)
         unixctl_command_register("netdev-dpdk/set-admin-state",
                                  "[netdev] up|down", 1, 2,
                                  netdev_dpdk_set_admin_state, NULL);
-        unixctl_command_register("netdev-dpdk/port-attach",
-                                 "pci address of device", 1, 1,
-                                 netdev_dpdk_port_attach, NULL);
-        unixctl_command_register("netdev-dpdk/port-detach",
-                                 "port", 1, 1,
-                                 netdev_dpdk_port_detach, NULL);
 
         ovsthread_once_done(&once);
     }
diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml
index 99c1476..16318c5 100644
--- a/vswitchd/vswitch.xml
+++ b/vswitchd/vswitch.xml
@@ -2301,6 +2301,14 @@
         </p>
       </column>
 
+      <column name="options" key="dpdk-devargs"
+              type='{"type": "string"}'>
+        <p>
+          Specifies the PCI address of a physical dpdk device.
+          Only supported by 'dpdk' devices.
+        </p>
+      </column>
+
       <column name="other_config" key="pmd-rxq-affinity">
         <p>Specifies mapping of RX queues of this interface to CPU cores.</p>
         <p>Value should be set in the following form:</p>
-- 
2.4.3




More information about the dev mailing list