Em qui., 19 de set. de 2024 às 11:19, Roberto Bartzen Acosta < [email protected]> escreveu:
> The OVN-IC feature can handle multiple points of redistribution when > we include more than one TS in the same Logical Router. So, it is a > good idea to use route tagging to prevent learing routes from logical > routers in the same user domain via Transit switch created for > peer-links with another user domain. > > This means that there can be a logical separation by user domain > (e.g. VPCs), and a Transit Switch that peers between the different > VPCs, connecting the routers in the VPC1 with the routers in the VPC2, > for example. In this case, the route tag can ensure that the Logical > Routers of VPC1 does not learn routes from VPC1 itself via the peering > TS, avoiding installing additional openflow flows to handle > multipath/ecmp unnecessarily. > > To use this route tag feature, new options were created to be configured > in the Logical Router Port connected to the TS. This configuration must > be performed in the LRP insted of the LR because the LRP is the path used > to advertise and learn routes connected to a specific TS (nexthop). > > Signed-off-by: Roberto Bartzen Acosta <[email protected]> > --- > ic/ovn-ic.c | 80 ++++++++++++++----- > ovn-nb.xml | 27 +++++++ > tests/ovn-ic.at | 200 ++++++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 288 insertions(+), 19 deletions(-) > > diff --git a/ic/ovn-ic.c b/ic/ovn-ic.c > index 69bac4ab2..452416e8b 100644 > --- a/ic/ovn-ic.c > +++ b/ic/ovn-ic.c > @@ -874,6 +874,7 @@ struct ic_route_info { > struct in6_addr nexthop; > const char *origin; > const char *route_table; > + const char *route_tag; > > const struct nbrec_logical_router *nb_lr; > > @@ -1124,7 +1125,8 @@ add_to_routes_ad(struct hmap *routes_ad, const > struct in6_addr prefix, > const char *origin, const char *route_table, > const struct nbrec_logical_router_port *nb_lrp, > const struct nbrec_logical_router_static_route *nb_route, > - const struct nbrec_logical_router *nb_lr) > + const struct nbrec_logical_router *nb_lr, > + const char *route_tag) > { > if (route_table == NULL) { > route_table = ""; > @@ -1143,6 +1145,7 @@ add_to_routes_ad(struct hmap *routes_ad, const > struct in6_addr prefix, > ic_route->route_table = route_table; > ic_route->nb_lrp = nb_lrp; > ic_route->nb_lr = nb_lr; > + ic_route->route_tag = route_tag; > hmap_insert(routes_ad, &ic_route->node, hash); > } else { > static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); > @@ -1158,7 +1161,8 @@ add_static_to_routes_ad( > const struct nbrec_logical_router_static_route *nb_route, > const struct nbrec_logical_router *nb_lr, > const struct lport_addresses *nexthop_addresses, > - const struct smap *nb_options) > + const struct smap *nb_options, > + const char *route_tag) > { > struct in6_addr prefix, nexthop; > unsigned int plen; > @@ -1199,7 +1203,7 @@ add_static_to_routes_ad( > } > > add_to_routes_ad(routes_ad, prefix, plen, nexthop, > ROUTE_ORIGIN_STATIC, > - nb_route->route_table, NULL, nb_route, nb_lr); > + nb_route->route_table, NULL, nb_route, nb_lr, > route_tag); > } > > static void > @@ -1207,7 +1211,8 @@ add_network_to_routes_ad(struct hmap *routes_ad, > const char *network, > const struct nbrec_logical_router_port *nb_lrp, > const struct lport_addresses *nexthop_addresses, > const struct smap *nb_options, > - const struct nbrec_logical_router *nb_lr) > + const struct nbrec_logical_router *nb_lr, > + const char *route_tag) > { > struct in6_addr prefix, nexthop; > unsigned int plen; > @@ -1246,7 +1251,7 @@ add_network_to_routes_ad(struct hmap *routes_ad, > const char *network, > > /* directly-connected routes go to <main> route table */ > add_to_routes_ad(routes_ad, prefix, plen, nexthop, > ROUTE_ORIGIN_CONNECTED, > - NULL, nb_lrp, NULL, nb_lr); > + NULL, nb_lrp, NULL, nb_lr, route_tag); > } > > static bool > @@ -1315,8 +1320,8 @@ get_lrp_name_by_ts_port_name(struct ic_context *ctx, > const char *ts_port_name) > return smap_get(&nb_lsp->options, "router-port"); > } > > -static const char * > -get_route_table_by_lrp_name(struct ic_context *ctx, const char *lrp_name) > +static const struct nbrec_logical_router_port * > +get_lrp_by_lrp_name(struct ic_context *ctx, const char *lrp_name) > { > const struct nbrec_logical_router_port *lrp; > const struct nbrec_logical_router_port *lrp_key = > @@ -1326,10 +1331,7 @@ get_route_table_by_lrp_name(struct ic_context *ctx, > const char *lrp_name) > lrp_key); > nbrec_logical_router_port_index_destroy_row(lrp_key); > > - if (lrp) { > - return smap_get_def(&lrp->options, "route_table", ""); > - } > - return ""; /* <main> route table */ > + return lrp; > } > > static bool > @@ -1359,12 +1361,21 @@ sync_learned_routes(struct ic_context *ctx, > nbrec_nb_global_first(ctx->ovnnb_idl); > ovs_assert(nb_global); > > - const char *lrp_name, *ts_route_table; > + const char *lrp_name, *ts_route_table, *route_filter_tag; > const struct icsbrec_port_binding *isb_pb; > + const struct nbrec_logical_router_port *lrp; > for (int i = 0; i < ic_lr->n_isb_pbs; i++) { > isb_pb = ic_lr->isb_pbs[i]; > lrp_name = get_lrp_name_by_ts_port_name(ctx, > isb_pb->logical_port); > - ts_route_table = get_route_table_by_lrp_name(ctx, lrp_name); > + lrp = get_lrp_by_lrp_name(ctx, lrp_name); > + if (lrp) { > + ts_route_table = smap_get_def(&lrp->options, "route_table", > ""); > + route_filter_tag = smap_get_def(&lrp->options, > + "ic-route-filter-tag", ""); > + } else { > + ts_route_table = ""; > + route_filter_tag = ""; > + } > > isb_route_key = > icsbrec_route_index_init_row(ctx->icsbrec_route_by_ts); > icsbrec_route_index_set_transit_switch(isb_route_key, > @@ -1384,6 +1395,17 @@ sync_learned_routes(struct ic_context *ctx, > continue; > } > > + const char *isb_route_tag = smap_get(&isb_route->external_ids, > + "ic-route-tag"); > + if ((isb_route_tag != NULL) && > + (!strcmp(isb_route_tag, route_filter_tag))) { > + VLOG_DBG("Skip learning route %s -> %s as either " > + "its route tag %s is filtered by %s of TS LRP ", > + isb_route->ip_prefix, isb_route->nexthop, > + isb_route_tag, route_filter_tag); > + continue; > + } > + > if (isb_route->route_table[0] && > strcmp(isb_route->route_table, ts_route_table)) { > if (VLOG_IS_DBG_ENABLED()) { > @@ -1471,6 +1493,7 @@ ad_route_sync_external_ids(const struct > ic_route_info *route_adv, > const struct icsbrec_route *isb_route) > { > struct uuid isb_ext_id, nb_id, isb_ext_lr_id, lr_id; > + const char *route_tag; > smap_get_uuid(&isb_route->external_ids, "nb-id", &isb_ext_id); > smap_get_uuid(&isb_route->external_ids, "lr-id", &isb_ext_lr_id); > nb_id = route_adv->nb_route ? route_adv->nb_route->header_.uuid > @@ -1488,6 +1511,16 @@ ad_route_sync_external_ids(const struct > ic_route_info *route_adv, > uuid_s); > free(uuid_s); > } > + if (strcmp(route_adv->route_tag, "")) { > + icsbrec_route_update_external_ids_setkey(isb_route, > "ic-route-tag", > + route_adv->route_tag); > + } else { > + route_tag = smap_get(&isb_route->external_ids, "ic-route-tag"); > + if (route_tag) { > + icsbrec_route_update_external_ids_delkey(isb_route, > + "ic-route-tag"); > + } > + } > } > > /* Sync routes from routes_ad to IC-SB. */ > @@ -1580,7 +1613,8 @@ build_ts_routes_to_adv(struct ic_context *ctx, > struct hmap *routes_ad, > struct lport_addresses *ts_port_addrs, > const struct nbrec_nb_global *nb_global, > - const char *ts_route_table) > + const char *ts_route_table, > + const char *route_tag) > { > const struct nbrec_logical_router *lr = ic_lr->lr; > > @@ -1603,7 +1637,7 @@ build_ts_routes_to_adv(struct ic_context *ctx, > } else if (!strcmp(ts_route_table, nb_route->route_table)) { > /* It may be a route to be advertised */ > add_static_to_routes_ad(routes_ad, nb_route, lr, > ts_port_addrs, > - &nb_global->options); > + &nb_global->options, route_tag); > } > } > > @@ -1615,7 +1649,7 @@ build_ts_routes_to_adv(struct ic_context *ctx, > add_network_to_routes_ad(routes_ad, lrp->networks[j], lrp, > ts_port_addrs, > &nb_global->options, > - lr); > + lr, route_tag); > } > } else { > /* The router port of the TS port is ignored. */ > @@ -1635,9 +1669,10 @@ collect_lr_routes(struct ic_context *ctx, > ovs_assert(nb_global); > > const struct icsbrec_port_binding *isb_pb; > - const char *lrp_name, *ts_name, *route_table; > + const char *lrp_name, *ts_name, *route_table, *route_tag; > struct lport_addresses ts_port_addrs; > const struct icnbrec_transit_switch *key; > + const struct nbrec_logical_router_port *lrp; > > struct hmap *routes_ad; > const struct icnbrec_transit_switch *t_sw; > @@ -1669,9 +1704,16 @@ collect_lr_routes(struct ic_context *ctx, > continue; > } > lrp_name = get_lrp_name_by_ts_port_name(ctx, > isb_pb->logical_port); > - route_table = get_route_table_by_lrp_name(ctx, lrp_name); > + lrp = get_lrp_by_lrp_name(ctx, lrp_name); > + if (lrp) { > + route_table = smap_get_def(&lrp->options, "route_table", ""); > + route_tag = smap_get_def(&lrp->options, "ic-route-tag", ""); > + } else { > + route_table = ""; > + route_tag = ""; > + } > build_ts_routes_to_adv(ctx, ic_lr, routes_ad, &ts_port_addrs, > - nb_global, route_table); > + nb_global, route_table, route_tag); > destroy_lport_addresses(&ts_port_addrs); > } > } > diff --git a/ovn-nb.xml b/ovn-nb.xml > index 2836f58f5..adb9144ae 100644 > --- a/ovn-nb.xml > +++ b/ovn-nb.xml > @@ -3662,6 +3662,33 @@ or > > </ul> > </column> > + > + <column name="options" key="ic-route-tag" type='{"type": "string"}'> > + <p> > + This option expects a name of a route-tag that's present in the > + Logical Router Port. If set, it causes any route advertised by > + the Logical Router Port to include the <code>route-tag</code> in > + the <code> external_ids </code> register of the advertised route > + entry in the <ref table="Route" db="OVN_IC_Southbound"/> table > of > + the <ref db="OVN_IC_Southbound"/> database. > + > + This allows to tag and filter route tags in the process of > + advertising and learning routes in <code>ovn-ic</code> daemon. > + </p> > + </column> > + > + <column name="options" key="ic-route-filter-tag" > + type='{"type": "string"}'> > + <p> > + This option expects a name of a filtered route-tag that's > present > + in the Logical Router Port. If set, it causes any route learned > by > + the Logical Router Port with the <code>route-tag</code> present > in > + the external_ids register of the advertised route entry in the > + <ref table="Route" db="OVN_IC_Southbound"/> table of the > + <ref db="OVN_IC_Southbound"/> database, will be filtered and not > + learned by the <code>ovn-ic</code> daemon. > + </p> > + </column> > </group> > > <group title="Attachment"> > diff --git a/tests/ovn-ic.at b/tests/ovn-ic.at > index 9fa41200e..33ad37f2e 100644 > --- a/tests/ovn-ic.at > +++ b/tests/ovn-ic.at > @@ -2357,3 +2357,203 @@ OVN_CLEANUP_SBOX([hv2], ["/IGMP Querier enabled > without a valid IPv4/d > OVN_CLEANUP_IC([az1],[az2]) > AT_CLEANUP > ]) > + > +OVN_FOR_EACH_NORTHD([ > +AT_SETUP([ovn-ic -- route tag -- tagging and filtering routes]) > + > +ovn_init_ic_db > +ovn-ic-nbctl ts-add ts1 > + > +for i in 1 2; do > + ovn_start az$i > + ovn_as az$i > + > + # Enable route learning at AZ level > + ovn-nbctl set nb_global . options:ic-route-learn=true > + # Enable route advertising at AZ level > + ovn-nbctl set nb_global . options:ic-route-adv=true > +done > + > +# Create new transit switches and LRs. Test topology is next: > +# VPC1: > +# / transit switch (ts11) \ > +# logical router (lr11) - transit switch (ts12) - logical router (lr12) > +# \ / > +# transit switch (tspeer) > +# VPC2: / \ > +# logical router (lr21) - transit switch (ts21) - logical router (lr22) > +# \ transit switch (ts22) / > +# > + > +# VPC1 > +# create lr11, lr12, ts11, ts12 and connect them > +for i in 1 2; do > + ovn_as az$i > + > + lr=lr1$i > + ovn-nbctl lr-add $lr > + > + for j in 1 2; do > + ts=ts1$j > + ovn-ic-nbctl --wait=sb --may-exist ts-add $ts > + > + lrp=lrp-$lr-$ts > + lsp=lsp-$ts-$lr > + # Create LRP and connect to TS > + ovn-nbctl lrp-add $lr $lrp aa:aa:aa:aa:a$j:0$i 169.254.10$j.$i/24 > + ovn-nbctl lsp-add $ts $lsp \ > + -- lsp-set-addresses $lsp router \ > + -- lsp-set-type $lsp router \ > + -- lsp-set-options $lsp router-port=$lrp > + done > +done > + > +# VPC2 > +# create lr21, lr22, ts21, ts22 and connect them > +for i in 1 2; do > + ovn_as az$i > + > + lr=lr2$i > + ovn-nbctl lr-add $lr > + > + for j in 1 2; do > + ts=ts2$j > + ovn-ic-nbctl --wait=sb --may-exist ts-add $ts > + > + lrp=lrp-$lr-$ts > + lsp=lsp-$ts-$lr > + # Create LRP and connect to TS > + ovn-nbctl lrp-add $lr $lrp aa:aa:aa:aa:a$j:0$i 169.254.10$j.$i/24 > + ovn-nbctl lsp-add $ts $lsp \ > + -- lsp-set-addresses $lsp router \ > + -- lsp-set-type $lsp router \ > + -- lsp-set-options $lsp router-port=$lrp > + done > +done > + > +# Create directly-connected route in VPC1 > +ovn_as az2 ovn-nbctl lrp-add lr12 lrp-lr12 aa:aa:aa:aa:bb:01 " > 192.168.0.1/24" > + > +# Create directly-connected route in VPC2 > +ovn_as az2 ovn-nbctl --wait=sb lrp-add lr22 lrp-lr22 aa:aa:aa:aa:cc:01 " > 192.168.1.1/24" > + > +check ovn-ic-nbctl --wait=sb sync > + > +# Test direct routes from lr12 were learned to lr11 > +OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl lr-route-list lr11 | grep > 192.168 | > + grep learned | awk '{print $1, $2, $5}' | sort ], [0], [dnl > +192.168.0.0/24 169.254.101.2 ecmp > +192.168.0.0/24 169.254.102.2 ecmp > +]) > + > +# Test direct routes from lr22 were learned to lr21 > +OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl lr-route-list lr21 | grep > 192.168 | > + grep learned | awk '{print $1, $2, $5}' | sort ], [0], [dnl > +192.168.1.0/24 169.254.101.2 ecmp > +192.168.1.0/24 169.254.102.2 ecmp > +]) > + > +# Create peering TS > +ovn-ic-nbctl --wait=sb --may-exist ts-add tspeer > + > +# Create LRPs and connect to the peering TS > +ovn_as az1 > +ovn-nbctl lrp-add lr11 lrp-lr11-tspeer aa:aa:aa:aa:11:01 > 169.254.103.11/24 > +ovn-nbctl <http://169.254.103.11/24+ovn-nbctl> lsp-add tspeer > lsp-tspeer-lr11 \ > + -- lsp-set-addresses lsp-tspeer-lr11 router \ > + -- lsp-set-type lsp-tspeer-lr11 router \ > + -- lsp-set-options lsp-tspeer-lr11 router-port=lrp-lr11-tspeer > + > +ovn_as az2 > +ovn-nbctl lrp-add lr12 lrp-lr12-tspeer aa:aa:aa:aa:12:01 > 169.254.103.12/24 > +ovn-nbctl <http://169.254.103.12/24+ovn-nbctl> lsp-add tspeer > lsp-tspeer-lr12 \ > + -- lsp-set-addresses lsp-tspeer-lr12 router \ > + -- lsp-set-type lsp-tspeer-lr12 router \ > + -- lsp-set-options lsp-tspeer-lr12 router-port=lrp-lr12-tspeer > + > +ovn_as az1 > +ovn-nbctl lrp-add lr21 lrp-lr21-tspeer aa:aa:aa:aa:21:01 > 169.254.103.21/24 > +ovn-nbctl <http://169.254.103.21/24+ovn-nbctl> lsp-add tspeer > lsp-tspeer-lr21 \ > + -- lsp-set-addresses lsp-tspeer-lr21 router \ > + -- lsp-set-type lsp-tspeer-lr21 router \ > + -- lsp-set-options lsp-tspeer-lr21 router-port=lrp-lr21-tspeer > + > +ovn_as az2 > +ovn-nbctl lrp-add lr22 lrp-lr22-tspeer aa:aa:aa:aa:22:01 > 169.254.103.22/24 > +ovn-nbctl <http://169.254.103.22/24+ovn-nbctl> lsp-add tspeer > lsp-tspeer-lr22 \ > + -- lsp-set-addresses lsp-tspeer-lr22 router \ > + -- lsp-set-type lsp-tspeer-lr22 router \ > + -- lsp-set-options lsp-tspeer-lr22 router-port=lrp-lr22-tspeer > + > +check ovn-ic-nbctl --wait=sb sync > + > +# Test direct routes from lr12/lr22 were learned to lr11 > +OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl lr-route-list lr11 | grep > 192.168 | > + grep learned | awk '{print $1, $2}' | sort ], [0], [dnl > +192.168.0.0/24 169.254.101.2 > +192.168.0.0/24 169.254.102.2 > +192.168.0.0/24 169.254.103.12 > +192.168.1.0/24 169.254.103.22 > +]) > + > +# Test direct routes from lr22/lr12 were learned to lr21 > +OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl lr-route-list lr21 | grep > 192.168 | > + grep learned | awk '{print $1, $2}' | sort ], [0], [dnl > +192.168.0.0/24 169.254.103.12 > +192.168.1.0/24 169.254.101.2 > +192.168.1.0/24 169.254.102.2 > +192.168.1.0/24 169.254.103.22 > +]) > + > +# VPC1: Create a route tag for VPC1 mark its own routes via lrp-lr12 > +ovn_as az2 ovn-nbctl set logical_router_port lrp-lr12-tspeer > options:ic-route-tag=vpc1 > + > +# Test advertised routes with the vpc1 route tag present > +ovn-ic-sbctl list route > +wait_row_count ic-sb:Route 1 ip_prefix=192.168.0.1/24 > nexthop=169.254.103.12 origin=connected external_ids:ic-route-tag=vpc1 > + > +# Filter routes on VPC1 lrp-lr11-tspeer with the route tag vpc1 present > +ovn_as az1 ovn-nbctl set logical_router_port lrp-lr11-tspeer > options:ic-route-filter-tag=vpc1 > + > +# Test remaining direct routes from lr12 were learned to lr11 > +# Routes from the 169.254.101.2 nexthop have been filtered > +OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl lr-route-list lr11 | grep > 192.168 | > + grep learned | awk '{print $1, $2}' | sort ], [0], [dnl > +192.168.0.0/24 169.254.101.2 > +192.168.0.0/24 169.254.102.2 > +192.168.1.0/24 169.254.103.22 > +]) > + > +# Remove the route tag used for advertisement > +ovn_as az2 ovn-nbctl remove logical_router_port lrp-lr12-tspeer options > ic-route-tag=vpc1 > + > +# Test advertised routes with the vpc1 route tag present > +ovn-ic-sbctl list route > +wait_row_count ic-sb:Route 0 ip_prefix=192.168.0.1/24 > nexthop=169.254.103.12 origin=connected external_ids:ic-route-tag=vpc1 > + > +# Test the original direct routes from lr12/lr22 were learned to lr11 > +OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl lr-route-list lr11 | grep > 192.168 | > + grep learned | awk '{print $1, $2}' | sort ], [0], [dnl > +192.168.0.0/24 169.254.101.2 > +192.168.0.0/24 169.254.102.2 > +192.168.0.0/24 169.254.103.12 > +192.168.1.0/24 169.254.103.22 > +]) > + > +# Remove route tag filter and add route tag on lrp-lr12-tspeer advertised > routes > +ovn_as az1 ovn-nbctl remove logical_router_port lrp-lr11-tspeer options > ic-route-filter-tag=vpc1 > +ovn_as az2 ovn-nbctl set logical_router_port lrp-lr12-tspeer > options:ic-route-tag=vpc1 > + > +# Test if all the routes are learned because we no longer have the filter > tag option enabled > +OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl lr-route-list lr11 | grep > 192.168 | > + grep learned | awk '{print $1, $2}' | sort ], [0], [dnl > +192.168.0.0/24 169.254.101.2 > +192.168.0.0/24 169.254.102.2 > +192.168.0.0/24 169.254.103.12 > +192.168.1.0/24 169.254.103.22 > +]) > + > +OVN_CLEANUP_IC([az1], [az2]) > + > +AT_CLEANUP > +]) > -- > 2.34.1 > > -- _‘Esta mensagem é direcionada apenas para os endereços constantes no cabeçalho inicial. Se você não está listado nos endereços constantes no cabeçalho, pedimos-lhe que desconsidere completamente o conteúdo dessa mensagem e cuja cópia, encaminhamento e/ou execução das ações citadas estão imediatamente anuladas e proibidas’._ * **‘Apesar do Magazine Luiza tomar todas as precauções razoáveis para assegurar que nenhum vírus esteja presente nesse e-mail, a empresa não poderá aceitar a responsabilidade por quaisquer perdas ou danos causados por esse e-mail ou por seus anexos’.* _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
