ebb439
From c8cf2e5c7f859bc3c781948e8a9cdd832035a7ee Mon Sep 17 00:00:00 2001
ebb439
From: Dumitru Ceara <dceara@redhat.com>
ebb439
Date: Sun, 11 Oct 2020 14:05:59 +0200
ebb439
Subject: [PATCH 5/7] ofctrl.c: Simplify active desired flow selection.
ebb439
ebb439
Always consider the first "desired flow" in the list of flows that refer an
ebb439
"installed flow" as the active flow.  This simplifies the logic of the flow
ebb439
update code and is used in a further commit to implement a partial ordering
ebb439
of desired flows within installed flows.
ebb439
ebb439
Signed-off-by: Dumitru Ceara <dceara@redhat.com>
ebb439
Signed-off-by: Han Zhou <hzhou@ovn.org>
ebb439
(cherry picked from upstream commit 107bb25029350bd0f7dfeeb0ef3053adbd504e3e)
ebb439
ebb439
Change-Id: I5e5aca6f18601a3cbd9decc913dad3507ee0a448
ebb439
---
ebb439
 controller/ofctrl.c | 91 +++++++++++++++++++++--------------------------------
ebb439
 1 file changed, 36 insertions(+), 55 deletions(-)
ebb439
ebb439
diff --git a/controller/ofctrl.c b/controller/ofctrl.c
ebb439
index 20cf3ac..ba0c61c 100644
ebb439
--- a/controller/ofctrl.c
ebb439
+++ b/controller/ofctrl.c
ebb439
@@ -188,6 +188,8 @@ struct sb_flow_ref {
ebb439
  * relationship is 1 to N. A link is added when a flow addition is processed.
ebb439
  * A link is removed when a flow deletion is processed, the desired flow
ebb439
  * table is cleared, or the installed flow table is cleared.
ebb439
+ * The first desired_flow in the list is the active one, the one that is
ebb439
+ * actually installed.
ebb439
  */
ebb439
 struct installed_flow {
ebb439
     struct ovn_flow flow;
ebb439
@@ -199,11 +201,6 @@ struct installed_flow {
ebb439
      * installed flow, e.g. when there are conflict/duplicated ACLs that
ebb439
      * generates same match conditions). */
ebb439
     struct ovs_list desired_refs;
ebb439
-
ebb439
-    /* The corresponding flow in desired table. It must be one of the flows in
ebb439
-     * desired_refs list.  If there are more than one flows in references list,
ebb439
-     * this is the one that is actually installed. */
ebb439
-    struct desired_flow *desired_flow;
ebb439
 };
ebb439
 
ebb439
 typedef bool
ebb439
@@ -231,6 +228,7 @@ static struct installed_flow *installed_flow_lookup(
ebb439
     const struct ovn_flow *target);
ebb439
 static void installed_flow_destroy(struct installed_flow *);
ebb439
 static struct installed_flow *installed_flow_dup(struct desired_flow *);
ebb439
+static struct desired_flow *installed_flow_get_active(struct installed_flow *);
ebb439
 
ebb439
 static uint32_t ovn_flow_match_hash(const struct ovn_flow *);
ebb439
 static char *ovn_flow_to_string(const struct ovn_flow *);
ebb439
@@ -796,24 +794,6 @@ ofctrl_recv(const struct ofp_header *oh, enum ofptype type)
ebb439
         log_openflow_rl(&rl, VLL_DBG, oh, "OpenFlow packet ignored");
ebb439
     }
ebb439
 }
ebb439
-
ebb439
-/* Returns true if a desired flow is active (the one currently installed
ebb439
- * among the list of desired flows that are linked to the same installed
ebb439
- * flow). */
ebb439
-static inline bool
ebb439
-desired_flow_is_active(struct desired_flow *d)
ebb439
-{
ebb439
-    return (d->installed_flow && d->installed_flow->desired_flow == d);
ebb439
-}
ebb439
-
ebb439
-/* Set a desired flow as the active one among the list of desired flows
ebb439
- * that are linked to the same installed flow. */
ebb439
-static inline void
ebb439
-desired_flow_set_active(struct desired_flow *d)
ebb439
-{
ebb439
-    ovs_assert(d->installed_flow);
ebb439
-    d->installed_flow->desired_flow = d;
ebb439
-}
ebb439
 
ebb439
 static bool
ebb439
 flow_action_has_conj(const struct ovn_flow *f)
ebb439
@@ -831,27 +811,22 @@ flow_action_has_conj(const struct ovn_flow *f)
ebb439
 /* Adds the desired flow to the list of desired flows that have same match
ebb439
  * conditions as the installed flow.
ebb439
  *
ebb439
- * If the newly added desired flow is the first one in the list, it is also set
ebb439
- * as the active one.
ebb439
- *
ebb439
  * It is caller's responsibility to make sure the link between the pair didn't
ebb439
- * exist before. */
ebb439
-static void
ebb439
+ * exist before.
ebb439
+ *
ebb439
+ * Returns true if the newly added desired flow is selected to be the active
ebb439
+ * one.
ebb439
+ */
ebb439
+static bool
ebb439
 link_installed_to_desired(struct installed_flow *i, struct desired_flow *d)
ebb439
 {
ebb439
-    ovs_assert(i->desired_flow != d);
ebb439
-    if (ovs_list_is_empty(&i->desired_refs)) {
ebb439
-        ovs_assert(!i->desired_flow);
ebb439
-        i->desired_flow = d;
ebb439
-    }
ebb439
-    ovs_list_insert(&i->desired_refs, &d->installed_ref_list_node);
ebb439
     d->installed_flow = i;
ebb439
+    ovs_list_push_back(&i->desired_refs, &d->installed_ref_list_node);
ebb439
+    return installed_flow_get_active(i) == d;
ebb439
 }
ebb439
 
ebb439
 /* Replaces 'old_desired' with 'new_desired' in the list of desired flows
ebb439
  * that have same match conditions as the installed flow.
ebb439
- *
ebb439
- * If 'old_desired' was the active flow, 'new_desired' becomes the active one.
ebb439
  */
ebb439
 static void
ebb439
 replace_installed_to_desired(struct installed_flow *i,
ebb439
@@ -863,24 +838,22 @@ replace_installed_to_desired(struct installed_flow *i,
ebb439
                      &old_desired->installed_ref_list_node);
ebb439
     old_desired->installed_flow = NULL;
ebb439
     new_desired->installed_flow = i;
ebb439
-    if (i->desired_flow == old_desired) {
ebb439
-        i->desired_flow = new_desired;
ebb439
-    }
ebb439
 }
ebb439
 
ebb439
-static void
ebb439
+/* Removes the desired flow from the list of desired flows that have the same
ebb439
+ * match conditions as the installed flow.
ebb439
+ *
ebb439
+ * Returns true if the desired flow was the previously active flow.
ebb439
+ */
ebb439
+static bool
ebb439
 unlink_installed_to_desired(struct installed_flow *i, struct desired_flow *d)
ebb439
 {
ebb439
-    ovs_assert(i && i->desired_flow && !ovs_list_is_empty(&i->desired_refs));
ebb439
+    struct desired_flow *old_active = installed_flow_get_active(i);
ebb439
+
ebb439
     ovs_assert(d && d->installed_flow == i);
ebb439
     ovs_list_remove(&d->installed_ref_list_node);
ebb439
     d->installed_flow = NULL;
ebb439
-    if (i->desired_flow == d) {
ebb439
-        i->desired_flow = ovs_list_is_empty(&i->desired_refs) ? NULL :
ebb439
-            CONTAINER_OF(ovs_list_front(&i->desired_refs),
ebb439
-                         struct desired_flow,
ebb439
-                         installed_ref_list_node);
ebb439
-    }
ebb439
+    return old_active == d;
ebb439
 }
ebb439
 
ebb439
 static void
