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
  • [ovs-dev] [PA... Paulo Guilherme da Silva via dev
    • Re: [ovs... Dumitru Ceara via dev
      • Re: ... Lucas Vargas Dias (Dev - Cloud IaaS Network R&D) via dev
        • ... Dumitru Ceara via dev
    • [ovs-dev... Paulo Guilherme da Silva via dev

Reply via email to