summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorEli Britstein <elibr@nvidia.com>2021-07-26 11:14:54 +0300
committerIlya Maximets <i.maximets@ovn.org>2021-08-02 18:56:56 +0200
commit6f69e0e30b2385a3146c358f6d1fe29dad9747ea (patch)
tree96fd8ccd9aab8166c6c8478333d8655028af92ea /lib
parent0d25621e4d9fb50e2e2ddf3332bd7abe90b3e67b (diff)
downloadopenvswitch-6f69e0e30b2385a3146c358f6d1fe29dad9747ea.tar.gz
dpif-netdev: Fix offloads of modified flows.
Association of a mark to a flow is done as part of its offload handling, in the offloading thread. However, the PMD thread specifies whether an offload request is an "add" or "modify" by the association of a mark to the flow. This is exposed to a race condition. A flow might be created with actions that cannot be fully offloaded, for example flooding (before MAC learning), and later modified to have actions that can be fully offloaded. If the two requests are queued before the offload thread handling, they are both marked as "add". When the offload thread handles them, the first request is partially offloaded, and the second one is ignored as the flow is already considered as offloaded. Fix it by specifying add/modify of an offload request by the actual flow state change, without relying on the mark. Fixes: 3c7330ebf036 ("netdev-offload-dpdk: Support offload of output action.") Signed-off-by: Eli Britstein <elibr@nvidia.com> Reviewed-by: Gaetan Rivet <gaetanr@nvidia.com> Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
Diffstat (limited to 'lib')
-rw-r--r--lib/dpif-netdev.c13
1 files changed, 4 insertions, 9 deletions
diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index 3532059e2..b3535d293 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -2714,10 +2714,9 @@ static void
queue_netdev_flow_put(struct dp_netdev_pmd_thread *pmd,
struct dp_netdev_flow *flow, struct match *match,
const struct nlattr *actions, size_t actions_len,
- odp_port_t orig_in_port)
+ odp_port_t orig_in_port, int op)
{
struct dp_flow_offload_item *offload;
- int op;
if (!netdev_is_flow_api_enabled()) {
return;
@@ -2730,11 +2729,6 @@ queue_netdev_flow_put(struct dp_netdev_pmd_thread *pmd,
ovsthread_once_done(&offload_thread_once);
}
- if (flow->mark != INVALID_FLOW_MARK) {
- op = DP_NETDEV_FLOW_OFFLOAD_OP_MOD;
- } else {
- op = DP_NETDEV_FLOW_OFFLOAD_OP_ADD;
- }
offload = dp_netdev_alloc_flow_offload(pmd, flow, op);
offload->match = *match;
offload->actions = xmalloc(actions_len);
@@ -3584,7 +3578,7 @@ dp_netdev_flow_add(struct dp_netdev_pmd_thread *pmd,
dp_netdev_flow_hash(&flow->ufid));
queue_netdev_flow_put(pmd, flow, match, actions, actions_len,
- orig_in_port);
+ orig_in_port, DP_NETDEV_FLOW_OFFLOAD_OP_ADD);
if (OVS_UNLIKELY(!VLOG_DROP_DBG((&upcall_rl)))) {
struct ds ds = DS_EMPTY_INITIALIZER;
@@ -3671,7 +3665,8 @@ flow_put_on_pmd(struct dp_netdev_pmd_thread *pmd,
ovsrcu_set(&netdev_flow->actions, new_actions);
queue_netdev_flow_put(pmd, netdev_flow, match,
- put->actions, put->actions_len, ODPP_NONE);
+ put->actions, put->actions_len, ODPP_NONE,
+ DP_NETDEV_FLOW_OFFLOAD_OP_MOD);
if (stats) {
get_dpif_flow_status(pmd->dp, netdev_flow, stats, NULL);