> In an interconnect topology, when a logical router (LR) is connected to a
> transit-switch (TS), the static routes on the LR as well as routes for the
> connected subnets get advertised to the other sites via the IC-SB.
> 
> This commit adds two new nb_global options ic-route-adv-lb and
> ic-route-learn-lb, which will help propagate the LB VIP based routes.
> Default value for both the options is false. Also these options come into
> effect only if the exisiting options ic-route-adv and ic-route-learn are
> true.
> 
> ic-route-adv-lb: If this is set to true, add routes in the IC-SB for the
> VIPs associated with the LB instances linked to the logical router. These
> routes would have the VIP as destination and IP of the LRP connected to TS
> as next hop The origin would be set as "loadbalancer".
> 
> ic-route-learn-lb: If this is set to true, routes with origin loadbalancer
> are synced from the IC-SB and applied to the LR as learned route.
> 
> This change makes services hosted behind LB in one site become accessible by
> clients in other locations, via interconnect.
> 
> Signed-off-by: Sragdhara Datta Chaudhuri <[email protected]>

Acked-by: Lorenzo Bianconi <[email protected]>

> 
> ---
> v2: Address Lorenzo's comments.
> ---
>  ic/ovn-ic.c         | 198 +++++++++++++++++++++++++++--
>  lib/ovn-util.h      |   1 +
>  ovn-ic-sb.ovsschema |   7 +-
>  ovn-ic-sb.xml       |  10 +-
>  ovn-nb.xml          |  21 +++-
>  tests/ovn-ic.at     | 295 ++++++++++++++++++++++++++++++++++++++++++++
>  6 files changed, 517 insertions(+), 15 deletions(-)
> 
> diff --git a/ic/ovn-ic.c b/ic/ovn-ic.c
> index c8796680b..f1abdcb05 100644
> --- a/ic/ovn-ic.c
> +++ b/ic/ovn-ic.c
> @@ -939,14 +939,17 @@ struct ic_route_info {
>  
>      const struct nbrec_logical_router *nb_lr;
>  
> -    /* Either nb_route or nb_lrp is set and the other one must be NULL.
> +    /* One of nb_route, nb_lrp, nb_lb is set and the other ones must be NULL.
>       * - For a route that is learned from IC-SB, or a static route that is
>       *   generated from a route that is configured in NB, the "nb_route"
>       *   is set.
>       * - For a route that is generated from a direct-connect subnet of
> -     *   a logical router port, the "nb_lrp" is set. */
> +     *   a logical router port, the "nb_lrp" is set.
> +     * - For a route that is generated from a load-balancer vip of
> +     *   a logical router, the "nb_lb" is set. */
>      const struct nbrec_logical_router_static_route *nb_route;
>      const struct nbrec_logical_router_port *nb_lrp;
> +    const struct nbrec_load_balancer *nb_lb;
>  };
>  
>  static uint32_t
> @@ -1163,9 +1166,10 @@ add_to_routes_ad(struct hmap *routes_ad, const struct 
> in6_addr prefix,
>                   const struct nbrec_logical_router_port *nb_lrp,
>                   const struct nbrec_logical_router_static_route *nb_route,
>                   const struct nbrec_logical_router *nb_lr,
> +                 const struct nbrec_load_balancer *nb_lb,
>                   const char *route_tag)
>  {
> -    ovs_assert(nb_route || nb_lrp);
> +    ovs_assert(nb_route || nb_lrp || nb_lb);
>  
>      if (route_table == NULL) {
>          route_table = "";
> @@ -1184,6 +1188,7 @@ add_to_routes_ad(struct hmap *routes_ad, const struct 
> in6_addr prefix,
>          ic_route->route_table = route_table;
>          ic_route->nb_lrp = nb_lrp;
>          ic_route->nb_lr = nb_lr;
> +        ic_route->nb_lb = nb_lb;
>          ic_route->route_tag = route_tag;
>          hmap_insert(routes_ad, &ic_route->node, hash);
>      } else {
> @@ -1193,6 +1198,9 @@ add_to_routes_ad(struct hmap *routes_ad, const struct 
> in6_addr prefix,
>          if (nb_route) {
>              VLOG_WARN_RL(&rl, msg_fmt, origin, "route",
>                           UUID_ARGS(&nb_route->header_.uuid));
> +        } else if (nb_lb) {
> +            VLOG_WARN_RL(&rl, msg_fmt, origin, "loadbalancer",
> +                         UUID_ARGS(&nb_lb->header_.uuid));
>          } else {
>              VLOG_WARN_RL(&rl, msg_fmt, origin, "lrp",
>                           UUID_ARGS(&nb_lrp->header_.uuid));
> @@ -1248,7 +1256,8 @@ add_static_to_routes_ad(
>      }
>  
>      add_to_routes_ad(routes_ad, prefix, plen, nexthop, ROUTE_ORIGIN_STATIC,
> -                     nb_route->route_table, NULL, nb_route, nb_lr, 
> route_tag);
> +                     nb_route->route_table, NULL, nb_route, nb_lr,
> +                     NULL, route_tag);
>  }
>  
>  static void
> @@ -1296,7 +1305,65 @@ add_network_to_routes_ad(struct hmap *routes_ad, const 
> char *network,
>  
>      /* directly-connected routes go to <main> route table */
>      add_to_routes_ad(routes_ad, prefix, plen, nexthop, 
> ROUTE_ORIGIN_CONNECTED,
> -                     NULL, nb_lrp, NULL, nb_lr, route_tag);
> +                     NULL, nb_lrp, NULL, nb_lr, NULL, route_tag);
> +}
> +
> +static void
> +add_lb_vip_to_routes_ad(struct hmap *routes_ad, const char *vip_key,
> +                        const struct nbrec_load_balancer *nb_lb,
> +                        const struct lport_addresses *nexthop_addresses,
> +                        const struct smap *nb_options,
> +                        const struct nbrec_logical_router *nb_lr,
> +                        const char *route_tag)
> +{
> +    char *vip_str = NULL;
> +    struct in6_addr vip_ip, nexthop;
> +    uint16_t vip_port;
> +    int addr_family;
> +    static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
> +
> +    if (!ip_address_and_port_from_lb_key(vip_key, &vip_str, &vip_ip,
> +                                         &vip_port, &addr_family)) {
> +        VLOG_WARN_RL(&rl, "Route ad: Parsing failed for lb vip %s", vip_key);
> +        return;
> +    }
> +    if (vip_str == NULL) {
> +        return;
> +    }
> +    unsigned int plen = (addr_family == AF_INET) ? 32 : 128;
> +    if (!route_need_advertise(NULL, &vip_ip, plen, nb_options)) {
> +        VLOG_DBG("Route ad: skip lb vip %s.", vip_key);
> +        goto out;
> +    }
> +    if (!get_nexthop_from_lport_addresses(IN6_IS_ADDR_V4MAPPED(&vip_ip),
> +                                          nexthop_addresses,
> +                                          &nexthop)) {
> +        VLOG_WARN_RL(&rl, "Route ad: failed to get nexthop for lb vip");
> +        goto out;
> +    }
> +
> +    if (VLOG_IS_DBG_ENABLED()) {
> +        struct ds msg = DS_EMPTY_INITIALIZER;
> +
> +        ds_put_format(&msg, "Adding lb vip route to <main> routing "
> +                      "table: %s, nexthop ", vip_str);
> +
> +        if (IN6_IS_ADDR_V4MAPPED(&nexthop)) {
> +            ds_put_format(&msg, IP_FMT,
> +                          IP_ARGS(in6_addr_get_mapped_ipv4(&nexthop)));
> +        } else {
> +            ipv6_format_addr(&nexthop, &msg);
> +        }
> +
> +        VLOG_DBG("%s", ds_cstr(&msg));
> +        ds_destroy(&msg);
> +    }
> +
> +    /* Lb vip routes go to <main> route table */
> +    add_to_routes_ad(routes_ad, vip_ip, plen, nexthop, ROUTE_ORIGIN_LB,
> +                     NULL, NULL, NULL, nb_lr, nb_lb, route_tag);
> +out:
> +    free(vip_str);
>  }
>  
>  static bool
> @@ -1315,6 +1382,45 @@ route_has_local_gw(const struct nbrec_logical_router 
> *lr,
>      return false;
>  }
>  
> +static bool
> +route_matches_local_lb(const struct nbrec_load_balancer *nb_lb,
> +                       const char *ip_prefix)
> +{
> +    char *vip_str = NULL;
> +    struct in6_addr vip_ip;
> +    uint16_t vip_port;
> +    int addr_family;
> +    unsigned int plen;
> +    char vip_cidr[50];
> +    struct smap_node *node;
> +    static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1);
> +
> +    SMAP_FOR_EACH (node, &nb_lb->vips) {
> +        if (node->key) {
> +            if (ip_address_and_port_from_lb_key(node->key, &vip_str,
> +                                                &vip_ip, &vip_port,
> +                                                &addr_family)) {
> +                if (vip_str) {
> +                    plen = (addr_family == AF_INET) ? 32 : 128;
> +                    snprintf(vip_cidr, sizeof(vip_cidr), "%s/%d",
> +                             vip_str, plen);
> +                    if (!strcmp(vip_cidr, ip_prefix)) {
> +                       free(vip_str);
> +                       return true;
> +                    }
> +                }
> +            } else {
> +                VLOG_WARN_RL(
> +                    &rl,
> +                    "Route learn: Parsing failed for local lb vip %s",
> +                    node->key);
> +            }
> +        }
> +    }
> +    free(vip_str);
> +    return false;
> +}
> +
>  static bool
>  route_need_learn(const struct nbrec_logical_router *lr,
>                   const struct icsbrec_route *isb_route,
> @@ -1330,6 +1436,11 @@ route_need_learn(const struct nbrec_logical_router *lr,
>          return false;
>      }
>  
> +    if (!strcmp(isb_route->origin, ROUTE_ORIGIN_LB) &&
> +        !smap_get_bool(nb_options, "ic-route-learn-lb", false)) {
> +        return false;
> +    }
> +
>      if (prefix_is_link_local(prefix, plen)) {
>          return false;
>      }
> @@ -1344,6 +1455,29 @@ route_need_learn(const struct nbrec_logical_router *lr,
>          return false;
>      }
>  
> +    for (int i = 0; i < lr->n_load_balancer; i++) {
> +        if (route_matches_local_lb(lr->load_balancer[i],
> +                                   isb_route->ip_prefix)) {
> +            VLOG_DBG("Skip learning %s (rtb:%s) route, as we've got local"
> +                     " LB with matching VIP", isb_route->ip_prefix,
> +                     isb_route->route_table);
> +            return false;
> +        }
> +    }
> +    for (int i = 0; i < lr->n_load_balancer_group; i++) {
> +        const struct nbrec_load_balancer_group *nb_lbg;
> +        nb_lbg = lr->load_balancer_group[i];
> +        for (int j = 0; j < nb_lbg->n_load_balancer; j++) {
> +            if (route_matches_local_lb(nb_lbg->load_balancer[j],
> +                                       isb_route->ip_prefix)) {
> +                VLOG_DBG("Skip learning %s (rtb:%s) route, as we've got 
> local"
> +                         " LB with matching VIP", isb_route->ip_prefix,
> +                         isb_route->route_table);
> +                return false;
> +            }
> +        }
> +    }
> +
>      return true;
>  }
>  
> @@ -1535,8 +1669,10 @@ ad_route_sync_external_ids(const struct ic_route_info 
> *route_adv,
>      const char *route_tag;
>      smap_get_uuid(&isb_route->external_ids, "nb-id", &isb_ext_id);
>      smap_get_uuid(&isb_route->external_ids, "lr-id", &isb_ext_lr_id);
> -    nb_id = route_adv->nb_route ? route_adv->nb_route->header_.uuid
> -                               : route_adv->nb_lrp->header_.uuid;
> +    nb_id = route_adv->nb_lb ? route_adv->nb_lb->header_.uuid :
> +            route_adv->nb_route ? route_adv->nb_route->header_.uuid :
> +            route_adv->nb_lrp->header_.uuid;
> +
>      lr_id = route_adv->nb_lr->header_.uuid;
>      if (!uuid_equals(&isb_ext_id, &nb_id)) {
>          char *uuid_s = xasprintf(UUID_FMT, UUID_ARGS(&nb_id));
> @@ -1696,6 +1832,40 @@ build_ts_routes_to_adv(struct ic_context *ctx,
>                       lrp->name);
>          }
>      }
> +
> +    /* Check loadbalancers associated with the LR */
> +    if (smap_get_bool(&nb_global->options, "ic-route-adv-lb", false)) {
> +        for (int i = 0; i < lr->n_load_balancer; i++) {
> +            const struct nbrec_load_balancer *nb_lb = lr->load_balancer[i];
> +            struct smap_node *node;
> +            SMAP_FOR_EACH (node, &nb_lb->vips) {
> +                if (node->key) {
> +                    add_lb_vip_to_routes_ad(routes_ad, node->key, nb_lb,
> +                                            ts_port_addrs,
> +                                            &nb_global->options,
> +                                            lr, route_tag);
> +                }
> +            }
> +        }
> +
> +        for (int i = 0; i < lr->n_load_balancer_group; i++) {
> +            const struct nbrec_load_balancer_group *nb_lbg;
> +            nb_lbg = lr->load_balancer_group[i];
> +            for (int j = 0; j < nb_lbg->n_load_balancer; j++) {
> +                const struct nbrec_load_balancer *nb_lb;
> +                nb_lb = nb_lbg->load_balancer[j];
> +                struct smap_node *node;
> +                SMAP_FOR_EACH (node, &nb_lb->vips) {
> +                    if (node->key) {
> +                        add_lb_vip_to_routes_ad(routes_ad, node->key, nb_lb,
> +                                                ts_port_addrs,
> +                                                &nb_global->options,
> +                                                lr, route_tag);
> +                    }
> +                }
> +            }
> +        }
> +    }
>  }
>  
>  static void
> @@ -2213,6 +2383,10 @@ main(int argc, char *argv[])
>                           &nbrec_logical_router_col_options);
>      ovsdb_idl_add_column(ovnnb_idl_loop.idl,
>                           &nbrec_logical_router_col_external_ids);
> +    ovsdb_idl_add_column(ovnnb_idl_loop.idl,
> +                         &nbrec_logical_router_col_load_balancer);
> +    ovsdb_idl_add_column(ovnnb_idl_loop.idl,
> +                         &nbrec_logical_router_col_load_balancer_group);
>  
>      ovsdb_idl_add_table(ovnnb_idl_loop.idl, 
> &nbrec_table_logical_router_port);
>      ovsdb_idl_add_column(ovnnb_idl_loop.idl,
> @@ -2252,6 +2426,16 @@ main(int argc, char *argv[])
>      ovsdb_idl_add_column(ovnnb_idl_loop.idl,
>                           &nbrec_logical_switch_port_col_external_ids);
>  
> +    ovsdb_idl_add_table(ovnnb_idl_loop.idl,
> +                        &nbrec_table_load_balancer);
> +    ovsdb_idl_add_column(ovnnb_idl_loop.idl,
> +                         &nbrec_load_balancer_col_vips);
> +
> +    ovsdb_idl_add_table(ovnnb_idl_loop.idl,
> +                        &nbrec_table_load_balancer_group);
> +    ovsdb_idl_add_column(ovnnb_idl_loop.idl,
> +                         &nbrec_load_balancer_group_col_load_balancer);
> +
>      /* ovn-sb db. */
>      struct ovsdb_idl_loop ovnsb_idl_loop = OVSDB_IDL_LOOP_INITIALIZER(
>          ovsdb_idl_create(ovnsb_db, &sbrec_idl_class, false, true));
> diff --git a/lib/ovn-util.h b/lib/ovn-util.h
> index 0fff9b463..5db7cb8d4 100644
> --- a/lib/ovn-util.h
> +++ b/lib/ovn-util.h
> @@ -30,6 +30,7 @@
>  
>  #define ROUTE_ORIGIN_CONNECTED "connected"
>  #define ROUTE_ORIGIN_STATIC "static"
> +#define ROUTE_ORIGIN_LB "loadbalancer"
>  
>  #define ETH_CRC_LENGTH 4
>  #define ETHERNET_OVERHEAD (ETH_HEADER_LEN + ETH_CRC_LENGTH)
> diff --git a/ovn-ic-sb.ovsschema b/ovn-ic-sb.ovsschema
> index 459c3833e..e92cf8f58 100644
> --- a/ovn-ic-sb.ovsschema
> +++ b/ovn-ic-sb.ovsschema
> @@ -1,7 +1,7 @@
>  {
>      "name": "OVN_IC_Southbound",
> -    "version": "2.0.0",
> -    "cksum": "197748428 7081",
> +    "version": "2.0.1",
> +    "cksum": "3470037528 7126",
>      "tables": {
>          "IC_SB_Global": {
>              "columns": {
> @@ -99,7 +99,8 @@
>                  "nexthop": {"type": "string"},
>                  "origin": {"type": {"key": {
>                      "type": "string",
> -                    "enum": ["set", ["connected", "static"]]}}},
> +                    "enum": ["set",
> +                             ["connected", "static", "loadbalancer"]]}}},
>                  "external_ids": {
>                      "type": {"key": "string", "value": "string",
>                               "min": 0, "max": "unlimited"}}},
> diff --git a/ovn-ic-sb.xml b/ovn-ic-sb.xml
> index 5f0743dc3..8f98c7ebb 100644
> --- a/ovn-ic-sb.xml
> +++ b/ovn-ic-sb.xml
> @@ -356,10 +356,12 @@
>        </column>
>  
>        <column name="origin">
> -        Can be one of <code>connected</code> or <code>static</code>.  Routes 
> to
> -        directly-connected subnets - LRP's CIDRs are inserted to OVN IC SB DB
> -        with <code>connected</code> value in <ref column="origin"/>.  Static
> -        routes are inserted to OVN IC SB DB with <code>static</code> value.
> +        Can be one of <code>connected</code>, <code>static</code> or
> +        <code>loadbalancer</code>.  Routes to directly-connected subnets -
> +        LRP's CIDRs are inserted to OVN IC SB DB with <code>connected</code>
> +        value in <ref column="origin"/>.  Static routes are inserted to OVN 
> IC
> +        SB DB with <code>static</code> value.  Routes for LB VIPs are 
> inserted
> +        in OVN IC SB DB with <code>loadbalancer</code> value.
>          Next when route is learned to another AZ NB DB by ovn-ic, route 
> origin
>          is synced to <ref table="Logical_Router_Static_Route" 
> column="options"
>          key="origin"/>.
> diff --git a/ovn-nb.xml b/ovn-nb.xml
> index 17346f228..f8a160041 100644
> --- a/ovn-nb.xml
> +++ b/ovn-nb.xml
> @@ -437,7 +437,7 @@
>            through the global <ref db="OVN_IC_Southbound"/> database.  Only
>            routers with ports connected to interconnection transit switches
>            participate in route advertisement.  For each of these routers, 
> there
> -          are two types of routes to be advertised:
> +          are three types of routes to be advertised:
>          </p>
>  
>          <p>
> @@ -450,6 +450,11 @@
>            are considered as directly connected subnets on the router.
>          </p>
>  
> +        <p>
> +          Thirdly, the vips of the loadbalancers associated with the logical
> +          router are advertised.
> +        </p>
> +
>          <p>
>            Link local prefixes (IPv4 169.254.0.0/16 and IPv6 FE80::/10)
>            are never advertised.
> @@ -490,6 +495,20 @@
>            <code>ic-route-learn</code> is <code>true</code>.
>          </column>
>  
> +        <column name="options" key="ic-route-adv-lb">
> +          A boolean value that enables advertising routes for loadbalancer 
> vips
> +          to the global <ref db="OVN_IC_Southbound"/> database.  Default is
> +          <code>false</code>.  This option takes effect only when option
> +          <code>ic-route-adv</code> is <code>true</code>.
> +        </column>
> +
> +        <column name="options" key="ic-route-learn-lb">
> +          A boolean value that enables learning routes for loadbalancer
> +          routes from the global <ref db="OVN_IC_Southbound"/> database.
> +          Default is <code>false</code>.  This option takes effect only when
> +          option <code>ic-route-learn</code> is <code>true</code>.
> +        </column>
> +
>          <column name="options" key="ic-route-denylist">
>            A string value contains a list of CIDRs delimited by ",".  A route
>            will not be advertised or learned if the route's prefix belongs to
> diff --git a/tests/ovn-ic.at b/tests/ovn-ic.at
> index c8276189c..ba4095a98 100644
> --- a/tests/ovn-ic.at
> +++ b/tests/ovn-ic.at
> @@ -752,6 +752,301 @@ OVN_CLEANUP_IC([az1], [az2])
>  AT_CLEANUP
>  ])
>  
> +OVN_FOR_EACH_NORTHD([
> +AT_SETUP([ovn-ic -- route sync -- loadbalancer])
> +
> +ovn_init_ic_db
> +ovn-ic-nbctl ts-add ts1
> +
> +for i in 1 2; do
> +    ovn_start az$i
> +    ovn_as az$i
> +    check ovn-ic-nbctl --wait=sb sync
> +    # Enable 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
> +
> +    # Enable route advertising for loadbalancer VIP
> +    check ovn-nbctl set nb_global . options:ic-route-adv-lb=true
> +    # Enable route learning for loadbalancer VIP
> +    check ovn-nbctl set nb_global . options:ic-route-learn-lb=true
> +
> +    # Create LRP and connect to TS
> +    check ovn-nbctl lr-add lr$i
> +    check ovn-nbctl lrp-add lr$i lrp-lr$i-ts1 aa:aa:aa:aa:aa:0$i 
> 169.254.100.$i/24 2001:db8:1::$i/64
> +    check ovn-nbctl lsp-add ts1 lsp-ts1-lr$i \
> +            -- lsp-set-addresses lsp-ts1-lr$i router \
> +            -- lsp-set-type lsp-ts1-lr$i router \
> +            -- lsp-set-options lsp-ts1-lr$i router-port=lrp-lr$i-ts1
> +
> +    # Create LB
> +    check ovn-nbctl lb-add lb$i 200.1.$i.50:80 1.1.$i.1:80,1.1.$i.2:80
> +    check ovn-nbctl lr-lb-add lr$i lb$i
> +done
> +
> +for i in 1 2; do
> +    OVS_WAIT_UNTIL([ovn_as az$i ovn-nbctl lr-route-list lr$i | grep learned])
> +done
> +
> +wait_row_count ic-sb:Route 1 ip_prefix=200.1.1.50/32 origin=loadbalancer
> +wait_row_count ic-sb:Route 1 ip_prefix=200.1.2.50/32 origin=loadbalancer
> +
> +AT_CHECK([ovn_as az1 ovn-nbctl lr-route-list lr1], [0], [dnl
> +IPv4 Routes
> +Route Table <main>:
> +               200.1.2.50             169.254.100.2 dst-ip (learned)
> +])
> +
> +AT_CHECK([ovn_as az2 ovn-nbctl lr-route-list lr2], [0], [dnl
> +IPv4 Routes
> +Route Table <main>:
> +               200.1.1.50             169.254.100.1 dst-ip (learned)
> +])
> +
> +# Add another few instances of LB in AZ1, some with same VIP IP.
> +ovn_as az1 ovn-nbctl lb-add lb3 200.1.1.53:80 
> 1.1.1.1:80,1.1.1.2:80,1.1.1.3:80
> +ovn_as az1 ovn-nbctl lb-add lb4 200.1.1.53:8080 1.1.1.1:8080,1.1.1.2:8080
> +ovn_as az1 ovn-nbctl lb-add lb5 200.1.1.54:80 1.1.1.1:80,1.1.1.2:80
> +ovn_as az1 ovn-nbctl lr-lb-add lr1 lb3
> +ovn_as az1 ovn-nbctl lr-lb-add lr1 lb4
> +ovn_as az1 ovn-nbctl lr-lb-add lr1 lb5
> +wait_row_count ic-sb:Route 1 ip_prefix=200.1.1.53/32 origin=loadbalancer
> +wait_row_count ic-sb:Route 1 ip_prefix=200.1.1.54/32 origin=loadbalancer
> +OVS_WAIT_UNTIL([ovn_as az2 ovn-nbctl lr-route-list lr2 | grep learned | grep 
> 200.1.1.53])
> +OVS_WAIT_UNTIL([ovn_as az2 ovn-nbctl lr-route-list lr2 | grep learned | grep 
> 200.1.1.54])
> +
> +AT_CHECK([ovn_as az2 ovn-nbctl lr-route-list lr2], [0], [dnl
> +IPv4 Routes
> +Route Table <main>:
> +               200.1.1.50             169.254.100.1 dst-ip (learned)
> +               200.1.1.53             169.254.100.1 dst-ip (learned)
> +               200.1.1.54             169.254.100.1 dst-ip (learned)
> +])
> +
> +# Remove one LB.
> +ovn_as az1 ovn-nbctl lr-lb-del lr1 lb5
> +OVS_WAIT_WHILE([ovn_as az2 ovn-nbctl lr-route-list lr2 | grep learned | grep 
> 200.1.1.54])
> +AT_CHECK([ovn_as az2 ovn-nbctl lr-route-list lr2], [0], [dnl
> +IPv4 Routes
> +Route Table <main>:
> +               200.1.1.50             169.254.100.1 dst-ip (learned)
> +               200.1.1.53             169.254.100.1 dst-ip (learned)
> +])
> +
> +# Add load balancer group.
> +ovn_as az1 ovn-nbctl lb-add lb6 250.1.1.11:80 1.1.1.1:80,1.1.1.2:80
> +ovn_as az1 ovn-nbctl lb-add lb7 250.1.1.12:80 1.1.1.1:80,1.1.1.2:80
> +lb6=$(ovn_as az1 fetch_column nb:load_balancer _uuid name=lb6)
> +lb7=$(ovn_as az1 fetch_column nb:load_balancer _uuid name=lb7)
> +
> +ovn_as az1
> +lbg=$(ovn-nbctl create load_balancer_group name=lbg -- \
> +  add load_balancer_group lbg load_balancer $lb6 -- \
> +  add load_balancer_group lbg load_balancer $lb7)
> +ovn_as az1 ovn-nbctl add logical_router lr1 load_balancer_group $lbg
> +OVS_WAIT_UNTIL([ovn_as az2 ovn-nbctl lr-route-list lr2 | grep learned | grep 
> 250.1.1.11])
> +OVS_WAIT_UNTIL([ovn_as az2 ovn-nbctl lr-route-list lr2 | grep learned | grep 
> 250.1.1.12])
> +
> +AT_CHECK([ovn_as az2 ovn-nbctl lr-route-list lr2], [0], [dnl
> +IPv4 Routes
> +Route Table <main>:
> +               200.1.1.50             169.254.100.1 dst-ip (learned)
> +               200.1.1.53             169.254.100.1 dst-ip (learned)
> +               250.1.1.11             169.254.100.1 dst-ip (learned)
> +               250.1.1.12             169.254.100.1 dst-ip (learned)
> +])
> +
> +# Remove the LB group from LR.
> +ovn_as az1 ovn-nbctl remove logical_router lr1 load_balancer_group $lbg
> +OVS_WAIT_WHILE([ovn_as az2 ovn-nbctl lr-route-list lr2 | grep learned | grep 
> 250.1.1.11])
> +OVS_WAIT_WHILE([ovn_as az2 ovn-nbctl lr-route-list lr2 | grep learned | grep 
> 250.1.1.12])
> +
> +AT_CHECK([ovn_as az2 ovn-nbctl lr-route-list lr2], [0], [dnl
> +IPv4 Routes
> +Route Table <main>:
> +               200.1.1.50             169.254.100.1 dst-ip (learned)
> +               200.1.1.53             169.254.100.1 dst-ip (learned)
> +])
> +
> +# Disable LB route-advertising for AZ1.
> +ovn_as az1 ovn-nbctl set nb_global . options:ic-route-adv-lb=false
> +OVS_WAIT_WHILE([ovn_as az2 ovn-nbctl lr-route-list lr2 | grep learned | grep 
> 200.1.1])
> +AT_CHECK([ovn_as az2 ovn-nbctl lr-route-list lr2], [0], [])
> +
> +# Enable LB route-advertising back for AZ1.
> +ovn_as az1 ovn-nbctl set nb_global . options:ic-route-adv-lb=true
> +wait_row_count ic-sb:Route 1 ip_prefix=200.1.1.50/32 origin=loadbalancer
> +wait_row_count ic-sb:Route 1 ip_prefix=200.1.1.53/32 origin=loadbalancer
> +OVS_WAIT_UNTIL([ovn_as az2 ovn-nbctl lr-route-list lr2 | grep learned | grep 
> 200.1.1.50])
> +OVS_WAIT_UNTIL([ovn_as az2 ovn-nbctl lr-route-list lr2 | grep learned | grep 
> 200.1.1.53])
> +
> +AT_CHECK([ovn_as az2 ovn-nbctl lr-route-list lr2], [0], [dnl
> +IPv4 Routes
> +Route Table <main>:
> +               200.1.1.50             169.254.100.1 dst-ip (learned)
> +               200.1.1.53             169.254.100.1 dst-ip (learned)
> +])
> +
> +# Disable LB route-learning for AZ2.
> +ovn_as az2 ovn-nbctl set nb_global . options:ic-route-learn-lb=false
> +wait_row_count ic-sb:Route 1 ip_prefix=200.1.1.50/32 origin=loadbalancer
> +wait_row_count ic-sb:Route 1 ip_prefix=200.1.1.53/32 origin=loadbalancer
> +OVS_WAIT_WHILE([ovn_as az2 ovn-nbctl lr-route-list lr2 | grep learned | grep 
> 200.1.1])
> +AT_CHECK([ovn_as az2 ovn-nbctl lr-route-list lr2], [0], [])
> +
> +# Enable LB route-learning back for AZ2.
> +ovn_as az2 ovn-nbctl set nb_global . options:ic-route-learn-lb=true
> +OVS_WAIT_UNTIL([ovn_as az2 ovn-nbctl lr-route-list lr2 | grep learned | grep 
> 200.1.1.50])
> +OVS_WAIT_UNTIL([ovn_as az2 ovn-nbctl lr-route-list lr2 | grep learned | grep 
> 200.1.1.53])
> +
> +AT_CHECK([ovn_as az2 ovn-nbctl lr-route-list lr2], [0], [dnl
> +IPv4 Routes
> +Route Table <main>:
> +               200.1.1.50             169.254.100.1 dst-ip (learned)
> +               200.1.1.53             169.254.100.1 dst-ip (learned)
> +])
> +
> +# Add IPv6 LB.
> +ovn_as az1 ovn-nbctl lb-add lb_v6 [[4242::1]]:80 "[[4242::2]]:80"
> +ovn_as az1 ovn-nbctl lr-lb-add lr1 lb_v6
> +OVS_WAIT_UNTIL([ovn_as az2 ovn-nbctl lr-route-list lr2 | grep learned | grep 
> 4242])
> +
> +AT_CHECK([ovn-ic-sbctl list route | grep 4242 -A 2], [0], [dnl
> +ip_prefix           : "4242::1/128"
> +nexthop             : "2001:db8:1::1"
> +origin              : loadbalancer
> +])
> +
> +AT_CHECK([ovn_as az2 ovn-nbctl lr-route-list lr2], [0], [dnl
> +IPv4 Routes
> +Route Table <main>:
> +               200.1.1.50             169.254.100.1 dst-ip (learned)
> +               200.1.1.53             169.254.100.1 dst-ip (learned)
> +
> +IPv6 Routes
> +Route Table <main>:
> +                  4242::1             2001:db8:1::1 dst-ip (learned)
> +])
> +
> +# Remove IPv6 LB
> +ovn_as az1 ovn-nbctl lr-lb-del lr1 lb_v6
> +OVS_WAIT_WHILE([ovn_as az2 ovn-nbctl lr-route-list lr2 | grep learned | grep 
> 4242])
> +AT_CHECK([ovn_as az2 ovn-nbctl lr-route-list lr2], [0], [dnl
> +IPv4 Routes
> +Route Table <main>:
> +               200.1.1.50             169.254.100.1 dst-ip (learned)
> +               200.1.1.53             169.254.100.1 dst-ip (learned)
> +])
> +
> +# Configure same LB VIP locally as in remote az. Ensure learnt route is 
> removed.
> +ovn_as az2 ovn-nbctl lb-add lb_temp 200.1.1.50:80 1.1.1.1:80,1.1.1.2:80
> +ovn_as az2 ovn-nbctl lr-lb-add lr2 lb_temp
> +wait_row_count ic-sb:Route 2 ip_prefix=200.1.1.50/32 origin=loadbalancer
> +OVS_WAIT_WHILE([ovn_as az2 ovn-nbctl lr-route-list lr2 | grep learned | grep 
> 200.1.1.50])
> +AT_CHECK([ovn_as az2 ovn-nbctl lr-route-list lr2], [0], [dnl
> +IPv4 Routes
> +Route Table <main>:
> +               200.1.1.53             169.254.100.1 dst-ip (learned)
> +])
> +ovn_as az2 ovn-nbctl lr-lb-del lr2 lb_temp
> +ovn_as az2 ovn-nbctl lb-del lb_temp
> +OVS_WAIT_UNTIL([ovn_as az2 ovn-nbctl lr-route-list lr2 | grep learned | grep 
> 200.1.1.50])
> +AT_CHECK([ovn_as az2 ovn-nbctl lr-route-list lr2], [0], [dnl
> +IPv4 Routes
> +Route Table <main>:
> +               200.1.1.50             169.254.100.1 dst-ip (learned)
> +               200.1.1.53             169.254.100.1 dst-ip (learned)
> +])
> +
> +# Configure static route in remote az. Route would be learnt. Add local LB 
> VIP
> +# same as static route prefix. Ensure route is removed.
> +ovn_as az1 ovn-nbctl lr-route-add lr1 200.1.3.55 169.1.1.1
> +OVS_WAIT_UNTIL([ovn_as az2 ovn-nbctl lr-route-list lr2 | grep learned | grep 
> 200.1.3.55])
> +AT_CHECK([ovn_as az2 ovn-nbctl lr-route-list lr2], [0], [dnl
> +IPv4 Routes
> +Route Table <main>:
> +               200.1.1.50             169.254.100.1 dst-ip (learned)
> +               200.1.1.53             169.254.100.1 dst-ip (learned)
> +               200.1.3.55             169.254.100.1 dst-ip (learned)
> +])
> +
> +ovn_as az2 ovn-nbctl lb-add lb_temp 200.1.3.55:80 1.1.1.1:80,1.1.1.2:80
> +ovn_as az2 ovn-nbctl lr-lb-add lr2 lb_temp
> +OVS_WAIT_WHILE([ovn_as az2 ovn-nbctl lr-route-list lr2 | grep learned | grep 
> 200.1.3.55])
> +AT_CHECK([ovn_as az2 ovn-nbctl lr-route-list lr2], [0], [dnl
> +IPv4 Routes
> +Route Table <main>:
> +               200.1.1.50             169.254.100.1 dst-ip (learned)
> +               200.1.1.53             169.254.100.1 dst-ip (learned)
> +])
> +
> +ovn_as az2 ovn-nbctl lr-lb-del lr2 lb_temp
> +ovn_as az2 ovn-nbctl lb-del lb_temp
> +OVS_WAIT_UNTIL([ovn_as az2 ovn-nbctl lr-route-list lr2 | grep learned | grep 
> 200.1.3.55])
> +AT_CHECK([ovn_as az2 ovn-nbctl lr-route-list lr2], [0], [dnl
> +IPv4 Routes
> +Route Table <main>:
> +               200.1.1.50             169.254.100.1 dst-ip (learned)
> +               200.1.1.53             169.254.100.1 dst-ip (learned)
> +               200.1.3.55             169.254.100.1 dst-ip (learned)
> +])
> +ovn_as az1 ovn-nbctl lr-route-del lr1 200.1.3.55 169.1.1.1
> +OVS_WAIT_WHILE([ovn_as az2 ovn-nbctl lr-route-list lr2 | grep learned | grep 
> 200.1.3.55])
> +AT_CHECK([ovn_as az2 ovn-nbctl lr-route-list lr2], [0], [dnl
> +IPv4 Routes
> +Route Table <main>:
> +               200.1.1.50             169.254.100.1 dst-ip (learned)
> +               200.1.1.53             169.254.100.1 dst-ip (learned)
> +])
> +
> +# Create a third az
> +ovn_start az3
> +ovn_as az3
> +check ovn-ic-nbctl --wait=sb sync
> +check ovn-nbctl set nb_global . options:ic-route-learn=true
> +check ovn-nbctl set nb_global . options:ic-route-adv=true
> +
> +check ovn-nbctl set nb_global . options:ic-route-adv-lb=true
> +check ovn-nbctl set nb_global . options:ic-route-learn-lb=true
> +
> +check ovn-nbctl lr-add lr3
> +check ovn-nbctl lrp-add lr3 lrp-lr3-ts1 aa:aa:aa:aa:aa:03 169.254.100.3/24 
> 2001:db8:1::3/64
> +check ovn-nbctl lsp-add ts1 lsp-ts1-lr3 \
> +        -- lsp-set-addresses lsp-ts1-lr3 router \
> +        -- lsp-set-type lsp-ts1-lr3 router \
> +        -- lsp-set-options lsp-ts1-lr3 router-port=lrp-lr3-ts1
> +
> +# Create LB in 3rd az and check that the route propagates to az1 LR
> +ovn_as az3 ovn-nbctl lb-add lb3 200.1.3.50:80 1.1.3.1:80,1.1.3.2:80
> +ovn_as az3 ovn-nbctl lr-lb-add lr3 lb3
> +OVS_WAIT_UNTIL([ovn_as az2 ovn-nbctl lr-route-list lr2 | grep learned | grep 
> 200.1.3.50])
> +AT_CHECK([ovn_as az2 ovn-nbctl lr-route-list lr2], [0], [dnl
> +IPv4 Routes
> +Route Table <main>:
> +               200.1.1.50             169.254.100.1 dst-ip (learned)
> +               200.1.1.53             169.254.100.1 dst-ip (learned)
> +               200.1.3.50             169.254.100.3 dst-ip (learned)
> +])
> +
> +# Create LB in az3 with same VIP as az1, check for ECMP route in az2 LR
> +ovn_as az3 ovn-nbctl lb-add lb4 200.1.1.50:80 1.1.3.1:80,1.1.3.2:80
> +ovn_as az3 ovn-nbctl lr-lb-add lr3 lb4
> +OVS_WAIT_UNTIL([ovn_as az2 ovn-nbctl lr-route-list lr2 | grep learned | grep 
> ecmp])
> +AT_CHECK([ovn_as az2 ovn-nbctl lr-route-list lr2], [0], [dnl
> +IPv4 Routes
> +Route Table <main>:
> +               200.1.1.50             169.254.100.1 dst-ip (learned) ecmp
> +               200.1.1.50             169.254.100.3 dst-ip (learned) ecmp
> +               200.1.1.53             169.254.100.1 dst-ip (learned)
> +               200.1.3.50             169.254.100.3 dst-ip (learned)
> +])
> +
> +OVN_CLEANUP_IC([az1], [az2])
> +
> +AT_CLEANUP
> +])
> +
>  OVN_FOR_EACH_NORTHD([
>  AT_SETUP([ovn-ic -- route sync -- IPv6 route tables])
>  AT_KEYWORDS([IPv6-route-sync])
> -- 
> 2.39.3
> 
> _______________________________________________
> dev mailing list
> [email protected]
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
> 
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to