[ovs-dev] [PATCH v17 3/5] Persist lport_index and mcgroup_index structures

Ryan Moats rmoats at us.ibm.com
Sun May 22 21:36:20 UTC 2016


This is preparatory to making physical_run and lflow_run process
incrementally as changes to the data in these structures control
that processing.

Signed-off-by: Ryan Moats <rmoats at us.ibm.com>
---
 ovn/controller/lport.c          | 215 +++++++++++++++++++++++++++++++++-------
 ovn/controller/lport.h          |  22 +++-
 ovn/controller/ovn-controller.c |  16 +--
 3 files changed, 207 insertions(+), 46 deletions(-)

diff --git a/ovn/controller/lport.c b/ovn/controller/lport.c
index a7ae320..4810fbd 100644
--- a/ovn/controller/lport.c
+++ b/ovn/controller/lport.c
@@ -17,6 +17,7 @@
 
 #include "lport.h"
 #include "hash.h"
+#include "lflow.h"
 #include "openvswitch/vlog.h"
 #include "ovn/lib/ovn-sb-idl.h"
 
@@ -24,48 +25,109 @@ VLOG_DEFINE_THIS_MODULE(lport);
 
 /* A logical port. */
 struct lport {
-    struct hmap_node name_node; /* Index by name. */
-    struct hmap_node key_node;  /* Index by (dp_key, port_key). */
+    struct hmap_node name_node;  /* Index by name. */
+    struct hmap_node key_node;   /* Index by (dp_key, port_key). */
+    struct hmap_node uuid_node;  /* Index by row uuid. */
+    const struct uuid *uuid;
     const struct sbrec_port_binding *pb;
 };
 
+static bool full_lport_rebuild = false;
+static bool full_mc_rebuild = false;
+
+void
+flag_rebuild_lport_mcast_indexes(void)
+{
+    full_lport_rebuild = true;
+    full_mc_rebuild = true;
+}
+
 void
-lport_index_init(struct lport_index *lports, struct ovsdb_idl *ovnsb_idl)
+lport_index_init(struct lport_index *lports)
 {
     hmap_init(&lports->by_name);
     hmap_init(&lports->by_key);
+    hmap_init(&lports->by_uuid);
+}
 
