[ovs-dev] [PATCH ovn v3 07/10] ovn: Add tunnel_key concept to Bindings table, assign in ovn-northd.

Ben Pfaff blp at nicira.com
Fri Apr 24 22:34:57 UTC 2015


When packets travel among nodes in OVN over tunnels, a tunnel key value is
needed to convey the logical port to which the packet is destined.  This
commit adds a tunnel_key column to the Bindings table and adds code to
ovn-northd to assign a unique tunnel_key value to each logical port.

Signed-off-by: Ben Pfaff <blp at nicira.com>
---
 ovn/northd/ovn-northd.c |   78 ++++++++++++++++++++++++++++++++++-------------
 ovn/ovn-sb.ovsschema    |    6 +++-
 ovn/ovn-sb.xml          |    4 +++
 3 files changed, 66 insertions(+), 22 deletions(-)

diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c
index 1680290..1b508c2 100644
--- a/ovn/northd/ovn-northd.c
+++ b/ovn/northd/ovn-northd.c
@@ -416,6 +416,26 @@ tags_equal(const struct sbrec_bindings *binding,
     return binding->n_tag ? (binding->tag[0] == lport->tag[0]) : true;
 }
 
+struct binding_hash_node {
+    struct hmap_node lp_node; /* In 'lp_map', by binding->logical_port. */
+    struct hmap_node tk_node; /* In 'tk_map', by binding->tunnel_key. */
+    const struct sbrec_bindings *binding;
+};
+
+static bool
+tunnel_key_in_use(const struct hmap *tk_hmap, uint16_t tunnel_key)
+{
+    const struct binding_hash_node *hash_node;
+
+    HMAP_FOR_EACH_IN_BUCKET (hash_node, tk_node, hash_int(tunnel_key, 0),
+                             tk_hmap) {
+        if (hash_node->binding->tunnel_key == tunnel_key) {
+            return true;
+        }
+    }
+    return false;
+}
+
 /*
  * When a change has occurred in the OVN_Northbound database, we go through and
  * make sure that the contents of the Bindings table in the OVN_Southbound
@@ -425,38 +445,41 @@ tags_equal(const struct sbrec_bindings *binding,
 static void
 set_bindings(struct northd_context *ctx)
 {
-    struct hmap bindings_hmap;
     const struct sbrec_bindings *binding;
     const struct nbrec_logical_port *lport;
 
-    struct binding_hash_node {
-        struct hmap_node node;
-        const struct sbrec_bindings *binding;
-    } *hash_node, *hash_node_next;
-
     /*
      * We will need to look up a binding for every logical port.  We don't want
      * to have to do an O(n) search for every binding, so start out by hashing
      * them on the logical port.
      *
      * As we go through every logical port, we will update the binding if it
-     * exists or create one otherwise.  When the update is done, we'll remove it
-     * from the hashmap.  At the end, any bindings left in the hashmap are for
-     * logical ports that have been deleted.
+     * exists or create one otherwise.  When the update is done, we'll remove
+     * it from the hashmap.  At the end, any bindings left in the hashmap are
+     * for logical ports that have been deleted.
+     *
+     * We index the logical_port column because that's the shared key between
+     * the OVN_NB and OVN_SB databases.  We index the tunnel_key column to
+     * allow us to choose a unique tunnel key for any Binding rows we have to
+     * add.
      */
