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 <b...@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 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev