diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index 157694bcf0e..0b623fcea45 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -3380,13 +3380,14 @@ static inline void netdev_flow_key_init(struct netdev_flow_key *key, const struct flow *flow) { + uint64_t *dst = miniflow_values(&key->mf); uint32_t hash = 0; uint64_t value; miniflow_map_init(&key->mf, flow); miniflow_init(&key->mf, flow); - size_t n = miniflow_n_values(&key->mf); + size_t n = dst - miniflow_get_values(&key->mf); FLOW_FOR_EACH_IN_MAPS (value, flow, key->mf.map) { hash = hash_add64(hash, value); @@ -4205,7 +4206,7 @@ flow_put_on_pmd(struct dp_netdev_pmd_thread *pmd, const struct dpif_flow_put *put, struct dpif_flow_stats *stats) { - struct dp_netdev_flow *netdev_flow = NULL; + struct dp_netdev_flow *netdev_flow; int error = 0; if (stats) { @@ -4213,35 +4214,16 @@ flow_put_on_pmd(struct dp_netdev_pmd_thread *pmd, } ovs_mutex_lock(&pmd->flow_mutex); - if (put->ufid) { - netdev_flow = dp_netdev_pmd_find_flow(pmd, put->ufid, - put->key, put->key_len); - } else { - /* Use key instead of the locally generated ufid - * to search netdev_flow. */ - netdev_flow = dp_netdev_pmd_lookup_flow(pmd, key, NULL); - } - - if (put->flags & DPIF_FP_CREATE) { - if (!netdev_flow) { - dp_netdev_flow_add(pmd, match, ufid, - put->actions, put->actions_len, ODPP_NONE); + netdev_flow = dp_netdev_pmd_lookup_flow(pmd, key, NULL); + if (!netdev_flow) { + if (put->flags & DPIF_FP_CREATE) { + dp_netdev_flow_add(pmd, match, ufid, put->actions, + put->actions_len, ODPP_NONE); } else { - error = EEXIST; - } - goto exit; - } - - if (put->flags & DPIF_FP_MODIFY) { - if (!netdev_flow) { error = ENOENT; - } else { - if (!put->ufid && !flow_equal(&match->flow, &netdev_flow->flow)) { - /* Overlapping flow. */ - error = EINVAL; - goto exit; - } - + } + } else { + if (put->flags & DPIF_FP_MODIFY) { struct dp_netdev_actions *new_actions; struct dp_netdev_actions *old_actions; @@ -4272,11 +4254,15 @@ flow_put_on_pmd(struct dp_netdev_pmd_thread *pmd, * counter, and subtracting it before outputting the stats */ error = EOPNOTSUPP; } + ovsrcu_postpone(dp_netdev_actions_free, old_actions); + } else if (put->flags & DPIF_FP_CREATE) { + error = EEXIST; + } else { + /* Overlapping flow. */ + error = EINVAL; } } - -exit: ovs_mutex_unlock(&pmd->flow_mutex); return error; }