-    hmap_init(&bindings_hmap);
+    struct hmap lp_hmap = HMAP_INITIALIZER(&lp_hmap);
+    struct hmap tk_hmap = HMAP_INITIALIZER(&tk_hmap);
 
     SBREC_BINDINGS_FOR_EACH(binding, ctx->ovnsb_idl) {
-        hash_node = xzalloc(sizeof *hash_node);
+        struct binding_hash_node *hash_node = xzalloc(sizeof *hash_node);
         hash_node->binding = binding;
-        hmap_insert(&bindings_hmap, &hash_node->node,
-                hash_string(binding->logical_port, 0));
+        hmap_insert(&lp_hmap, &hash_node->lp_node,
+                    hash_string(binding->logical_port, 0));
+        hmap_insert(&tk_hmap, &hash_node->tk_node,
+                    hash_int(binding->tunnel_key, 0));
     }
 
     NBREC_LOGICAL_PORT_FOR_EACH(lport, ctx->ovnnb_idl) {
+        struct binding_hash_node *hash_node;
         binding = NULL;
-        HMAP_FOR_EACH_WITH_HASH(hash_node, node,
-                hash_string(lport->name, 0), &bindings_hmap) {
+        HMAP_FOR_EACH_WITH_HASH(hash_node, lp_node,
+                                hash_string(lport->name, 0), &lp_hmap) {
             if (!strcmp(lport->name, hash_node->binding->logical_port)) {
                 binding = hash_node->binding;
                 break;
@@ -474,9 +497,7 @@ set_bindings(struct northd_context *ctx)
             /* We found an existing binding for this logical port.  Update its
              * contents. */
 
-            hmap_remove(&bindings_hmap, &hash_node->node);
-            free(hash_node);
-            hash_node = NULL;
+            hmap_remove(&lp_hmap, &hash_node->lp_node);
 
             if (!macs_equal(binding->mac, binding->n_mac,
                         lport->macs, lport->n_macs)) {
@@ -505,16 +526,30 @@ set_bindings(struct northd_context *ctx)
                 sbrec_bindings_set_tag(binding, lport->tag, lport->n_tag);
             }
 
+            /* Choose unique tunnel_key for the logical port. */
+            static uint16_t next_tunnel_key = 1;
+            while (tunnel_key_in_use(&tk_hmap, next_tunnel_key)) {
+                next_tunnel_key++;
+            }
+            sbrec_bindings_set_tunnel_key(binding, next_tunnel_key++);
+
             sbrec_bindings_set_logical_datapath(binding, logical_datapath);
         }
     }
 
-    HMAP_FOR_EACH_SAFE(hash_node, hash_node_next, node, &bindings_hmap) {
-        hmap_remove(&bindings_hmap, &hash_node->node);
+    struct binding_hash_node *hash_node;
+    HMAP_FOR_EACH (hash_node, lp_node, &lp_hmap) {
+        hmap_remove(&lp_hmap, &hash_node->lp_node);
         sbrec_bindings_delete(hash_node->binding);
+    }
+    hmap_destroy(&lp_hmap);
+
+    struct binding_hash_node *hash_node_next;
+    HMAP_FOR_EACH_SAFE (hash_node, hash_node_next, tk_node, &tk_hmap) {
+        hmap_remove(&tk_hmap, &hash_node->tk_node);
         free(hash_node);
     }
-    hmap_destroy(&bindings_hmap);
+    hmap_destroy(&tk_hmap);
 }
 
 static void
@@ -705,6 +740,7 @@ main(int argc, char *argv[])
     ovsdb_idl_add_column(ovnsb_idl, &sbrec_bindings_col_tag);
     ovsdb_idl_add_column(ovnsb_idl, &sbrec_bindings_col_parent_port);
     ovsdb_idl_add_column(ovnsb_idl, &sbrec_bindings_col_logical_datapath);
+    ovsdb_idl_add_column(ovnsb_idl, &sbrec_bindings_col_tunnel_key);
     ovsdb_idl_add_column(ovnsb_idl, &sbrec_pipeline_col_logical_datapath);
     ovsdb_idl_omit_alert(ovnsb_idl, &sbrec_pipeline_col_logical_datapath);
     ovsdb_idl_add_column(ovnsb_idl, &sbrec_pipeline_col_table_id);
diff --git a/ovn/ovn-sb.ovsschema b/ovn/ovn-sb.ovsschema
index 5f2d1a4..9fd5363 100644
--- a/ovn/ovn-sb.ovsschema
+++ b/ovn/ovn-sb.ovsschema
@@ -47,6 +47,10 @@
             "columns": {
                 "logical_datapath": {"type": "uuid"},
                 "logical_port": {"type": "string"},
+                "tunnel_key": {
+                     "type": {"key": {"type": "integer",
+                                      "minInteger": 1,
+                                      "maxInteger": 65535}}},
                 "parent_port": {"type": {"key": "string", "min": 0, "max": 1}},
                 "tag": {
                      "type": {"key": {"type": "integer",
@@ -57,6 +61,6 @@
                 "mac": {"type": {"key": "string",
                                  "min": 0,
                                  "max": "unlimited"}}},
-            "indexes": [["logical_port"]],
+            "indexes": [["logical_port"], ["tunnel_key"]],
             "isRoot": true}},
     "version": "1.0.0"}
diff --git a/ovn/ovn-sb.xml b/ovn/ovn-sb.xml
index bc648e1..8a4114f 100644
--- a/ovn/ovn-sb.xml
+++ b/ovn/ovn-sb.xml
@@ -665,6 +665,10 @@
       prescribe a particular format for the logical port ID.
     </column>
 
+    <column name="tunnel_key">
+      A number that represents the logical port in tunnel IDs.
+    </column>
+
     <column name="parent_port">
       For containers created inside a VM, this is taken from
       <ref table="Logical_Port" column="parent_name" db="OVN_Northbound"/>
-- 
1.7.10.4




More information about the dev mailing list