diff mbox series

[ovs-dev,v2,1/1] dpdk: Update to use DPDK v21.11.

Message ID 1639063304-26675-1-git-send-email-ian.stokes@intel.com
State Accepted
Commit 17346b3899d98730fc90f039a966b107aeae30b5
Headers show
Series [ovs-dev,v2,1/1] dpdk: Update to use DPDK v21.11. | expand

Commit Message

Stokes, Ian Dec. 9, 2021, 3:21 p.m. UTC
This commit adds support for DPDK v21.11, it includes the following
changes.

1. ci: Install python elftools for DPDK 21.02.
2. ci: Update meson requirement for DPDK 21.05.
3. netdev-dpdk: Fix build with 21.05.
4. ci: Compile DPDK in non developer mode.

   http://patchwork.ozlabs.org/project/openvswitch/list/?series=242480&state=*

5. netdev-dpdk: Remove access to DPDK internals.
6. netdev-dpdk: Remove unused attribute from rte_flow rule.
7. netdev-dpdk: Fix mbuf macros namespace with 21.11-rc1.
8. netdev-dpdk: Fix vhost namespace with 21.11-rc2.

   http://patchwork.ozlabs.org/project/openvswitch/list/?series=271040&state=*

In addition documentaion and DPDK unit tests were also updated in this
commit for use with DPDK v21.11.

For credit all authors of the original commits to 'dpdk-latest' with the above
changes have been added as co-authors for this commit.

Signed-off-by: David Marchand <david.marchand@redhat.com>
Co-authored-by: David Marchand <david.marchand@redhat.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
Signed-off-by: Ian Stokes <ian.stokes@intel.com>

---
v1 -> v2
* Modified openvswitch-fedora.spec.in instead of generated files.

RFC -> V1
* Add telemetry warning to OVS DPDK unit tests.
* Update TSO documentation link to 21.11.
* Update fedora spec to use 21.11.
---
 .ci/linux-build.sh                       |   6 +-
 .ci/linux-prepare.sh                     |   4 +-
 Documentation/faq/releases.rst           |   2 +-
 Documentation/intro/install/dpdk.rst     |  16 ++---
 Documentation/topics/dpdk/phy.rst        |   8 +--
 Documentation/topics/dpdk/vdev.rst       |   2 +-
 Documentation/topics/dpdk/vhost-user.rst |   2 +-
 Documentation/topics/testing.rst         |   2 +-
 Documentation/topics/userspace-tso.rst   |   2 +-
 NEWS                                     |   1 +
 lib/dp-packet.h                          |  26 +++----
 lib/netdev-dpdk.c                        | 115 ++++++++++++++++---------------
 rhel/openvswitch-fedora.spec.in          |   2 +-
 tests/system-dpdk.at                     |  16 +++--
 14 files changed, 110 insertions(+), 94 deletions(-)

Comments

Kevin Traynor Dec. 9, 2021, 6:07 p.m. UTC | #1
On 09/12/2021 15:21, Ian Stokes wrote:
> This commit adds support for DPDK v21.11, it includes the following
> changes.
> 
> 1. ci: Install python elftools for DPDK 21.02.
> 2. ci: Update meson requirement for DPDK 21.05.
> 3. netdev-dpdk: Fix build with 21.05.
> 4. ci: Compile DPDK in non developer mode.
> 
>     http://patchwork.ozlabs.org/project/openvswitch/list/?series=242480&state=*
> 
> 5. netdev-dpdk: Remove access to DPDK internals.
> 6. netdev-dpdk: Remove unused attribute from rte_flow rule.
> 7. netdev-dpdk: Fix mbuf macros namespace with 21.11-rc1.
> 8. netdev-dpdk: Fix vhost namespace with 21.11-rc2.
> 
>     http://patchwork.ozlabs.org/project/openvswitch/list/?series=271040&state=*
> 

There was a v3, so it should be:
http://patchwork.ozlabs.org/project/openvswitch/list/?series=271159&state=*

> In addition documentaion and DPDK unit tests were also updated in this
> commit for use with DPDK v21.11.
> 

typo, documentation

> For credit all authors of the original commits to 'dpdk-latest' with the above
> changes have been added as co-authors for this commit.
> 
> Signed-off-by: David Marchand<david.marchand@redhat.com>
> Co-authored-by: David Marchand<david.marchand@redhat.com>
> Reviewed-by: Maxime Coquelin<maxime.coquelin@redhat.com>
> Signed-off-by: Ian Stokes<ian.stokes@intel.com>
> 

There's no tested-by or mention of testing above. I didn't see it in the 
email threads either. Maybe that can be mentioned in the commit message 
to confirm it was done.

> ---

Just a few nits in the commit message that can be fixed on applying.

Otherwise assuming it went through Intel OVS ci, the patches lgtm 
(though i didn't review the ethdev internals one in detail). Built and 
ran a basic test to move some pkts, no issue.

btw, having links to the relevant DPDK commits in the ovs commit logs is 
really helpful for cross referencing, we should keep doing that. David++.
Stokes, Ian Dec. 9, 2021, 8:12 p.m. UTC | #2
> On 09/12/2021 15:21, Ian Stokes wrote:
> > This commit adds support for DPDK v21.11, it includes the following
> > changes.
> >
> > 1. ci: Install python elftools for DPDK 21.02.
> > 2. ci: Update meson requirement for DPDK 21.05.
> > 3. netdev-dpdk: Fix build with 21.05.
> > 4. ci: Compile DPDK in non developer mode.
> >
> >
> http://patchwork.ozlabs.org/project/openvswitch/list/?series=242480&state=*
> >
> > 5. netdev-dpdk: Remove access to DPDK internals.
> > 6. netdev-dpdk: Remove unused attribute from rte_flow rule.
> > 7. netdev-dpdk: Fix mbuf macros namespace with 21.11-rc1.
> > 8. netdev-dpdk: Fix vhost namespace with 21.11-rc2.
> >
> >
> http://patchwork.ozlabs.org/project/openvswitch/list/?series=271040&state=*
> >
> 
> There was a v3, so it should be:
> http://patchwork.ozlabs.org/project/openvswitch/list/?series=271159&state=*
> 
> > In addition documentaion and DPDK unit tests were also updated in this
> > commit for use with DPDK v21.11.
> >
> 
> typo, documentation
> 
> > For credit all authors of the original commits to 'dpdk-latest' with the above
> > changes have been added as co-authors for this commit.
> >
> > Signed-off-by: David Marchand<david.marchand@redhat.com>
> > Co-authored-by: David Marchand<david.marchand@redhat.com>
> > Reviewed-by: Maxime Coquelin<maxime.coquelin@redhat.com>
> > Signed-off-by: Ian Stokes<ian.stokes@intel.com>
> >
> 
> There's no tested-by or mention of testing above. I didn't see it in the
> email threads either. Maybe that can be mentioned in the commit message
> to confirm it was done.
> 
> > ---
> 
> Just a few nits in the commit message that can be fixed on applying.
> 
> Otherwise assuming it went through Intel OVS ci, the patches lgtm
> (though i didn't review the ethdev internals one in detail). Built and
> ran a basic test to move some pkts, no issue.
> 
> btw, having links to the relevant DPDK commits in the ovs commit logs is
> really helpful for cross referencing, we should keep doing that. David++.
+1

Thanks for the review Kevin, I've applied the changes and pushed to master.

Thanks all for all the work on this, much appreciated.

Thanks
Ian
diff mbox series

Patch

diff --git a/.ci/linux-build.sh b/.ci/linux-build.sh
index 863f02388..ff6ae4b10 100755
--- a/.ci/linux-build.sh
+++ b/.ci/linux-build.sh
@@ -159,6 +159,10 @@  function install_dpdk()
     # Disable building DPDK unit tests. Not needed for OVS build or tests.
     DPDK_OPTS="$DPDK_OPTS -Dtests=false"
 
+    # Disable DPDK developer mode, this results in less build checks and less
+    # meson verbose outputs.
+    DPDK_OPTS="$DPDK_OPTS -Ddeveloper_mode=disabled"
+
     # Install DPDK using prefix.
     DPDK_OPTS="$DPDK_OPTS --prefix=$(pwd)/build"
 
@@ -216,7 +220,7 @@  fi
 
 if [ "$DPDK" ] || [ "$DPDK_SHARED" ]; then
     if [ -z "$DPDK_VER" ]; then
-        DPDK_VER="20.11.1"
+        DPDK_VER="21.11"
     fi
     install_dpdk $DPDK_VER
     if [ "$CC" = "clang" ]; then
diff --git a/.ci/linux-prepare.sh b/.ci/linux-prepare.sh
index 360c0a68e..b3addf404 100755
--- a/.ci/linux-prepare.sh
+++ b/.ci/linux-prepare.sh
@@ -21,8 +21,8 @@  make -j4 HAVE_LLVM= HAVE_SQLITE= install
 cd ..
 
 pip3 install --disable-pip-version-check --user \
-    flake8 hacking sphinx wheel setuptools
-pip3 install --user  'meson==0.47.1'
+    flake8 hacking sphinx wheel setuptools pyelftools
+pip3 install --user  'meson==0.49.2'
 
 if [ "$M32" ]; then
     # Installing 32-bit libraries.
diff --git a/Documentation/faq/releases.rst b/Documentation/faq/releases.rst
index 64bc577e0..59d55202d 100644
--- a/Documentation/faq/releases.rst
+++ b/Documentation/faq/releases.rst
@@ -225,7 +225,7 @@  Q: Are all the DPDK releases that OVS versions work with maintained?
     The latest information about DPDK stable and LTS releases can be found
     at `DPDK stable`_.
 
-.. _DPDK stable: http://doc.dpdk.org/guides-20.11/contributing/stable.html
+.. _DPDK stable: http://doc.dpdk.org/guides-21.11/contributing/stable.html
 
 Q: I get an error like this when I configure Open vSwitch:
 
diff --git a/Documentation/intro/install/dpdk.rst b/Documentation/intro/install/dpdk.rst
index d554409fc..d9f44055d 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 20.11.1
+- DPDK 21.11
 
 - A `DPDK supported NIC`_
 
@@ -59,8 +59,8 @@  vSwitch with DPDK will require the following:
 
 Detailed system requirements can be found at `DPDK requirements`_.
 
-.. _DPDK supported NIC: https://doc.dpdk.org/guides-20.11/nics/index.html
-.. _DPDK requirements: https://doc.dpdk.org/guides-20.11/linux_gsg/sys_reqs.html
+.. _DPDK supported NIC: https://doc.dpdk.org/guides-21.11/nics/index.html
+.. _DPDK requirements: https://doc.dpdk.org/guides-21.11/linux_gsg/sys_reqs.html
 
 .. _dpdk-install:
 
@@ -73,9 +73,9 @@  Install DPDK
 #. Download the `DPDK sources`_, extract the file and set ``DPDK_DIR``::
 
        $ cd /usr/src/
-       $ wget https://fast.dpdk.org/rel/dpdk-20.11.1.tar.xz
-       $ tar xf dpdk-20.11.1.tar.xz
-       $ export DPDK_DIR=/usr/src/dpdk-stable-20.11.1
+       $ wget https://fast.dpdk.org/rel/dpdk-21.11.tar.xz
+       $ tar xf dpdk-21.11.tar.xz
+       $ export DPDK_DIR=/usr/src/dpdk-21.11
        $ cd $DPDK_DIR
 
 #. Configure and install DPDK using Meson
@@ -121,7 +121,7 @@  Install DPDK
 
 .. _DPDK sources: http://dpdk.org/rel
 .. _DPDK documentation:
-   https://doc.dpdk.org/guides-20.11/linux_gsg/build_dpdk.html
+   https://doc.dpdk.org/guides-21.11/linux_gsg/build_dpdk.html
 
 Install OVS
 ~~~~~~~~~~~
@@ -722,7 +722,7 @@  Limitations
   release notes`_.
 
 .. _DPDK release notes:
-   https://doc.dpdk.org/guides-20.11/rel_notes/release_20_11.html
+   https://doc.dpdk.org/guides-21.11/rel_notes/release_21_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/phy.rst b/Documentation/topics/dpdk/phy.rst
index 986dbd38e..937f4c40e 100644
--- a/Documentation/topics/dpdk/phy.rst
+++ b/Documentation/topics/dpdk/phy.rst
@@ -117,7 +117,7 @@  tool::
 
 For more information, refer to the `DPDK documentation <dpdk-drivers>`__.
 
-.. _dpdk-drivers: https://doc.dpdk.org/guides-20.11/linux_gsg/linux_drivers.html
+.. _dpdk-drivers: https://doc.dpdk.org/guides-21.11/linux_gsg/linux_drivers.html
 
 .. _dpdk-phy-multiqueue:
 
@@ -235,7 +235,7 @@  To hotplug a port with igb_uio in this case, DPDK must be configured to use
 physical addressing for IOVA mode. For more information regarding IOVA modes
 in DPDK please refer to the `DPDK IOVA Mode Detection`__.
 
-__ https://doc.dpdk.org/guides-20.11/prog_guide/env_abstraction_layer.html#iova-mode-detection
+__ https://doc.dpdk.org/guides-21.11/prog_guide/env_abstraction_layer.html#iova-mode-detection
 
 To configure OVS DPDK to use physical addressing for IOVA::
 
@@ -267,7 +267,7 @@  Representors are multi devices created on top of one PF.
 
 For more information, refer to the `DPDK documentation`__.
 
-__ https://doc.dpdk.org/guides-20.11/prog_guide/switch_representation.html
+__ https://doc.dpdk.org/guides-21.11/prog_guide/switch_representation.html
 
 Prior to port representors there was a one-to-one relationship between the PF
 and the eth device. With port representors the relationship becomes one PF to
@@ -401,7 +401,7 @@  in the ``options`` column of the ``Interface`` table.
    kernel netdevice, and be inherited from it when Open vSwitch is restarted,
    even if the options described in this section are unset from Open vSwitch.
 
-.. _bifurcated-drivers: https://doc.dpdk.org/guides-20.11/linux_gsg/linux_drivers.html#bifurcated-driver
+.. _bifurcated-drivers: https://doc.dpdk.org/guides-21.11/linux_gsg/linux_drivers.html#bifurcated-driver
 
 - Configure the VF MAC address::
 
diff --git a/Documentation/topics/dpdk/vdev.rst b/Documentation/topics/dpdk/vdev.rst
index 7bd48165e..97ac6d9a5 100644
--- a/Documentation/topics/dpdk/vdev.rst
+++ b/Documentation/topics/dpdk/vdev.rst
@@ -63,4 +63,4 @@  run::
 More information on the different types of virtual DPDK PMDs can be found in
 the `DPDK documentation`__.
 
-__ https://doc.dpdk.org/guides-20.11/nics/overview.html
+__ https://doc.dpdk.org/guides-21.11/nics/overview.html
diff --git a/Documentation/topics/dpdk/vhost-user.rst b/Documentation/topics/dpdk/vhost-user.rst
index 4545f8f64..97e66a99e 100644
--- a/Documentation/topics/dpdk/vhost-user.rst
+++ b/Documentation/topics/dpdk/vhost-user.rst
@@ -539,4 +539,4 @@  shown with::
 
 Further information can be found in the
 `DPDK documentation
-<https://doc.dpdk.org/guides-20.11/prog_guide/vhost_lib.html>`__
+<https://doc.dpdk.org/guides-21.11/prog_guide/vhost_lib.html>`__
diff --git a/Documentation/topics/testing.rst b/Documentation/topics/testing.rst
index 0ddcbd58a..ea11700e3 100644
--- a/Documentation/topics/testing.rst
+++ b/Documentation/topics/testing.rst
@@ -353,7 +353,7 @@  All tests are skipped if no hugepages are configured. User must look into the DP
 manual to figure out how to `Configure hugepages`_.
 The phy test will skip if no compatible physical device is available.
 
-.. _Configure hugepages: https://doc.dpdk.org/guides-20.11/linux_gsg/sys_reqs.html
+.. _Configure hugepages: https://doc.dpdk.org/guides-21.11/linux_gsg/sys_reqs.html
 
 All the features documented under `Unit Tests`_ are available for the DPDK
 datapath testsuite.
diff --git a/Documentation/topics/userspace-tso.rst b/Documentation/topics/userspace-tso.rst
index bd64e7ed3..33a85965c 100644
--- a/Documentation/topics/userspace-tso.rst
+++ b/Documentation/topics/userspace-tso.rst
@@ -46,7 +46,7 @@  datasheet for compatibility. Secondly, the NIC must have an associated DPDK
 Poll Mode Driver (PMD) which supports `TSO`. For a list of features per PMD,
 refer to the `DPDK documentation`__.
 
-__ https://doc.dpdk.org/guides-20.11/nics/overview.html
+__ https://doc.dpdk.org/guides-21.11/nics/overview.html
 
 Enabling TSO
 ~~~~~~~~~~~~
diff --git a/NEWS b/NEWS
index f5bd79b5a..2a4856c1a 100644
--- a/NEWS
+++ b/NEWS
@@ -10,6 +10,7 @@  Post-v2.16.0
        limiting behavior.
      * Add hardware offload support for matching IPv4/IPv6 frag types
        (experimental).
+     * Add support for DPDK 21.11.
    - Python:
      * For SSL support, the use of the pyOpenSSL library has been replaced
        with the native 'ssl' module.
diff --git a/lib/dp-packet.h b/lib/dp-packet.h
index 3dc582fbf..ee0805ae6 100644
--- a/lib/dp-packet.h
+++ b/lib/dp-packet.h
@@ -58,29 +58,31 @@  enum OVS_PACKED_ENUM dp_packet_source {
 enum dp_packet_offload_mask {
     /* Value 0 is not used. */
     /* Is the 'rss_hash' valid? */
-    DEF_OL_FLAG(DP_PACKET_OL_RSS_HASH, PKT_RX_RSS_HASH, 0x1),
+    DEF_OL_FLAG(DP_PACKET_OL_RSS_HASH, RTE_MBUF_F_RX_RSS_HASH, 0x1),
     /* Is the 'flow_mark' valid? */
-    DEF_OL_FLAG(DP_PACKET_OL_FLOW_MARK, PKT_RX_FDIR_ID, 0x2),
+    DEF_OL_FLAG(DP_PACKET_OL_FLOW_MARK, RTE_MBUF_F_RX_FDIR_ID, 0x2),
     /* Bad L4 checksum in the packet. */
-    DEF_OL_FLAG(DP_PACKET_OL_RX_L4_CKSUM_BAD, PKT_RX_L4_CKSUM_BAD, 0x4),
+    DEF_OL_FLAG(DP_PACKET_OL_RX_L4_CKSUM_BAD, RTE_MBUF_F_RX_L4_CKSUM_BAD, 0x4),
     /* Bad IP checksum in the packet. */
-    DEF_OL_FLAG(DP_PACKET_OL_RX_IP_CKSUM_BAD, PKT_RX_IP_CKSUM_BAD, 0x8),
+    DEF_OL_FLAG(DP_PACKET_OL_RX_IP_CKSUM_BAD, RTE_MBUF_F_RX_IP_CKSUM_BAD, 0x8),
     /* Valid L4 checksum in the packet. */
-    DEF_OL_FLAG(DP_PACKET_OL_RX_L4_CKSUM_GOOD, PKT_RX_L4_CKSUM_GOOD, 0x10),
+    DEF_OL_FLAG(DP_PACKET_OL_RX_L4_CKSUM_GOOD, RTE_MBUF_F_RX_L4_CKSUM_GOOD,
+                0x10),
     /* Valid IP checksum in the packet. */
-    DEF_OL_FLAG(DP_PACKET_OL_RX_IP_CKSUM_GOOD, PKT_RX_IP_CKSUM_GOOD, 0x20),
+    DEF_OL_FLAG(DP_PACKET_OL_RX_IP_CKSUM_GOOD, RTE_MBUF_F_RX_IP_CKSUM_GOOD,
+                0x20),
     /* TCP Segmentation Offload. */
-    DEF_OL_FLAG(DP_PACKET_OL_TX_TCP_SEG, PKT_TX_TCP_SEG, 0x40),
+    DEF_OL_FLAG(DP_PACKET_OL_TX_TCP_SEG, RTE_MBUF_F_TX_TCP_SEG, 0x40),
     /* Offloaded packet is IPv4. */
-    DEF_OL_FLAG(DP_PACKET_OL_TX_IPV4, PKT_TX_IPV4, 0x80),
+    DEF_OL_FLAG(DP_PACKET_OL_TX_IPV4, RTE_MBUF_F_TX_IPV4, 0x80),
     /* Offloaded packet is IPv6. */
-    DEF_OL_FLAG(DP_PACKET_OL_TX_IPV6, PKT_TX_IPV6, 0x100),
+    DEF_OL_FLAG(DP_PACKET_OL_TX_IPV6, RTE_MBUF_F_TX_IPV6, 0x100),
     /* Offload TCP checksum. */
-    DEF_OL_FLAG(DP_PACKET_OL_TX_TCP_CKSUM, PKT_TX_TCP_CKSUM, 0x200),
+    DEF_OL_FLAG(DP_PACKET_OL_TX_TCP_CKSUM, RTE_MBUF_F_TX_TCP_CKSUM, 0x200),
     /* Offload UDP checksum. */
-    DEF_OL_FLAG(DP_PACKET_OL_TX_UDP_CKSUM, PKT_TX_UDP_CKSUM, 0x400),
+    DEF_OL_FLAG(DP_PACKET_OL_TX_UDP_CKSUM, RTE_MBUF_F_TX_UDP_CKSUM, 0x400),
     /* Offload SCTP checksum. */
-    DEF_OL_FLAG(DP_PACKET_OL_TX_SCTP_CKSUM, PKT_TX_SCTP_CKSUM, 0x800),
+    DEF_OL_FLAG(DP_PACKET_OL_TX_SCTP_CKSUM, RTE_MBUF_F_TX_SCTP_CKSUM, 0x800),
     /* Adding new field requires adding to DP_PACKET_OL_SUPPORTED_MASK. */
 };
 
diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c
index ca92c947a..d1fd6c766 100644
--- a/lib/netdev-dpdk.c
+++ b/lib/netdev-dpdk.c
@@ -181,7 +181,7 @@  static int vring_state_changed(int vid, uint16_t queue_id, int enable);
 static void destroy_connection(int vid);
 static void vhost_guest_notified(int vid);
 
-static const struct vhost_device_ops virtio_net_device_ops =
+static const struct rte_vhost_device_ops virtio_net_device_ops =
 {
     .new_device =  new_device,
     .destroy_device = destroy_device,
@@ -1279,26 +1279,6 @@  common_construct(struct netdev *netdev, dpdk_port_t port_no,
     return 0;
 }
 
-/* Get the number of OVS interfaces which have the same DPDK
- * rte device (e.g. same pci bus address).
- * FIXME: avoid direct access to DPDK internal array rte_eth_devices.
- */
-static int
-netdev_dpdk_get_num_ports(struct rte_device *device)
-    OVS_REQUIRES(dpdk_mutex)
-{
-    struct netdev_dpdk *dev;
-    int count = 0;
-
-    LIST_FOR_EACH (dev, list_node, &dpdk_list) {
-        if (rte_eth_devices[dev->port_id].device == device
-        && rte_eth_devices[dev->port_id].state != RTE_ETH_DEV_UNUSED) {
-            count++;
-        }
-    }
-    return count;
-}
-
 static int
 vhost_common_construct(struct netdev *netdev)
     OVS_REQUIRES(dpdk_mutex)
@@ -1452,8 +1432,6 @@  static void
 netdev_dpdk_destruct(struct netdev *netdev)
 {
     struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
-    struct rte_device *rte_dev;
-    struct rte_eth_dev *eth_dev;
 
     ovs_mutex_lock(&dpdk_mutex);
 
@@ -1461,20 +1439,43 @@  netdev_dpdk_destruct(struct netdev *netdev)
     dev->started = false;
 
     if (dev->attached) {
-        /* Retrieve eth device data before closing it.
-         * FIXME: avoid direct access to DPDK internal array rte_eth_devices.
-         */
-        eth_dev = &rte_eth_devices[dev->port_id];
-        rte_dev = eth_dev->device;
+        bool dpdk_resources_still_used = false;
+        struct rte_eth_dev_info dev_info;
+        dpdk_port_t sibling_port_id;
+
+        /* Check if this netdev has siblings (i.e. shares DPDK resources) among
+         * other OVS netdevs. */
+        RTE_ETH_FOREACH_DEV_SIBLING (sibling_port_id, dev->port_id) {
+            struct netdev_dpdk *sibling;
+
+            /* RTE_ETH_FOREACH_DEV_SIBLING lists dev->port_id as part of the
+             * loop. */
+            if (sibling_port_id == dev->port_id) {
+                continue;
+            }
+            LIST_FOR_EACH (sibling, list_node, &dpdk_list) {
+                if (sibling->port_id != sibling_port_id) {
+                    continue;
+                }
+                dpdk_resources_still_used = true;
+                break;
+            }
+            if (dpdk_resources_still_used) {
+                break;
+            }
+        }
+
+        /* Retrieve eth device data before closing it. */
+        rte_eth_dev_info_get(dev->port_id, &dev_info);
 
         /* Remove the eth device. */
         rte_eth_dev_close(dev->port_id);
 
-        /* Remove this rte device and all its eth devices if all the eth
-         * devices belonging to the rte device are closed.
-         */
-        if (!netdev_dpdk_get_num_ports(rte_dev)) {
-            int ret = rte_dev_remove(rte_dev);
+        /* Remove the rte device if no associated eth device is used by OVS.
+         * Note: any remaining eth devices associated to this rte device are
+         * closed by DPDK ethdev layer. */
+        if (!dpdk_resources_still_used) {
+            int ret = rte_dev_remove(dev_info.device);
 
             if (ret < 0) {
                 VLOG_ERR("Device '%s' can not be detached: %s.",
@@ -2165,14 +2166,14 @@  netdev_dpdk_prep_hwol_packet(struct netdev_dpdk *dev, struct rte_mbuf *mbuf)
 {
     struct dp_packet *pkt = CONTAINER_OF(mbuf, struct dp_packet, mbuf);
 
-    if (mbuf->ol_flags & PKT_TX_L4_MASK) {
+    if (mbuf->ol_flags & RTE_MBUF_F_TX_L4_MASK) {
         mbuf->l2_len = (char *)dp_packet_l3(pkt) - (char *)dp_packet_eth(pkt);
         mbuf->l3_len = (char *)dp_packet_l4(pkt) - (char *)dp_packet_l3(pkt);
         mbuf->outer_l2_len = 0;
         mbuf->outer_l3_len = 0;
     }
 
-    if (mbuf->ol_flags & PKT_TX_TCP_SEG) {
+    if (mbuf->ol_flags & RTE_MBUF_F_TX_TCP_SEG) {
         struct tcp_header *th = dp_packet_l4(pkt);
 
         if (!th) {
@@ -2182,11 +2183,11 @@  netdev_dpdk_prep_hwol_packet(struct netdev_dpdk *dev, struct rte_mbuf *mbuf)
         }
 
         mbuf->l4_len = TCP_OFFSET(th->tcp_ctl) * 4;
-        mbuf->ol_flags |= PKT_TX_TCP_CKSUM;
+        mbuf->ol_flags |= RTE_MBUF_F_TX_TCP_CKSUM;
         mbuf->tso_segsz = dev->mtu - mbuf->l3_len - mbuf->l4_len;
 
-        if (mbuf->ol_flags & PKT_TX_IPV4) {
-            mbuf->ol_flags |= PKT_TX_IP_CKSUM;
+        if (mbuf->ol_flags & RTE_MBUF_F_TX_IPV4) {
+            mbuf->ol_flags |= RTE_MBUF_F_TX_IP_CKSUM;
         }
     }
     return true;
@@ -2533,7 +2534,7 @@  netdev_dpdk_filter_packet_len(struct netdev_dpdk *dev, struct rte_mbuf **pkts,
     for (i = 0; i < pkt_cnt; i++) {
         pkt = pkts[i];
         if (OVS_UNLIKELY((pkt->pkt_len > dev->max_packet_len)
-            && !(pkt->ol_flags & PKT_TX_TCP_SEG))) {
+            && !(pkt->ol_flags & RTE_MBUF_F_TX_TCP_SEG))) {
             VLOG_WARN_RL(&rl, "%s: Too big size %" PRIu32 " "
                          "max_packet_len %d", dev->up.name, pkt->pkt_len,
                          dev->max_packet_len);
@@ -2755,12 +2756,12 @@  dpdk_copy_dp_packet_to_mbuf(struct rte_mempool *mp, struct dp_packet *pkt_orig)
     mbuf_dest->tx_offload = pkt_orig->mbuf.tx_offload;
     mbuf_dest->packet_type = pkt_orig->mbuf.packet_type;
     mbuf_dest->ol_flags |= (pkt_orig->mbuf.ol_flags &
-                            ~(EXT_ATTACHED_MBUF | IND_ATTACHED_MBUF));
+                            ~(RTE_MBUF_F_EXTERNAL | RTE_MBUF_F_INDIRECT));
 
     memcpy(&pkt_dest->l2_pad_size, &pkt_orig->l2_pad_size,
            sizeof(struct dp_packet) - offsetof(struct dp_packet, l2_pad_size));
 
-    if (mbuf_dest->ol_flags & PKT_TX_L4_MASK) {
+    if (mbuf_dest->ol_flags & RTE_MBUF_F_TX_L4_MASK) {
         mbuf_dest->l2_len = (char *)dp_packet_l3(pkt_dest)
                                 - (char *)dp_packet_eth(pkt_dest);
         mbuf_dest->l3_len = (char *)dp_packet_l4(pkt_dest)
@@ -2805,7 +2806,7 @@  dpdk_do_tx_copy(struct netdev *netdev, int qid, struct dp_packet_batch *batch)
         uint32_t size = dp_packet_size(packet);
 
         if (size > dev->max_packet_len
-            && !(packet->mbuf.ol_flags & PKT_TX_TCP_SEG)) {
+            && !(packet->mbuf.ol_flags & RTE_MBUF_F_TX_TCP_SEG)) {
             VLOG_WARN_RL(&rl, "Too big size %u max_packet_len %d", size,
                          dev->max_packet_len);
             mtu_drops++;
@@ -3679,8 +3680,8 @@  netdev_dpdk_get_status(const struct netdev *netdev, struct smap *args)
     ovs_mutex_unlock(&dev->mutex);
     const struct rte_bus *bus;
     const struct rte_pci_device *pci_dev;
-    uint16_t vendor_id = PCI_ANY_ID;
-    uint16_t device_id = PCI_ANY_ID;
+    uint16_t vendor_id = RTE_PCI_ANY_ID;
+    uint16_t device_id = RTE_PCI_ANY_ID;
     bus = rte_bus_find_by_device(dev_info.device);
     if (bus && !strcmp(bus->name, "pci")) {
         pci_dev = RTE_DEV_TO_PCI(dev_info.device);
@@ -3793,12 +3794,12 @@  static void
 netdev_dpdk_detach(struct unixctl_conn *conn, int argc OVS_UNUSED,
                    const char *argv[], void *aux OVS_UNUSED)
 {
-    char *response;
-    dpdk_port_t port_id;
-    struct netdev_dpdk *dev;
-    struct rte_device *rte_dev;
     struct ds used_interfaces = DS_EMPTY_INITIALIZER;
+    struct rte_eth_dev_info dev_info;
+    dpdk_port_t sibling_port_id;
+    dpdk_port_t port_id;
     bool used = false;
+    char *response;
 
     ovs_mutex_lock(&dpdk_mutex);
 
@@ -3808,18 +3809,21 @@  netdev_dpdk_detach(struct unixctl_conn *conn, int argc OVS_UNUSED,
         goto error;
     }
 
-    rte_dev = rte_eth_devices[port_id].device;
     ds_put_format(&used_interfaces,
                   "Device '%s' is being used by the following interfaces:",
                   argv[1]);
 
-    LIST_FOR_EACH (dev, list_node, &dpdk_list) {
-        /* FIXME: avoid direct access to DPDK array rte_eth_devices. */
-        if (rte_eth_devices[dev->port_id].device == rte_dev
-            && rte_eth_devices[dev->port_id].state != RTE_ETH_DEV_UNUSED) {
+    RTE_ETH_FOREACH_DEV_SIBLING (sibling_port_id, port_id) {
+        struct netdev_dpdk *dev;
+
+        LIST_FOR_EACH (dev, list_node, &dpdk_list) {
+            if (dev->port_id != sibling_port_id) {
+                continue;
+            }
             used = true;
             ds_put_format(&used_interfaces, " %s",
                           netdev_get_name(&dev->up));
+            break;
         }
     }
 
@@ -3831,8 +3835,9 @@  netdev_dpdk_detach(struct unixctl_conn *conn, int argc OVS_UNUSED,
     }
     ds_destroy(&used_interfaces);
 
+    rte_eth_dev_info_get(port_id, &dev_info);
     rte_eth_dev_close(port_id);
-    if (rte_dev_remove(rte_dev) < 0) {
+    if (rte_dev_remove(dev_info.device) < 0) {
         response = xasprintf("Device '%s' can not be detached", argv[1]);
         goto error;
     }
@@ -5272,7 +5277,7 @@  netdev_dpdk_rte_flow_query_count(struct netdev *netdev,
                                  struct rte_flow_query_count *query,
                                  struct rte_flow_error *error)
 {
-    struct rte_flow_action_count count = { .shared = 0, .id = 0 };
+    struct rte_flow_action_count count = { .id = 0, };
     const struct rte_flow_action actions[] = {
         {
             .type = RTE_FLOW_ACTION_TYPE_COUNT,
diff --git a/rhel/openvswitch-fedora.spec.in b/rhel/openvswitch-fedora.spec.in
index 90f242b1f..16ef1ac3a 100644
--- a/rhel/openvswitch-fedora.spec.in
+++ b/rhel/openvswitch-fedora.spec.in
@@ -74,7 +74,7 @@  BuildRequires: libcap-ng libcap-ng-devel
 %endif
 %if %{with dpdk}
 BuildRequires: libpcap-devel numactl-devel
-BuildRequires: dpdk-devel >= 20.11
+BuildRequires: dpdk-devel >= 21.11
 Provides: %{name}-dpdk = %{version}-%{release}
 %endif
 %if %{with afxdp}
diff --git a/tests/system-dpdk.at b/tests/system-dpdk.at
index e5c6e92ab..0e0b340d7 100644
--- a/tests/system-dpdk.at
+++ b/tests/system-dpdk.at
@@ -15,7 +15,8 @@  AT_CHECK([grep "DPDK Enabled - initialized" ovs-vswitchd.log], [], [stdout])
 OVS_VSWITCHD_STOP(["/Global register is changed during/d
 /EAL:   Invalid NUMA socket, default to 0/d
 /EAL: WARNING: cpu flags constant_tsc=yes nonstop_tsc=no -> using unreliable clock cycles !/d
-/EAL: No free hugepages reported in hugepages-1048576kB/d"])
+/EAL: No free hugepages reported in hugepages-1048576kB/d
+/TELEMETRY: No legacy callbacks, legacy socket not created/d"])
 AT_CLEANUP
 dnl --------------------------------------------------------------------------
 
@@ -37,12 +38,12 @@  sleep 2
 
 dnl Clean up
 AT_CHECK([ovs-vsctl del-port br10 phy0], [], [stdout], [stderr])
-OVS_VSWITCHD_STOP("/does not exist. The Open vSwitch kernel module is probably not loaded./d
+OVS_VSWITCHD_STOP(["/does not exist. The Open vSwitch kernel module is probably not loaded./d
 /Failed to enable flow control/d
 /Global register is changed during/d
 /EAL: WARNING: cpu flags constant_tsc=yes nonstop_tsc=no -> using unreliable clock cycles !/d
 /EAL: No free hugepages reported in hugepages-1048576kB/d
-")
+/TELEMETRY: No legacy callbacks, legacy socket not created/d"])
 AT_CLEANUP
 dnl --------------------------------------------------------------------------
 
@@ -74,7 +75,8 @@  OVS_VSWITCHD_STOP(["\@does not exist. The Open vSwitch kernel module is probably
 \@Global register is changed during@d
 \@EAL:   Invalid NUMA socket, default to 0@d
 \@EAL: WARNING: cpu flags constant_tsc=yes nonstop_tsc=no -> using unreliable clock cycles !@d
-\@EAL: No free hugepages reported in hugepages-1048576kB@d"])
+\@EAL: No free hugepages reported in hugepages-1048576kB@d
+\@TELEMETRY: No legacy callbacks, legacy socket not created@d"])
 AT_CLEANUP
 dnl --------------------------------------------------------------------------
 
@@ -152,7 +154,8 @@  OVS_VSWITCHD_STOP(["\@does not exist. The Open vSwitch kernel module is probably
 \@failed to enumerate system datapaths: No such file or directory@d
 \@EAL:   Invalid NUMA socket, default to 0@d
 \@EAL: WARNING: cpu flags constant_tsc=yes nonstop_tsc=no -> using unreliable clock cycles !@d
-\@EAL: No free hugepages reported in hugepages-1048576kB@d"])
+\@EAL: No free hugepages reported in hugepages-1048576kB@d
+\@TELEMETRY: No legacy callbacks, legacy socket not created@d"])
 AT_CLEANUP
 dnl --------------------------------------------------------------------------
 
@@ -227,7 +230,8 @@  OVS_VSWITCHD_STOP(["\@does not exist. The Open vSwitch kernel module is probably
 \@failed to enumerate system datapaths: No such file or directory@d
 \@EAL:   Invalid NUMA socket, default to 0@d
 \@EAL: WARNING: cpu flags constant_tsc=yes nonstop_tsc=no -> using unreliable clock cycles !@d
-\@EAL: No free hugepages reported in hugepages-1048576kB@d"])
+\@EAL: No free hugepages reported in hugepages-1048576kB@d
+\@TELEMETRY: No legacy callbacks, legacy socket not created@d"])
 AT_CLEANUP
 dnl --------------------------------------------------------------------------