[ovs-dev] [PATCH ovn 1/4] ovn-controller: Fix incremental processing for multicast group dependency.

Han Zhou hzhou at ovn.org
Fri May 28 19:23:36 UTC 2021


Multicast group changes are handled for physical flows in I-P, but not
handled for logical flows. Although logical flow doesn't care about the
content of a multicast group, the existance of it matters for logical
flow processing. If the multicast group is not found when the logical
flow is processed at first but laster it is created/monitored by
ovn-controller, the logical flow that has been processed before should
be reprocessed. This would avoid the workaound of ovn_lflow_add_unique()
used in northd when adding multicast group related logical flows.

Signed-off-by: Han Zhou <hzhou at ovn.org>
---
 controller/lflow.c          | 40 +++++++++++++++++++++++++++++++++++++
 controller/lflow.h          |  5 ++++-
 controller/ovn-controller.c | 13 +++++++++++-
 lib/ovn-util.h              |  8 ++++++++
 4 files changed, 64 insertions(+), 2 deletions(-)

diff --git a/controller/lflow.c b/controller/lflow.c
index 680b8cca1..0abb6eb96 100644
--- a/controller/lflow.c
+++ b/controller/lflow.c
@@ -55,6 +55,8 @@ struct lookup_port_aux {
     struct ovsdb_idl_index *sbrec_multicast_group_by_name_datapath;
     struct ovsdb_idl_index *sbrec_port_binding_by_name;
     const struct sbrec_datapath_binding *dp;
+    const struct sbrec_logical_flow *lflow;
+    struct lflow_resource_ref *lfrr;
 };
 
 struct condition_aux {
@@ -103,6 +105,16 @@ lookup_port_cb(const void *aux_, const char *port_name, unsigned int *portp)
         return true;
     }
 
+    /* Store the key (DP + name) that used to lookup the multicast group to
+     * lflow reference, so that in the future when the multicast group's
+     * existance (found/not found) changes, the logical flow that references
+     * this multicast group can be reprocessed. */
+    struct ds mg_key = DS_EMPTY_INITIALIZER;
+    get_mc_group_key(port_name, aux->dp->tunnel_key, &mg_key);
+    lflow_resource_add(aux->lfrr, REF_TYPE_MC_GROUP, ds_cstr(&mg_key),
+                       &aux->lflow->header_.uuid);
+    ds_destroy(&mg_key);
+
     const struct sbrec_multicast_group *mg = mcgroup_lookup_by_dp_name(
         aux->sbrec_multicast_group_by_name_datapath, aux->dp, port_name);
     if (mg) {
@@ -570,6 +582,8 @@ add_matches_to_flow_table(const struct sbrec_logical_flow *lflow,
             = l_ctx_in->sbrec_multicast_group_by_name_datapath,
         .sbrec_port_binding_by_name = l_ctx_in->sbrec_port_binding_by_name,
         .dp = dp,
+        .lflow = lflow,
+        .lfrr = l_ctx_out->lfrr,
     };
 
     /* Encode OVN logical actions into OpenFlow. */
@@ -769,6 +783,8 @@ consider_logical_flow__(const struct sbrec_logical_flow *lflow,
             = l_ctx_in->sbrec_multicast_group_by_name_datapath,
         .sbrec_port_binding_by_name = l_ctx_in->sbrec_port_binding_by_name,
         .dp = dp,
+        .lflow = lflow,
+        .lfrr = l_ctx_out->lfrr,
     };
     struct condition_aux cond_aux = {
         .sbrec_port_binding_by_name = l_ctx_in->sbrec_port_binding_by_name,
@@ -1745,6 +1761,30 @@ lflow_handle_flows_for_lport(const struct sbrec_port_binding *pb,
                                     l_ctx_in, l_ctx_out, &changed);
 }
 
+bool
+lflow_handle_mc_group_changes(struct lflow_ctx_in *l_ctx_in,
+                              struct lflow_ctx_out *l_ctx_out)
+{
+    bool changed, ret = true;
+    struct ds mg_key = DS_EMPTY_INITIALIZER;
+    const struct sbrec_multicast_group *mg;
+    SBREC_MULTICAST_GROUP_TABLE_FOR_EACH_TRACKED (mg,
+                                                  l_ctx_in->mc_group_table) {
+        get_mc_group_key(mg->name, mg->datapath->tunnel_key, &mg_key);
+        if (!sbrec_multicast_group_is_new(mg)
+            && !sbrec_multicast_group_is_deleted(mg)) {
+            continue;
+        }
+        if (!lflow_handle_changed_ref(REF_TYPE_MC_GROUP, ds_cstr(&mg_key),
+                                      l_ctx_in, l_ctx_out, &changed)) {
+            ret = false;
+            break;
+        }
+    }
+    ds_destroy(&mg_key);
+    return ret;
+}
+
 bool
 lflow_handle_changed_lbs(struct lflow_ctx_in *l_ctx_in,
                          struct lflow_ctx_out *l_ctx_out)
diff --git a/controller/lflow.h b/controller/lflow.h
index 3c929d8a6..07263ff47 100644
--- a/controller/lflow.h
+++ b/controller/lflow.h
@@ -78,7 +78,8 @@ struct uuid;
 enum ref_type {
     REF_TYPE_ADDRSET,
     REF_TYPE_PORTGROUP,
-    REF_TYPE_PORTBINDING
+    REF_TYPE_PORTBINDING,
+    REF_TYPE_MC_GROUP
 };
 
 struct ref_lflow_node {
@@ -179,4 +180,6 @@ bool lflow_add_flows_for_datapath(const struct sbrec_datapath_binding *,
 bool lflow_handle_flows_for_lport(const struct sbrec_port_binding *,
                                   struct lflow_ctx_in *,
                                   struct lflow_ctx_out *);
+bool lflow_handle_mc_group_changes(struct lflow_ctx_in *,
+                                   struct lflow_ctx_out *);
 #endif /* controller/lflow.h */
diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
index d48ddc7a2..bf29aaaad 100644
--- a/controller/ovn-controller.c
+++ b/controller/ovn-controller.c
@@ -2272,6 +2272,13 @@ flow_output_sb_multicast_group_handler(struct engine_node *node, void *data)
     struct ed_type_flow_output *fo = data;
     struct ovn_desired_flow_table *flow_table = &fo->flow_table;
 
+    struct lflow_ctx_in l_ctx_in;
+    struct lflow_ctx_out l_ctx_out;
+    init_lflow_ctx(node, rt_data, fo, &l_ctx_in, &l_ctx_out);
+    if (!lflow_handle_mc_group_changes(&l_ctx_in, &l_ctx_out)) {
+        return false;
+    }
+
     struct physical_ctx p_ctx;
     init_physical_ctx(node, rt_data, &p_ctx);
 
@@ -2345,8 +2352,12 @@ _flow_output_resource_ref_handler(struct engine_node *node, void *data,
             deleted = &pg_data->deleted;
             break;
 
-        /* This ref type is handled in the flow_output_runtime_data_handler. */
         case REF_TYPE_PORTBINDING:
+            /* This ref type is handled in the
+             * flow_output_runtime_data_handler. */
+        case REF_TYPE_MC_GROUP:
+            /* This ref type is handled in the
+             * flow_output_sb_multicast_group_handler. */
         default:
             OVS_NOT_REACHED();
     }
diff --git a/lib/ovn-util.h b/lib/ovn-util.h
index 5533dbd0c..bf01668b5 100644
--- a/lib/ovn-util.h
+++ b/lib/ovn-util.h
@@ -138,6 +138,14 @@ get_unique_lport_key(uint64_t dp_tunnel_key, uint64_t lport_tunnel_key,
              lport_tunnel_key);
 }
 
+static inline void
+get_mc_group_key(const char *mg_name, int64_t dp_tunnel_key,
+                 struct ds *mg_key)
+{
+    ds_clear(mg_key);
+    ds_put_format(mg_key, "%"PRId64"_%s", dp_tunnel_key, mg_name);
+}
+
 static inline void
 get_sb_port_group_name(const char *nb_pg_name, int64_t dp_tunnel_key,
                        struct ds *sb_pg_name)
-- 
2.30.2



More information about the dev mailing list