Use IDL index for multicast group table lookups, avoiding the overhead
of creating/destroying an index hmap for each iteration of the
ovn-controller main loop.

Signed-off-by: Lance Richardson <lrich...@redhat.com>
---
 v7: New patch.

 ovn/controller/lflow.c          | 20 +++++-----
 ovn/controller/lflow.h          |  2 -
 ovn/controller/lport.c          | 85 ++++++++++++++++-------------------------
 ovn/controller/lport.h          | 20 ++--------
 ovn/controller/ovn-controller.c | 26 ++++++++++---
 5 files changed, 65 insertions(+), 88 deletions(-)

diff --git a/ovn/controller/lflow.c b/ovn/controller/lflow.c
index b1b4b2372..56a7c02c2 100644
--- a/ovn/controller/lflow.c
+++ b/ovn/controller/lflow.c
@@ -45,8 +45,8 @@ lflow_init(void)
 }
 
 struct lookup_port_aux {
+    struct ovsdb_idl *ovnsb_idl;
     const struct lport_index *lports;
-    const struct mcgroup_index *mcgroups;
     const struct sbrec_datapath_binding *dp;
 };
 
@@ -55,8 +55,8 @@ struct condition_aux {
     const struct sbrec_chassis *chassis;
 };
 
-static void consider_logical_flow(const struct lport_index *lports,
-                                  const struct mcgroup_index *mcgroups,
+static void consider_logical_flow(struct controller_ctx *ctx,
+                                  const struct lport_index *lports,
                                   const struct sbrec_logical_flow *lflow,
                                   const struct hmap *local_datapaths,
                                   struct group_table *group_table,
@@ -80,7 +80,7 @@ lookup_port_cb(const void *aux_, const char *port_name, 
unsigned int *portp)
     }
 
     const struct sbrec_multicast_group *mg
-        = mcgroup_lookup_by_dp_name(aux->mcgroups, aux->dp, port_name);
+        = mcgroup_lookup_by_dp_name(aux->ovnsb_idl, aux->dp, port_name);
     if (mg) {
         *portp = mg->tunnel_key;
         return true;
@@ -118,7 +118,6 @@ is_gateway_router(const struct sbrec_datapath_binding *ldp,
 /* Adds the logical flows from the Logical_Flow table to flow tables. */
 static void
 add_logical_flows(struct controller_ctx *ctx, const struct lport_index *lports,
-                  const struct mcgroup_index *mcgroups,
                   const struct hmap *local_datapaths,
                   struct group_table *group_table,
                   const struct sbrec_chassis *chassis,
@@ -144,7 +143,7 @@ add_logical_flows(struct controller_ctx *ctx, const struct 
lport_index *lports,
     }
 
     SBREC_LOGICAL_FLOW_FOR_EACH (lflow, ctx->ovnsb_idl) {
-        consider_logical_flow(lports, mcgroups, lflow, local_datapaths,
+        consider_logical_flow(ctx, lports, lflow, local_datapaths,
                               group_table, chassis,
                               &dhcp_opts, &dhcpv6_opts, &conj_id_ofs,
                               addr_sets, flow_table);
@@ -155,8 +154,8 @@ add_logical_flows(struct controller_ctx *ctx, const struct 
lport_index *lports,
 }
 
 static void
-consider_logical_flow(const struct lport_index *lports,
-                      const struct mcgroup_index *mcgroups,
+consider_logical_flow(struct controller_ctx *ctx,
+                      const struct lport_index *lports,
                       const struct sbrec_logical_flow *lflow,
                       const struct hmap *local_datapaths,
                       struct group_table *group_table,
@@ -220,7 +219,7 @@ consider_logical_flow(const struct lport_index *lports,
     struct ofpbuf ofpacts = OFPBUF_STUB_INITIALIZER(ofpacts_stub);
     struct lookup_port_aux aux = {
         .lports = lports,
-        .mcgroups = mcgroups,
+        .ovnsb_idl = ctx->ovnsb_idl,
         .dp = lflow->logical_datapath
     };
     struct ovnact_encode_params ep = {
@@ -387,13 +386,12 @@ void
 lflow_run(struct controller_ctx *ctx,
           const struct sbrec_chassis *chassis,
           const struct lport_index *lports,
-          const struct mcgroup_index *mcgroups,
           const struct hmap *local_datapaths,
           struct group_table *group_table,
           const struct shash *addr_sets,
           struct hmap *flow_table)
 {
-    add_logical_flows(ctx, lports, mcgroups, local_datapaths, group_table,
+    add_logical_flows(ctx, lports, local_datapaths, group_table,
                       chassis, addr_sets, flow_table);
     add_neighbor_flows(ctx, lports, flow_table);
 }
diff --git a/ovn/controller/lflow.h b/ovn/controller/lflow.h
index a23cde099..60d86cdc8 100644
--- a/ovn/controller/lflow.h
+++ b/ovn/controller/lflow.h
@@ -39,7 +39,6 @@ struct controller_ctx;
 struct group_table;
 struct hmap;
 struct lport_index;
-struct mcgroup_index;
 struct sbrec_chassis;
 struct simap;
 struct uuid;
@@ -65,7 +64,6 @@ void lflow_init(void);
 void lflow_run(struct controller_ctx *,
                const struct sbrec_chassis *chassis,
                const struct lport_index *,
-               const struct mcgroup_index *,
                const struct hmap *local_datapaths,
                struct group_table *group_table,
                const struct shash *addr_sets,
diff --git a/ovn/controller/lport.c b/ovn/controller/lport.c
index 906fda222..7636d911c 100644
--- a/ovn/controller/lport.c
+++ b/ovn/controller/lport.c
@@ -22,6 +22,8 @@
 
 VLOG_DEFINE_THIS_MODULE(lport);
 
+static struct ovsdb_idl_index_cursor mc_grp_by_dp_name_cursor;
+
 static struct ldatapath *ldatapath_lookup_by_key__(
     const struct ldatapath_index *, uint32_t dp_key);
 
@@ -177,63 +179,42 @@ lport_lookup_by_key(const struct lport_index *lports,
     return NULL;
 }
 
-struct mcgroup {
-    struct hmap_node dp_name_node; /* Index by (logical datapath, name). */
-    const struct sbrec_multicast_group *mg;
-};
-
-void
-mcgroup_index_init(struct mcgroup_index *mcgroups, struct ovsdb_idl *ovnsb_idl)
-{
-    hmap_init(&mcgroups->by_dp_name);
-
-    const struct sbrec_multicast_group *mg;
-    SBREC_MULTICAST_GROUP_FOR_EACH (mg, ovnsb_idl) {
-        const struct uuid *dp_uuid = &mg->datapath->header_.uuid;
-        if (mcgroup_lookup_by_dp_name(mcgroups, mg->datapath, mg->name)) {
-            static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
-            VLOG_WARN_RL(&rl, "datapath "UUID_FMT" contains duplicate "
-                         "multicast group '%s'", UUID_ARGS(dp_uuid), mg->name);
-            continue;
-        }
-
-        struct mcgroup *m = xmalloc(sizeof *m);
-        hmap_insert(&mcgroups->by_dp_name, &m->dp_name_node,
-                    hash_string(mg->name, uuid_hash(dp_uuid)));
-        m->mg = mg;
-    }
-}
-
-void
-mcgroup_index_destroy(struct mcgroup_index *mcgroups)
+/* Finds and returns the logical multicast group with the given 'name' and
+ * datapath binding, or NULL if no such logical multicast group exists. */
+const struct sbrec_multicast_group *
+mcgroup_lookup_by_dp_name(struct ovsdb_idl *idl,
+                           const struct sbrec_datapath_binding *dp,
+                           const char *name)
 {
-    if (!mcgroups) {
-        return;
+    struct sbrec_multicast_group *mcval;
+    const struct sbrec_multicast_group *mc, *retval = NULL;
+
+    /* Build key for an indexed lookup. */
+    mcval = sbrec_multicast_group_index_init_row(idl,
+                                                 &sbrec_table_multicast_group);
+    sbrec_multicast_group_index_set_name(mcval, name);
+    sbrec_multicast_group_index_set_datapath(mcval, dp);
+
+    /* Find an entry with matching logical multicast group name and datapath.
+     * Since this column pair is declared to be an index in the OVN_Southbound
+     * schema, the first match (if any) will be the only match. */
+    SBREC_MULTICAST_GROUP_FOR_EACH_EQUAL (mc, &mc_grp_by_dp_name_cursor,
+                                          mcval) {
+        retval = mc;
+        break;
     }
 
-    struct mcgroup *mcgroup, *next;
-    HMAP_FOR_EACH_SAFE (mcgroup, next, dp_name_node, &mcgroups->by_dp_name) {
-        hmap_remove(&mcgroups->by_dp_name, &mcgroup->dp_name_node);
-        free(mcgroup);
-    }
+    sbrec_multicast_group_index_destroy_row(mcval);
 
-    hmap_destroy(&mcgroups->by_dp_name);
+    return retval;
 }
 
-const struct sbrec_multicast_group *
-mcgroup_lookup_by_dp_name(const struct mcgroup_index *mcgroups,
-                          const struct sbrec_datapath_binding *dp,
-                          const char *name)
+void
+lport_init(struct ovsdb_idl *idl)
 {
-    const struct uuid *dp_uuid = &dp->header_.uuid;
-    const struct mcgroup *mcgroup;
-    HMAP_FOR_EACH_WITH_HASH (mcgroup, dp_name_node,
-                             hash_string(name, uuid_hash(dp_uuid)),
-                             &mcgroups->by_dp_name) {
-        if (uuid_equals(&mcgroup->mg->datapath->header_.uuid, dp_uuid)
-            && !strcmp(mcgroup->mg->name, name)) {
-            return mcgroup->mg;
-        }
-    }
-    return NULL;
+    /* Create a cursor for searching multicast group table by datapath
+     * and group name. */
+    ovsdb_idl_initialize_cursor(idl, &sbrec_table_multicast_group,
+                                "multicast-group-by-dp-name",
+                                &mc_grp_by_dp_name_cursor);
 }
diff --git a/ovn/controller/lport.h b/ovn/controller/lport.h
index fe0e430ac..4ee19a536 100644
--- a/ovn/controller/lport.h
+++ b/ovn/controller/lport.h
@@ -71,26 +71,12 @@ const struct sbrec_port_binding *lport_lookup_by_name(
 const struct sbrec_port_binding *lport_lookup_by_key(
     const struct lport_index *, uint32_t dp_key, uint16_t port_key);
 
-/* Multicast group index
- * =====================
- *
- * This is separate from the logical port index because of namespace issues:
- * logical port names are globally unique, but multicast group names are only
- * unique within the scope of a logical datapath.
- *
- * Multicast groups could be indexed by number also, but so far the clients do
- * not need this index. */
-
-struct mcgroup_index {
-    struct hmap by_dp_name;
-};
-
-void mcgroup_index_init(struct mcgroup_index *, struct ovsdb_idl *);
-void mcgroup_index_destroy(struct mcgroup_index *);
 
 const struct sbrec_multicast_group *mcgroup_lookup_by_dp_name(
-    const struct mcgroup_index *,
+    struct ovsdb_idl *idl,
     const struct sbrec_datapath_binding *,
     const char *name);
 
+void lport_init(struct ovsdb_idl *idl);
+
 #endif /* ovn/lport.h */
diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c
index 45a670b5d..d01227d53 100644
--- a/ovn/controller/ovn-controller.c
+++ b/ovn/controller/ovn-controller.c
@@ -525,6 +525,20 @@ ctrl_register_ovs_idl(struct ovsdb_idl *ovs_idl)
     physical_register_ovs_idl(ovs_idl);
 }
 
+static void
+create_ovnsb_indexes(struct ovsdb_idl *ovnsb_idl)
+{
+    struct ovsdb_idl_index *index;
+
+    /* Index multicast group table by name and datapath. */
+    index = ovsdb_idl_create_index(ovnsb_idl, &sbrec_table_multicast_group,
+                                   "multicast-group-by-dp-name");
+    ovsdb_idl_index_add_column(index, &sbrec_multicast_group_col_name,
+                               OVSDB_INDEX_ASC, NULL);
+    ovsdb_idl_index_add_column(index, &sbrec_multicast_group_col_datapath,
+                               OVSDB_INDEX_ASC, NULL);
+}
+
 int
 main(int argc, char *argv[])
 {
@@ -569,6 +583,10 @@ main(int argc, char *argv[])
     char *ovnsb_remote = get_ovnsb_remote(ovs_idl_loop.idl);
     struct ovsdb_idl_loop ovnsb_idl_loop = OVSDB_IDL_LOOP_INITIALIZER(
         ovsdb_idl_create(ovnsb_remote, &sbrec_idl_class, true, true));
+
+    create_ovnsb_indexes(ovnsb_idl_loop.idl);
+    lport_init(ovnsb_idl_loop.idl);
+
     ovsdb_idl_omit_alert(ovnsb_idl_loop.idl, &sbrec_chassis_col_nb_cfg);
     update_sb_monitors(ovnsb_idl_loop.idl, NULL, NULL, NULL);
     ovsdb_idl_get_initial_snapshot(ovnsb_idl_loop.idl);
@@ -626,10 +644,8 @@ main(int argc, char *argv[])
 
         struct ldatapath_index ldatapaths;
         struct lport_index lports;
-        struct mcgroup_index mcgroups;
         ldatapath_index_init(&ldatapaths, ctx.ovnsb_idl);
         lport_index_init(&lports, ctx.ovnsb_idl);
-        mcgroup_index_init(&mcgroups, ctx.ovnsb_idl);
 
         const struct sbrec_chassis *chassis = NULL;
         if (chassis_id) {
@@ -656,9 +672,8 @@ main(int argc, char *argv[])
                     commit_ct_zones(br_int, &pending_ct_zones);
 
                     struct hmap flow_table = HMAP_INITIALIZER(&flow_table);
-                    lflow_run(&ctx, chassis, &lports, &mcgroups,
-                              &local_datapaths, &group_table,
-                              &addr_sets, &flow_table);
+                    lflow_run(&ctx, chassis, &lports, &local_datapaths,
+                              &group_table, &addr_sets, &flow_table);
 
                     physical_run(&ctx, mff_ovn_geneve,
                                  br_int, chassis, &ct_zones, &lports,
@@ -706,7 +721,6 @@ main(int argc, char *argv[])
             free(pending_pkt.flow_s);
         }
 
-        mcgroup_index_destroy(&mcgroups);
         lport_index_destroy(&lports);
         ldatapath_index_destroy(&ldatapaths);
 
-- 
2.13.0

_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to