On Tue, Jan 16, 2024 at 9:48 PM Han Zhou <hz...@ovn.org> wrote:
>
> In commit dd527a283cd8, it created separate tunnels for different remote
> encap IPs of the same remote chassis, but when the current chassis is
> the one that has multiple encap IPs configured, it only uses the first
> encap IP. This patch creates separate tunnels taking into consideration
> the multiple encap IPs in current chassis and sets corresponding
> local_ip for each tunnel interface in such cases.
>
> Co-authored-by: Lei Huang <l...@ovn.org>
> Signed-off-by: Lei Huang <l...@ovn.org>

Oops, I made a silly mistake in Lei's email address, which should be
l...@nvidia.com instead. Sorry for that.

Han

> Signed-off-by: Han Zhou <hz...@ovn.org>
> ---
>  controller/bfd.c        |   4 +-
>  controller/encaps.c     | 158 ++++++++++++++++++++++------------------
>  controller/encaps.h     |   9 ++-
>  controller/lflow.c      |   2 +-
>  controller/local_data.c |  14 ++--
>  controller/local_data.h |   5 +-
>  controller/physical.c   |  28 +++----
>  controller/pinctrl.c    |   2 +-
>  tests/ovn-ipsec.at      |  49 -------------
>  tests/ovn.at            |  88 +++++++++++++++++-----
>  10 files changed, 192 insertions(+), 167 deletions(-)
>
> diff --git a/controller/bfd.c b/controller/bfd.c
> index cf011e382c6c..f24bfd063888 100644
> --- a/controller/bfd.c
> +++ b/controller/bfd.c
> @@ -75,7 +75,7 @@ bfd_calculate_active_tunnels(const struct ovsrec_bridge
*br_int,
>                              char *chassis_name = NULL;
>
>                              if (encaps_tunnel_id_parse(id, &chassis_name,
> -                                                       NULL)) {
> +                                                       NULL, NULL)) {
>                                  if (!sset_contains(active_tunnels,
>                                                     chassis_name)) {
>                                      sset_add(active_tunnels,
chassis_name);
> @@ -204,7 +204,7 @@ bfd_run(const struct ovsrec_interface_table
*interface_table,
>
>              sset_add(&tunnels, port_name);
>
> -            if (encaps_tunnel_id_parse(tunnel_id, &chassis_name, NULL)) {
> +            if (encaps_tunnel_id_parse(tunnel_id, &chassis_name, NULL,
NULL)) {
>                  if (sset_contains(&bfd_chassis, chassis_name)) {
>                      sset_add(&bfd_ifaces, port_name);
>                  }
> diff --git a/controller/encaps.c b/controller/encaps.c
> index 1f6e667a606c..28237f6191c8 100644
> --- a/controller/encaps.c
> +++ b/controller/encaps.c
> @@ -32,10 +32,9 @@ VLOG_DEFINE_THIS_MODULE(encaps);
>  /*
>   * Given there could be multiple tunnels with different IPs to the same
>   * chassis we annotate the external_ids:ovn-chassis-id in tunnel port
with
> - * <chassis_name>OVN_MVTEP_CHASSISID_DELIM<IP>. The external_id key
> + * <chassis_name>@<remote IP>%<local IP>. The external_id key
>   * "ovn-chassis-id" is kept for backward compatibility.
>   */
> -#define        OVN_MVTEP_CHASSISID_DELIM '@'
>  #define OVN_TUNNEL_ID "ovn-chassis-id"
>
>  static char *current_br_int_name = NULL;
> @@ -95,72 +94,93 @@ tunnel_create_name(struct tunnel_ctx *tc, const char
*chassis_id)
>  }
>
>  /*
> - * Returns a tunnel-id of the form 'chassis_id'-delimiter-'encap_ip'.
> + * Returns a tunnel-id of the form chassis_id@remote_encap_ip
%local_encap_ip.
>   */
>  char *
> -encaps_tunnel_id_create(const char *chassis_id, const char *encap_ip)
> +encaps_tunnel_id_create(const char *chassis_id, const char
*remote_encap_ip,
> +                        const char *local_encap_ip)
>  {
> -    return xasprintf("%s%c%s", chassis_id, OVN_MVTEP_CHASSISID_DELIM,
> -                     encap_ip);
> +    return xasprintf("%s%c%s%c%s", chassis_id, '@', remote_encap_ip,
> +                     '%', local_encap_ip);
>  }
>
>  /*
> - * Parses a 'tunnel_id' of the form <chassis_name><delimiter><IP>.
> + * Parses a 'tunnel_id' of the form <chassis_name>@<remote IP>%<local
IP>.
>   * If the 'chassis_id' argument is not NULL the function will allocate
memory
>   * and store the chassis_name part of the tunnel-id at '*chassis_id'.
> - * If the 'encap_ip' argument is not NULL the function will allocate
memory
> - * and store the encapsulation IP part of the tunnel-id at '*encap_ip'.
> + * Same for remote_encap_ip and local_encap_ip.
>   */
>  bool
>  encaps_tunnel_id_parse(const char *tunnel_id, char **chassis_id,
> -                       char **encap_ip)
> +                       char **remote_encap_ip, char **local_encap_ip)
>  {
> -    /* Find the delimiter.  Fail if there is no delimiter or if
<chassis_name>
> -     * or <IP> is the empty string.*/
> -    const char *d = strchr(tunnel_id, OVN_MVTEP_CHASSISID_DELIM);
> +    /* Find the @.  Fail if there is no @ or if any part is empty. */
> +    const char *d = strchr(tunnel_id, '@');
>      if (d == tunnel_id || !d || !d[1]) {
>          return false;
>      }
>
> +    /* Find the %.  Fail if there is no % or if any part is empty. */
> +    const char *d2 = strchr(d + 1, '%');
> +    if (d2 == d + 1 || !d2 || !d2[1]) {
> +        return false;
> +    }
> +
>      if (chassis_id) {
>          *chassis_id = xmemdup0(tunnel_id, d - tunnel_id);
>      }
> -    if (encap_ip) {
> -        *encap_ip = xstrdup(d + 1);
> +
> +    if (remote_encap_ip) {
> +        *remote_encap_ip = xmemdup0(d + 1, d2 - (d + 1));
> +    }
> +
> +    if (local_encap_ip) {
> +        *local_encap_ip = xstrdup(d2 + 1);
>      }
>      return true;
>  }
>
>  /*
> - * Returns true if 'tunnel_id' contains 'chassis_id' and, if specified,
the
> - * given 'encap_ip'. Returns false otherwise.
> + * Returns true if 'tunnel_id' in the format
> + *      <chassis_id>@<remote_encap_ip>%<local_encap_ip>
> + * contains 'chassis_id' and, if specified, the given 'remote_encap_ip'
and
> + * 'local_encap_ip'. Returns false otherwise.
>   */
>  bool
>  encaps_tunnel_id_match(const char *tunnel_id, const char *chassis_id,
> -                       const char *encap_ip)
> +                       const char *remote_encap_ip, const char
*local_encap_ip)
>  {
> -    while (*tunnel_id == *chassis_id) {
> -        if (!*tunnel_id) {
> -            /* 'tunnel_id' and 'chassis_id' are equal strings.  This is a
> -             * mismatch because 'tunnel_id' is missing the delimiter and
IP. */
> -            return false;
> -        }
> -        tunnel_id++;
> -        chassis_id++;
> +    char *tokstr = xstrdup(tunnel_id);
> +    char *saveptr = NULL;
> +    bool ret = false;
> +
> +    char *token_chassis = strtok_r(tokstr, "@", &saveptr);
> +    if (!token_chassis || strcmp(token_chassis, chassis_id)) {
> +        goto out;
> +    }
> +
> +    char *token_remote_ip = strtok_r(NULL, "%", &saveptr);
> +    if (remote_encap_ip &&
> +        (!token_remote_ip || strcmp(token_remote_ip, remote_encap_ip))) {
> +        goto out;
>      }
>
> -    /* We found the first byte that disagrees between 'tunnel_id' and
> -     * 'chassis_id'.  If we consumed all of 'chassis_id' and arrived at
the
> -     * delimiter in 'tunnel_id' (and if 'encap_ip' is correct, if it was
> -     * supplied), it's a match. */
> -    return (*tunnel_id == OVN_MVTEP_CHASSISID_DELIM
> -            && *chassis_id == '\0'
> -            && (!encap_ip || !strcmp(tunnel_id + 1, encap_ip)));
> +    char *token_local_ip = strtok_r(NULL, "", &saveptr);
> +    if (local_encap_ip &&
> +        (!token_local_ip || strcmp(token_local_ip, local_encap_ip))) {
> +        goto out;
> +    }
> +
> +    ret = true;
> +out:
> +    free(tokstr);
> +    return ret;
>  }
>
>  static void
>  tunnel_add(struct tunnel_ctx *tc, const struct sbrec_sb_global *sbg,
>             const char *new_chassis_id, const struct sbrec_encap *encap,
> +           bool must_set_local_ip, const char *local_ip,
>             const struct ovsrec_open_vswitch_table *ovs_table)
>  {
>      struct smap options = SMAP_INITIALIZER(&options);
> @@ -173,10 +193,11 @@ tunnel_add(struct tunnel_ctx *tc, const struct
sbrec_sb_global *sbg,
>      /*
>       * Since a chassis may have multiple encap-ip, we can't just add the
>       * chassis name as the OVN_TUNNEL_ID for the port; we use the
> -     * combination of the chassis_name and the encap-ip to identify
> -     * a specific tunnel to the chassis.
> +     * combination of the chassis_name and the remote and local
encap-ips to
> +     * identify a specific tunnel to the remote chassis.
>       */
> -    tunnel_entry_id = encaps_tunnel_id_create(new_chassis_id, encap->ip);
> +    tunnel_entry_id = encaps_tunnel_id_create(new_chassis_id, encap->ip,
> +                                              local_ip);
>      if (csum && (!strcmp(csum, "true") || !strcmp(csum, "false"))) {
>          smap_add(&options, "csum", csum);
>      }
> @@ -187,7 +208,7 @@ tunnel_add(struct tunnel_ctx *tc, const struct
sbrec_sb_global *sbg,
>      const struct ovsrec_open_vswitch *cfg =
>          ovsrec_open_vswitch_table_first(ovs_table);
>
> -    bool set_local_ip = false;
> +    bool set_local_ip = must_set_local_ip;
>      if (cfg) {
>          /* If the tos option is configured, get it */
>          const char *encap_tos =
> @@ -208,11 +229,13 @@ tunnel_add(struct tunnel_ctx *tc, const struct
sbrec_sb_global *sbg,
>              smap_add(&options, "df_default", encap_df);
>          }
>
> -        /* If ovn-set-local-ip option is configured, get it */
> -        set_local_ip =
> -            get_chassis_external_id_value_bool(
> -                &cfg->external_ids, tc->this_chassis->name,
> -                "ovn-set-local-ip", false);
> +        if (!set_local_ip) {
> +            /* If ovn-set-local-ip option is configured, get it */
> +            set_local_ip =
> +                get_chassis_external_id_value_bool(
> +                    &cfg->external_ids, tc->this_chassis->name,
> +                    "ovn-set-local-ip", false);
> +        }
>      }
>
>      /* Add auth info if ipsec is enabled. */
> @@ -237,30 +260,7 @@ tunnel_add(struct tunnel_ctx *tc, const struct
sbrec_sb_global *sbg,
>      }
>
>      if (set_local_ip) {
> -        const struct sbrec_chassis *this_chassis = tc->this_chassis;
> -        const char *local_ip = NULL;
> -
> -        /* Determine 'ovn-encap-ip' of the local chassis as this will be
the
> -         * tunnel port's 'local_ip'. We do not support the case in which
> -         * 'ovn-encap-ip' holds multiple comma-delimited IP addresses.
> -         */
> -        for (int i = 0; i < this_chassis->n_encaps; i++) {
> -            if (local_ip && strcmp(local_ip,
this_chassis->encaps[i]->ip)) {
> -                static struct vlog_rate_limit rl =
VLOG_RATE_LIMIT_INIT(5, 1);
> -                VLOG_ERR_RL(&rl, "ovn-encap-ip has been configured as a
list. "
> -                            "This is unsupported for IPsec and explicit "
> -                            "local_ip configuration.");
> -                /* No need to loop further as we know this condition has
been
> -                 * hit */
> -                break;
> -            } else {
> -                local_ip = this_chassis->encaps[i]->ip;
> -            }
> -        }
> -
> -        if (local_ip) {
> -            smap_add(&options, "local_ip", local_ip);
> -        }
> +        smap_add(&options, "local_ip", local_ip);
>      }
>
>      /* If there's an existing tunnel record that does not need any
change,
> @@ -362,9 +362,29 @@ chassis_tunnel_add(const struct sbrec_chassis
*chassis_rec,
>          if (tun_type != pref_type) {
>              continue;
>          }
> -        tunnel_add(tc, sbg, chassis_rec->name, chassis_rec->encaps[i],
> -                   ovs_table);
> -        tuncnt++;
> +
> +        /* Check if need to pass the local ip. We always set local ip if
there
> +         * are multiple local IPs for the selected encap type. */
> +        int count = 0;
> +        bool set_local_ip = false;
> +        for (int j = 0; j < this_chassis->n_encaps; j++) {
> +            if (pref_type ==
get_tunnel_type(this_chassis->encaps[j]->type) &&
> +                count++ > 0) {
> +                set_local_ip = true;
> +                break;
> +            }
> +        }
> +
> +        for (int j = 0; j < this_chassis->n_encaps; j++) {
> +            if (pref_type !=
get_tunnel_type(this_chassis->encaps[j]->type)) {
> +                continue;
> +            }
> +            VLOG_DBG("tunnel_add: '%s', local ip: %s", chassis_rec->name,
> +                     this_chassis->encaps[j]->ip);
> +            tunnel_add(tc, sbg, chassis_rec->name,
chassis_rec->encaps[i],
> +                       set_local_ip, this_chassis->encaps[j]->ip,
ovs_table);
> +            tuncnt++;
> +        }
>      }
>      return tuncnt;
>  }
> diff --git a/controller/encaps.h b/controller/encaps.h
> index 3e58b3c82805..6f9891ee5907 100644
> --- a/controller/encaps.h
> +++ b/controller/encaps.h
> @@ -41,11 +41,14 @@ void encaps_run(struct ovsdb_idl_txn *ovs_idl_txn,
>  bool encaps_cleanup(struct ovsdb_idl_txn *ovs_idl_txn,
>                      const struct ovsrec_bridge *br_int);
>
> -char *encaps_tunnel_id_create(const char *chassis_id, const char
*encap_ip);
> +char *encaps_tunnel_id_create(const char *chassis_id,
> +                              const char *remote_encap_ip,
> +                              const char *local_encap_ip);
>  bool  encaps_tunnel_id_parse(const char *tunnel_id, char **chassis_id,
> -                             char **encap_ip);
> +                             char **remote_encap_ip, char
**local_encap_ip);
>  bool  encaps_tunnel_id_match(const char *tunnel_id, const char
*chassis_id,
> -                             const char *encap_ip);
> +                             const char *remote_encap_ip,
> +                             const char *local_encap_ip);
>
>  void encaps_destroy(void);
>
> diff --git a/controller/lflow.c b/controller/lflow.c
> index b0cf4253c482..c0cf0aa10646 100644
> --- a/controller/lflow.c
> +++ b/controller/lflow.c
> @@ -164,7 +164,7 @@ tunnel_ofport_cb(const void *aux_, const char
*port_name, ofp_port_t *ofport)
>      }
>
>      if (!get_chassis_tunnel_ofport(aux->chassis_tunnels,
pb->chassis->name,
> -                                   NULL, ofport)) {
> +                                   ofport)) {
>          return false;
>      }
>
> diff --git a/controller/local_data.c b/controller/local_data.c
> index 3a7d3afebe0b..a9092783958f 100644
> --- a/controller/local_data.c
> +++ b/controller/local_data.c
> @@ -388,7 +388,7 @@ local_nonvif_data_run(const struct ovsrec_bridge
*br_int,
>                                           "ovn-chassis-id");
>          if (tunnel_id && encaps_tunnel_id_match(tunnel_id,
>                                                  chassis_rec->name,
> -                                                NULL)) {
> +                                                NULL, NULL)) {
>              continue;
>          }
>
> @@ -439,7 +439,7 @@ local_nonvif_data_run(const struct ovsrec_bridge
*br_int,
>                  char *hash_id = NULL;
>                  char *ip = NULL;
>
> -                if (!encaps_tunnel_id_parse(tunnel_id, &hash_id, &ip)) {
> +                if (!encaps_tunnel_id_parse(tunnel_id, &hash_id, &ip,
NULL)) {
>                      continue;
>                  }
>                  struct chassis_tunnel *tun = xmalloc(sizeof *tun);
> @@ -477,11 +477,10 @@ local_nonvif_data_handle_ovs_iface_changes(
>
>  bool
>  get_chassis_tunnel_ofport(const struct hmap *chassis_tunnels,
> -                          const char *chassis_name, char *encap_ip,
> -                          ofp_port_t *ofport)
> +                          const char *chassis_name, ofp_port_t *ofport)
>  {
>      struct chassis_tunnel *tun = NULL;
> -    tun = chassis_tunnel_find(chassis_tunnels, chassis_name, encap_ip);
> +    tun = chassis_tunnel_find(chassis_tunnels, chassis_name, NULL, NULL);
>      if (!tun) {
>          return false;
>      }
> @@ -515,7 +514,7 @@ chassis_tunnels_destroy(struct hmap *chassis_tunnels)
>   */
>  struct chassis_tunnel *
>  chassis_tunnel_find(const struct hmap *chassis_tunnels, const char
*chassis_id,
> -                    char *encap_ip)
> +                    char *remote_encap_ip, char *local_encap_ip)
>  {
>      /*
>       * If the specific encap_ip is given, look for the chassisid_ip
entry,
> @@ -524,7 +523,8 @@ chassis_tunnel_find(const struct hmap
*chassis_tunnels, const char *chassis_id,
>      struct chassis_tunnel *tun = NULL;
>      HMAP_FOR_EACH_WITH_HASH (tun, hmap_node, hash_string(chassis_id, 0),
>                               chassis_tunnels) {
> -        if (encaps_tunnel_id_match(tun->chassis_id, chassis_id,
encap_ip)) {
> +        if (encaps_tunnel_id_match(tun->chassis_id, chassis_id,
> +                                   remote_encap_ip, local_encap_ip)) {
>              return tun;
>          }
>      }
> diff --git a/controller/local_data.h b/controller/local_data.h
> index f6d8f725f805..bab95bcc3824 100644
> --- a/controller/local_data.h
> +++ b/controller/local_data.h
> @@ -149,10 +149,11 @@ bool local_nonvif_data_handle_ovs_iface_changes(
>
>  struct chassis_tunnel *chassis_tunnel_find(const struct hmap
*chassis_tunnels,
>                                             const char *chassis_id,
> -                                           char *encap_ip);
> +                                           char *remote_encap_ip,
> +                                           char *local_encap_ip);
>
>  bool get_chassis_tunnel_ofport(const struct hmap *chassis_tunnels,
> -                               const char *chassis_name, char *encap_ip,
> +                               const char *chassis_name,
>                                 ofp_port_t *ofport);
>
>  void chassis_tunnels_destroy(struct hmap *chassis_tunnels);
> diff --git a/controller/physical.c b/controller/physical.c
> index eda0854410b6..e93bfbd2cffb 100644
> --- a/controller/physical.c
> +++ b/controller/physical.c
> @@ -137,16 +137,18 @@ put_resubmit(uint8_t table_id, struct ofpbuf
*ofpacts)
>   * port.
>   */
>  static struct chassis_tunnel *
> -get_port_binding_tun(const struct sbrec_encap *encap,
> +get_port_binding_tun(const struct sbrec_encap *remote_encap,
> +                     const struct sbrec_encap *local_encap,
>                       const struct sbrec_chassis *chassis,
>                       const struct hmap *chassis_tunnels)
>  {
>      struct chassis_tunnel *tun = NULL;
> -    if (encap) {
> -        tun = chassis_tunnel_find(chassis_tunnels, chassis->name,
encap->ip);
> -    }
> +    tun = chassis_tunnel_find(chassis_tunnels, chassis->name,
> +                              remote_encap ? remote_encap->ip : NULL,
> +                              local_encap ? local_encap->ip : NULL);
> +
>      if (!tun) {
> -        tun = chassis_tunnel_find(chassis_tunnels, chassis->name, NULL);
> +        tun = chassis_tunnel_find(chassis_tunnels, chassis->name, NULL,
NULL);
>      }
>      return tun;
>  }
> @@ -335,7 +337,7 @@ get_remote_tunnels(const struct sbrec_port_binding
*binding,
>      ovs_list_init(tunnels);
>
>      if (binding->chassis && binding->chassis != chassis) {
> -        tun = get_port_binding_tun(binding->encap, binding->chassis,
> +        tun = get_port_binding_tun(binding->encap, NULL,
binding->chassis,
>                                     chassis_tunnels);
>          if (!tun) {
>              static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5,
1);
> @@ -356,7 +358,7 @@ get_remote_tunnels(const struct sbrec_port_binding
*binding,
>          }
>          const struct sbrec_encap *additional_encap;
>          additional_encap = find_additional_encap_for_chassis(binding,
chassis);
> -        tun = get_port_binding_tun(additional_encap,
> +        tun = get_port_binding_tun(additional_encap, NULL,
>                                     binding->additional_chassis[i],
>                                     chassis_tunnels);
>          if (!tun) {
> @@ -432,10 +434,10 @@ put_remote_port_redirect_overlay_ha_remote(
>              continue;
>          }
>          if (!tun) {
> -            tun = chassis_tunnel_find(chassis_tunnels, ch->name, NULL);
> +            tun = chassis_tunnel_find(chassis_tunnels, ch->name, NULL,
NULL);
>          } else {
>              struct chassis_tunnel *chassis_tunnel =
> -                chassis_tunnel_find(chassis_tunnels, ch->name, NULL);
> +                chassis_tunnel_find(chassis_tunnels, ch->name, NULL,
NULL);
>              if (chassis_tunnel &&
>                  tun->type != chassis_tunnel->type) {
>                  static struct vlog_rate_limit rl =
> @@ -469,7 +471,7 @@ put_remote_port_redirect_overlay_ha_remote(
>          if (!ch) {
>              continue;
>          }
> -        tun = chassis_tunnel_find(chassis_tunnels, ch->name, NULL);
> +        tun = chassis_tunnel_find(chassis_tunnels, ch->name, NULL, NULL);
>          if (!tun) {
>              continue;
>          }
> @@ -1930,7 +1932,7 @@ tunnel_to_chassis(enum mf_field_id mff_ovn_geneve,
>                    uint16_t outport, struct ofpbuf *remote_ofpacts)
>  {
>      const struct chassis_tunnel *tun
> -        = chassis_tunnel_find(chassis_tunnels, chassis_name, NULL);
> +        = chassis_tunnel_find(chassis_tunnels, chassis_name, NULL, NULL);
>      if (!tun) {
>          return;
>      }
> @@ -1953,7 +1955,7 @@ fanout_to_chassis(enum mf_field_id mff_ovn_geneve,
>      const struct chassis_tunnel *prev = NULL;
>      SSET_FOR_EACH (chassis_name, remote_chassis) {
>          const struct chassis_tunnel *tun
> -            = chassis_tunnel_find(chassis_tunnels, chassis_name, NULL);
> +            = chassis_tunnel_find(chassis_tunnels, chassis_name, NULL,
NULL);
>          if (!tun) {
>              continue;
>          }
> @@ -2492,7 +2494,7 @@ physical_run(struct physical_ctx *p_ctx,
>
>              if (!binding->chassis ||
>                  !encaps_tunnel_id_match(tun->chassis_id,
> -                                        binding->chassis->name, NULL)) {
> +                                        binding->chassis->name, NULL,
NULL)) {
>                  continue;
>              }
>
> diff --git a/controller/pinctrl.c b/controller/pinctrl.c
> index 4992eab0892b..4e35af0fb074 100644
> --- a/controller/pinctrl.c
> +++ b/controller/pinctrl.c
> @@ -5780,7 +5780,7 @@ get_localnet_vifs_l3gwports(
>          const char *tunnel_id = smap_get(&port_rec->external_ids,
>                                            "ovn-chassis-id");
>          if (tunnel_id &&
> -                encaps_tunnel_id_match(tunnel_id, chassis->name, NULL)) {
> +                encaps_tunnel_id_match(tunnel_id, chassis->name, NULL,
NULL)) {
>              continue;
>          }
>          const char *localnet = smap_get(&port_rec->external_ids,
> diff --git a/tests/ovn-ipsec.at b/tests/ovn-ipsec.at
> index f8df8d60e4b3..7579124db2e1 100644
> --- a/tests/ovn-ipsec.at
> +++ b/tests/ovn-ipsec.at
> @@ -58,52 +58,3 @@ AT_CHECK([as hv1 ovs-vsctl get Interface ovn-hv2-0
options:remote_name | tr -d '
>  AT_CHECK([as hv1 ovs-vsctl get Interface ovn-hv2-0
options:ipsec_encapsulation | tr -d '\n'], [0], [yes])
>
>  AT_CLEANUP
> -
> -AT_SETUP([ipsec -- unsupported multiple ovn-encap-ip values])
> -ovn_start
> -
> -# Configure the Northbound database
> -ovn-nbctl ls-add lsw0
> -
> -ovn-nbctl lsp-add lsw0 lp1
> -ovn-nbctl lsp-set-addresses lp1 "f0:00:00:00:00:01 10.1.1.1"
> -
> -ovn-nbctl lsp-add lsw0 lp2
> -ovn-nbctl lsp-set-addresses lp2 "f0:00:00:00:00:02 10.1.1.2"
> -
> -net_add n1               # Network to connect hv1 and hv2
> -
> -# Enable IPsec
> -ovn-nbctl set nb_global . ipsec=true
> -
> -# Create hypervisor hv1 connected to n1
> -sim_add hv1
> -as hv1
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.1
> -ovs-vsctl add-port br-int vif1 -- set Interface vif1
external-ids:iface-id=lp1
> -ovs-vsctl \
> -    -- set Open_vSwitch . external-ids:system-id=hv1 \
> -    -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \
> -    -- set Open_vSwitch . external-ids:ovn-encap-ip="192.168.0.1,
192.169.0.1" \
> -    -- set Open_vSwitch . other_config:certificate=dummy-cert.pem \
> -    -- set Open_vSwitch . other_config:private_key=dummy-privkey.pem \
> -    -- set Open_vSwitch . other_config:ca_cert=dummy-cacert.pem
> -
> -# Create hypervisor hv2 connected to n1
> -sim_add hv2
> -as hv2
> -ovs-vsctl add-br br-phys
> -ovn_attach n1 br-phys 192.168.0.2
> -ovs-vsctl add-port br-int vif2 -- set Interface vif2
external-ids:iface-id=lp2
> -ovs-vsctl \
> -    -- set Open_vSwitch . external-ids:system-id=hv2 \
> -    -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \
> -    -- set Open_vSwitch . external-ids:ovn-encap-ip="192.168.0.2,
192.169.0.2" \
> -    -- set Open_vSwitch . other_config:certificate=dummy-cert.pem \
> -    -- set Open_vSwitch . other_config:private_key=dummy-privkey.pem \
> -    -- set Open_vSwitch . other_config:ca_cert=dummy-cacert.pem
> -
> -OVS_WAIT_UNTIL([grep "ovn-encap-ip has been configured as a list. This
is unsupported for IPsec." hv1/ovn-controller.log])
> -
> -AT_CLEANUP
> diff --git a/tests/ovn.at b/tests/ovn.at
> index 2dd46fd79452..243fe0b8246c 100644
> --- a/tests/ovn.at
> +++ b/tests/ovn.at
> @@ -30333,6 +30333,54 @@ OVN_CLEANUP([hv1])
>  AT_CLEANUP
>  ])
>
> +
> +OVN_FOR_EACH_NORTHD([
> +AT_SETUP([multiple encap ips tunnel creation])
> +ovn_start
> +net_add n1
> +
> +# 2 HVs, each with 2 encap-ips.
> +for i in 1 2; do
> +    sim_add hv$i
> +    as hv$i
> +    ovs-vsctl add-br br-phys-$j
> +    ovn_attach n1 br-phys-$j 192.168.0.${i}1
> +    ovs-vsctl set open .
external_ids:ovn-encap-ip=192.168.0.${i}1,192.168.0.${i}2
> +done
> +
> +check ovn-nbctl --wait=hv sync
> +
> +check_tunnel_port() {
> +    local hv=$1
> +    local br=$2
> +    local id=$3
> +
> +    as $hv
> +    OVS_WAIT_UNTIL([
> +        test "$(ovs-vsctl --format=table --no-headings find port
external_ids:ovn-chassis-id="$id" | wc -l)" = "1"
> +    ])
> +    local tunnel_id=$(ovs-vsctl --bare --columns _uuid find port
external_ids:ovn-chassis-id="$id")
> +    AT_CHECK([ovs-vsctl --bare --columns ports find bridge name="$br" |
grep -q "$tunnel_id"])
> +}
> +
> +# Check that both chassis have tunnels.
> +# 'tunnel_id' in the format:
> +#   <chassis_id>@<remote_encap_ip>%<local_encap_ip>
> +check_tunnel_port hv1 br-int hv2@192.168.0.21%192.168.0.11
> +check_tunnel_port hv1 br-int hv2@192.168.0.22%192.168.0.11
> +check_tunnel_port hv1 br-int hv2@192.168.0.21%192.168.0.12
> +check_tunnel_port hv1 br-int hv2@192.168.0.22%192.168.0.12
> +
> +check_tunnel_port hv2 br-int hv1@192.168.0.11%192.168.0.21
> +check_tunnel_port hv2 br-int hv1@192.168.0.12%192.168.0.21
> +check_tunnel_port hv2 br-int hv1@192.168.0.11%192.168.0.22
> +check_tunnel_port hv2 br-int hv1@192.168.0.12%192.168.0.22
> +
> +OVN_CLEANUP([hv1],[hv2])
> +AT_CLEANUP
> +])
> +
> +
>  OVN_FOR_EACH_NORTHD([
>  AT_SETUP([Load Balancer LS hairpin OF flows])
>  ovn_start
> @@ -36174,14 +36222,14 @@ check_tunnel_port() {
>  }
>
>  # Check that both chassis have tunnel
> -check_tunnel_port hv1 br-int hv2@192.168.0.2
> -check_tunnel_port hv2 br-int hv1@192.168.0.1
> +check_tunnel_port hv1 br-int hv2@192.168.0.2%192.168.0.1
> +check_tunnel_port hv2 br-int hv1@192.168.0.1%192.168.0.2
>
>  # Stop ovn-controller on hv1
>  check as hv1 ovn-appctl -t ovn-controller exit --restart
>
>  # The tunnel should remain intact
> -check_tunnel_port hv1 br-int hv2@192.168.0.2
> +check_tunnel_port hv1 br-int hv2@192.168.0.2%192.168.0.1
>
>  # Change the bridge to br-int1 on hv1
>  as hv1
> @@ -36191,8 +36239,8 @@ start_daemon ovn-controller --verbose="encaps:dbg"
>  check ovn-nbctl --wait=hv sync
>
>  # Check that the tunnel was created on br-int1 instead
> -check_tunnel_port hv1 br-int1 hv2@192.168.0.2
> -check grep -q "Clearing old tunnel port \"ovn-hv2-0\" (hv2@192.168.0.2)
from bridge \"br-int\"" hv1/ovn-controller.log
> +check_tunnel_port hv1 br-int1 hv2@192.168.0.2%192.168.0.1
> +check grep -q "Clearing old tunnel port \"ovn-hv2-0\" 
> (hv2@192.168.0.2%192.168.0.1)
from bridge \"br-int\"" hv1/ovn-controller.log
>
>  # Change the bridge to br-int1 on hv2
>  as hv2
> @@ -36203,21 +36251,21 @@ check ovn-nbctl --wait=hv sync
>
>
>  # Check that the tunnel was created on br-int1 instead
> -check_tunnel_port hv2 br-int1 hv1@192.168.0.1
> -check grep -q "Clearing old tunnel port \"ovn-hv1-0\" (hv1@192.168.0.1)
from bridge \"br-int\"" hv2/ovn-controller.log
> +check_tunnel_port hv2 br-int1 hv1@192.168.0.1%192.168.0.2
> +check grep -q "Clearing old tunnel port \"ovn-hv1-0\" 
> (hv1@192.168.0.1%192.168.0.2)
from bridge \"br-int\"" hv2/ovn-controller.log
>
>  # Stop ovn-controller on hv1
>  check as hv1 ovn-appctl -t ovn-controller exit --restart
>
>  # The tunnel should remain intact
> -check_tunnel_port hv1 br-int1 hv2@192.168.0.2
> -prev_id=$(ovs-vsctl --bare --columns _uuid find port
external_ids:ovn-chassis-id="hv2@192.168.0.2")
> +check_tunnel_port hv1 br-int1 hv2@192.168.0.2%192.168.0.1
> +prev_id=$(ovs-vsctl --bare --columns _uuid find port
external_ids:ovn-chassis-id="hv2@192.168.0.2%192.168.0.1")
>
>  # Start the controller again
>  start_daemon ovn-controller --verbose="encaps:dbg"
>  check ovn-nbctl --wait=hv sync
> -check_tunnel_port hv1 br-int1 hv2@192.168.0.2
> -current_id=$(ovs-vsctl --bare --columns _uuid find port
external_ids:ovn-chassis-id="hv2@192.168.0.2")
> +check_tunnel_port hv1 br-int1 hv2@192.168.0.2%192.168.0.1
> +current_id=$(ovs-vsctl --bare --columns _uuid find port
external_ids:ovn-chassis-id="hv2@192.168.0.2%192.168.0.1")
>
>  # The tunnel should be the same after restart
>  check test "$current_id" = "$prev_id"
> @@ -36276,10 +36324,10 @@ check_tunnel_port() {
>      AT_CHECK([ovs-vsctl --bare --columns ports find bridge name="$br" |
grep -q "$tunnel_id"])
>  }
>
> -check_tunnel_port hv1 br-int hv2@192.168.0.2
> -check_tunnel_port hv1 br-int-2 hv1@192.168.0.1
> -prev_id1=$(ovs-vsctl --bare --columns _uuid find port
external_ids:ovn-chassis-id="hv1@192.168.0.1")
> -prev_id2=$(ovs-vsctl --bare --columns _uuid find port
external_ids:ovn-chassis-id="hv2@192.168.0.2")
> +check_tunnel_port hv1 br-int hv2@192.168.0.2%192.168.0.1
> +check_tunnel_port hv1 br-int-2 hv1@192.168.0.1%192.168.0.2
> +prev_id1=$(ovs-vsctl --bare --columns _uuid find port
external_ids:ovn-chassis-id="hv1@192.168.0.1%192.168.0.2")
> +prev_id2=$(ovs-vsctl --bare --columns _uuid find port
external_ids:ovn-chassis-id="hv2@192.168.0.2%192.168.0.1")
>
>  # The hv2 is running we can remove the override file
>  rm -f ${OVN_SYSCONFDIR}/system-id-override
> @@ -36300,13 +36348,13 @@ start_daemon ovn-controller
--verbose="encaps:dbg" \
>
>  check ovn-nbctl --wait=hv sync
>
> -check_tunnel_port hv1 br-int hv2@192.168.0.2
> -check_tunnel_port hv1 br-int-2 hv1@192.168.0.1
> -current_id1=$(ovs-vsctl --bare --columns _uuid find port
external_ids:ovn-chassis-id="hv1@192.168.0.1")
> -current_id2=$(ovs-vsctl --bare --columns _uuid find port
external_ids:ovn-chassis-id="hv2@192.168.0.2")
> +check_tunnel_port hv1 br-int hv2@192.168.0.2%192.168.0.1
> +check_tunnel_port hv1 br-int-2 hv1@192.168.0.1%192.168.0.2
> +current_id1=$(ovs-vsctl --bare --columns _uuid find port
external_ids:ovn-chassis-id="hv1@192.168.0.1%192.168.0.2")
> +current_id2=$(ovs-vsctl --bare --columns _uuid find port
external_ids:ovn-chassis-id="hv2@192.168.0.2%192.168.0.1")
>
>  # Check that restart of hv1 ovn-controller did not interfere with hv2
> -AT_CHECK([grep -q "Clearing old tunnel port \"ovn0-hv1-0\" (
hv1@192.168.0.1) from bridge \"br-int-2\"" hv1/ovn-controller.log], [1])
> +AT_CHECK([grep -q "Clearing old tunnel port \"ovn0-hv1-0\" (
hv1@192.168.0.1%192.168.0.2) from bridge \"br-int-2\""
hv1/ovn-controller.log], [1])
>  check test "$current_id1" = "$prev_id1"
>  check test "$current_id2" = "$prev_id2"
>
> --
> 2.38.1
>
_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to