Commit [1] introduced a flag in dpif-netdev level, to optimize
performance and avoid hw_miss_packet_recover() for devices with no such
support.
However, there is a race condition between traffic processing and
assigning a 'flow_api' object to the netdev. In such case, EOPNOTSUPP is
returned by netdev_hw_miss_packet_recover() in netdev-offload.c layer
because 'flow_api' is not yet initialized. As a result, the flag is
falsely disabled, and subsequent packets won't be recovered, though they
should.
In order to fix it, move the flag to be in netdev-offload layer, to
avoid that race.
[1]: 6e50c1651869 ("dpif-netdev: Avoid hw_miss_packet_recover() for devices
with no support.")
Fixes: 6e50c1651869 ("dpif-netdev: Avoid hw_miss_packet_recover() for devices
with no support.")
Signed-off-by: Eli Britstein <[email protected]>
---
lib/dpif-netdev.c | 15 ++++-----------
lib/netdev-offload.c | 25 ++++++++++++++++++++-----
lib/netdev-offload.h | 1 +
3 files changed, 25 insertions(+), 16 deletions(-)
Github actions:
- v1: https://github.com/elibritstein/OVS/actions/runs/2587743230
diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index f46b9fe183..a286050b57 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -431,7 +431,6 @@ struct dp_netdev_rxq {
unsigned intrvl_idx; /* Write index for 'cycles_intrvl'. */
struct dp_netdev_pmd_thread *pmd; /* pmd thread that polls this queue. */
bool is_vhost; /* Is rxq of a vhost port. */
- bool hw_miss_api_supported; /* hw_miss_packet_recover() supported.*/
/* Counters of cycles spent successfully polling and processing pkts. */
atomic_ullong cycles[RXQ_N_CYCLES];
@@ -5421,7 +5420,6 @@ port_reconfigure(struct dp_netdev_port *port)
port->rxqs[i].port = port;
port->rxqs[i].is_vhost = !strncmp(port->type, "dpdkvhost", 9);
- port->rxqs[i].hw_miss_api_supported = true;
err = netdev_rxq_open(netdev, &port->rxqs[i].rx, i);
if (err) {
@@ -8039,16 +8037,11 @@ dp_netdev_hw_flow(const struct dp_netdev_pmd_thread
*pmd,
/* Restore the packet if HW processing was terminated before completion. */
struct dp_netdev_rxq *rxq = pmd->ctx.last_rxq;
- if (rxq->hw_miss_api_supported) {
+ if (rxq->port->netdev->hw_info.miss_api_supported) {
int err = netdev_hw_miss_packet_recover(rxq->port->netdev, packet);
- if (err) {
- if (err != EOPNOTSUPP) {
- COVERAGE_INC(datapath_drop_hw_miss_recover);
- return -1;
- } else {
- /* API unsupported by the port; avoid subsequent calls. */
- rxq->hw_miss_api_supported = false;
- }
+ if (err && err != EOPNOTSUPP) {
+ COVERAGE_INC(datapath_drop_hw_miss_recover);
+ return -1;
}
}
#endif
diff --git a/lib/netdev-offload.c b/lib/netdev-offload.c
index fb108c0d50..50c5076a63 100644
--- a/lib/netdev-offload.c
+++ b/lib/netdev-offload.c
@@ -182,6 +182,7 @@ netdev_assign_flow_api(struct netdev *netdev)
CMAP_FOR_EACH (rfa, cmap_node, &netdev_flow_apis) {
if (!rfa->flow_api->init_flow_api(netdev)) {
ovs_refcount_ref(&rfa->refcnt);
+ netdev->hw_info.miss_api_supported = true;
ovsrcu_set(&netdev->flow_api, rfa->flow_api);
VLOG_INFO("%s: Assigned flow API '%s'.",
netdev_get_name(netdev), rfa->flow_api->type);
@@ -190,6 +191,7 @@ netdev_assign_flow_api(struct netdev *netdev)
VLOG_DBG("%s: flow API '%s' is not suitable.",
netdev_get_name(netdev), rfa->flow_api->type);
}
+ netdev->hw_info.miss_api_supported = false;
VLOG_INFO("%s: No suitable flow API found.", netdev_get_name(netdev));
return -1;
@@ -263,12 +265,25 @@ int
netdev_hw_miss_packet_recover(struct netdev *netdev,
struct dp_packet *packet)
{
- const struct netdev_flow_api *flow_api =
- ovsrcu_get(const struct netdev_flow_api *, &netdev->flow_api);
+ const struct netdev_flow_api *flow_api;
+ int rv;
+
+ if (!netdev->hw_info.miss_api_supported) {
+ return EOPNOTSUPP;
+ }
+
+ flow_api = ovsrcu_get(const struct netdev_flow_api *, &netdev->flow_api);
+ if (!flow_api || !flow_api->hw_miss_packet_recover) {
+ return EOPNOTSUPP;
+ }
+
+ rv = flow_api->hw_miss_packet_recover(netdev, packet);
+ if (rv == EOPNOTSUPP) {
+ /* API unsupported by the port; avoid subsequent calls. */
+ netdev->hw_info.miss_api_supported = false;
+ }
- return (flow_api && flow_api->hw_miss_packet_recover)
- ? flow_api->hw_miss_packet_recover(netdev, packet)
- : EOPNOTSUPP;
+ return rv;
}
int
diff --git a/lib/netdev-offload.h b/lib/netdev-offload.h
index 8237a85ddb..c56f9d49ad 100644
--- a/lib/netdev-offload.h
+++ b/lib/netdev-offload.h
@@ -45,6 +45,7 @@ struct ovs_action_push_tnl;
/* Offload-capable (HW) netdev information */
struct netdev_hw_info {
bool oor; /* Out of Offload Resources ? */
+ bool miss_api_supported; /* hw_miss_packet_recover() supported.*/
int offload_count; /* Pending (non-offloaded) flow count */
int pending_count; /* Offloaded flow count */
OVSRCU_TYPE(void *) offload_data; /* Offload metadata. */
--
2.26.2.1730.g385c171
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev