[ovs-dev] [PATCH ovn v9 2/4] northd: Add IP routing and ARP resolution flows for NAT/LB addresses.

Numan Siddique numans at ovn.org
Wed Jul 7 17:28:55 UTC 2021


On Wed, Jun 30, 2021 at 7:57 PM Mark Michelson <mmichels at redhat.com> wrote:
>
> Dealing with NAT and load balancer IPs has been a bit of a pain point.
> It requires creating static routes if east-west traffic to those
> addresses is desired. Further, it requires ARPs to be sent between the
> logical routers in order to create MAC Bindings.
>
> This commit seeks to make things easier. NAT and load balancer addresess
> automatically have IP routing logical flows and ARP resolution logical
> flows created for reachable routers. This eliminates the need to create
> static routes, and it also eliminates the need for ARPs to be sent
> between logical routers.
>
> In this commit, the behavior is not optional. The next commit will
> introduce configuration to make the behavior optional.
>
> Signed-off-by: Mark Michelson <mmichels at redhat.com>

Hi Mark,

There is one small problem.  Please see below.  With that addressed:
Acked-by: Numan Siddique <numans at ovn.org>

Numan

> ---
>  northd/ovn-northd.c  | 129 +++++++++++++++++++++++++-
>  northd/ovn_northd.dl |  57 ++++++++++++
>  tests/ovn-northd.at  | 214 +++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 395 insertions(+), 5 deletions(-)
>
> diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
> index 694c3b2c4..58132bc5c 100644
> --- a/northd/ovn-northd.c
> +++ b/northd/ovn-northd.c
> @@ -1378,6 +1378,21 @@ build_datapaths(struct northd_context *ctx, struct hmap *datapaths,
>      }
>  }
>
> +/* Structure representing logical router port
> + * routable addresses. This includes DNAT and Load Balancer
> + * addresses. This structure will only be filled in if the
> + * router port is a gateway router port. Otherwise, all pointers
> + * will be NULL and n_addrs will be 0.
> + */
> +struct ovn_port_routable_addresses {
> +    /* Array of address strings suitable for writing to a database table */
> +    char **addresses;
> +    /* The addresses field parsed into component parts */
> +    struct lport_addresses *laddrs;
> +    /* Number of items in each of the above arrays */
> +    size_t n_addrs;
> +};
> +
>  /* A logical switch port or logical router port.
>   *
>   * In steady state, an ovn_port points to a northbound Logical_Switch_Port
> @@ -1421,6 +1436,8 @@ struct ovn_port {
>
>      struct lport_addresses lrp_networks;
>
> +    struct ovn_port_routable_addresses routables;
> +
>      /* Logical port multicast data. */
>      struct mcast_port_info mcast_info;
>
> @@ -1447,6 +1464,44 @@ struct ovn_port {
>      struct ovs_list list;       /* In list of similar records. */
>  };
>
> +static void
> +destroy_routable_addresses(struct ovn_port_routable_addresses *ra)
> +{
> +    for (size_t i = 0; i < ra->n_addrs; i++) {
> +        free(ra->addresses[i]);
> +        destroy_lport_addresses(&ra->laddrs[i]);
> +    }
> +    free(ra->addresses);
> +    free(ra->laddrs);
> +}
> +
> +static char **get_nat_addresses(const struct ovn_port *op, size_t *n);
> +
> +static void
> +assign_routable_addresses(struct ovn_port *op)
> +{
> +    size_t n;
> +    char **nats = get_nat_addresses(op, &n);
> +
> +    if (!nats) {
> +        return;
> +    }
> +
> +    struct lport_addresses *laddrs = xcalloc(n, sizeof(*laddrs));
> +    for (size_t i = 0; i < n; i++) {
> +        int ofs;
> +        if (!extract_addresses(nats[i], &laddrs[i], &ofs)){
> +            continue;
> +        }
> +    }
> +
> +    /* Everything seems to have worked out */
> +    op->routables.addresses = nats;
> +    op->routables.laddrs = laddrs;
> +    op->routables.n_addrs = n;

The n_addrs would have the wrong value if 'extract_addresses()' fails.
You probably want to maintain another variable for n_addrs.

Thanks
Numan

> +}
> +
> +
>  static void
>  ovn_port_set_nb(struct ovn_port *op,
>                  const struct nbrec_logical_switch_port *nbsp,
> @@ -1496,6 +1551,8 @@ ovn_port_destroy(struct hmap *ports, struct ovn_port *port)
>          }
>          free(port->ps_addrs);
>
> +        destroy_routable_addresses(&port->routables);
> +
>          destroy_lport_addresses(&port->lrp_networks);
>          free(port->json_key);
>          free(port->key);
> @@ -2403,6 +2460,8 @@ join_logical_ports(struct northd_context *ctx,
>                       * use during flow creation. */
>                      od->l3dgw_port = op;
>                      od->l3redirect_port = crp;
> +
> +                    assign_routable_addresses(op);
>                  }
>              }
>          }
> @@ -2486,7 +2545,7 @@ get_nat_addresses(const struct ovn_port *op, size_t *n)
>  {
>      size_t n_nats = 0;
>      struct eth_addr mac;
> -    if (!op->nbrp || !op->od || !op->od->nbr
> +    if (!op || !op->nbrp || !op->od || !op->od->nbr
>          || (!op->od->nbr->n_nat && !op->od->nbr->n_load_balancer)
>          || !eth_addr_from_string(op->nbrp->mac, &mac)) {
>          *n = n_nats;
> @@ -3067,7 +3126,6 @@ ovn_port_update_sbrec(struct northd_context *ctx,
>              } else {
>                  sbrec_port_binding_set_options(op->sb, NULL);
>              }
> -
>              const char *nat_addresses = smap_get(&op->nbsp->options,
>                                             "nat-addresses");
>              size_t n_nats = 0;
> @@ -3123,6 +3181,7 @@ ovn_port_update_sbrec(struct northd_context *ctx,
>              if (add_router_port_garp) {
>                  struct ds garp_info = DS_EMPTY_INITIALIZER;
>                  ds_put_format(&garp_info, "%s", op->peer->lrp_networks.ea_s);
> +
>                  for (size_t i = 0; i < op->peer->lrp_networks.n_ipv4_addrs;
>                       i++) {
>                      ds_put_format(&garp_info, " %s",
> @@ -3139,7 +3198,6 @@ ovn_port_update_sbrec(struct northd_context *ctx,
>                  nats[n_nats - 1] = ds_steal_cstr(&garp_info);
>                  ds_destroy(&garp_info);
>              }
> -
>              sbrec_port_binding_set_nat_addresses(op->sb,
>                                                   (const char **) nats, n_nats);
>              for (size_t i = 0; i < n_nats; i++) {
> @@ -9910,7 +9968,7 @@ build_ND_RA_flows_for_lrouter(struct ovn_datapath *od, struct hmap *lflows)
>   */
>  static void
>  build_ip_routing_flows_for_lrouter_port(
> -        struct ovn_port *op, struct hmap *lflows)
> +        struct ovn_port *op, struct hmap *ports,struct hmap *lflows)
>  {
>      if (op->nbrp) {
>
> @@ -9927,6 +9985,31 @@ build_ip_routing_flows_for_lrouter_port(
>                        op->lrp_networks.ipv6_addrs[i].plen, NULL, false,
>                        &op->nbrp->header_, false);
>          }
> +    } else if (lsp_is_router(op->nbsp)) {
> +        struct ovn_port *peer = ovn_port_get_peer(ports, op);
> +        if (!peer || !peer->nbrp || !peer->lrp_networks.n_ipv4_addrs) {
> +            return;
> +        }
> +
> +        for (int i = 0; i < op->od->n_router_ports; i++) {
> +            struct ovn_port *router_port = ovn_port_get_peer(
> +                    ports, op->od->router_ports[i]);
> +            if (!router_port || !router_port->nbrp || router_port == peer) {
> +                continue;
> +            }
> +
> +            struct ovn_port_routable_addresses *ra = &router_port->routables;
> +            for (size_t j = 0; j < ra->n_addrs; j++) {
> +                struct lport_addresses *laddrs = &ra->laddrs[j];
> +                for (size_t k = 0; k < laddrs->n_ipv4_addrs; k++) {
> +                    add_route(lflows, peer->od, peer,
> +                              peer->lrp_networks.ipv4_addrs[0].addr_s,
> +                              laddrs->ipv4_addrs[k].network_s,
> +                              laddrs->ipv4_addrs[k].plen, NULL, false,
> +                              &peer->nbrp->header_, false);
> +                }
> +            }
> +        }
>      }
>  }
>
> @@ -10105,6 +10188,36 @@ build_arp_resolve_flows_for_lrouter(
>      }
>  }
>
> +static void
> +routable_addresses_to_lflows(struct hmap *lflows, struct ovn_port *router_port,
> +                             struct ovn_port *peer, struct ds *match,
> +                             struct ds *actions)
> +{
> +    struct ovn_port_routable_addresses *ra = &router_port->routables;
> +    if (!ra->n_addrs) {
> +        return;
> +    }
> +
> +    for (size_t i = 0; i < ra->n_addrs; i++) {
> +        ds_clear(match);
> +        ds_put_format(match, "outport == %s && "REG_NEXT_HOP_IPV4" == {", peer->json_key);
> +        bool first = true;
> +        for (size_t j = 0; j < ra->laddrs[i].n_ipv4_addrs; j++) {
> +            if (!first) {
> +                ds_put_cstr(match, ", ");
> +            }
> +            ds_put_cstr(match, ra->laddrs[i].ipv4_addrs[j].addr_s);
> +            first = false;
> +        }
> +        ds_put_cstr(match, "}");
> +
> +        ds_clear(actions);
> +        ds_put_format(actions, "eth.dst = %s; next;", ra->laddrs[i].ea_s);
> +        ovn_lflow_add(lflows, peer->od, S_ROUTER_IN_ARP_RESOLVE, 100,
> +                      ds_cstr(match), ds_cstr(actions));
> +    }
> +}
> +
>  /* Local router ingress table ARP_RESOLVE: ARP Resolution.
>   *
>   * Any unicast packet that reaches this table is an IP packet whose
> @@ -10427,6 +10540,12 @@ build_arp_resolve_flows_for_lrouter_port(
>                                          ds_cstr(match), ds_cstr(actions),
>                                          &op->nbsp->header_);
>              }
> +
> +            if (smap_get(&peer->od->nbr->options, "chassis") ||
> +                (peer->od->l3dgw_port && peer == peer->od->l3dgw_port)) {
> +                routable_addresses_to_lflows(lflows, router_port, peer,
> +                                             match, actions);
> +            }
>          }
>      }
>
> @@ -11972,7 +12091,7 @@ build_lswitch_and_lrouter_iterate_by_op(struct ovn_port *op,
>                                            &lsi->actions);
>      build_neigh_learning_flows_for_lrouter_port(op, lsi->lflows, &lsi->match,
>                                                  &lsi->actions);
> -    build_ip_routing_flows_for_lrouter_port(op, lsi->lflows);
> +    build_ip_routing_flows_for_lrouter_port(op, lsi->ports, lsi->lflows);
>      build_ND_RA_flows_for_lrouter_port(op, lsi->lflows, &lsi->match,
>                                         &lsi->actions);
>      build_arp_resolve_flows_for_lrouter_port(op, lsi->lflows, lsi->ports,
> diff --git a/northd/ovn_northd.dl b/northd/ovn_northd.dl
> index ce6680e97..35d40ff5a 100644
> --- a/northd/ovn_northd.dl
> +++ b/northd/ovn_northd.dl
> @@ -23,6 +23,7 @@ import multicast
>  import helpers
>  import ipam
>  import vec
> +import set
>
>  index Logical_Flow_Index() on sb::Out_Logical_Flow()
>
> @@ -6467,6 +6468,45 @@ Route(key, dst.port, dst.src_ip, Some{dst.nexthop}) :-
>      dsts.size() == 1,
>      Some{var dst} = dsts.nth(0).
>
> +/* Create routes from peer to port's routable addresses */
> +Route(key, peer, src_ip, None) :-
> +    RouterPortRoutableAddresses(port, addresses),
> +    FirstHopRouterPortRoutableAddresses(port, peer_uuid),
> +    peer_lrp in &nb::Logical_Router_Port(._uuid = peer_uuid),
> +    peer in &RouterPort(.lrp = peer_lrp, .networks = networks),
> +    Some{var src} = networks.ipv4_addrs.first(),
> +    var src_ip = IPv4{src.addr},
> +    var addr = FlatMap(addresses),
> +    var ip4_addr = FlatMap(addr.ipv4_addrs),
> +    var key = RouteKey{DstIp, IPv4{ip4_addr.addr}, ip4_addr.plen}.
> +
> +/* This relation indicates that logical router port "port" has routable
> + * addresses (i.e. DNAT and Load Balancer VIPs) and that logical router
> + * port "peer" is reachable via a hop across a single logical switch.
> + */
> +relation FirstHopRouterPortRoutableAddresses(
> +    port: uuid,
> +    peer: uuid)
> +FirstHopRouterPortRoutableAddresses(port_uuid, peer_uuid) :-
> +    FirstHopLogicalRouter(r1, ls),
> +    FirstHopLogicalRouter(r2, ls),
> +    r1 != r2,
> +    LogicalRouterPort(port_uuid, r1),
> +    LogicalRouterPort(peer_uuid, r2),
> +    RouterPortRoutableAddresses(.rport = port_uuid),
> +    lrp in &nb::Logical_Router_Port(._uuid = port_uuid),
> +    peer_lrp in &nb::Logical_Router_Port(._uuid = peer_uuid),
> +    LogicalSwitchRouterPort(_, lrp.name, ls),
> +    LogicalSwitchRouterPort(_, peer_lrp.name, ls).
> +
> +relation RouterPortRoutableAddresses(
> +    rport: uuid,
> +    addresses: Set<lport_addresses>)
> +RouterPortRoutableAddresses(port.lrp._uuid, addresses) :-
> +    port in &RouterPort(.is_redirect = true),
> +    var addresses = get_nat_addresses(port).filter_map(extract_addresses),
> +    addresses != set_empty().
> +
>  /* Return a vector of pairs (1, set[0]), ... (n, set[n - 1]). */
>  function numbered_vec(set: Set<'A>) : Vec<(bit<16>, 'A)> = {
>      var vec = vec_with_capacity(set.size());
> @@ -6954,6 +6994,23 @@ Flow(.logical_datapath = lr_uuid,
>      snat_ips.contains_key(IPv6{addr.addr}),
>      var match_ips = "${addr.addr}".group_by((lr_uuid, lrp_uuid)).to_vec().
>
> +/* Create ARP resolution flows for NAT and LB addresses for first hop
> + * logical routers
> + */
> +Flow(.logical_datapath = peer.router._uuid,
> +     .stage = s_ROUTER_IN_ARP_RESOLVE(),
> +     .priority = 100,
> +     .__match = "outport == ${peer.json_name} && " ++ rEG_NEXT_HOP() ++ " == {${ips}}",
> +     .actions = "eth.dst = ${addr.ea}; next;",
> +     .external_ids = stage_hint(lrp._uuid)) :-
> +     RouterPortRoutableAddresses(port, addresses),
> +     FirstHopRouterPortRoutableAddresses(port, peer_uuid),
> +     peer in &RouterPort(.lrp = lrp),
> +     lrp._uuid == peer_uuid,
> +     not peer.router.options.get_bool_def("dynamic_neigh_routers", false),
> +     var addr = FlatMap(addresses),
> +     var ips = addr.ipv4_addrs.map(|a| a.addr.to_string()).join(", ").
> +
>  /* This is a logical switch port that backs a VM or a container.
>   * Extract its addresses. For each of the address, go through all
>   * the router ports attached to the switch (to which this port
> diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
> index 2c811f094..feb38ea5e 100644
> --- a/tests/ovn-northd.at
> +++ b/tests/ovn-northd.at
> @@ -3787,3 +3787,217 @@ AT_CHECK([grep -w "ls_in_dhcp_options" sw0flows | sort], [0], [dnl
>
>  AT_CLEANUP
>  ])
> +
> +# XXX This test currently only runs for ovn-northd.c. The test fails
> +# with ovn-northd-ddlog because of the section where 2 HA_Chassis_Groups
> +# are used by 2 routers. For some reason, this causes ovn-northd-ddlog
> +# to stop processing new changes to the northbound database and to
> +# seemingly infinitely loop. This issue has been reported, but there is
> +# currently no fix for it. Once this issue is fixed, we can run this
> +# test for both C and DDLog versions of northd.
> +AT_SETUP([ovn -- NAT and Load Balancer flows])
> +
> +# Determine if expected flows are present. The only parameter to this
> +# function is the number of expected flows per NAT destination address.
> +# This should always be either 0 or 1. 0 means that we do not expect
> +# lflows to be present. 1 means we expect an lflow to be present
> +check_lflows() {
> +    expected=$1
> +    ro1_flows=$(ovn-sbctl lflow-list ro1)
> +
> +    ro1_ip_routing=$(grep lr_in_ip_routing <<< "$ro1_flows")
> +    match=$(grep -c "match=(ip4.dst == 20.0.0.100/32)" <<< "$ro1_ip_routing")
> +    AT_CHECK([test "$expected" = "$match"])
> +
> +    ro1_arp_resolve=$(grep lr_in_arp_resolve <<< "$ro1_flows")
> +    match=$(grep -c 'match=(outport == "ro1-sw" && reg0 == {20.0.0.100})' <<< "$ro1_arp_resolve")
> +    AT_CHECK([test "$expected" = "$match"])
> +
> +    ro2_flows=$(ovn-sbctl lflow-list ro2)
> +
> +    ro2_ip_routing=$(grep lr_in_ip_routing <<< "$ro2_flows")
> +    match=$(grep -c "match=(ip4.dst == 10.0.0.100/32)" <<< "$ro2_ip_routing")
> +    AT_CHECK([test "$expected" = "$match"])
> +
> +    ro2_arp_resolve=$(grep lr_in_arp_resolve <<< "$ro2_flows")
> +    match=$(grep -c 'match=(outport == "ro2-sw" && reg0 == {10.0.0.100})' <<< "$ro2_arp_resolve")
> +    AT_CHECK([test "$expected" = "$match"])
> +}
> +
> +ovn_start
> +
> +AS_BOX([Setting up the logical network])
> +
> +check ovn-nbctl ls-add sw
> +
> +check ovn-nbctl lr-add ro1
> +check ovn-nbctl lrp-add ro1 ro1-sw 00:00:00:00:00:01 10.0.0.1/24
> +check ovn-nbctl lsp-add sw sw-ro1
> +
> +check ovn-nbctl lr-add ro2
> +check ovn-nbctl lrp-add ro2 ro2-sw 00:00:00:00:00:02 20.0.0.1/24
> +check ovn-nbctl --wait=sb lsp-add sw sw-ro2
> +
> +check ovn-nbctl ls-add ls1
> +check ovn-nbctl lsp-add ls1 vm1
> +check ovn-nbctl lsp-set-addresses vm1 "00:00:00:00:01:02 192.168.1.2"
> +check ovn-nbctl lrp-add ro1 ro1-ls1 00:00:00:00:01:01 192.168.1.1/24
> +check ovn-nbctl lsp-add ls1 ls1-ro1
> +check ovn-nbctl lsp-set-type ls1-ro1 router
> +check ovn-nbctl lsp-set-addresses ls1-ro1 router
> +check ovn-nbctl lsp-set-options ls1-ro1 router-port=ro1-ls1
> +
> +check ovn-nbctl ls-add ls2
> +check ovn-nbctl lsp-add ls2 vm2
> +check ovn-nbctl lsp-set-addresses vm2 "00:00:00:00:02:02 192.168.2.2"
> +check ovn-nbctl lrp-add ro2 ro2-ls2 00:00:00:00:02:01 192.168.2.1/24
> +check ovn-nbctl lsp-add ls2 ls2-ro2
> +check ovn-nbctl lsp-set-type ls2-ro2 router
> +check ovn-nbctl lsp-set-addresses ls2-ro2 router
> +check ovn-nbctl lsp-set-options ls2-ro2 router-port=ro2-ls2
> +
> +check ovn-nbctl ha-chassis-group-add grp1
> +check ovn-nbctl ha-chassis-group-add-chassis grp1 hv1 100
> +grp1_uuid=$(ovn-nbctl --columns=_uuid --bare find HA_Chassis_group name=grp1)
> +
> +check ovn-nbctl ha-chassis-group-add grp2
> +check ovn-nbctl ha-chassis-group-add-chassis grp2 hv2 100
> +grp2_uuid=$(ovn-nbctl --columns=_uuid --bare find HA_Chassis_group name=grp2)
> +
> +AS_BOX([Checking that unconnected logical switch ports generate no lflows])
> +
> +check_lflows 0
> +
> +AS_BOX([Checking that connected logical switch ports have no lflows for non-gateway ports])
> +
> +check ovn-nbctl lsp-set-type sw-ro1 router
> +check ovn-nbctl lsp-set-addresses sw-ro1 router
> +check ovn-nbctl lsp-set-options sw-ro1 router-port=ro1-sw
> +
> +check ovn-nbctl lsp-set-type sw-ro2 router
> +check ovn-nbctl lsp-set-addresses sw-ro2 router
> +check ovn-nbctl --wait=sb lsp-set-options sw-ro2 router-port=ro2-sw
> +
> +check_lflows 0
> +
> +AS_BOX([Checking that NAT flows are not installed for non-gateway routers])
> +
> +check ovn-nbctl lr-nat-add ro1 dnat 10.0.0.100 192.168.1.100
> +check ovn-nbctl lr-nat-add ro2 dnat 20.0.0.100 192.168.2.100
> +
> +check_lflows 0
> +
> +AS_BOX([Checking that NAT flows are installed for gateway routers])
> +
> +check ovn-nbctl lrp-set-gateway-chassis ro1-sw hv1 100
> +check ovn-nbctl --wait=sb lrp-set-gateway-chassis ro2-sw hv2 100
> +
> +check_lflows 1
> +
> +AS_BOX([Checking that NAT flows are not installed for routers with gateway chassis removed])
> +
> +check ovn-nbctl lrp-del-gateway-chassis ro1-sw hv1
> +check ovn-nbctl --wait=sb lrp-del-gateway-chassis ro2-sw hv2
> +
> +check_lflows 0
> +
> +AS_BOX([Checking that NAT flows are installed for routers with HA_Chassis_Group])
> +
> +check ovn-nbctl set logical_router_port ro1-sw ha_chassis_group="$grp1_uuid"
> +check ovn-nbctl --wait=sb set logical_router_port ro2-sw ha_chassis_group="$grp2_uuid"
> +
> +check_lflows 1
> +
> +AS_BOX([Checking that NAT flows are not installed for routers with HA_Chassis_Group removed])
> +
> +check ovn-nbctl clear logical_router_port ro1-sw ha_chassis_group
> +check ovn-nbctl --wait=sb clear logical_router_port ro2-sw ha_chassis_group
> +
> +check_lflows 0
> +
> +AS_BOX([Checking that Floating IP NAT flows are not installed with no gateway port set])
> +
> +check ovn-nbctl lr-nat-del ro1
> +check ovn-nbctl lr-nat-del ro2
> +
> +check ovn-nbctl lr-nat-add ro1 dnat_and_snat 10.0.0.100 192.168.1.2 vm1 00:00:00:00:00:01
> +check ovn-nbctl lr-nat-add ro2 dnat_and_snat 20.0.0.100 192.168.2.2 vm2 00:00:00:00:00:02
> +
> +check_lflows 0
> +
> +AS_BOX([Checking that Floating IP NAT flows are installed for gateway routers])
> +
> +check ovn-nbctl lrp-set-gateway-chassis ro1-sw hv1 100
> +check ovn-nbctl --wait=sb lrp-set-gateway-chassis ro2-sw hv2 100
> +
> +check_lflows 1
> +
> +AS_BOX([Checking that Floating IP NAT flows are not installed for routers with gateway chassis removed])
> +
> +check ovn-nbctl lrp-del-gateway-chassis ro1-sw hv1
> +check ovn-nbctl --wait=sb lrp-del-gateway-chassis ro2-sw hv2
> +
> +check_lflows 0
> +
> +AS_BOX([Checking that Floating IP NAT flows are installed for routers with ha_chassis_group])
> +
> +grp1_uuid=$(ovn-nbctl --columns=_uuid --bare find HA_Chassis_group name=grp1)
> +check ovn-nbctl set logical_router_port ro1-sw ha_chassis_group="$grp1_uuid"
> +
> +grp2_uuid=$(ovn-nbctl --columns=_uuid --bare find HA_Chassis_group name=grp2)
> +check ovn-nbctl --wait=sb set logical_router_port ro2-sw ha_chassis_group="$grp2_uuid"
> +
> +check_lflows 1
> +
> +AS_BOX([Checking that Floating IP NAT flows are not installed for routers with HA_Chassis_Group removed])
> +
> +check ovn-nbctl clear logical_router_port ro1-sw ha_chassis_group
> +check ovn-nbctl --wait=sb clear logical_router_port ro2-sw ha_chassis_group
> +
> +check_lflows 0
> +
> +AS_BOX([Checking that Load Balancer VIP flows are not installed for routers with no gateway port])
> +
> +check ovn-nbctl lr-nat-del ro1
> +check ovn-nbctl lr-nat-del ro2
> +
> +check ovn-nbctl lb-add lb1 10.0.0.100 192.168.1.2
> +check ovn-nbctl lr-lb-add ro1 lb1
> +
> +check ovn-nbctl lb-add lb2 20.0.0.100 192.168.2.2
> +check ovn-nbctl lr-lb-add ro2 lb2
> +
> +check_lflows 0
> +
> +AS_BOX([Checking that Load Balancer VIP flows are installed for gateway routers])
> +
> +check ovn-nbctl lrp-set-gateway-chassis ro1-sw hv1 100
> +check ovn-nbctl --wait=sb lrp-set-gateway-chassis ro2-sw hv2 100
> +
> +check_lflows 1
> +
> +AS_BOX([Checking that Load Balancer VIP flows are not installed for routers with gateway chassis removed])
> +
> +check ovn-nbctl lrp-del-gateway-chassis ro1-sw hv1
> +check ovn-nbctl --wait=sb lrp-del-gateway-chassis ro2-sw hv2
> +
> +check_lflows 0
> +
> +AS_BOX([Checking that Load Balancer VIP flows are installed for routers with ha_chassis_group])
> +
> +grp1_uuid=$(ovn-nbctl --columns=_uuid --bare find HA_Chassis_group name=grp1)
> +check ovn-nbctl set logical_router_port ro1-sw ha_chassis_group="$grp1_uuid"
> +
> +grp2_uuid=$(ovn-nbctl --columns=_uuid --bare find HA_Chassis_group name=grp2)
> +check ovn-nbctl --wait=sb set logical_router_port ro2-sw ha_chassis_group="$grp2_uuid"
> +
> +check_lflows 1
> +
> +AS_BOX([Checking that Load Balancer VIP flows are not iinstalled for routers with HA_Chassis_Group removed])
> +
> +check ovn-nbctl clear logical_router_port ro1-sw ha_chassis_group
> +check ovn-nbctl --wait=sb clear logical_router_port ro2-sw ha_chassis_group
> +
> +check_lflows 0
> +
> +AT_CLEANUP
> --
> 2.31.1
>
> _______________________________________________
> dev mailing list
> dev at openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>


More information about the dev mailing list