Please note this patch is targeted for dpdk-latest and dpdk-hwol branches > -----Original Message----- > From: Ophir Munk > Sent: Wednesday, November 14, 2018 7:13 PM > To: ovs-dev@openvswitch.org > Cc: Asaf Penso <as...@mellanox.com>; Ian Stokes <ian.sto...@intel.com>; > Ben Pfaff <b...@ovn.org>; Shahaf Shuler <shah...@mellanox.com>; Thomas > Monjalon <tho...@monjalon.net>; Olga Shern <ol...@mellanox.com>; > Ophir Munk <ophi...@mellanox.com>; Kevin Traynor > <ktray...@redhat.com>; Tiago Lam <tiago....@intel.com> > Subject: [PATCH v1] netdev-dpdk: Upgrade to dpdk v18.11 > > 1. Enable compilation and linkage with dpdk 18.11.x > > 2. Update references to DPDK version 18.11 in Documentation and in travis > linux-build script > > 3. Replace deprecated functions calls > - rte_eth_dev_attach > - rte_eth_dev_detach > with their respective new calls > - rte_dev_probe > - rte_dev_remove > > 4. Dpdk port representors were introduced in dpdk 18.xx. > Commits examples are listed in [1]. dpdk representors documentation > appears in [2]. A sample configuration which uses two representors ports > (the output of "ovs-vsctl show" command) is shown in [3]. > > OVS remains backward compatible in supporting dpdk legacy PCI ports which > do not include representors. > > 5. Starting from dpdk 18.xx there is no more one to one relationship between > an rte device (e.g. PCI bus) and an eth device (seen as dpdk port ids by OVS). > The relationship became one (rte device) to many (eth devices). > For example in [3] there are two devices (representors) using the same PCI > address 0000:08:00.0. > This commit handles the new one to many relationship. For example, when > one of the devices representors is closed - the PCI bus cannot be detached > until the other device is closed as well. > > 6. HW offload capability DEV_RX_OFFLOAD_CRC_STRIP was replaced with > DEV_RX_OFFLOAD_KEEP_CRC. > > [1] > e0cb96204b71 ("net/i40e: add support for representor ports") > cf80ba6e2038 ("net/ixgbe: add support for representor ports") > 26c08b979d26 ("net/mlx5: add port representor awareness") > > [2] > doc/guides/prog_guide/switch_representation.rst > > [3] > Bridge "ovs_br0" > Port "ovs_br0" > Interface "ovs_br0" > type: internal > Port "port-rep3" > Interface "port-rep3" > type: dpdk > options: {dpdk-devargs="0000:08:00.0,representor=[3]"} > Port "port-rep5" > Interface "port-rep5" > type: dpdk > options: {dpdk-devargs="0000:08:00.0,representor=[5]"} > ovs_version: "2.10.90" > > Signed-off-by: Ophir Munk <ophi...@mellanox.com> > --- > v1: > Initial version > > .travis/linux-build.sh | 2 +- > Documentation/intro/install/dpdk.rst | 12 ++-- > Documentation/topics/dpdk/vhost-user.rst | 6 +- > lib/netdev-dpdk.c | 111 > ++++++++++++++++++++++--------- > 4 files changed, 91 insertions(+), 40 deletions(-) > > diff --git a/.travis/linux-build.sh b/.travis/linux-build.sh index > 4c9e952..1d3a955 100755 > --- a/.travis/linux-build.sh > +++ b/.travis/linux-build.sh > @@ -83,7 +83,7 @@ fi > > if [ "$DPDK" ]; then > if [ -z "$DPDK_VER" ]; then > - DPDK_VER="18.08" > + DPDK_VER="18.11" > fi > install_dpdk $DPDK_VER > if [ "$CC" = "clang" ]; then > diff --git a/Documentation/intro/install/dpdk.rst > b/Documentation/intro/install/dpdk.rst > index bab3560..8815427 100644 > --- a/Documentation/intro/install/dpdk.rst > +++ b/Documentation/intro/install/dpdk.rst > @@ -42,7 +42,7 @@ Build requirements > In addition to the requirements described in :doc:`general`, building Open > vSwitch with DPDK will require the following: > > -- DPDK 18.08.0 > +- DPDK 18.11.0 > > - A `DPDK supported NIC`_ > > @@ -71,9 +71,9 @@ Install DPDK > #. Download the `DPDK sources`_, extract the file and set ``DPDK_DIR``:: > > $ cd /usr/src/ > - $ wget http://fast.dpdk.org/rel/dpdk-18.08.tar.xz > + $ wget http://fast.dpdk.org/rel/dpdk-18.11.tar.xz > $ tar xf dpdk-18.08.tar.xz > - $ export DPDK_DIR=/usr/src/dpdk-stable-18.08 > + $ export DPDK_DIR=/usr/src/dpdk-stable-18.11 > $ cd $DPDK_DIR > > #. (Optional) Configure DPDK as a shared library @@ -283,9 +283,9 @@ > with either the ovs-vswitchd logs, or by running either of the commands:: > > $ ovs-vswitchd --version > ovs-vswitchd (Open vSwitch) 2.9.0 > - DPDK 18.08.0 > + DPDK 18.11.0 > $ ovs-vsctl get Open_vSwitch . dpdk_version > - "DPDK 18.08.0" > + "DPDK 18.11.0" > > At this point you can use ovs-vsctl to set up bridges and other Open vSwitch > features. Seeing as we've configured the DPDK datapath, we will use DPDK- > type @@ -672,7 +672,7 @@ Limitations > The latest list of validated firmware versions can be found in the `DPDK > release notes`_. > > -.. _DPDK release notes: > http://dpdk.org/doc/guides/rel_notes/release_18_08.html > +.. _DPDK release notes: > +http://dpdk.org/doc/guides/rel_notes/release_18_11.html > > - Upper bound MTU: DPDK device drivers differ in how the L2 frame for a > given MTU value is calculated e.g. i40e driver includes 2 x vlan headers in > diff --git a/Documentation/topics/dpdk/vhost-user.rst > b/Documentation/topics/dpdk/vhost-user.rst > index 062605c..1f6389d 100644 > --- a/Documentation/topics/dpdk/vhost-user.rst > +++ b/Documentation/topics/dpdk/vhost-user.rst > @@ -320,9 +320,9 @@ To begin, instantiate a guest as described in > :ref:`dpdk-vhost-user` or DPDK sources to VM and build DPDK:: > > $ cd /root/dpdk/ > - $ wget http://fast.dpdk.org/rel/dpdk-18.08.tar.xz > - $ tar xf dpdk-18.08.tar.xz > - $ export DPDK_DIR=/root/dpdk/dpdk-stable-18.08 > + $ wget http://fast.dpdk.org/rel/dpdk-18.11.tar.xz > + $ tar xf dpdk-18.11.tar.xz > + $ export DPDK_DIR=/root/dpdk/dpdk-stable-18.11 > $ export DPDK_TARGET=x86_64-native-linuxapp-gcc > $ export DPDK_BUILD=$DPDK_DIR/$DPDK_TARGET > $ cd $DPDK_DIR > diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c index 1480bf8..8432426 > 100644 > --- a/lib/netdev-dpdk.c > +++ b/lib/netdev-dpdk.c > @@ -929,8 +929,9 @@ dpdk_eth_dev_port_config(struct netdev_dpdk > *dev, int n_rxq, int n_txq) > conf.rxmode.offloads |= DEV_RX_OFFLOAD_CHECKSUM; > } > > - if (dev->hw_ol_features & NETDEV_RX_HW_CRC_STRIP) { > - conf.rxmode.offloads |= DEV_RX_OFFLOAD_CRC_STRIP; > + if (!(dev->hw_ol_features & NETDEV_RX_HW_CRC_STRIP) && > + (info.rx_offload_capa & DEV_RX_OFFLOAD_KEEP_CRC)) { > + conf.rxmode.offloads |= DEV_RX_OFFLOAD_KEEP_CRC; > } > > /* Limit configured rss hash functions to only those supported @@ - > 1215,6 +1216,23 @@ dpdk_dev_parse_name(const char dev_name[], const > char prefix[], > } > } > > +/* get the number of OVS interfaces which have the same DPDK > + * rte device (e.g. same pci bus address). */ static int > +netdev_dpdk_get_num_ports(struct rte_device *device) > + OVS_REQUIRES(dpdk_mutex) > +{ > + struct netdev_dpdk *dev; > + int count; > + > + count = 0; > + LIST_FOR_EACH (dev, list_node, &dpdk_list) { > + if (rte_eth_devices[dev->port_id].device == device) > + count++; > + } > + return count; > +} > + > static int > vhost_common_construct(struct netdev *netdev) > OVS_REQUIRES(dpdk_mutex) > @@ -1350,19 +1368,22 @@ static void > netdev_dpdk_destruct(struct netdev *netdev) { > struct netdev_dpdk *dev = netdev_dpdk_cast(netdev); > - char devname[RTE_ETH_NAME_MAX_LEN]; > + struct rte_device *rte_dev; > > ovs_mutex_lock(&dpdk_mutex); > > rte_eth_dev_stop(dev->port_id); > dev->started = false; > - > if (dev->attached) { > + /* Remove the port eth device */ > rte_eth_dev_close(dev->port_id); > - if (rte_eth_dev_detach(dev->port_id, devname) < 0) { > - VLOG_ERR("Device '%s' can not be detached", dev->devargs); > - } else { > - VLOG_INFO("Device '%s' has been detached", devname); > + VLOG_INFO("Device '%s' has been removed", dev->devargs); > + /* if this is the last port_id using this rte device > + * remove this rte device and all its eth devices */ > + rte_dev = rte_eth_devices[dev->port_id].device; > + if (netdev_dpdk_get_num_ports(rte_dev) == 1) { > + if (rte_dev_remove(rte_dev) < 0) > + VLOG_ERR("Device '%s' can not be detached", > + dev->devargs); > } > } > > @@ -1628,8 +1649,26 @@ netdev_dpdk_get_port_by_mac(const char > *mac_str) > return DPDK_ETH_PORT_ID_INVALID; > } > > +/* return the first DPDK port_id matching the devargs pattern */ static > +dpdk_port_t netdev_dpdk_get_port_by_devargs(const char *devargs) { > + struct rte_dev_iterator iterator; > + dpdk_port_t port_id; > + > + if (rte_dev_probe(devargs)) { > + port_id = DPDK_ETH_PORT_ID_INVALID; > + } else { > + RTE_ETH_FOREACH_MATCHING_DEV(port_id, devargs, &iterator) { > + break; > + } > + } > + return port_id; > +} > + > /* > - * Normally, a PCI id is enough for identifying a specific DPDK port. > + * Normally, a PCI id (optionally followed by a representor number) > + * is enough for identifying a specific DPDK port. > * However, for some NICs having multiple ports sharing the same PCI > * id, using PCI id won't work then. > * > @@ -1642,28 +1681,31 @@ static dpdk_port_t > netdev_dpdk_process_devargs(struct netdev_dpdk *dev, > const char *devargs, char **errp) { > - char *name; > dpdk_port_t new_port_id = DPDK_ETH_PORT_ID_INVALID; > > if (strncmp(devargs, "class=eth,mac=", 14) == 0) { > new_port_id = netdev_dpdk_get_port_by_mac(&devargs[14]); > } else { > - name = xmemdup0(devargs, strcspn(devargs, ",")); > - if (rte_eth_dev_get_port_by_name(name, &new_port_id) > - || !rte_eth_dev_is_valid_port(new_port_id)) { > - /* Device not found in DPDK, attempt to attach it */ > - if (!rte_eth_dev_attach(devargs, &new_port_id)) { > - /* Attach successful */ > - dev->attached = true; > - VLOG_INFO("Device '%s' attached to DPDK", devargs); > - } else { > - /* Attach unsuccessful */ > + new_port_id = netdev_dpdk_get_port_by_devargs(devargs); > + if (!rte_eth_dev_is_valid_port(new_port_id)) { > + new_port_id = DPDK_ETH_PORT_ID_INVALID; > + } else { > + struct netdev_dpdk *dup_dev; > + > + dup_dev = netdev_dpdk_lookup_by_port_id(new_port_id); > + if (dup_dev) { > + VLOG_WARN_BUF(errp, "'%s' is trying to use device '%s' " > + "which is already in use by '%s'", > + netdev_get_name(&dev->up), devargs, > + netdev_get_name(&dup_dev->up)); > new_port_id = DPDK_ETH_PORT_ID_INVALID; > + } else { > + /* device successfully found */ > + dev->attached = true; > + VLOG_INFO("Device '%s' attached to DPDK port %d", > + devargs, new_port_id); > } > } > - free(name); > } > - > if (new_port_id == DPDK_ETH_PORT_ID_INVALID) { > VLOG_WARN_BUF(errp, "Error attaching device '%s' to DPDK", > devargs); > } > @@ -3208,15 +3250,18 @@ static void > netdev_dpdk_detach(struct unixctl_conn *conn, int argc OVS_UNUSED, > const char *argv[], void *aux OVS_UNUSED) { > - int ret; > char *response; > dpdk_port_t port_id; > - char devname[RTE_ETH_NAME_MAX_LEN]; > struct netdev_dpdk *dev; > + struct rte_device *rte_dev; > + struct rte_dev_iterator iterator; > > ovs_mutex_lock(&dpdk_mutex); > > - if (rte_eth_dev_get_port_by_name(argv[1], &port_id)) { > + RTE_ETH_FOREACH_MATCHING_DEV(port_id, argv[1], &iterator) { > + break; > + } > + if (port_id == DPDK_ETH_PORT_ID_INVALID) { > response = xasprintf("Device '%s' not found in DPDK", argv[1]); > goto error; > } > @@ -3229,15 +3274,21 @@ netdev_dpdk_detach(struct unixctl_conn > *conn, int argc OVS_UNUSED, > goto error; > } > > - rte_eth_dev_close(port_id); > + rte_dev = rte_eth_devices[port_id].device; > + if (netdev_dpdk_get_num_ports(rte_dev)) { > + response = xasprintf("Device '%s' is being shared with other " > + "interfaces. Remove them before detaching.", > + argv[1]); > + goto error; > + } > > - ret = rte_eth_dev_detach(port_id, devname); > - if (ret < 0) { > - response = xasprintf("Device '%s' can not be detached", argv[1]); > + rte_eth_dev_close(port_id); > + if (rte_dev_remove(rte_dev) < 0) { > + response = xasprintf("Device '%s' can not be removed", > + argv[1]); > goto error; > } > > - response = xasprintf("Device '%s' has been detached", argv[1]); > + response = xasprintf("All devices shared with device '%s' have been > + detached", argv[1]); > > ovs_mutex_unlock(&dpdk_mutex); > unixctl_command_reply(conn, response); > -- > 1.8.3.1
_______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev