Skip to content

Commit

Permalink
netdev-offload-dpdk: Fix flushing of a physdev.
Browse files Browse the repository at this point in the history
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 still has references on.
Trying to remove it and re-add it fails with "already in use" error.

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: adbd430 ("netdev-offload-dpdk: Use per-netdev offload metadata.")
Reported-by: [email protected]
Acked-by: Simon Horman <[email protected]>
Signed-off-by: Eli Britstein <[email protected]>
Signed-off-by: Ilya Maximets <[email protected]>
  • Loading branch information
elibritstein authored and igsilya committed Oct 9, 2023
1 parent b784276 commit 0aeb06e
Showing 1 changed file with 30 additions and 5 deletions.
35 changes: 30 additions & 5 deletions lib/netdev-offload-dpdk.c
Original file line number Diff line number Diff line change
Expand Up @@ -2537,15 +2537,15 @@ netdev_offload_dpdk_flow_get(struct netdev *netdev,
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) {
Expand All @@ -2556,6 +2556,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;
}
Expand Down

0 comments on commit 0aeb06e

Please sign in to comment.