On 6/11/26 12:57 AM, Numan Siddique wrote:
> On Sun, May 17, 2026 at 11:20 PM Sragdhara Datta Chaudhuri <
> [email protected]> wrote:
>
>> Advertise address_set from one AZ to others via ovn-ic.
>> The address sets from SB are advertised to the IC-SB Address_Set.
>> The address sets from IC SB that belong to remote AZ are synced
>> to the local NB Address_Set.
>>
>> A new table Address_Set has been added to IC-SB.
>> "Address_Set": {
>> "columns": {
>> "name": {"type": "string"},
>> "addresses": {"type": {"key": "string",
>> "min": 0,
>> "max": "unlimited"}},
>> "availability_zone": {"type": {"key": {"type": "uuid",
>> "refTable": "Availability_Zone"}}},
>> "external_ids": {
>> "type": {"key": "string", "value": "string",
>> "min": 0, "max": "unlimited"}}},
>> "indexes": [["name"]],
>> "isRoot": true}
>> }
>>
>> New "options" field has been added to NB Address_Set table.
>> ic-adv - A boolean value that enables advertisement of this
>> Address_Set to IC-SB. Default is false.
>> New "options" field has been added to SB Address_Set table.
>> The options from NB Address_Set gets synced to the SB entry.
>>
>> Two new nb_global options have been added:
>> ic-as-adv - If this is set to true, the Address_Sets in this AZ that have
>> option ic-adv set to true get advertised to the IC-SB.
>> Default is false.
>> ic-as-learn - If this is set to true, the Address_Sets in IC-SB get
>> synced to the NB Address_Set table of this AZ. Default
>> value of the option is false. The synced address_sets
>> would have external-id "ic-learnt" set to true.
>>
>> The existing northd code that syncs Address_Set from NB to SB has been
>> enhanced to sync "options".
>>
>> New logic has been added in ovn-ic to sync address sets with IC-SB.
>> Advertise logic (from SB to IC-SB):
>> - Each SB address set that needs to be advertised (ic-adv option set),
>> check if it is already present in IC-SB. If not, create new entry in
>> IC-SB. Otherwise sync addresses from local address set to IC-SB entry.
>> - Delete extra address sets in IC-SB that were earlier learnt from this
>> AZ, but is no longer present, or not enabled for advertisement.
>>
>> Learning logic (from IC-SB to NB):
>> - For each NB Address set entries that were earlier learnt from IC-SB
>> (external-id "ic-learnt" set to true), check if it is still present
>> in IC-SB. If not, delete local entry in NB. If yes, sync addresses
>> from IC-SB to NB.
>> - Any remote address sets in IC-SB (AZ not same as local AZ) that is not
>> present in local AZ, create local entry in NB with external-id
>> "ic-learnt" set to true.
>>
>> Signed-off-by: Sragdhara Datta Chaudhuri <[email protected]>
>> Acked-by: Priyankar Jain <[email protected]>
>>
>
> Hi Sragdhara,
>
Hi Sragdhara, Numan,
> What is the motivation for this patch ?
> Technically speaking CMS can create the Address sets on the desired AZ NB
> DBs right ?
>
> Is the main motivation the operational ease for CMS ?
>
+1 to Numan's question.
Also, if we sync Address_Sets why not also sync Port_Groups?
> Thanks
> Numan
>
Regards,
Dumitru
> ---
>> ic/inc-proc-ic.c | 12 ++-
>> ic/ovn-ic.c | 188 ++++++++++++++++++++++++++++++++++++++++++++
>> northd/en-sync-sb.c | 35 +++++++--
>> ovn-ic-sb.ovsschema | 17 +++-
>> ovn-ic-sb.xml | 26 ++++++
>> ovn-nb.ovsschema | 9 ++-
>> ovn-nb.xml | 31 ++++++++
>> ovn-sb.ovsschema | 9 ++-
>> ovn-sb.xml | 4 +
>> tests/ovn-ic.at | 172 ++++++++++++++++++++++++++++++++++++++++
>> 10 files changed, 486 insertions(+), 17 deletions(-)
>>
>> diff --git a/ic/inc-proc-ic.c b/ic/inc-proc-ic.c
>> index 2c0420292..bbcbcdd17 100644
>> --- a/ic/inc-proc-ic.c
>> +++ b/ic/inc-proc-ic.c
>> @@ -41,7 +41,8 @@ VLOG_DEFINE_THIS_MODULE(inc_proc_ic);
>> NB_NODE(logical_switch, "logical_switch") \
>> NB_NODE(logical_switch_port, "logical_switch_port") \
>> NB_NODE(load_balancer, "load_balancer") \
>> - NB_NODE(load_balancer_group, "load_balancer_group")
>> + NB_NODE(load_balancer_group, "load_balancer_group") \
>> + NB_NODE(address_set, "address_set")
>>
>> enum nb_engine_node {
>> #define NB_NODE(NAME, NAME_STR) NB_##NAME,
>> @@ -66,7 +67,8 @@ VLOG_DEFINE_THIS_MODULE(inc_proc_ic);
>> SB_NODE(datapath_binding, "datapath_binding") \
>> SB_NODE(port_binding, "port_binding") \
>> SB_NODE(service_monitor, "service_monitor") \
>> - SB_NODE(learned_route, "learned_route")
>> + SB_NODE(learned_route, "learned_route") \
>> + SB_NODE(address_set, "address_set")
>>
>> enum sb_engine_node {
>> #define SB_NODE(NAME, NAME_STR) SB_##NAME,
>> @@ -114,7 +116,8 @@ VLOG_DEFINE_THIS_MODULE(inc_proc_ic);
>> ICSB_NODE(datapath_binding, "datapath_binding") \
>> ICSB_NODE(encap, "encap") \
>> ICSB_NODE(gateway, "gateway") \
>> - ICSB_NODE(port_binding, "port_binding")
>> + ICSB_NODE(port_binding, "port_binding") \
>> + ICSB_NODE(address_set, "address_set")
>>
>> enum icsb_engine_node {
>> #define ICSB_NODE(NAME, NAME_STR) ICSB_##NAME,
>> @@ -176,6 +179,7 @@ void inc_proc_ic_init(struct ovsdb_idl_loop *nb,
>> engine_add_input(&en_ic, &en_nb_logical_switch_port, NULL);
>> engine_add_input(&en_ic, &en_nb_load_balancer, NULL);
>> engine_add_input(&en_ic, &en_nb_load_balancer_group, NULL);
>> + engine_add_input(&en_ic, &en_nb_address_set, NULL);
>>
>> engine_add_input(&en_ic, &en_sb_sb_global, NULL);
>> engine_add_input(&en_ic, &en_sb_chassis, NULL);
>> @@ -184,6 +188,7 @@ void inc_proc_ic_init(struct ovsdb_idl_loop *nb,
>> engine_add_input(&en_ic, &en_sb_port_binding, NULL);
>> engine_add_input(&en_ic, &en_sb_service_monitor, NULL);
>> engine_add_input(&en_ic, &en_sb_learned_route, NULL);
>> + engine_add_input(&en_ic, &en_sb_address_set, NULL);
>>
>> engine_add_input(&en_ic, &en_icnb_ic_nb_global, NULL);
>> engine_add_input(&en_ic, &en_icnb_transit_switch, NULL);
>> @@ -198,6 +203,7 @@ void inc_proc_ic_init(struct ovsdb_idl_loop *nb,
>> engine_add_input(&en_ic, &en_icsb_gateway, NULL);
>> engine_add_input(&en_ic, &en_icsb_route, NULL);
>> engine_add_input(&en_ic, &en_icsb_datapath_binding, NULL);
>> + engine_add_input(&en_ic, &en_icsb_address_set, NULL);
>>
>> struct engine_arg engine_arg = {
>> .nb_idl = nb->idl,
>> diff --git a/ic/ovn-ic.c b/ic/ovn-ic.c
>> index ba9490658..c1718cca8 100644
>> --- a/ic/ovn-ic.c
>> +++ b/ic/ovn-ic.c
>> @@ -526,6 +526,173 @@ sync_sb_gw_to_isb(struct ic_context *ctx,
>> free(isb_encaps);
>> }
>>
>> +static void
>> +nb_addr_set_apply_diff(const void *arg, const char *item, bool add)
>> +{
>> + const struct nbrec_address_set *as = arg;
>> + if (add) {
>> + nbrec_address_set_update_addresses_addvalue(as, item);
>> + } else {
>> + nbrec_address_set_update_addresses_delvalue(as, item);
>> + }
>> +}
>> +
>> +static void
>> +update_nb_addr_set(const struct icsbrec_address_set *icsb_as,
>> + const struct nbrec_address_set *nb_as)
>> +{
>> + struct sorted_array nb_addrs =
>> + sorted_array_from_dbrec(nb_as, addresses);
>> + struct sorted_array icsb_addrs =
>> + sorted_array_from_dbrec(icsb_as, addresses);
>> + sorted_array_apply_diff(&icsb_addrs, &nb_addrs,
>> + nb_addr_set_apply_diff, nb_as);
>> + sorted_array_destroy(&icsb_addrs);
>> + sorted_array_destroy(&nb_addrs);
>> +}
>> +
>> +static void
>> +icsb_addr_set_apply_diff(const void *arg, const char *item, bool add)
>> +{
>> + const struct icsbrec_address_set *as = arg;
>> + if (add) {
>> + icsbrec_address_set_update_addresses_addvalue(as, item);
>> + } else {
>> + icsbrec_address_set_update_addresses_delvalue(as, item);
>> + }
>> +}
>> +
>> +static void
>> +update_icsb_addr_set(struct sorted_array *nb_addrs,
>> + const struct icsbrec_address_set *icsb_as)
>> +{
>> + struct sorted_array icsb_addrs =
>> + sorted_array_from_dbrec(icsb_as, addresses);
>> + sorted_array_apply_diff(nb_addrs, &icsb_addrs,
>> + icsb_addr_set_apply_diff, icsb_as);
>> + sorted_array_destroy(&icsb_addrs);
>> +}
>> +
>> +static void
>> +sync_addr_set_to_icsb(struct ovsdb_idl_txn *ovnisb_txn,
>> + const struct sbrec_address_set *sb_as,
>> + const struct icsbrec_address_set *icsb_as,
>> + const struct icsbrec_availability_zone *az)
>> +{
>> + struct sorted_array addrs =
>> + sorted_array_from_dbrec(sb_as, addresses);
>> + if (!icsb_as) {
>> + icsb_as = icsbrec_address_set_insert(ovnisb_txn);
>> + icsbrec_address_set_set_name(icsb_as, sb_as->name);
>> + icsbrec_address_set_set_availability_zone(icsb_as, az);
>> + icsbrec_address_set_set_addresses(icsb_as, addrs.arr, addrs.n);
>> + } else {
>> + update_icsb_addr_set(&addrs, icsb_as);
>> + }
>> + sorted_array_destroy(&addrs);
>> +}
>> +
>> +static void
>> +sync_addr_set_from_icsb(struct ovsdb_idl_txn *ovnnb_txn,
>> + const struct icsbrec_address_set *icsb_as)
>> +{
>> + struct nbrec_address_set *nb_as;
>> + struct sorted_array addrs =
>> + sorted_array_from_dbrec(icsb_as, addresses);
>> +
>> + nb_as = nbrec_address_set_insert(ovnnb_txn);
>> + nbrec_address_set_set_name(nb_as, icsb_as->name);
>> + nbrec_address_set_update_external_ids_setkey(nb_as, "ic-learnt",
>> "true");
>> + nbrec_address_set_set_addresses(nb_as, addrs.arr, addrs.n);
>> + sorted_array_destroy(&addrs);
>> +}
>> +
>> +static void
>> +address_set_run(struct ic_context *ctx)
>> +{
>> + if (!ctx->ovnisb_unlocked_txn || !ctx->ovnnb_txn || !ctx->ovnsb_txn) {
>> + return;
>> + }
>> +
>> + struct shash ic_local_as = SHASH_INITIALIZER(&ic_local_as);
>> + struct shash ic_remote_as = SHASH_INITIALIZER(&ic_remote_as);
>> + const struct icsbrec_address_set *ic_as;
>> + ICSBREC_ADDRESS_SET_FOR_EACH (ic_as, ctx->ovnisb_unlocked_idl) {
>> + if (ic_as->availability_zone == ctx->runned_az) {
>> + shash_add(&ic_local_as, ic_as->name, ic_as);
>> + } else {
>> + shash_add(&ic_remote_as, ic_as->name, ic_as);
>> + }
>> + }
>> +
>> + const struct nbrec_nb_global *nb_global =
>> + nbrec_nb_global_first(ctx->ovnnb_idl);
>> + ovs_assert(nb_global);
>> + bool global_learn = smap_get_bool(&nb_global->options, "ic-as-learn",
>> + false);
>> + bool global_adv = smap_get_bool(&nb_global->options, "ic-as-adv",
>> false);
>> +
>> + /* Advertise address set - from SB to IC-SB:
>> + * - Each SB address set that needs to be advertised (ic-adv option
>> set),
>> + * check if it is already present in IC-SB. If not, create new entry
>> in
>> + * IC-SB. Otherwise sync addresses from local address set to IC-SB
>> entry.
>> + * - Delete extra address sets in IC-SB that were earlier learnt from
>> this
>> + * AZ, but is no longer present, or not enabled for advertisement.
>> + */
>> + if (global_adv) {
>> + const struct sbrec_address_set *sb_as;
>> + SBREC_ADDRESS_SET_FOR_EACH (sb_as, ctx->ovnsb_idl) {
>> + if (smap_get_bool(&sb_as->options, "ic-adv", false)) {
>> + const struct icsbrec_address_set *icsb_as;
>> + icsb_as = shash_find_and_delete(&ic_local_as,
>> sb_as->name);
>> + sync_addr_set_to_icsb(ctx->ovnisb_unlocked_txn, sb_as,
>> icsb_as,
>> + ctx->runned_az);
>> + }
>> + }
>> + }
>> + struct shash_node *node;
>> + SHASH_FOR_EACH (node, &ic_local_as) {
>> + icsbrec_address_set_delete(node->data);
>> + }
>> + shash_destroy(&ic_local_as);
>> +
>> + /* Learn address set - from IC-SB to NB:
>> + * - For each NB Address set entries that were earlier learnt from
>> IC-SB
>> + * (external-id "ic-learnt" set to true), check if it is still present
>> + * in IC-SB. If not, delete local entry in NB. If yes, sync addresses
>> + * from IC-SB to NB.
>> + * - Any remote address sets in IC-SB (AZ not same as local AZ) that
>> is not
>> + * present in local AZ, create local entry in NB with external-id
>> + * "ic-learnt" set to true.
>> + */
>> + const struct nbrec_address_set *nb_as;
>> + NBREC_ADDRESS_SET_FOR_EACH (nb_as, ctx->ovnnb_idl) {
>> + const struct icsbrec_address_set *icsb_as;
>> + icsb_as = shash_find_and_delete(&ic_remote_as, nb_as->name);
>> + if (smap_get_bool(&nb_as->external_ids, "ic-learnt", false)) {
>> + if (!icsb_as || !global_learn) {
>> + nbrec_address_set_delete(nb_as);
>> + } else {
>> + update_nb_addr_set(icsb_as, nb_as);
>> + }
>> + }
>> + }
>> +
>> + if (global_learn) {
>> + SHASH_FOR_EACH (node, &ic_remote_as) {
>> + /* In case local address-set with same name exists, we
>> + * will not overwrite it because such address sets are already
>> + * removed from ic_remote_as in the loop above.
>> + */
>> + if (node->data) {
>> + sync_addr_set_from_icsb(ctx->ovnnb_txn, node->data);
>> + }
>> + }
>> + }
>> + shash_destroy(&ic_remote_as);
>> +}
>> +
>> +
>> static void
>> gateway_run(struct ic_context *ctx)
>> {
>> @@ -3199,6 +3366,7 @@ ovn_db_run(struct ic_context *ctx)
>> port_binding_run(ctx);
>> route_run(ctx);
>> sync_service_monitor(ctx);
>> + address_set_run(ctx);
>>
>> ovn_destroy_tnlids(&dp_tnlids);
>> shash_destroy(&isb_ts_dps);
>> @@ -3536,6 +3704,17 @@ main(int argc, char *argv[])
>> ovsdb_idl_track_add_column(ovnnb_idl_loop.idl,
>>
>> &nbrec_load_balancer_group_col_load_balancer);
>>
>> + ovsdb_idl_add_table(ovnnb_idl_loop.idl, &nbrec_table_address_set);
>> + ovsdb_idl_track_add_column(ovnnb_idl_loop.idl,
>> + &nbrec_address_set_col_name);
>> + ovsdb_idl_track_add_column(ovnnb_idl_loop.idl,
>> + &nbrec_address_set_col_addresses);
>> + ovsdb_idl_track_add_column(ovnnb_idl_loop.idl,
>> + &nbrec_address_set_col_options);
>> + ovsdb_idl_track_add_column(ovnnb_idl_loop.idl,
>> + &nbrec_address_set_col_external_ids);
>> +
>> +
>> /* ovn-sb db. */
>> struct ovsdb_idl_loop ovnsb_idl_loop = OVSDB_IDL_LOOP_INITIALIZER(
>> ovsdb_idl_create(ovnsb_db, &sbrec_idl_class, false, true));
>> @@ -3621,6 +3800,15 @@ main(int argc, char *argv[])
>> &sbrec_learned_route_col_ip_prefix);
>> ovsdb_idl_track_add_column(ovnsb_idl_loop.idl,
>> &sbrec_learned_route_col_datapath);
>> +
>> + ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_address_set);
>> + ovsdb_idl_track_add_column(ovnsb_idl_loop.idl,
>> + &sbrec_address_set_col_name);
>> + ovsdb_idl_track_add_column(ovnsb_idl_loop.idl,
>> + &sbrec_address_set_col_addresses);
>> + ovsdb_idl_track_add_column(ovnsb_idl_loop.idl,
>> + &sbrec_address_set_col_options);
>> +
>> /* Create IDL indexes */
>> struct ovsdb_idl_index *nbrec_ls_by_name
>> = ovsdb_idl_index_create1(ovnnb_idl_loop.idl,
>> diff --git a/northd/en-sync-sb.c b/northd/en-sync-sb.c
>> index 0b2a85b3b..b3d96af16 100644
>> --- a/northd/en-sync-sb.c
>> +++ b/northd/en-sync-sb.c
>> @@ -43,7 +43,8 @@ VLOG_DEFINE_THIS_MODULE(en_sync_to_sb);
>>
>> static void sync_addr_set(struct ovsdb_idl_txn *ovnsb_txn, const char
>> *name,
>> struct sorted_array *addresses,
>> - struct shash *sb_address_sets);
>> + struct shash *sb_address_sets,
>> + const struct smap *options);
>> static void sync_addr_sets(struct ovsdb_idl_txn *ovnsb_txn,
>> const struct nbrec_address_set_table *,
>> const struct nbrec_port_group_table *,
>> @@ -118,6 +119,18 @@ en_sync_to_sb_addr_set_cleanup(void *data OVS_UNUSED)
>>
>> }
>>
>> +static void
>> +sync_address_set_options(const struct sbrec_address_set *sb_addr_set,
>> + const struct smap *nb_options)
>> +{
>> + if (!smap_equal(&sb_addr_set->options, nb_options)) {
>> + struct smap new_options;
>> + smap_clone(&new_options, nb_options);
>> + sbrec_address_set_set_options(sb_addr_set, &new_options);
>> + smap_destroy(&new_options);
>> + }
>> +}
>> +
>> enum engine_input_handler_result
>> sync_to_sb_addr_set_nb_address_set_handler(struct engine_node *node,
>> void *data OVS_UNUSED)
>> @@ -153,6 +166,7 @@ sync_to_sb_addr_set_nb_address_set_handler(struct
>> engine_node *node,
>> sorted_array_from_dbrec(nb_addr_set, addresses);
>> update_sb_addr_set(&addrs, sb_addr_set);
>> sorted_array_destroy(&addrs);
>> + sync_address_set_options(sb_addr_set, &nb_addr_set->options);
>> }
>>
>> return EN_HANDLED_UNCHANGED;
>> @@ -449,7 +463,8 @@ sync_to_sb_pb_lr_stateful_handler(struct engine_node
>> *node,
>> static void
>> sync_addr_set(struct ovsdb_idl_txn *ovnsb_txn, const char *name,
>> struct sorted_array *addresses,
>> - struct shash *sb_address_sets)
>> + struct shash *sb_address_sets,
>> + const struct smap *options)
>> {
>> const struct sbrec_address_set *sb_address_set;
>> sb_address_set = shash_find_and_delete(sb_address_sets,
>> @@ -462,6 +477,9 @@ sync_addr_set(struct ovsdb_idl_txn *ovnsb_txn, const
>> char *name,
>> } else {
>> update_sb_addr_set(addresses, sb_address_set);
>> }
>> + if (options) {
>> + sync_address_set_options(sb_address_set, options);
>> + }
>> }
>>
>> /* OVN_Southbound Address_Set table contains same records as in north
>> @@ -500,7 +518,7 @@ sync_addr_sets(struct ovsdb_idl_txn *ovnsb_txn,
>> const char *svc_macs[] = {svc_monitor_macp, svc_monitor_macp_dst};
>> struct sorted_array svc =
>> sorted_array_from_unsorted(svc_macs, ARRAY_SIZE(svc_macs), false);
>> - sync_addr_set(ovnsb_txn, "svc_monitor_mac", &svc, &sb_address_sets);
>> + sync_addr_set(ovnsb_txn, "svc_monitor_mac", &svc, &sb_address_sets,
>> NULL);
>> sorted_array_destroy(&svc);
>>
>> /* sync port group generated address sets first */
>> @@ -519,9 +537,9 @@ sync_addr_sets(struct ovsdb_idl_txn *ovnsb_txn,
>> sorted_array_from_svec(&ipv6_addrs);
>>
>> sync_addr_set(ovnsb_txn, ipv4_addrs_name,
>> - &ipv4_addrs_sorted, &sb_address_sets);
>> + &ipv4_addrs_sorted, &sb_address_sets, NULL);
>> sync_addr_set(ovnsb_txn, ipv6_addrs_name,
>> - &ipv6_addrs_sorted, &sb_address_sets);
>> + &ipv6_addrs_sorted, &sb_address_sets, NULL);
>> sorted_array_destroy(&ipv4_addrs_sorted);
>> sorted_array_destroy(&ipv6_addrs_sorted);
>> svec_destroy(&ipv4_addrs);
>> @@ -544,7 +562,7 @@ sync_addr_sets(struct ovsdb_idl_txn *ovnsb_txn,
>> &lr_stateful_rec->lb_ips->ips_v4_reachable);
>>
>> sync_addr_set(ovnsb_txn, ipv4_addrs_name,
>> - &ipv4_addrs_sorted, &sb_address_sets);
>> + &ipv4_addrs_sorted, &sb_address_sets, NULL);
>> sorted_array_destroy(&ipv4_addrs_sorted);
>> free(ipv4_addrs_name);
>> }
>> @@ -556,7 +574,7 @@ sync_addr_sets(struct ovsdb_idl_txn *ovnsb_txn,
>> &lr_stateful_rec->lb_ips->ips_v6_reachable);
>>
>> sync_addr_set(ovnsb_txn, ipv6_addrs_name,
>> - &ipv6_addrs_sorted, &sb_address_sets);
>> + &ipv6_addrs_sorted, &sb_address_sets, NULL);
>> sorted_array_destroy(&ipv6_addrs_sorted);
>> free(ipv6_addrs_name);
>> }
>> @@ -570,7 +588,8 @@ sync_addr_sets(struct ovsdb_idl_txn *ovnsb_txn,
>> struct sorted_array addrs =
>> sorted_array_from_dbrec(nb_address_set, addresses);
>> sync_addr_set(ovnsb_txn, nb_address_set->name,
>> - &addrs, &sb_address_sets);
>> + &addrs, &sb_address_sets,
>> + &nb_address_set->options);
>> sorted_array_destroy(&addrs);
>> }
>>
>> diff --git a/ovn-ic-sb.ovsschema b/ovn-ic-sb.ovsschema
>> index e0e0fef5e..dd1b2533c 100644
>> --- a/ovn-ic-sb.ovsschema
>> +++ b/ovn-ic-sb.ovsschema
>> @@ -1,7 +1,7 @@
>> {
>> "name": "OVN_IC_Southbound",
>> - "version": "2.5.0",
>> - "cksum": "1892994110 9713",
>> + "version": "2.6.0",
>> + "cksum": "3333694935 10343",
>> "tables": {
>> "IC_SB_Global": {
>> "columns": {
>> @@ -192,6 +192,19 @@
>> "external_ids": {
>> "type": {"key": "string", "value": "string",
>> "min": 0, "max": "unlimited"}}},
>> + "isRoot": true},
>> + "Address_Set": {
>> + "columns": {
>> + "name": {"type": "string"},
>> + "addresses": {"type": {"key": "string",
>> + "min": 0,
>> + "max": "unlimited"}},
>> + "availability_zone": {"type": {"key": {"type": "uuid",
>> + "refTable": "Availability_Zone"}}},
>> + "external_ids": {
>> + "type": {"key": "string", "value": "string",
>> + "min": 0, "max": "unlimited"}}},
>> + "indexes": [["name"]],
>> "isRoot": true}
>> }
>> }
>> diff --git a/ovn-ic-sb.xml b/ovn-ic-sb.xml
>> index f30760100..4fe491fac 100644
>> --- a/ovn-ic-sb.xml
>> +++ b/ovn-ic-sb.xml
>> @@ -775,4 +775,30 @@
>> Copy from source SBDB record.
>> </column>
>> </table>
>> +
>> + <table name="Address_Set" title="Address Sets">
>> + <p>
>> + Each row in this table represents an Address_Set advertised.
>> + </p>
>> +
>> + <column name="name">
>> + A name for the address set. Names are ASCII and must match
>> + <code>[a-zA-Z_.][a-zA-Z_.0-9]*</code>.
>> + </column>
>> +
>> + <column name="addresses">
>> + The set of addresses in string form.
>> + </column>
>> +
>> + <column name="availability_zone">
>> + The availability zone that has advertised the Address_Set.
>> + </column>
>> +
>> + <group title="Common Columns">
>> + <column name="external_ids">
>> + See <em>External IDs</em> at the beginning of this document.
>> + </column>
>> + </group>
>> + </table>
>> +
>> </database>
>> diff --git a/ovn-nb.ovsschema b/ovn-nb.ovsschema
>> index e5945b831..00909fff4 100644
>> --- a/ovn-nb.ovsschema
>> +++ b/ovn-nb.ovsschema
>> @@ -1,7 +1,7 @@
>> {
>> "name": "OVN_Northbound",
>> - "version": "7.18.0",
>> - "cksum": "1537030958 45190",
>> + "version": "7.18.1",
>> + "cksum": "2442107800 45407",
>> "tables": {
>> "NB_Global": {
>> "columns": {
>> @@ -292,6 +292,11 @@
>> "addresses": {"type": {"key": "string",
>> "min": 0,
>> "max": "unlimited"}},
>> + "options": {
>> + "type": {"key": "string",
>> + "value": "string",
>> + "min": 0,
>> + "max": "unlimited"}},
>> "external_ids": {
>> "type": {"key": "string", "value": "string",
>> "min": 0, "max": "unlimited"}}},
>> diff --git a/ovn-nb.xml b/ovn-nb.xml
>> index 2e8a6a6f1..d98f3244d 100644
>> --- a/ovn-nb.xml
>> +++ b/ovn-nb.xml
>> @@ -583,6 +583,25 @@
>> </column>
>> </group>
>>
>> + <group title="Options for interconnection address_set
>> advertisement">
>> + <p>
>> + These options control whether address_sets propagate from one
>> OVN
>> + deployment to another via the global <ref
>> db="OVN_IC_Southbound"/>.
>> + </p>
>> +
>> + <column name="options" key="ic-as-adv">
>> + A boolean value that enables address_set advertisement to the
>> global
>> + <ref db="OVN_IC_Southbound"/> database. Default is
>> + <code>false</code>.
>> + </column>
>> +
>> + <column name="options" key="ic-as-learn">
>> + A boolean value that enables address_set learning from the
>> global
>> + <ref db="OVN_IC_Southbound"/> database. Default is
>> + <code>false</code>.
>> + </column>
>> + </group>
>> +
>> </group>
>>
>> <group title="Connection Options">
>> @@ -2409,6 +2428,18 @@
>> See <em>External IDs</em> at the beginning of this document.
>> </column>
>> </group>
>> +
>> + <group title="Common options">
>> + <column name="options">
>> + This column provides general key/value settings. The supported
>> + options are described individually below.
>> + </column>
>> +
>> + <column name="options" key="ic-adv">
>> + A boolean value that enables advertisement of this Address_Set to
>> + the global OVN_IC_Southbound database. Default is false.
>> + </column>
>> + </group>
>> </table>
>>
>> <table name="Port_Group" title="Port Groups">
>> diff --git a/ovn-sb.ovsschema b/ovn-sb.ovsschema
>> index d9a91739c..7057178ce 100644
>> --- a/ovn-sb.ovsschema
>> +++ b/ovn-sb.ovsschema
>> @@ -1,7 +1,7 @@
>> {
>> "name": "OVN_Southbound",
>> "version": "21.8.0",
>> - "cksum": "614397313 36713",
>> + "cksum": "2227484712 36930",
>> "tables": {
>> "SB_Global": {
>> "columns": {
>> @@ -77,7 +77,12 @@
>> "name": {"type": "string"},
>> "addresses": {"type": {"key": "string",
>> "min": 0,
>> - "max": "unlimited"}}},
>> + "max": "unlimited"}},
>> + "options": {
>> + "type": {"key": "string",
>> + "value": "string",
>> + "min": 0,
>> + "max": "unlimited"}}},
>> "indexes": [["name"]],
>> "isRoot": true},
>> "Port_Group": {
>> diff --git a/ovn-sb.xml b/ovn-sb.xml
>> index 46568da62..51c16600d 100644
>> --- a/ovn-sb.xml
>> +++ b/ovn-sb.xml
>> @@ -588,6 +588,10 @@
>>
>> <column name="name"/>
>> <column name="addresses"/>
>> + <group title="Common Columns">
>> + <column name="options">
>> + </column>
>> + </group>
>> </table>
>>
>> <table name="Port_Group" title="Port Groups">
>> diff --git a/tests/ovn-ic.at b/tests/ovn-ic.at
>> index 0fa7c4f29..45f64e551 100644
>> --- a/tests/ovn-ic.at
>> +++ b/tests/ovn-ic.at
>> @@ -487,6 +487,178 @@ OVN_CLEANUP_IC([az1], [az2])
>> AT_CLEANUP
>> ])
>>
>> +OVN_FOR_EACH_NORTHD([
>> +AT_SETUP([ovn-ic -- address-set sync])
>> +
>> +ovn_init_ic_db
>> +ovn-ic-nbctl ts-add ts1
>> +
>> +for i in 1 2; do
>> + ovn_start az$i
>> + ovn_as az$i
>> + check ovn-ic-nbctl --wait=sb sync
>> + # Enable address-set learning at AZ level
>> + check ovn-nbctl set nb_global . options:ic-as-learn=true
>> + # Enable address-set advertising at AZ level
>> + check ovn-nbctl set nb_global . options:ic-as-adv=true
>> +
>> + # Create address-set to advertise
>> + check_uuid ovn-nbctl create Address_Set name=az$i-as1
>> addresses=\"$i.1.1.1\",\"$i.1.1.2\" options:ic-adv=true
>> +done
>> +
>> +wait_row_count ic-sb:Address_Set 2
>> +AT_CHECK([ovn-ic-sbctl --columns=addresses find Address_Set
>> name=az1-as1], [0], [dnl
>> +addresses : [["1.1.1.1", "1.1.1.2"]]
>> +])
>> +
>> +AT_CHECK([ovn-ic-sbctl --columns=addresses find Address_Set
>> name=az2-as1], [0], [dnl
>> +addresses : [["2.1.1.1", "2.1.1.2"]]
>> +])
>> +
>> +for i in 1 2; do
>> + OVS_WAIT_UNTIL([ovn_as az$i ovn-nbctl list Address_Set | grep learnt])
>> +done
>> +
>> +AT_CHECK([ovn_as az1 ovn-nbctl --columns=addresses,external_ids list
>> Address_Set az2-as1], [0], [dnl
>> +addresses : [["2.1.1.1", "2.1.1.2"]]
>> +external_ids : {ic-learnt="true"}
>> +])
>> +
>> +AT_CHECK([ovn_as az2 ovn-nbctl --columns=addresses,external_ids list
>> Address_Set az1-as1], [0], [dnl
>> +addresses : [["1.1.1.1", "1.1.1.2"]]
>> +external_ids : {ic-learnt="true"}
>> +])
>> +
>> +# Update AZ1 address_set (add 2 new IPs and delete one) and check it is
>> synced to IC and AZ2.
>> +ovn_as az1 ovn-nbctl set Address_Set az1-as1
>> addresses=\"1.1.1.1\",\"1.1.1.3\",\"1.1.1.4\"
>> +AT_CHECK([ovn-ic-sbctl --columns=addresses find Address_Set
>> name=az1-as1], [0], [dnl
>> +addresses : [["1.1.1.1", "1.1.1.3", "1.1.1.4"]]
>> +])
>> +AT_CHECK([ovn_as az2 ovn-nbctl --columns=addresses,external_ids list
>> Address_Set az1-as1], [0], [dnl
>> +addresses : [["1.1.1.1", "1.1.1.3", "1.1.1.4"]]
>> +external_ids : {ic-learnt="true"}
>> +])
>> +
>> +# Add 2 new address-sets in AZ1 - one to advertise, another not to.
>> +ovn_as az1 ovn-nbctl create Address_Set name=az1-as2
>> addresses=\"1.1.2.1\",\"1.1.2.2\" options:ic-adv=true
>> +ovn_as az1 ovn-nbctl create Address_Set name=az1-as3
>> addresses=\"1.1.3.1\",\"1.1.3.2\"
>> +wait_row_count ic-sb:Address_Set 3
>> +AT_CHECK([ovn-ic-sbctl --columns=addresses find Address_Set
>> name=az1-as2], [0], [dnl
>> +addresses : [["1.1.2.1", "1.1.2.2"]]
>> +])
>> +AT_CHECK([ovn-ic-sbctl --columns=addresses find Address_Set
>> name=az1-as3], [0], [dnl
>> +])
>> +AT_CHECK([ovn_as az2 ovn-nbctl --columns=addresses,external_ids list
>> Address_Set az1-as2], [0], [dnl
>> +addresses : [["1.1.2.1", "1.1.2.2"]]
>> +external_ids : {ic-learnt="true"}
>> +])
>> +AT_CHECK([ovn_as az2 ovn-nbctl --columns=addresses,external_ids find
>> Address_Set name=az1-as3], [0], [dnl
>> +])
>> +
>> +# Now set the option field of the above address-set to advertise it.
>> +ovn_as az1 ovn-nbctl set Address_Set az1-as3 options={ic-adv=true}
>> +wait_row_count ic-sb:Address_Set 4
>> +AT_CHECK([ovn-ic-sbctl --columns=addresses find Address_Set
>> name=az1-as3], [0], [dnl
>> +addresses : [["1.1.3.1", "1.1.3.2"]]
>> +])
>> +AT_CHECK([ovn_as az2 ovn-nbctl --columns=addresses,external_ids list
>> Address_Set az1-as3], [0], [dnl
>> +addresses : [["1.1.3.1", "1.1.3.2"]]
>> +external_ids : {ic-learnt="true"}
>> +])
>> +
>> +# Change the options of one of the address-sets to not advertise.
>> +ovn_as az1 ovn-nbctl set Address_Set az1-as2 options={ic-adv=false}
>> +wait_row_count ic-sb:Address_Set 3
>> +AT_CHECK([ovn-ic-sbctl --columns=addresses find Address_Set
>> name=az1-as2], [0], [dnl
>> +])
>> +AT_CHECK([ovn_as az2 ovn-nbctl --columns=addresses,external_ids find
>> Address_Set name=az1-as2], [0], [dnl
>> +])
>> +
>> +# Delete one of the advertised address-sets in AZ1.
>> +ovn_as az1 ovn-nbctl destroy Address_Set az1-as3
>> +wait_row_count ic-sb:Address_Set 2
>> +AT_CHECK([ovn-ic-sbctl --columns=addresses find Address_Set
>> name=az1-as3], [0], [dnl
>> +])
>> +AT_CHECK([ovn_as az2 ovn-nbctl --columns=addresses,external_ids find
>> Address_Set name=az1-as3], [0], [dnl
>> +])
>> +
>> +# Add an IPv6 address-set in AZ2.
>> +ovn_as az2 ovn-nbctl create Address_Set name=az2-as2
>> addresses=\"2001:0db8:85a3:0000:0000:8a2e:0370:7334\",\"2001:0db8:85a3:0000:0000:8a2e:0370:7335\"
>> options:ic-adv=true
>> +wait_row_count ic-sb:Address_Set 3
>> +AT_CHECK([ovn-ic-sbctl --columns=addresses find Address_Set
>> name=az2-as2], [0], [dnl
>> +addresses : [["2001:0db8:85a3:0000:0000:8a2e:0370:7334",
>> "2001:0db8:85a3:0000:0000:8a2e:0370:7335"]]
>> +])
>> +AT_CHECK([ovn_as az1 ovn-nbctl --columns=addresses,external_ids list
>> Address_Set az2-as2], [0], [dnl
>> +addresses : [["2001:0db8:85a3:0000:0000:8a2e:0370:7334",
>> "2001:0db8:85a3:0000:0000:8a2e:0370:7335"]]
>> +external_ids : {ic-learnt="true"}
>> +])
>> +
>> +# Set the global option in AZ1 to not learn.
>> +ovn_as az1 ovn-nbctl set nb_global . options:ic-as-learn=false
>> +OVS_WAIT_WHILE([ovn_as az1 ovn-nbctl list Address_Set | grep learnt])
>> +ovn_as az1 wait_row_count nb:Address_Set 2
>> +
>> +# Set the global option in AZ1 back to learn.
>> +ovn_as az1 ovn-nbctl set nb_global . options:ic-as-learn=true
>> +OVS_WAIT_UNTIL([ovn_as az1 ovn-nbctl list Address_Set | grep learnt])
>> +ovn_as az1 wait_row_count nb:Address_Set 4
>> +AT_CHECK([ovn_as az1 ovn-nbctl --columns=addresses,external_ids list
>> Address_Set az2-as2], [0], [dnl
>> +addresses : [["2001:0db8:85a3:0000:0000:8a2e:0370:7334",
>> "2001:0db8:85a3:0000:0000:8a2e:0370:7335"]]
>> +external_ids : {ic-learnt="true"}
>> +])
>> +AT_CHECK([ovn_as az1 ovn-nbctl --columns=addresses,external_ids list
>> Address_Set az2-as1], [0], [dnl
>> +addresses : [["2.1.1.1", "2.1.1.2"]]
>> +external_ids : {ic-learnt="true"}
>> +])
>> +
>> +# Set the global option in AZ2 to not advertise.
>> +ovn_as az2 ovn-nbctl set nb_global . options:ic-as-adv=false
>> +wait_row_count ic-sb:Address_Set 1
>> +AT_CHECK([ovn-ic-sbctl --columns=addresses find Address_Set
>> name=az2-as1], [0], [dnl])
>> +AT_CHECK([ovn-ic-sbctl --columns=addresses find Address_Set
>> name=az2-as2], [0], [dnl])
>> +OVS_WAIT_WHILE([ovn_as az1 ovn-nbctl list Address_Set | grep learnt])
>> +
>> +# Set the global option in AZ2 back to advertise.
>> +ovn_as az2 ovn-nbctl set nb_global . options:ic-as-adv=true
>> +wait_row_count ic-sb:Address_Set 3
>> +ovn_as az1 wait_row_count nb:Address_Set 4
>> +AT_CHECK([ovn-ic-sbctl --columns=addresses find Address_Set
>> name=az2-as1], [0], [dnl
>> +addresses : [["2.1.1.1", "2.1.1.2"]]
>> +])
>> +AT_CHECK([ovn-ic-sbctl --columns=addresses find Address_Set
>> name=az2-as2], [0], [dnl
>> +addresses : [["2001:0db8:85a3:0000:0000:8a2e:0370:7334",
>> "2001:0db8:85a3:0000:0000:8a2e:0370:7335"]]
>> +])
>> +AT_CHECK([ovn_as az1 ovn-nbctl --columns=addresses,external_ids list
>> Address_Set az2-as1], [0], [dnl
>> +addresses : [["2.1.1.1", "2.1.1.2"]]
>> +external_ids : {ic-learnt="true"}
>> +])
>> +AT_CHECK([ovn_as az1 ovn-nbctl --columns=addresses,external_ids list
>> Address_Set az2-as2], [0], [dnl
>> +addresses : [["2001:0db8:85a3:0000:0000:8a2e:0370:7334",
>> "2001:0db8:85a3:0000:0000:8a2e:0370:7335"]]
>> +external_ids : {ic-learnt="true"}
>> +])
>> +
>> +# Create an address-set in AZ1 and then try to advertise an address-set
>> with same name from AZ2.
>> +# It will sync to IC-SB but will not propagate to AZ1.
>> +ovn_as az1 ovn-nbctl create Address_Set name=dup-as addresses=\"5.5.5.1\"
>> +ovn_as az2 ovn-nbctl create Address_Set name=dup-as addresses=\"5.5.5.2\"
>> options:ic-adv=true
>> +wait_row_count ic-sb:Address_Set 4
>> +AT_CHECK([ovn-ic-sbctl --columns=addresses find Address_Set name=dup-as],
>> [0], [dnl
>> +addresses : [["5.5.5.2"]]
>> +])
>> +AT_CHECK([ovn_as az1 ovn-nbctl --columns=addresses,external_ids list
>> Address_Set dup-as], [0], [dnl
>> +addresses : [["5.5.5.1"]]
>> +external_ids : {}
>> +])
>> +AT_CHECK([ovn_as az2 ovn-nbctl --columns=addresses,external_ids list
>> Address_Set dup-as], [0], [dnl
>> +addresses : [["5.5.5.2"]]
>> +external_ids : {}
>> +])
>> +
>> +OVN_CLEANUP_IC([az1], [az2])
>> +
>> +AT_CLEANUP
>> +])
>> +
>> OVN_FOR_EACH_NORTHD([
>> AT_SETUP([ovn-ic -- route sync])
>>
>> --
>> 2.39.3
>>
>> _______________________________________________
>> dev mailing list
>> [email protected]
>> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>>
> _______________________________________________
> dev mailing list
> [email protected]
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev