Hi Sragdhara, On 7/1/26 10:52 PM, Sragdhara Datta Chaudhuri wrote: > Hi Dumitru, Numan, > > Sorry for the delay in responding. Let me try to explain our use case. > > > The motivation is to support cross AZ security policies, where the secured > entity is in zone1 but the src/dst endpoints are in zone2. > > Say you are applying a “to-port” ACL to a port-group in zone1, and you want > to deny traffic from a set of source endpoints that are in zone2. One way > would be to have some out-of-band mechanism whereby the zone1 CMS in figures > out the IP addresses of these endpoints in zone2 and creates an address-set > locally in zone1 (and keeps it updated with any changes in the AS membership > in the remote zone). We thought it would be better to provide a solution > based on the already available sync mechanism of OVN-IC. >
I think that I'm OK with that but I'll let Numan pitch in to make sure his question was answered. > * The OVN control plane in zone2 creates and maintains an address-set AS1 > with IPs of the interesting entities (e.g. based on pod label or VM tags). > * This address-set gets synced to zone1 via IC > * The OVN control plane in zone1 creates ACL for a local port-group with > source as AS1. > > Regarding syncing remote zone’s port-group, the ACL match based on “inport” > or “outport” can be done only for local ports managed by the OVN control > plane of this zone and learning about remote zone’s ports may not be useful > in this context. Well, if the ACL is applied on the transit switch, it could match on remote "inport"/"outport" without any issues. So we could also sync port groups that include transit switch ports IMO. Regards, Dumitru > > Thanks, > Sragdhara > > > From: Dumitru Ceara <[email protected]> > Date: Monday, June 22, 2026 at 5:07 AM > To: Numan Siddique <[email protected]>; Sragdhara Datta Chaudhuri > <[email protected]> > Cc: [email protected] <[email protected]> > Subject: Re: [ovs-dev] [PATCH OVN v1] ovn-ic: Address set synchronization > across AZs. > > !-------------------------------------------------------------------| > CAUTION: External Email > > |-------------------------------------------------------------------! > > 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://urldefense.proofpoint.com/v2/url?u=https-3A__mail.openvswitch.org_mailman_listinfo_ovs-2Ddev&d=DwIDaQ&c=s883GpUCOChKOHiocYtGcg&r=uXnTjPDrt8WYa8nbZqANTqL0TyzFTTKpPHphGFPgvBw&m=Sfq6W1O4ZvoTY48n5rYG-E4genNM9pYjs8B9yiomtXDlWouZwnBaHbur_Fwv1T_d&s=XhNdbV4XPSyYtQUneG3Qvv1IenY1xm2_83PENBDh2Us&e= >>> >> _______________________________________________ >> dev mailing list >> [email protected] >> https://urldefense.proofpoint.com/v2/url?u=https-3A__mail.openvswitch.org_mailman_listinfo_ovs-2Ddev&d=DwIDaQ&c=s883GpUCOChKOHiocYtGcg&r=uXnTjPDrt8WYa8nbZqANTqL0TyzFTTKpPHphGFPgvBw&m=Sfq6W1O4ZvoTY48n5rYG-E4genNM9pYjs8B9yiomtXDlWouZwnBaHbur_Fwv1T_d&s=XhNdbV4XPSyYtQUneG3Qvv1IenY1xm2_83PENBDh2Us&e= >> > _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