-    const struct sbrec_port_binding *pb;
-    SBREC_PORT_BINDING_FOR_EACH (pb, ovnsb_idl) {
-        if (lport_lookup_by_name(lports, pb->logical_port)) {
-            static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
-            VLOG_WARN_RL(&rl, "duplicate logical port name '%s'",
-                         pb->logical_port);
-            continue;
-        }
-
-        struct lport *p = xmalloc(sizeof *p);
-        hmap_insert(&lports->by_name, &p->name_node,
-                    hash_string(pb->logical_port, 0));
-        hmap_insert(&lports->by_key, &p->key_node,
-                    hash_int(pb->tunnel_key, pb->datapath->tunnel_key));
-        p->pb = pb;
+void
+lport_index_remove(struct lport_index *lports, const struct uuid *uuid)
+{
+    const struct lport *port = lport_lookup_by_uuid(lports, uuid);
+    if (port) {
+        hmap_remove(&lports->by_name, (struct hmap_node *) &port->name_node);
+        hmap_remove(&lports->by_key, (struct hmap_node *) &port->key_node);
+        hmap_remove(&lports->by_uuid, (struct hmap_node *) &port->uuid_node);
+        free((void *) port);
     }
 }
 
 void
-lport_index_destroy(struct lport_index *lports)
+lport_index_clear(struct lport_index *lports)
 {
     /* Destroy all of the "struct lport"s.
      *
-     * We don't have to remove the node from both indexes. */
-    struct lport *port;
-    HMAP_FOR_EACH_POP (port, name_node, &lports->by_name) {
+     * We have to remove the node from all indexes. */
+    struct lport *port, *next;
+    HMAP_FOR_EACH_SAFE (port, next, name_node, &lports->by_name) {
+        hmap_remove(&lports->by_name, &port->name_node);
+        hmap_remove(&lports->by_key, &port->key_node);
+        hmap_remove(&lports->by_uuid, &port->uuid_node);
         free(port);
     }
+}
+
+static void
+consider_lport_index(struct lport_index *lports,
+                     const struct sbrec_port_binding *pb)
+{
+    if (lport_lookup_by_name(lports, pb->logical_port)) {
+        return;
+    }
+
+    struct lport *p = xmalloc(sizeof *p);
+    hmap_insert(&lports->by_name, &p->name_node,
+                hash_string(pb->logical_port, 0));
+    hmap_insert(&lports->by_key, &p->key_node,
+                hash_int(pb->tunnel_key, pb->datapath->tunnel_key));
+    hmap_insert(&lports->by_uuid, &p->uuid_node,
+                uuid_hash(&pb->header_.uuid));
+    p->uuid = &pb->header_.uuid;
+    p->pb = pb;
+}
+
+void
+lport_index_fill(struct lport_index *lports, struct ovsdb_idl *ovnsb_idl)
+{
+    const struct sbrec_port_binding *pb;
+    if (full_lport_rebuild) {
+        lport_index_clear(lports);
+        SBREC_PORT_BINDING_FOR_EACH (pb, ovnsb_idl) {
+            consider_lport_index(lports, pb);
+        }
+        full_lport_rebuild = false;
+    } else {
+        SBREC_PORT_BINDING_FOR_EACH_TRACKED (pb, ovnsb_idl) {
+            bool is_delete = sbrec_port_binding_row_get_seqno(pb,
+                OVSDB_IDL_CHANGE_DELETE) > 0;
+
+            if (is_delete) {
+                lport_index_remove(lports, &pb->header_.uuid);
+                continue;
+            }
+            consider_lport_index(lports, pb);
+        }
+    }
+}
+
+void
+lport_index_destroy(struct lport_index *lports)
+{
+    lport_index_clear(lports);
 
     hmap_destroy(&lports->by_name);
     hmap_destroy(&lports->by_key);
+    hmap_destroy(&lports->by_uuid);
 }
 
 /* Finds and returns the lport with the given 'name', or NULL if no such lport
@@ -83,6 +145,20 @@ lport_lookup_by_name(const struct lport_index *lports, const char *name)
     return NULL;
 }
 
+const struct lport *
+lport_lookup_by_uuid(const struct lport_index *lports,
+                     const struct uuid *uuid)
+{
+    const struct lport *lport;
+    HMAP_FOR_EACH_WITH_HASH (lport, uuid_node, uuid_hash(uuid),
+                             &lports->by_uuid) {
+        if (uuid_equals(uuid, lport->uuid)) {
+            return lport;
+        }
+    }
+    return NULL;
+}
+
 const struct sbrec_port_binding *
 lport_lookup_by_key(const struct lport_index *lports,
                     uint32_t dp_key, uint16_t port_key)
@@ -100,43 +176,106 @@ lport_lookup_by_key(const struct lport_index *lports,
 
 struct mcgroup {
     struct hmap_node dp_name_node; /* Index by (logical datapath, name). */
+    struct hmap_node uuid_node;    /* Index by insert uuid. */
+    const struct uuid *uuid;
     const struct sbrec_multicast_group *mg;
 };
 
 void
-mcgroup_index_init(struct mcgroup_index *mcgroups, struct ovsdb_idl *ovnsb_idl)
+mcgroup_index_init(struct mcgroup_index *mcgroups)
 {
     hmap_init(&mcgroups->by_dp_name);
+    hmap_init(&mcgroups->by_uuid);
+}
 
-    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_remove(struct mcgroup_index *mcgroups, const struct uuid *uuid)
+{
+    const struct mcgroup *mcgroup = mcgroup_lookup_by_uuid(mcgroups, uuid);
+    if (mcgroup) {
+        hmap_remove(&mcgroups->by_dp_name,
+                    (struct hmap_node *) &mcgroup->dp_name_node);
+        hmap_remove(&mcgroups->by_uuid,
+                    (struct hmap_node *) &mcgroup->uuid_node);
+        free((void *) mcgroup);
     }
 }
 
 void
-mcgroup_index_destroy(struct mcgroup_index *mcgroups)
+mcgroup_index_clear(struct mcgroup_index *mcgroups)
 {
     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);
+        hmap_remove(&mcgroups->by_uuid, &mcgroup->uuid_node);
         free(mcgroup);
     }
+}
+
+static void
+consider_mcgroup_index(struct mcgroup_index *mcgroups,
+                       const struct sbrec_multicast_group *mg)
+{
+    const struct uuid *dp_uuid = &mg->datapath->header_.uuid;
+    if (mcgroup_lookup_by_dp_name(mcgroups, mg->datapath, mg->name)) {
+        return;
+    }
+
+    struct mcgroup *m = xmalloc(sizeof *m);
+    hmap_insert(&mcgroups->by_dp_name, &m->dp_name_node,
+                hash_string(mg->name, uuid_hash(dp_uuid)));
+    hmap_insert(&mcgroups->by_uuid, &m->uuid_node,
+                uuid_hash(&mg->header_.uuid));
+    m->uuid = &mg->header_.uuid;
+    m->mg = mg;
+}
+
+void
+mcgroup_index_fill(struct mcgroup_index *mcgroups, struct ovsdb_idl *ovnsb_idl)
+{
+    const struct sbrec_multicast_group *mg;
+    if (full_mc_rebuild) {
+        mcgroup_index_clear(mcgroups);
+        SBREC_MULTICAST_GROUP_FOR_EACH (mg, ovnsb_idl) {
+            consider_mcgroup_index(mcgroups, mg);
+        }
+        full_mc_rebuild = false;
+    } else {
+        SBREC_MULTICAST_GROUP_FOR_EACH_TRACKED (mg, ovnsb_idl) {
+            bool is_delete = sbrec_multicast_group_row_get_seqno(mg,
+                OVSDB_IDL_CHANGE_DELETE) > 0;
+
+            if (is_delete) {
+                mcgroup_index_remove(mcgroups, &mg->header_.uuid);
+                continue;
+            }
+            consider_mcgroup_index(mcgroups, mg);
+        }
+    }
+}
+
+void
+mcgroup_index_destroy(struct mcgroup_index *mcgroups)
+{
+    mcgroup_index_clear(mcgroups);
 
     hmap_destroy(&mcgroups->by_dp_name);
 }
 