ebb439
@@ -1280,7 +1253,6 @@ installed_flow_dup(struct desired_flow *src)
ebb439
 {
ebb439
     struct installed_flow *dst = xmalloc(sizeof *dst);
ebb439
     ovs_list_init(&dst->desired_refs);
ebb439
-    dst->desired_flow = NULL;
ebb439
     dst->flow.table_id = src->flow.table_id;
ebb439
     dst->flow.priority = src->flow.priority;
ebb439
     minimatch_clone(&dst->flow.match, &src->flow.match);
ebb439
@@ -1292,6 +1264,17 @@ installed_flow_dup(struct desired_flow *src)
ebb439
 }
ebb439
 
ebb439
 static struct desired_flow *
ebb439
+installed_flow_get_active(struct installed_flow *f)
ebb439
+{
ebb439
+    if (!ovs_list_is_empty(&f->desired_refs)) {
ebb439
+        return CONTAINER_OF(ovs_list_front(&f->desired_refs),
ebb439
+                            struct desired_flow,
ebb439
+                            installed_ref_list_node);
ebb439
+    }
ebb439
+    return NULL;
ebb439
+}
ebb439
+
ebb439
+static struct desired_flow *
ebb439
 desired_flow_lookup__(struct ovn_desired_flow_table *flow_table,
ebb439
                       const struct ovn_flow *target,
ebb439
                       desired_flow_match_cb match_cb,
ebb439
@@ -1439,8 +1422,7 @@ static void
ebb439
 installed_flow_destroy(struct installed_flow *f)
ebb439
 {
ebb439
     if (f) {
ebb439
-        ovs_assert(ovs_list_is_empty(&f->desired_refs));
ebb439
-        ovs_assert(!f->desired_flow);
ebb439
+        ovs_assert(!installed_flow_get_active(f));
ebb439
         ovn_flow_uninit(&f->flow);
ebb439
         free(f);
ebb439
     }
ebb439
@@ -1898,10 +1880,10 @@ update_installed_flows_by_track(struct ovn_desired_flow_table *flow_table,
ebb439
             /* The desired flow was deleted */
ebb439
             if (f->installed_flow) {
ebb439
                 struct installed_flow *i = f->installed_flow;
ebb439
-                bool was_active = desired_flow_is_active(f);
ebb439
-                unlink_installed_to_desired(i, f);
ebb439
+                bool was_active = unlink_installed_to_desired(i, f);
ebb439
+                struct desired_flow *d = installed_flow_get_active(i);
ebb439
 
ebb439
-                if (!i->desired_flow) {
ebb439
+                if (!d) {
ebb439
                     installed_flow_del(&i->flow, msgs);
ebb439
                     ovn_flow_log(&i->flow, "removing installed (tracked)");
ebb439
 
ebb439
@@ -1912,7 +1894,6 @@ update_installed_flows_by_track(struct ovn_desired_flow_table *flow_table,
ebb439
                      * installed flow, so update the OVS flow for the new
ebb439
                      * active flow (at least the cookie will be different,
ebb439
                      * even if the actions are the same). */
ebb439
-                    struct desired_flow *d = i->desired_flow;
ebb439
                     ovn_flow_log(&i->flow, "updating installed (tracked)");
ebb439
                     installed_flow_mod(&i->flow, &d->flow, msgs);
ebb439
                 }
ebb439
@@ -1931,7 +1912,7 @@ update_installed_flows_by_track(struct ovn_desired_flow_table *flow_table,
ebb439
                 hmap_insert(&installed_flows, &new_node->match_hmap_node,
ebb439
                             new_node->flow.hash);
ebb439
                 link_installed_to_desired(new_node, f);
ebb439
-            } else if (desired_flow_is_active(f)) {
ebb439
+            } else if (installed_flow_get_active(i) == f) {
ebb439
                 /* The installed flow is installed for f, but f has change
ebb439
                  * tracked, so it must have been modified. */
ebb439
                 ovn_flow_log(&i->flow, "updating installed (tracked)");
ebb439
-- 
ebb439
1.8.3.1
ebb439