Em qua., 2 de abr. de 2025 às 05:58, Dumitru Ceara <[email protected]> escreveu:
> On 3/20/25 6:37 PM, Paulo Guilherme da Silva via dev wrote: > > This commit adds the ability for ovn-ic to filter routes between VPCs. > > In use cases where the user is using vpc-peering(route tag) handling > > multiple points of redistribution, when we connect more than one TS in > > the same Logical Router it is essential that we have control over which > > routes will be filtered or advertised by transit switch. > > > > > > Co-authored-by: Lucas Vargas Dias <[email protected]> > > Signed-off-by: Lucas Vargas Dias <[email protected]> > > Signed-off-by: Paulo Guilherme da Silva <[email protected]> > > --- > > Hi Paulo, Lucas, > > Thanks for this new version! > > Unfortunately the "ovn-ic.at:2678 ovn-ic -- prefix filter -- > filtering routes" tests fail in CI. Please see: > > https://github.com/ovsrobot/ovn/actions/runs/13976556772/job/39131913912 > > ovn-nbctl set logical_router_port lrp-lr12-ts1 > options:ic-route-filter-adv=192.168.12.0/24,invalid > ../../../tests/ovn-macros.at:854: "$@" > ovn-ic.at:2678: waiting for output from ovn_as az1 ovn-nbctl > lr-route-list lr11 | grep 192.168 | > grep learned | awk '{print $1, $2}' | sort ... > ovn-ic.at:2678: wait failed after 30 seconds > --- wait-expected-stdout 2025-03-20 18:34:01.438738270 +0000 > +++ wait-stdout 2025-03-20 18:34:32.567690980 +0000 > > > ic/ovn-ic.c | 122 ++++++++------- > > lib/ovn-util.c | 49 ++++++ > > lib/ovn-util.h | 3 + > > ovn-nb.xml | 44 +++++- > > tests/ovn-ic.at | 399 ++++++++++++------------------------------------ > > 5 files changed, 260 insertions(+), 357 deletions(-) > > > > diff --git a/ic/ovn-ic.c b/ic/ovn-ic.c > > index c8796680b..1ef331420 100644 > > --- a/ic/ovn-ic.c > > +++ b/ic/ovn-ic.c > > @@ -1069,69 +1069,63 @@ get_nexthop_from_lport_addresses(bool is_v4, > > return true; > > } > > > > +static bool > > +prefix_is_filtered(struct in6_addr *prefix, > > + unsigned int plen, > > + const struct nbrec_logical_router *nb_lr, > > + const struct nbrec_logical_router_port *ts_lrp, > > + bool is_advertisement) > > +{ > > + struct ds filter_list = DS_EMPTY_INITIALIZER; > > + const char *filter_direction = is_advertisement ? > "ic-route-filter-adv" :\ > > Please remove the '\', it's not necessary. > > Ok, we'll adjust. > > + "ic-route-filter-learn"; > > + if (ts_lrp) { > > + const char *lrp_route_filter = smap_get(&ts_lrp->options, > > + filter_direction); > > + if (lrp_route_filter) { > > + ds_put_format(&filter_list, "%s,", lrp_route_filter); > > + } > > + } > > + const char *lr_route_filter = smap_get(&nb_lr->options, > > + filter_direction); > > + if (lr_route_filter) { > > + ds_put_format(&filter_list, "%s,", lr_route_filter); > > + } > > + > > + if (!filter_list.length) { > > + ds_destroy(&filter_list); > > + return true; > > + } > > + > > + bool matched = find_prefix_in_list(prefix, plen, > ds_cstr(&filter_list), > > + filter_direction); > > + ds_destroy(&filter_list); > > + return matched; > > +} > > + > > static bool > > prefix_is_deny_listed(const struct smap *nb_options, > > struct in6_addr *prefix, > > unsigned int plen) > > { > > - const char *denylist = smap_get(nb_options, "ic-route-denylist"); > > + const char *filter_name = "ic-route-denylist"; > > + const char *denylist = smap_get(nb_options, filter_name); > > if (!denylist || !denylist[0]) { > > denylist = smap_get(nb_options, "ic-route-blacklist"); > > if (!denylist || !denylist[0]) { > > return false; > > } > > } > > - struct in6_addr bl_prefix; > > - unsigned int bl_plen; > > - char *cur, *next, *start; > > - next = start = xstrdup(denylist); > > - bool matched = false; > > - while ((cur = strsep(&next, ",")) && *cur) { > > - if (!ip46_parse_cidr(cur, &bl_prefix, &bl_plen)) { > > - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, > 1); > > - VLOG_WARN_RL(&rl, "Bad format in nb_global options:" > > - "ic-route-denylist: %s. CIDR expected.", cur); > > - continue; > > - } > > - > > - if (IN6_IS_ADDR_V4MAPPED(&bl_prefix) != > IN6_IS_ADDR_V4MAPPED(prefix)) { > > - continue; > > - } > > - > > - /* 192.168.0.0/16 does not belong to 192.168.0.0/17 */ > > - if (plen < bl_plen) { > > - continue; > > - } > > - > > - if (IN6_IS_ADDR_V4MAPPED(prefix)) { > > - ovs_be32 bl_prefix_v4 = > in6_addr_get_mapped_ipv4(&bl_prefix); > > - ovs_be32 prefix_v4 = in6_addr_get_mapped_ipv4(prefix); > > - ovs_be32 mask = be32_prefix_mask(bl_plen); > > - > > - if ((prefix_v4 & mask) != (bl_prefix_v4 & mask)) { > > - continue; > > - } > > - } else { > > - struct in6_addr bl_mask = ipv6_create_mask(bl_plen); > > - struct in6_addr m_prefix = ipv6_addr_bitand(prefix, > &bl_mask); > > - struct in6_addr m_bl_prefix = ipv6_addr_bitand(&bl_prefix, > > - &bl_mask); > > - if (!ipv6_addr_equals(&m_prefix, &m_bl_prefix)) { > > - continue; > > - } > > - } > > - matched = true; > > - break; > > - } > > - free(start); > > - return matched; > > + return find_prefix_in_list(prefix, plen, denylist, filter_name); > > } > > > > static bool > > route_need_advertise(const char *policy, > > struct in6_addr *prefix, > > unsigned int plen, > > - const struct smap *nb_options) > > + const struct smap *nb_options, > > + const struct nbrec_logical_router *nb_lr, > > + const struct nbrec_logical_router_port *ts_lrp) > > { > > if (!smap_get_bool(nb_options, "ic-route-adv", false)) { > > return false; > > @@ -1153,6 +1147,11 @@ route_need_advertise(const char *policy, > > if (prefix_is_deny_listed(nb_options, prefix, plen)) { > > return false; > > } > > + > > + if (!prefix_is_filtered(prefix, plen, nb_lr, ts_lrp, true)) { > > + return false; > > + } > > + > > return true; > > } > > > > @@ -1207,7 +1206,8 @@ add_static_to_routes_ad( > > const struct nbrec_logical_router *nb_lr, > > const struct lport_addresses *nexthop_addresses, > > const struct smap *nb_options, > > - const char *route_tag) > > + const char *route_tag, > > + const struct nbrec_logical_router_port *ts_lrp) > > { > > struct in6_addr prefix, nexthop; > > unsigned int plen; > > @@ -1216,7 +1216,8 @@ add_static_to_routes_ad( > > return; > > } > > > > - if (!route_need_advertise(nb_route->policy, &prefix, plen, > nb_options)) { > > + if (!route_need_advertise(nb_route->policy, &prefix, plen, > nb_options, > > + nb_lr, ts_lrp)) { > > return; > > } > > > > @@ -1257,7 +1258,8 @@ add_network_to_routes_ad(struct hmap *routes_ad, > const char *network, > > const struct lport_addresses > *nexthop_addresses, > > const struct smap *nb_options, > > const struct nbrec_logical_router *nb_lr, > > - const char *route_tag) > > + const char *route_tag, > > + const struct nbrec_logical_router_port *ts_lrp) > > { > > struct in6_addr prefix, nexthop; > > unsigned int plen; > > @@ -1265,7 +1267,8 @@ add_network_to_routes_ad(struct hmap *routes_ad, > const char *network, > > return; > > } > > > > - if (!route_need_advertise(NULL, &prefix, plen, nb_options)) { > > + if (!route_need_advertise(NULL, &prefix, plen, nb_options, > > + nb_lr, ts_lrp)) { > > VLOG_DBG("Route ad: skip network %s of lrp %s.", > > network, nb_lrp->name); > > return; > > @@ -1319,7 +1322,8 @@ static bool > > route_need_learn(const struct nbrec_logical_router *lr, > > const struct icsbrec_route *isb_route, > > struct in6_addr *prefix, unsigned int plen, > > - const struct smap *nb_options) > > + const struct smap *nb_options, > > + const struct nbrec_logical_router_port *ts_lrp) > > { > > if (!smap_get_bool(nb_options, "ic-route-learn", false)) { > > return false; > > @@ -1338,6 +1342,11 @@ route_need_learn(const struct > nbrec_logical_router *lr, > > return false; > > } > > > > + if (!prefix_is_filtered(prefix, plen, lr, ts_lrp, false)) { > > + return false; > > + } > > + > > + > > if (route_has_local_gw(lr, isb_route->route_table, > isb_route->ip_prefix)) { > > VLOG_DBG("Skip learning %s (rtb:%s) route, as we've got one > with " > > "local GW", isb_route->ip_prefix, > isb_route->route_table); > > @@ -1467,7 +1476,7 @@ sync_learned_routes(struct ic_context *ctx, > > continue; > > } > > if (!route_need_learn(ic_lr->lr, isb_route, &prefix, plen, > > - &nb_global->options)) { > > + &nb_global->options, lrp)) { > > continue; > > } > > > > @@ -1653,7 +1662,8 @@ build_ts_routes_to_adv(struct ic_context *ctx, > > struct lport_addresses *ts_port_addrs, > > const struct nbrec_nb_global *nb_global, > > const char *ts_route_table, > > - const char *route_tag) > > + const char *route_tag, > > + const struct nbrec_logical_router_port *ts_lrp) > > { > > const struct nbrec_logical_router *lr = ic_lr->lr; > > > > @@ -1676,7 +1686,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, route_tag); > > + &nb_global->options, route_tag, > ts_lrp); > > } > > } > > > > @@ -1688,7 +1698,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, route_tag); > > + lr, route_tag, ts_lrp); > > } > > } else { > > /* The router port of the TS port is ignored. */ > > @@ -1752,7 +1762,7 @@ collect_lr_routes(struct ic_context *ctx, > > route_tag = ""; > > } > > build_ts_routes_to_adv(ctx, ic_lr, routes_ad, &ts_port_addrs, > > - nb_global, route_table, route_tag); > > + nb_global, route_table, route_tag, lrp); > > destroy_lport_addresses(&ts_port_addrs); > > } > > } > > diff --git a/lib/ovn-util.c b/lib/ovn-util.c > > index c65b36bb5..675890c32 100644 > > --- a/lib/ovn-util.c > > +++ b/lib/ovn-util.c > > @@ -1384,6 +1384,55 @@ prefix_is_link_local(const struct in6_addr > *prefix, unsigned int plen) > > ((prefix->s6_addr[1] & 0xc0) == 0x80)); > > } > > > > +bool > > +find_prefix_in_list(const struct in6_addr *prefix, unsigned int plen, > > + const char *prefix_list, const char *filter_name) > > +{ > > + struct in6_addr bl_prefix; > > + char *cur, *next, *start; > > + unsigned int bl_plen; > > + bool matched = false; > > + next = start = xstrdup(prefix_list); > > + while ((cur = strsep(&next, ",")) && *cur) { > > Nit: now that you're refactoring this it might be time to get rid of the > xstrdup/strsep custom parsing and maybe use a library function. Could > we make find_prefix_in_list() receive the prefix list as a 'const struct > sset *prefixes' argument. We could pre-parse the set of prefixes and > build that only once for each router/router port. > > We have the sset_from_delimited_string() function in the OVS libraries. > > Would that be cleaner? > I agree about use struct sset. I didn't understand about construct only once because the configuration of parameters could be dynamic as well the routes to be learned or advertised. My idea is something like the following code: struct sset prefix_list = SSET_INITIALIZER(&prefix_list); sset_from_delimited_string(&prefix_list, ds_cstr(&filter_list), ","); bool matched = find_prefix_in_list(prefix, plen, &prefix_list, filter_direction); > > > + if (!ip46_parse_cidr(cur, &bl_prefix, &bl_plen)) { > > + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, > 1); > > + VLOG_WARN_RL(&rl, "Bad format in LR, LRP or nb_global > options:" > > + "%s: %s. CIDR expected.", filter_name, cur); > > + continue; > > + } > > + > > + if (IN6_IS_ADDR_V4MAPPED(&bl_prefix) != > IN6_IS_ADDR_V4MAPPED(prefix)) { > > + continue; > > + } > > + > > + /* 192.168.0.0/16 does not belong to 192.168.0.0/17 */ > > + if (plen < bl_plen) { > > + continue; > > + } > > + > > + if (IN6_IS_ADDR_V4MAPPED(prefix)) { > > + ovs_be32 bl_prefix_v4 = > in6_addr_get_mapped_ipv4(&bl_prefix); > > + ovs_be32 prefix_v4 = in6_addr_get_mapped_ipv4(prefix); > > + ovs_be32 mask = be32_prefix_mask(bl_plen); > > + > > + if ((prefix_v4 & mask) != (bl_prefix_v4 & mask)) { > > + continue; > > + } > > + } else { > > + struct in6_addr bl_mask = ipv6_create_mask(bl_plen); > > + struct in6_addr m_prefix = ipv6_addr_bitand(prefix, > &bl_mask); > > + struct in6_addr m_bl_prefix = ipv6_addr_bitand(&bl_prefix, > > + &bl_mask); > > + if (!ipv6_addr_equals(&m_prefix, &m_bl_prefix)) { > > + continue; > > + } > > + } > > + matched = true; > > + break; > > + } > > + free(start); > > + return matched; > > +} > > const struct sbrec_port_binding * > > lport_lookup_by_name(struct ovsdb_idl_index *sbrec_port_binding_by_name, > > const char *name) > > diff --git a/lib/ovn-util.h b/lib/ovn-util.h > > index ce8cc0568..cdbd2f3d1 100644 > > --- a/lib/ovn-util.h > > +++ b/lib/ovn-util.h > > @@ -492,6 +492,9 @@ bool ovn_update_swconn_at(struct rconn *swconn, > const char *target, > > > > bool prefix_is_link_local(const struct in6_addr *prefix, unsigned int > plen); > > > > +bool find_prefix_in_list(const struct in6_addr *prefix, unsigned int > plen, > > + const char *prefix_list, const char > *filter_name); > > + > > const struct sbrec_port_binding *lport_lookup_by_name( > > struct ovsdb_idl_index *sbrec_port_binding_by_name, > > const char *name); > > diff --git a/ovn-nb.xml b/ovn-nb.xml > > index ff5f2f249..55872ea36 100644 > > --- a/ovn-nb.xml > > +++ b/ovn-nb.xml > > @@ -3161,8 +3161,29 @@ or > > for established sessions as we will commit everything in > addition > > to already existing stateful NATs and LBs. > > </column> > > - </group> > > > > + <column name="options" key="ic-route-filter-adv"> > > + <p> > > + This option expects list of CIDRs delimited by "," that's > present > > + in the Logical Router. A route will not be advertised if the > > + route's prefix belongs to any of the CIDRs listed. > > + > > + This allows to filter CIDR prefixes in the process of > advertising > > + routes in <code>ovn-ic</code> daemon. > > + </p> > > + </column> > > + > > + <column name="options" key="ic-route-filter-learn"> > > + <p> > > + This option expects list of CIDRs delimited by "," that's > present > > + in the Logical Router. A route will not be learned if the > > + route's prefix belongs to any of the CIDRs listed. > > + > > + This allows to filter CIDR prefixes in the process of learning > > + routes in <code>ovn-ic</code> daemon. > > + </p> > > + </column> > > + </group> > > Please add a NEWS entry mentioning these new options. Maybe something > like: > > - Added "ic-route-filter-adv" and "ic-route-filter-learn" options to > the Logical_Router/Logical_Router_Port tables to allow users to > filter advertised/learned IC routes. > > > <group title="Common Columns"> > > <column name="external_ids"> > > See <em>External IDs</em> at the beginning of this document. > > @@ -4097,6 +4118,27 @@ or > > instead of the autodiscovery. Also it is then irrelevant if the > port > > is bound locally. > > </column> > > + <column name="options" key="ic-route-filter-adv"> > > + <p> > > + This option expects list of CIDRs delimited by "," that's > present > > + in the Logical Router Port. A route will be advertised if the > > + route's prefix belongs to any of the CIDRs listed. > > + > > + This allows to filter CIDR prefixes in the process of > advertising > > + routes in <code>ovn-ic</code> daemon. > > + </p> > > + </column> > > + > > + <column name="options" key="ic-route-filter-learn"> > > + <p> > > + This option expects list of CIDRs delimited by "," that's > present > > + in the Logical Router Port. A route will be learned if the > > + route's prefix belongs to any of the CIDRs listed. > > + > > + This allows to filter CIDR prefixes in the process of > learning > > + routes in <code>ovn-ic</code> daemon. > > + </p> > > + </column> > > </group> > > > > <group title="Attachment"> > > diff --git a/tests/ovn-ic.at b/tests/ovn-ic.at > > index 0fd38acb2..508db8f75 100644 > > --- a/tests/ovn-ic.at > > +++ b/tests/ovn-ic.at > > @@ -2673,331 +2673,130 @@ OVN_CLEANUP_IC([az1], [az2]) > > AT_CLEANUP > > ]) > > > > + > > OVN_FOR_EACH_NORTHD([ > > -AT_SETUP([spine-leaf: 3 AZs, 3 HVs, 3 LSs, connected via transit spine > switch]) > > Why are we removing this test case? Was it by accident and did you > actually intend to just add a new test case for prefix filters? > > It was by accident, sorry. > > -AT_KEYWORDS([spine leaf]) > > -AT_SKIP_IF([test $HAVE_SCAPY = no]) > > +AT_SETUP([ovn-ic -- prefix filter -- filtering routes]) > > > > ovn_init_ic_db > > +ovn-ic-nbctl ts-add ts1 > > > > -ovn_start az1 > > -ovn_start az2 > > -ovn_start az3 > > +for i in 1 2; do > > + ovn_start az$i > > + ovn_as az$i > > > > -# Logical network: > > -# Single network 172.16.1.0/24. Three switches with VIF ports on HVs > in three > > -# separate AZs, connected to a spine transit switch via 'switch' ports. > > -# Third switch has a port with unknown address, but we're only sending > packets > > -# between ports on other two switches. > > + # Enable route learning at AZ level > > + check ovn-nbctl set nb_global . options:ic-route-learn=true > > + # Enable route advertising at AZ level > > + check ovn-nbctl set nb_global . options:ic-route-adv=true > > +done > > > > -ovn-ic-nbctl ts-add spine > > -ovn_as az1 check ovn-nbctl ls-add ls1 > > -ovn_as az2 check ovn-nbctl ls-add ls2 > > -ovn_as az3 check ovn-nbctl ls-add ls3 > > +# Create new transit switche and LRs. Test topology is next: > > +# logical router (lr11) - transit switch (ts1) - logical router (lr12) > > > > -# Connect ls1 to spine. > > -ovn_as az1 > > -check ovn-nbctl lsp-add spine spine-to-ls1 > > -check ovn-nbctl lsp-add ls1 ls1-to-spine > > -check ovn-nbctl lsp-set-type spine-to-ls1 switch peer=ls1-to-spine > > -check ovn-nbctl lsp-set-type ls1-to-spine switch peer=spine-to-ls1 > > > > -# Connect ls2 to spine. > > -ovn_as az2 > > -check ovn-nbctl lsp-add spine spine-to-ls2 > > -check ovn-nbctl lsp-add ls2 ls2-to-spine > > -check ovn-nbctl lsp-set-type spine-to-ls2 switch peer=ls2-to-spine > > -check ovn-nbctl lsp-set-type ls2-to-spine switch peer=spine-to-ls2 > > - > > -# Connect ls3 to spine. > > -ovn_as az3 > > -check ovn-nbctl lsp-add spine spine-to-ls3 > > -check ovn-nbctl lsp-add ls3 ls3-to-spine > > -check ovn-nbctl lsp-set-type spine-to-ls3 switch peer=ls3-to-spine > > -check ovn-nbctl lsp-set-type ls3-to-spine switch peer=spine-to-ls3 > > - > > -# Create logical port ls1-lp1 in ls1 > > -ovn_as az1 check ovn-nbctl lsp-add ls1 ls1-lp1 \ > > --- lsp-set-addresses ls1-lp1 "f0:00:00:01:02:01 172.16.1.1" > > -# Create logical port ls1-lp2 in ls1 > > -ovn_as az1 check ovn-nbctl lsp-add ls1 ls1-lp2 \ > > --- lsp-set-addresses ls1-lp2 "f0:00:00:01:02:02 172.16.1.2" > > - > > -# Create logical port ls2-lp1 in ls2 > > -ovn_as az2 check ovn-nbctl lsp-add ls2 ls2-lp1 \ > > --- lsp-set-addresses ls2-lp1 "f0:00:00:01:02:03 172.16.1.3" > > -# Create logical port ls2-lp2 in ls2 > > -ovn_as az2 check ovn-nbctl lsp-add ls2 ls2-lp2 \ > > --- lsp-set-addresses ls2-lp2 "f0:00:00:01:02:04 172.16.1.4" > > - > > -# Create logical port ls3-lp1 in ls3 with unknown address. > > -check ovn-nbctl lsp-add ls3 ls3-lp1 -- lsp-set-addresses ls3-lp1 unknown > > - > > -# Create hypervisors and OVS ports corresponding to logical ports. > > -net_add n1 > > +# create lr11, lr12 and connect them to ts1 > > +for i in 1 2; do > > + ovn_as az$i > > > > -sim_add hv1 > > -as hv1 > > -check ovs-vsctl add-br br-phys > > -ovn_az_attach az1 n1 br-phys 192.168.1.1 16 > > -check ovs-vsctl set open . external-ids:ovn-is-interconn=true > > -ovs-vsctl -- add-port br-int vif1 -- \ > > - set interface vif1 external-ids:iface-id=ls1-lp1 \ > > - options:tx_pcap=hv1/vif1-tx.pcap \ > > - options:rxq_pcap=hv1/vif1-rx.pcap \ > > - ofport-request=1 > > -ovs-vsctl -- add-port br-int vif2 -- \ > > - set interface vif2 external-ids:iface-id=ls1-lp2 \ > > - options:tx_pcap=hv1/vif2-tx.pcap \ > > - options:rxq_pcap=hv1/vif2-rx.pcap \ > > - ofport-request=2 > > + lr=lr1$i > > + check ovn-nbctl lr-add $lr > > > > -sim_add hv2 > > -as hv2 > > -check ovs-vsctl add-br br-phys > > -ovn_az_attach az2 n1 br-phys 192.168.2.1 16 > > -check ovs-vsctl set open . external-ids:ovn-is-interconn=true > > -ovs-vsctl -- add-port br-int vif3 -- \ > > - set interface vif3 external-ids:iface-id=ls2-lp1 \ > > - options:tx_pcap=hv2/vif3-tx.pcap \ > > - options:rxq_pcap=hv2/vif3-rx.pcap \ > > - ofport-request=3 > > -ovs-vsctl -- add-port br-int vif4 -- \ > > - set interface vif4 external-ids:iface-id=ls2-lp2 \ > > - options:tx_pcap=hv2/vif4-tx.pcap \ > > - options:rxq_pcap=hv2/vif4-rx.pcap \ > > - ofport-request=4 > > - > > -sim_add hv3 > > -as hv3 > > -check ovs-vsctl add-br br-phys > > -ovn_az_attach az3 n1 br-phys 192.168.3.1 16 > > -check ovs-vsctl set open . external-ids:ovn-is-interconn=true > > -ovs-vsctl -- add-port br-int vif5 -- \ > > - set interface vif5 external-ids:iface-id=ls3-lp1 \ > > - options:tx_pcap=hv3/vif5-tx.pcap \ > > - options:rxq_pcap=hv3/vif5-rx.pcap \ > > - ofport-request=5 > > + lrp=lrp-$lr-ts1 > > + lsp=lsp-ts1-$lr > > + # Create LRP and connect to TS > > + check ovn-nbctl lrp-add $lr $lrp aa:aa:aa:aa:ab:0$i > 169.254.101.$i/24 fe80:10::$i/64 > > + check ovn-nbctl lsp-add ts1 $lsp \ > > + -- lsp-set-addresses $lsp router \ > > + -- lsp-set-type $lsp router \ > > + -- lsp-set-options $lsp router-port=$lrp > > +done > > > > -# Bind transit switch ports to their chassis. > > -check ovn_as az1 ovn-nbctl lsp-set-options spine-to-ls1 > requested-chassis=hv1 > > -check ovn_as az2 ovn-nbctl lsp-set-options spine-to-ls2 > requested-chassis=hv2 > > -check ovn_as az3 ovn-nbctl lsp-set-options spine-to-ls3 > requested-chassis=hv3 > > > > -# Pre-populate the hypervisors' ARP tables so that we don't lose any > > -# packets for ARP resolution (native tunneling doesn't queue packets > > -# for ARP resolution). > > -OVN_POPULATE_ARP > > > > -ovn_as az1 > > -check ovn-nbctl --wait=hv sync > > -ovn-sbctl dump-flows > az1/sbflows > > +# Create directly-connected route in lr12 > > > > -ovn_as az2 > > -check ovn-nbctl --wait=hv sync > > -ovn-sbctl dump-flows > az2/sbflows > > +ovn_as az2 ovn-nbctl lrp-add lr12 lrp-lr12-1 aa:aa:aa:aa:bb:01 " > 192.168.12.1/24" "2001:db12::1/64" > > +ovn_as az2 ovn-nbctl lrp-add lr12 lrp-lr12-2 aa:aa:aa:aa:bb:02 " > 192.168.2.1/24" "2001:db22::1/64" > > > > -ovn_as az3 > > -check ovn-nbctl --wait=hv sync > > -ovn-sbctl dump-flows > az3/sbflows > > > > -dnl Check that FDB learning is enabled for remote ports in the egress > pipeline. > > -AT_CHECK([grep -E "ls_out.*fdb.*spine-to-" az1/sbflows | > ovn_strip_lflows], [0], [dnl > > - table=??(ls_out_lookup_fdb ), priority=100 , match=(inport == > "spine-to-ls2"), action=(reg0[[11]] = lookup_fdb(inport, eth.src); next;) > > - table=??(ls_out_lookup_fdb ), priority=100 , match=(inport == > "spine-to-ls3"), action=(reg0[[11]] = lookup_fdb(inport, eth.src); next;) > > - table=??(ls_out_put_fdb ), priority=100 , match=(inport == > "spine-to-ls2" && reg0[[11]] == 0), action=(put_fdb(inport, eth.src); next;) > > - table=??(ls_out_put_fdb ), priority=100 , match=(inport == > "spine-to-ls3" && reg0[[11]] == 0), action=(put_fdb(inport, eth.src); next;) > > +# Create directly-connected route in lr11 > > +ovn_as az1 ovn-nbctl --wait=sb lrp-add lr11 lrp-lr11 aa:aa:aa:aa:cc:01 " > 192.168.11.1/24" "2001:db11::1/64" > > + > > +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}' | sort ], [0], [dnl > > +192.168.12.0/24 169.254.101.2 > > +192.168.2.0/24 169.254.101.2 > > ]) > > -AT_CHECK([grep -E "ls_out.*fdb.*spine-to-" az2/sbflows | > ovn_strip_lflows], [0], [dnl > > - table=??(ls_out_lookup_fdb ), priority=100 , match=(inport == > "spine-to-ls1"), action=(reg0[[11]] = lookup_fdb(inport, eth.src); next;) > > - table=??(ls_out_lookup_fdb ), priority=100 , match=(inport == > "spine-to-ls3"), action=(reg0[[11]] = lookup_fdb(inport, eth.src); next;) > > - table=??(ls_out_put_fdb ), priority=100 , match=(inport == > "spine-to-ls1" && reg0[[11]] == 0), action=(put_fdb(inport, eth.src); next;) > > - table=??(ls_out_put_fdb ), priority=100 , match=(inport == > "spine-to-ls3" && reg0[[11]] == 0), action=(put_fdb(inport, eth.src); next;) > > + > > +# Test direct routes from lr11 were learned to lr12 > > +OVS_WAIT_FOR_OUTPUT([ovn_as az2 ovn-nbctl lr-route-list lr12 | grep > 192.168 | > > + grep learned | awk '{print $1, $2}' | sort ], [0], [dnl > > +192.168.11.0/24 169.254.101.1 > > ]) > > -AT_CHECK([grep -E "ls_out.*fdb.*spine-to-" az3/sbflows | > ovn_strip_lflows], [0], [dnl > > - table=??(ls_out_lookup_fdb ), priority=100 , match=(inport == > "spine-to-ls1"), action=(reg0[[11]] = lookup_fdb(inport, eth.src); next;) > > - table=??(ls_out_lookup_fdb ), priority=100 , match=(inport == > "spine-to-ls2"), action=(reg0[[11]] = lookup_fdb(inport, eth.src); next;) > > - table=??(ls_out_put_fdb ), priority=100 , match=(inport == > "spine-to-ls1" && reg0[[11]] == 0), action=(put_fdb(inport, eth.src); next;) > > - table=??(ls_out_put_fdb ), priority=100 , match=(inport == > "spine-to-ls2" && reg0[[11]] == 0), action=(put_fdb(inport, eth.src); next;) > > + > > +ovn_as az2 check ovn-nbctl set logical_router_port lrp-lr12-ts1 > options:ic-route-filter-adv=192.168.12.0/24 > > +# 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}' | sort ], [0], [dnl > > +192.168.12.0/24 169.254.101.2 > > ]) > > > > -check ovn-ic-nbctl --wait=sb sync > > +# set ic-route-filter-adv with invalid CIDR to advertise all routes > > +ovn_as az2 check ovn-nbctl set logical_router_port lrp-lr12-ts1 > options:ic-route-filter-adv="192.168.12.0/24,invalid" > > > > -ovn-ic-nbctl show > ic-nbctl.dump > > -AT_CAPTURE_FILE([ic-nbctl.dump]) > > +# 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}' | sort ], [0], [dnl > > +192.168.12.0/24 169.254.101.2 > > +192.168.2.0/24 169.254.101.2 > > +]) > > > > -(echo "---------ISB dump-----" > > - ovn-ic-sbctl show > > - echo "---------------------" > > - ovn-ic-sbctl list gateway > > - echo "---------------------" > > - ovn-ic-sbctl list datapath_binding > > - echo "---------------------" > > - ovn-ic-sbctl list port_binding > > - echo "---------------------" > > - ovn-ic-sbctl list route > > - echo "---------------------") > ic-sbctl.dump > > -AT_CAPTURE_FILE([ic-sbctl.dump]) > > +ovn_as az2 check ovn-nbctl remove logical_router_port lrp-lr12-ts1 > options ic-route-filter-adv > > +ovn_as az1 check ovn-nbctl set logical_router_port lrp-lr11-ts1 > options:ic-route-filter-learn=192.168.2.0/24 > > > > -# Send ip packets between the two ports. > > -src_mac="f0:00:00:01:02:01" > > -dst_mac="f0:00:00:01:02:03" > > -src_ip=172.16.1.1 > > -dst_ip=172.16.1.3 > > -packet=$(fmt_pkt "Ether(dst='${dst_mac}', src='${src_mac}')/ \ > > - IP(src='${src_ip}', dst='${dst_ip}')/ \ > > - UDP(sport=1538, dport=4369)") > > - > > -# Check that datapath is not doing any extra work and sends the packet > out > > -# through the tunnels. We expect the packet to enter the spine switch, > be > > -# sent to userspace for FDB learning, then get broadcasted to other two > > -# zones via remote ports. > > -AT_CHECK([ovn_as az1 as hv1 ovs-appctl ofproto/trace --names \ > > - br-int in_port=vif1 $packet > ofproto-trace-1]) > > -AT_CAPTURE_FILE([ofproto-trace-1]) > > -AT_CHECK([grep 'Megaflow:' ofproto-trace-1], [0], [dnl > > -Megaflow: > recirc_id=0,eth,ip,in_port=vif1,dl_src=f0:00:00:01:02:01,dl_dst=f0:00:00:01:02:03,nw_ecn=0,nw_frag=no > > -]) > > -AT_CHECK([cat ofproto-trace-1 | tail -1 \ > > - | grep -oE > 'tnl_push|userspace|clone|br-phys_n1|vif[[0-9]]'], [0], [dnl > > -userspace > > -clone > > -tnl_push > > -br-phys_n1 > > -tnl_push > > -br-phys_n1 > > -]) > > - > > -# Actually send the packet. > > -check as hv1 ovs-appctl netdev-dummy/receive vif1 $packet > > - > > -# Wait for the FDB entries to be created and propagated to OpenFlow. > Only > > -# one entry will be created - the entry for spine-to-ls1 port in the > spine > > -# switch. > > -ovn_as az1 > > -wait_row_count FDB 1 > > -check ovn-nbctl --wait=hv 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}' | sort ], [0], [dnl > > +192.168.2.0/24 169.254.101.2 > > +]) > > > > -# Two entries are expected in the other zones - one for the remote port > on > > -# the spine switch and one for the switch port on the leaf. > > -ovn_as az2 > > -wait_row_count FDB 2 > > -check ovn-nbctl --wait=hv sync > > -ovn_as az3 > > -wait_row_count FDB 2 > > -check ovn-nbctl --wait=hv sync > > > > -# FDB entry was created from the userspace() action in the datapath, but > > -# those actions will be updated to not have it shortly, so just wait for > > -# that to happen and don't try to catch the action while it's still in > the > > -# datapath. > > -as hv2 ovs-appctl revalidator/wait > > -as hv3 ovs-appctl revalidator/wait > > - > > -# It's a little problematic to trace the other side, but we can check > datapath > > -# actions. Note: 'actions:br-phys' is a stray tunnel packet destined > for the > > -# other zone, but OVS from the 'main' namespace didn't learn addresses > yet, > > -# so it broadcasts. > > -AT_CHECK([as hv2 ovs-appctl dpctl/dump-flows --names \ > > - | grep actions | sed 's/.*\(actions:.*\)/\1/' | sort], [0], > [dnl > > -actions:br-phys > > -actions:tnl_pop(genev_sys_6081) > > -actions:vif3 > > -]) > > -AT_CHECK([as hv3 ovs-appctl dpctl/dump-flows --names \ > > - | grep actions | sed 's/.*\(actions:.*\)/\1/' | sort], [0], > [dnl > > -actions:br-phys > > -actions:tnl_pop(genev_sys_6081) > > -actions:vif5 > > -]) > > - > > -# No modifications expected. > > -AT_CHECK([echo $packet > expected]) > > - > > -AT_CHECK([touch empty]) > > - > > -# Check that it is delivered where needed and not delivered where not. > > -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [empty]) > > -OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [empty]) > > -OVN_CHECK_PACKETS([hv2/vif3-tx.pcap], [expected]) > > -OVN_CHECK_PACKETS([hv2/vif4-tx.pcap], [empty]) > > -OVN_CHECK_PACKETS([hv3/vif5-tx.pcap], [expected]) > > - > > -# Trace a reply packet. > > -reply=$(fmt_pkt "Ether(dst='${src_mac}', src='${dst_mac}')/ \ > > - IP(src='${dst_ip}', dst='${src_ip}')/ \ > > - UDP(sport=4369, dport=1538)") > > -# For the reply packet we expect only one userspace action for FDB > update on > > -# the spine switch and only one tunnel push and send, because we already > > -# learned that MAC of vif1 is behind spine-ls1 and no longer need to > broadcast > > -# to zone 3. > > -AT_CHECK([ovn_as az2 as hv2 ovs-appctl ofproto/trace --names \ > > - br-int in_port=vif3 $reply > ofproto-trace-2]) > > -AT_CAPTURE_FILE([ofproto-trace-2]) > > -AT_CHECK([grep 'Megaflow:' ofproto-trace-2], [0], [dnl > > -Megaflow: > recirc_id=0,eth,ip,in_port=vif3,dl_src=f0:00:00:01:02:03,dl_dst=f0:00:00:01:02:01,nw_ecn=0,nw_frag=no > > -]) > > -AT_CHECK([cat ofproto-trace-2 | tail -1 \ > > - | grep -oE > 'tnl_push|userspace|clone|br-phys_n1|vif[[0-9]]'], [0], [dnl > > -userspace > > -tnl_push > > -br-phys_n1 > > -]) > > - > > -# Now actually send it. > > -check as hv2 ovs-appctl netdev-dummy/receive vif3 $reply > > - > > -AT_CHECK([echo $reply > reply]) > > -# Check that it is delivered where needed and not delivered where not. > > -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [reply]) > > -OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [empty]) > > -OVN_CHECK_PACKETS([hv2/vif3-tx.pcap], [expected]) > > -OVN_CHECK_PACKETS([hv2/vif4-tx.pcap], [empty]) > > -OVN_CHECK_PACKETS([hv3/vif5-tx.pcap], [expected]) > > - > > -# Zones 1 and 2 should have 2 FDB entries now each. One for a remote > port and > > -# one per side of a switch-switch port connecting ls[12] with the > spine. Zone > > -# 3 still only has two entries created for the original request from > vif1. > > -ovn_as az1 > > -wait_row_count FDB 3 > > -check ovn-nbctl --wait=hv sync > > -ovn_as az2 > > -wait_row_count FDB 3 > > -check ovn-nbctl --wait=hv sync > > -ovn_as az3 > > -wait_row_count FDB 2 > > -check ovn-nbctl --wait=hv sync > > +ovn_as az1 check ovn-nbctl remove logical_router_port lrp-lr11-ts1 > options ic-route-filter-learn > > + > > +# Test direct routes from lr12 were learned to lr11 > > Nit (for all comments in the test changes): comments should be > sentences; they should start with a capital letter and end with dot. > > Ok, we'll adjust. > > +OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl lr-route-list lr11 | grep > 2001 | > > + grep learned | awk '{print $1, $2}' | sort ], [0], [dnl > > Nit (for all lr-route-list calls below too): this indentation is a bit > weird, maybe just use 4 spaces before the grep. > > > +2001:db12::/64 fe80:10::2 > > +2001:db22::/64 fe80:10::2 > > +]) > > + > > +ovn_as az2 check ovn-nbctl set logical_router_port lrp-lr12-ts1 > options:ic-route-filter-adv=2001:db22::/64 > > + > > +# Test direct routes from lr12 were learned to lr11 > > +OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl lr-route-list lr11 | grep > 2001 | > > + grep learned | awk '{print $1, $2}' | sort ], [0], [dnl > > +2001:db22::/64 fe80:10::2 > > +]) > > + > > +ovn_as az2 check ovn-nbctl remove logical_router_port lrp-lr12-ts1 > options ic-route-filter-adv > > +# Test direct routes from lr12 were learned to lr11 > > +OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl lr-route-list lr11 | grep > 2001 | > > + grep learned | awk '{print $1, $2}' | sort ], [0], [dnl > > +2001:db12::/64 fe80:10::2 > > +2001:db22::/64 fe80:10::2 > > +]) > > + > > +ovn_as az1 check ovn-nbctl set logical_router_port lrp-lr11-ts1 > options:ic-route-filter-learn=2001:db12::/64 > > +# Test direct routes from lr12 were learned to lr11 > > +OVS_WAIT_FOR_OUTPUT([ovn_as az1 ovn-nbctl lr-route-list lr11 | grep > 2001 | > > + grep learned | awk '{print $1, $2}' | sort ], [0], [dnl > > +2001:db12::/64 fe80:10::2 > > +]) > > + > > +OVN_CLEANUP_IC([az1], [az2]) > > > > -# Packets should flow directly to the destination (via tunnels) in both > > -# directions now. > > -AT_CHECK([as hv1 ovs-appctl ofproto/trace --names \ > > - br-int in_port=vif1 $packet | tail -2 \ > > - | grep -oE > 'Megaflow.*|tnl_push|userspace|clone|br-phys_n1|vif[[0-9]]'], [0], [dnl > > -Megaflow: > recirc_id=0,eth,ip,in_port=vif1,dl_src=f0:00:00:01:02:01,dl_dst=f0:00:00:01:02:03,nw_ecn=0,nw_frag=no > > -tnl_push > > -br-phys_n1 > > -]) > > -AT_CHECK([as hv2 ovs-appctl ofproto/trace --names \ > > - br-int in_port=vif3 $reply | tail -2 \ > > - | grep -oE > 'Megaflow.*|tnl_push|userspace|clone|br-phys_n1|vif[[0-9]]'], [0], [dnl > > -Megaflow: > recirc_id=0,eth,ip,in_port=vif3,dl_src=f0:00:00:01:02:03,dl_dst=f0:00:00:01:02:01,nw_ecn=0,nw_frag=no > > -tnl_push > > -br-phys_n1 > > -]) > > - > > -# Send and check one more time. > > -check as hv1 ovs-appctl netdev-dummy/receive vif1 $packet > > -check as hv2 ovs-appctl netdev-dummy/receive vif3 $reply > > - > > -AT_CHECK([cp expected expected-vif5]) > > -AT_CHECK([echo $packet >> expected]) > > -AT_CHECK([echo $reply >> reply]) > > -OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [reply]) > > -OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [empty]) > > -OVN_CHECK_PACKETS([hv2/vif3-tx.pcap], [expected]) > > -OVN_CHECK_PACKETS([hv2/vif4-tx.pcap], [empty]) > > -OVN_CHECK_PACKETS([hv3/vif5-tx.pcap], [expected-vif5]) > > - > > -OVN_CLEANUP_IC([az1], [az2], [az3]) > > AT_CLEANUP > > ]) > > Regards, > Dumitru > > Regards, Lucas -- _‘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
