Processing transit switches and sync between INB, ISB and NB. Signed-off-by: Han Zhou <hz...@ovn.org> --- ic/ovn-ic.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++ northd/ovn-northd.c | 8 ++++ ovn-nb.xml | 10 +++++ ovn-sb.xml | 9 +++++ tests/ovn-ic.at | 41 +++++++++++++++++++ 5 files changed, 181 insertions(+)
diff --git a/ic/ovn-ic.c b/ic/ovn-ic.c index a173a1d..cf9bf96 100644 --- a/ic/ovn-ic.c +++ b/ic/ovn-ic.c @@ -139,11 +139,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 3873665..174847d 100644 --- a/northd/ovn-northd.c +++ b/northd/ovn-northd.c @@ -875,6 +875,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); } diff --git a/ovn-nb.xml b/ovn-nb.xml index ca0b2ee..8ddba22 100644 --- a/ovn-nb.xml +++ b/ovn-nb.xml @@ -354,6 +354,16 @@ </column> </group> + <group title="Interconnection"> + <column name="other_config" key="interconn-ts" + type='{"type": "string"}'> + The <ref table="Transit_Switch" column="name" db="OVN_IC_Northbound"/> + of corresponding transit switch in <ref db="OVN_IC_Northbound"/> + database. This kind of logical switch is created and controlled + by <code>ovn-ic</code>. + </column> + </group> + <group title="Common Columns"> <column name="external_ids"> See <em>External IDs</em> at the beginning of this document. diff --git a/ovn-sb.xml b/ovn-sb.xml index e5fb51a..471310d 100644 --- a/ovn-sb.xml +++ b/ovn-sb.xml @@ -2291,6 +2291,15 @@ tcp.flags = RST; the <ref db="OVN_Northbound"/> database. </column> + <column name="external_ids" key="interconn-ts" type='{"type": "string"}'> + For a logical datapath that represents a logical switch that represents + a transit switch for interconnection, <code>ovn-northd</code> stores in + this key the value of the same <code>interconn-ts</code> key of the <ref + column="external_ids" table="Logical_Switch" db="OVN_Northbound"/> + column of the corresponding <ref table="Logical_Switch" + db="OVN_Northbound"/> row in the <ref db="OVN_Northbound"/> database. + </column> + <group title="Naming"> <p> <code>ovn-northd</code> copies these from the name fields in the <ref diff --git a/tests/ovn-ic.at b/tests/ovn-ic.at index 1e69820..7e6644d 100644 --- a/tests/ovn-ic.at +++ b/tests/ovn-ic.at @@ -27,3 +27,44 @@ availability-zone az3 OVN_CLEANUP_IC([az1], [az2]) AT_CLEANUP + +AT_SETUP([ovn-ic -- transit switch handling]) +AT_SKIP_IF([test $HAVE_PYTHON = no]) + +ovn_init_ic_db +ovn_start az1 + +AT_CHECK([ovn-inbctl ts-add ts1]) +AT_CHECK([ovn-inbctl ts-add ts2]) + +# Check ISB +OVS_WAIT_UNTIL([ovn-isbctl list datapath | grep ts2]) +AT_CHECK([ovn-isbctl -f csv -d bare --no-headings --columns transit_switch list datapath | sort], [0], [dnl +ts1 +ts2 +]) + +# Check NB +AT_CHECK([ovn-nbctl -f csv -d bare --no-headings --columns name list logical_switch | sort], [0], [dnl +ts1 +ts2 +]) + +# Check SB DP key +ts1_key=$(ovn-isbctl -f csv -d bare --no-headings --columns tunnel_key find datapath transit_switch=ts1) +sb_ts1_key=$(ovn-sbctl -f csv -d bare --no-headings --columns tunnel_key find datapath_binding external_ids:interconn-ts=ts1) +AT_CHECK([test $ts1_key = $sb_ts1_key]) + +# Test delete +AT_CHECK([ovn-inbctl ts-del ts1]) +OVS_WAIT_WHILE([ovn-isbctl list datapath | grep ts1]) +AT_CHECK([ovn-isbctl -f csv -d bare --no-headings --columns transit_switch list datapath], [0], [dnl +ts2 +]) +AT_CHECK([ovn-nbctl -f csv -d bare --no-headings --columns name list logical_switch | sort], [0], [dnl +ts2 +]) + +OVN_CLEANUP_IC([az1]) + +AT_CLEANUP -- 2.1.0 _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev