Vport's offloads are done on the tracked orig-in-port, but the flow itself
is associated in the vport's map.

Removing the physdev will flush all the ports that are on its map, but
not the ones on other netdevs' maps. Since flows take reference count on
both their vport and their physdev, the physdev fails to be removed.

Fix it by flushing the physdev's offload flows in all related netdevs,
e.g. the netdev itself, or for physical devices, all vports.

Fixes: adbd4301a249 ("netdev-offload-dpdk: Use per-netdev offload metadata.")
Reported-by: 15895987278 <[email protected]>
Signed-off-by: Eli Britstein <[email protected]>
---
 lib/netdev-offload-dpdk.c | 35 ++++++++++++++++++++++++++++++-----
 1 file changed, 30 insertions(+), 5 deletions(-)

diff --git a/lib/netdev-offload-dpdk.c b/lib/netdev-offload-dpdk.c
index cceefbc50..981897da1 100644
--- a/lib/netdev-offload-dpdk.c
+++ b/lib/netdev-offload-dpdk.c
@@ -2530,15 +2530,15 @@ out:
     return ret;
 }
 
-static int
-netdev_offload_dpdk_flow_flush(struct netdev *netdev)
+static void
+flush_netdev_flows_in_related(struct netdev *netdev, struct netdev *related)
 {
-    struct cmap *map = offload_data_map(netdev);
-    struct ufid_to_rte_flow_data *data;
     unsigned int tid = netdev_offload_thread_id();
+    struct cmap *map = offload_data_map(related);
+    struct ufid_to_rte_flow_data *data;
 
     if (!map) {
-        return -1;
+        return;
     }
 
     CMAP_FOR_EACH (data, node, map) {
@@ -2549,6 +2549,31 @@ netdev_offload_dpdk_flow_flush(struct netdev *netdev)
             netdev_offload_dpdk_flow_destroy(data);
         }
     }
+}
+
+static bool
+flush_in_vport_cb(struct netdev *vport,
+                  odp_port_t odp_port OVS_UNUSED,
+                  void *aux)
+{
+    struct netdev *netdev = aux;
+
+    /* Only vports are related to physical devices. */
+    if (netdev_vport_is_vport_class(vport->netdev_class)) {
+        flush_netdev_flows_in_related(netdev, vport);
+    }
+
+    return false;
+}
+
+static int
+netdev_offload_dpdk_flow_flush(struct netdev *netdev)
+{
+    flush_netdev_flows_in_related(netdev, netdev);
+
+    if (!netdev_vport_is_vport_class(netdev->netdev_class)) {
+        netdev_ports_traverse(netdev->dpif_type, flush_in_vport_cb, netdev);
+    }
 
     return 0;
 }
-- 
2.28.0.2311.g225365fb51

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to