[ovs-dev,RFC,ovn,07/10] ovn-ic: Transit switch controller.
diff mbox series

Message ID 1569623665-77390-8-git-send-email-hzhou8@ebay.com
State New
Headers show
Series
  • OVN Interconnection
Related show

Commit Message

Han Zhou Sept. 27, 2019, 10:34 p.m. UTC
From: Han Zhou <hzhou8@ebay.com>

Processing transit switches and sync between INB, ISB and NB.

Signed-off-by: Han Zhou <hzhou8@ebay.com>
---
 ic/ovn-ic.c         | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 northd/ovn-northd.c |   8 ++++
 2 files changed, 121 insertions(+)

Patch
diff mbox series

diff --git a/ic/ovn-ic.c b/ic/ovn-ic.c
index 59f798d..4de3e17 100644
--- a/ic/ovn-ic.c
+++ b/ic/ovn-ic.c
@@ -126,11 +126,124 @@  az_run(struct ic_context *ctx)
     return NULL;
 }
 
+static uint32_t
+allocate_ts_dp_key(struct hmap *dp_tnlids)
+{
+    static uint32_t hint = OVN_MIN_DP_KEY_GLOBAL;
+    return ovn_allocate_tnlid(dp_tnlids, "transit switch datapath",
+                              OVN_MIN_DP_KEY_GLOBAL, OVN_MAX_DP_KEY_GLOBAL,
+                              &hint);
+}
+
+static void
+ts_run(struct ic_context *ctx)
+{
+    const struct inbrec_transit_switch *ts;
+
+    /* Sync INB TS to AZ NB */
+    if (ctx->ovnnb_txn) {
+        struct shash nb_tses = SHASH_INITIALIZER(&nb_tses);
+        const struct nbrec_logical_switch *ls;
+
+        /* Get current NB Logical_Switch with other_config:interconn-ts */
+        NBREC_LOGICAL_SWITCH_FOR_EACH (ls, ctx->ovnnb_idl) {
+            const char *ts_name = smap_get(&ls->other_config, "interconn-ts");
+            if (ts_name) {
+                shash_add(&nb_tses, ts_name, ls);
+            }
+        }
+
+        /* Create NB Logical_Switch for each TS */
+        INBREC_TRANSIT_SWITCH_FOR_EACH (ts, ctx->ovninb_idl) {
+            ls = shash_find_and_delete(&nb_tses, ts->name);
+            if (!ls) {
+                ls = nbrec_logical_switch_insert(ctx->ovnnb_txn);
+                nbrec_logical_switch_set_name(ls, ts->name);
+                nbrec_logical_switch_update_other_config_setkey(ls,
+                                                                "interconn-ts",
+                                                                ts->name);
+            }
+        }
+
+        /* Delete extra NB Logical_Switch with other_config:interconn-ts */
+        struct shash_node *node;
+        SHASH_FOR_EACH (node, &nb_tses) {
+            nbrec_logical_switch_delete(node->data);
+        }
+        shash_destroy(&nb_tses);
+    }
+
+    struct hmap dp_tnlids = HMAP_INITIALIZER(&dp_tnlids);
+    struct shash isb_dps = SHASH_INITIALIZER(&isb_dps);
+    const struct isbrec_datapath_binding *isb_dp;
+    ISBREC_DATAPATH_BINDING_FOR_EACH (isb_dp, ctx->ovnisb_idl) {
+        shash_add(&isb_dps, isb_dp->transit_switch, isb_dp);
+        ovn_add_tnlid(&dp_tnlids, isb_dp->tunnel_key);
+    }
+
+    /* Sync ISB TS tunnel key to AZ SB datapath.  (AZ SB datapath is created by
+     * northd.) */
+    if (ctx->ovnsb_txn) {
+        const struct sbrec_datapath_binding *sb_dp;
+        SBREC_DATAPATH_BINDING_FOR_EACH (sb_dp, ctx->ovnsb_idl) {
+            const char *ts_name = smap_get(&sb_dp->external_ids,
+                                           "interconn-ts");
+            if (ts_name) {
+                isb_dp = shash_find_data(&isb_dps, ts_name);
+                if (!isb_dp) {
+                    VLOG_DBG("SB datapath "UUID_FMT" with interconn-ts %s not "
+                             "found in ISB, ignore.",
+                             UUID_ARGS(&sb_dp->header_.uuid),
+                             ts_name);
+                    continue;
+                }
+                sbrec_datapath_binding_set_tunnel_key(sb_dp,
+                                                      isb_dp->tunnel_key);
+            }
+        }
+    }
+
+    /* Sync TS between INB and ISB.  This is performed after syncing with AZ
+     * SB, to avoid uncommitted ISB datapath tunnel key to be synced back to
+     * AZ. */
+    if (ctx->ovnisb_txn) {
+        /* Create ISB Datapath_Binding */
+        INBREC_TRANSIT_SWITCH_FOR_EACH (ts, ctx->ovninb_idl) {
+            isb_dp = shash_find_and_delete(&isb_dps, ts->name);
+            if (!isb_dp) {
+                /* Allocate tunnel key */
+                int64_t dp_key = allocate_ts_dp_key(&dp_tnlids);
+                if (!dp_key) {
+                    continue;
+                }
+
+                isb_dp = isbrec_datapath_binding_insert(ctx->ovnisb_txn);
+                isbrec_datapath_binding_set_transit_switch(isb_dp, ts->name);
+                isbrec_datapath_binding_set_tunnel_key(isb_dp, dp_key);
+            }
+        }
+
+        /* Delete extra ISB Datapath_Binding */
+        struct shash_node *node;
+        SHASH_FOR_EACH (node, &isb_dps) {
+            isbrec_datapath_binding_delete(node->data);
+        }
+    }
+    ovn_destroy_tnlids(&dp_tnlids);
+    shash_destroy(&isb_dps);
+}
+
 static void
 ovn_db_run(struct ic_context *ctx)
 {
     const struct isbrec_availability_zone *az = az_run(ctx);
     VLOG_DBG("Availability zone: %s", az ? az->name : "not created yet.");
+
+    if (!az) {
+        return;
+    }
+
+    ts_run(ctx);
 }
 
 static void
diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
index f99adfb..32d70f8 100644
--- a/northd/ovn-northd.c
+++ b/northd/ovn-northd.c
@@ -823,6 +823,14 @@  ovn_datapath_update_external_ids(struct ovn_datapath *od)
     if (name2 && name2[0]) {
         smap_add(&ids, "name2", name2);
     }
+
+    /* Set interconn-ts. */
+    if (od->nbs) {
+        const char *ts = smap_get(&od->nbs->other_config, "interconn-ts");
+        if (ts) {
+            smap_add(&ids, "interconn-ts", ts);
+        }
+    }
     sbrec_datapath_binding_set_external_ids(od->sb, &ids);
     smap_destroy(&ids);
 }