When PMDs perform upcalls, the newly generated ukey will replace
the old, however, the newly generated mageflow will be discard
to reuse the old one without checking if the actions of new and
old are equal.

We observe in the production environment that sometimes a megaflow
with wrong actions keep staying in datapath. The coverage command shows
revalidators have dumped serveral times, however the correct
actions are not set. This implies that the ukey's action does not
equal to the meagaflow's, i.e. revalidators think the underlying
megaflow's actions are correct however they are not.

We also check the megaflow using the ofproto/trace command, and the
actions are not matched with the ones in the actual magaflow. By
performing a revalidator/purge command, the right actions are set.

Signed-off-by: Peng He <[email protected]>
---
 lib/dpif-netdev.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index ff57b3961..985c25c58 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -8305,7 +8305,22 @@ handle_packet_upcall(struct dp_netdev_pmd_thread *pmd,
          * to be locking revalidators out of making flow modifications. */
         ovs_mutex_lock(&pmd->flow_mutex);
         netdev_flow = dp_netdev_pmd_lookup_flow(pmd, key, NULL);
-        if (OVS_LIKELY(!netdev_flow)) {
+        if (OVS_UNLIKELY(netdev_flow)) {
+            struct dp_netdev_actions *old_act =
+                dp_netdev_flow_get_actions(netdev_flow);
+
+            if ((add_actions->size != old_act->size) ||
+                    memcmp(old_act->actions, add_actions->data,
+                                             add_actions->size)) {
+
+               struct dp_netdev_actions *new_act =
+                   dp_netdev_actions_create(add_actions->data,
+                                            add_actions->size);
+
+               ovsrcu_set(&netdev_flow->actions, new_act);
+               ovsrcu_postpone(dp_netdev_actions_free, old_act);
+            }
+        } else {
             netdev_flow = dp_netdev_flow_add(pmd, &match, &ufid,
                                              add_actions->data,
                                              add_actions->size, orig_in_port);
-- 
2.25.1

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

Reply via email to