+const struct mcgroup *
+mcgroup_lookup_by_uuid(const struct mcgroup_index *mcgroups,
+                       const struct uuid *uuid)
+{
+    const struct mcgroup *mcgroup;
+    HMAP_FOR_EACH_WITH_HASH (mcgroup, uuid_node, uuid_hash(uuid),
+                             &mcgroups->by_uuid) {
+        if (uuid_equals(mcgroup->uuid, uuid)) {
+            return mcgroup;
+        }
+    }
+    return NULL;
+}
+
 const struct sbrec_multicast_group *
 mcgroup_lookup_by_dp_name(const struct mcgroup_index *mcgroups,
                           const struct sbrec_datapath_binding *dp,
diff --git a/ovn/controller/lport.h b/ovn/controller/lport.h
index f09e2eb..aca2583 100644
--- a/ovn/controller/lport.h
+++ b/ovn/controller/lport.h
@@ -18,10 +18,13 @@
 
 #include <stdint.h>
 #include "hmap.h"
+#include "uuid.h"
 
 struct ovsdb_idl;
 struct sbrec_datapath_binding;
 
+void flag_rebuild_lport_mcast_indexes(void);
+
 /* Logical port and multicast group indexes
  * ========================================
  *
@@ -32,15 +35,23 @@ struct sbrec_datapath_binding;
 struct lport_index {
     struct hmap by_name;
     struct hmap by_key;
+    struct hmap by_uuid;
 };
 
-void lport_index_init(struct lport_index *, struct ovsdb_idl *);
+void lport_index_init(struct lport_index *);
+void lport_index_fill(struct lport_index *, struct ovsdb_idl *);
+void lport_index_remove(struct lport_index *, const struct uuid *);
+void lport_index_clear(struct lport_index *);
 void lport_index_destroy(struct lport_index *);
 
 const struct sbrec_port_binding *lport_lookup_by_name(
     const struct lport_index *, const char *name);
 const struct sbrec_port_binding *lport_lookup_by_key(
     const struct lport_index *, uint32_t dp_key, uint16_t port_key);
+
+const struct lport *lport_lookup_by_uuid(
+    const struct lport_index *, const struct uuid *uuid);
+
 
 /* Multicast group index
  * =====================
@@ -54,9 +65,13 @@ const struct sbrec_port_binding *lport_lookup_by_key(
 
 struct mcgroup_index {
     struct hmap by_dp_name;
+    struct hmap by_uuid;
 };
 
-void mcgroup_index_init(struct mcgroup_index *, struct ovsdb_idl *);
+void mcgroup_index_init(struct mcgroup_index *);
+void mcgroup_index_fill(struct mcgroup_index *, struct ovsdb_idl *);
+void mcgroup_index_remove(struct mcgroup_index *, const struct uuid *);
+void mcgroup_index_clear(struct mcgroup_index *);
 void mcgroup_index_destroy(struct mcgroup_index *);
 
 const struct sbrec_multicast_group *mcgroup_lookup_by_dp_name(
@@ -64,4 +79,7 @@ const struct sbrec_multicast_group *mcgroup_lookup_by_dp_name(
     const struct sbrec_datapath_binding *,
     const char *name);
 
+const struct mcgroup *mcgroup_lookup_by_uuid(
+    const struct mcgroup_index *, const struct uuid *uuid);
+
 #endif /* ovn/lport.h */
diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c
index da1d419..97d998d 100644
--- a/ovn/controller/ovn-controller.c
+++ b/ovn/controller/ovn-controller.c
@@ -257,6 +257,9 @@ get_ovnsb_remote_probe_interval(struct ovsdb_idl *ovs_idl, int *value)
 static struct hmap local_datapaths = HMAP_INITIALIZER(&local_datapaths);
 static struct hmap patched_datapaths = HMAP_INITIALIZER(&patched_datapaths);
 
+static struct lport_index lports;
+static struct mcgroup_index mcgroups;
+
 int
 main(int argc, char *argv[])
 {
@@ -287,6 +290,9 @@ main(int argc, char *argv[])
     pinctrl_init();
     lflow_init();
 
+    lport_index_init(&lports);
+    mcgroup_index_init(&mcgroups);
+
     /* Connect to OVS OVSDB instance.  We do not monitor all tables by
      * default, so modules must register their interest explicitly.  */
     struct ovsdb_idl_loop ovs_idl_loop = OVSDB_IDL_LOOP_INITIALIZER(
@@ -348,6 +354,8 @@ main(int argc, char *argv[])
             ovsdb_idl_set_remote(ovnsb_idl_loop.idl, ovnsb_remote, true);
             hmap_clear(&local_datapaths);
             hmap_clear(&patched_datapaths);
+            lport_index_clear(&lports);
+            mcgroup_index_clear(&mcgroups);
         } else {
             free(new_ovnsb_remote);
         }
@@ -372,10 +380,8 @@ main(int argc, char *argv[])
         if (br_int) {
             patch_run(&ctx, br_int, &local_datapaths, &patched_datapaths);
 
-            struct lport_index lports;
-            struct mcgroup_index mcgroups;
-            lport_index_init(&lports, ctx.ovnsb_idl);
-            mcgroup_index_init(&mcgroups, ctx.ovnsb_idl);
+            lport_index_fill(&lports, ctx.ovnsb_idl);
+            mcgroup_index_fill(&mcgroups, ctx.ovnsb_idl);
 
             enum mf_field_id mff_ovn_geneve = ofctrl_run(br_int);
 
@@ -391,8 +397,6 @@ main(int argc, char *argv[])
             }
             ofctrl_put(&flow_table);
             hmap_destroy(&flow_table);
-            mcgroup_index_destroy(&mcgroups);
-            lport_index_destroy(&lports);
         }
 
         unixctl_server_run(unixctl);
-- 
1.9.1




More information about the dev mailing list