[ovs-dev] [PATCH v3] ovn-controller: Fix parsing of OVN tunnel IDs

Dumitru Ceara dceara at redhat.com
Tue Jun 11 10:08:39 UTC 2019


On Fri, Jun 7, 2019 at 6:42 PM Ben Pfaff <blp at ovn.org> wrote:
>
> On Mon, May 27, 2019 at 10:55:52AM +0200, Dumitru Ceara wrote:
> > Encap tunnel-ids are of the form:
> > <chassis-id><OVN_MVTEP_CHASSISID_DELIM><encap-ip>.
> > In physical_run we were checking if a tunnel-id corresponds
> > to the local chassis-id by searching if the chassis-id string
> > is included in the tunnel-id (strstr). This can break quite
> > easily, for example, if the local chassis-id is a substring
> > of a remote chassis-id. In that case we were wrongfully
> > skipping the tunnel creation.
> >
> > To fix that new tunnel-id creation and parsing functions are added in
> > encaps.[ch]. These functions are now used everywhere where applicable.
> >
> > Acked-by: Venu Iyer <iyervl at ymail.com>
> > Reported-at: https://bugzilla.redhat.com/1708131
> > Reported-by: Haidong Li <haili at redhat.com>
> > Fixes: b520ca7 ("Support for multiple VTEP in OVN")
> > Signed-off-by: Dumitru Ceara <dceara at redhat.com>
> > ---
> >
> > v3: Rebase
> > v2: Update commit message
>
> This seems about right.
>
> Here's an incremental with some suggestions for encaps_tunnel_id_parse()
> and encaps_tunnel_id_match().  I'm pretty happy with the
> encaps_tunnel_id_parse() change; the encaps_tunnel_id_match() one might
> be going over the top.
>
> Let me know what you think.

Thanks for the suggestions.
I like the new encaps_tunnel_id_parse() as it's more succinct and even
though encaps_tunnel_id_match() might be going a bit over the top it's
the most efficient way to do it indeed.

Thanks,
Dumitru

>
> diff --git a/ovn/controller/encaps.c b/ovn/controller/encaps.c
> index 61b3eab3971f..3b3921a736e2 100644
> --- a/ovn/controller/encaps.c
> +++ b/ovn/controller/encaps.c
> @@ -102,64 +102,51 @@ encaps_tunnel_id_create(const char *chassis_id, const char *encap_ip)
>   * 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'.
>   */
> -bool encaps_tunnel_id_parse(const char *tunnel_id, char **chassis_id,
> -                            char **encap_ip)
> +bool
> +encaps_tunnel_id_parse(const char *tunnel_id, char **chassis_id,
> +                       char **encap_ip)
>  {
> -    const char *match = strchr(tunnel_id, OVN_MVTEP_CHASSISID_DELIM);
> -
> -    if (!match) {
> +    /* 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);
> +    if (d == tunnel_id || !d || !d[1]) {
>          return false;
>      }
>
>      if (chassis_id) {
> -        size_t chassis_id_len = (match - tunnel_id);
> -
> -        *chassis_id = xmemdup0(tunnel_id, chassis_id_len);
> +        *chassis_id = xmemdup0(tunnel_id, d - tunnel_id);
>      }
> -
> -    /* Consume the tunnel-id delimiter. */
> -    match++;
> -
>      if (encap_ip) {
> -        /*
> -         * If the value has morphed into something other than
> -         * <chassis-id><delim><encap-ip>, fail and free already allocated
> -         * memory (i.e., chassis_id).
> -         */
> -        if (*match == 0) {
> -            if (chassis_id) {
> -                free(*chassis_id);
> -            }
> -            return false;
> -        }
> -        *encap_ip = xstrdup(match);
> +        *encap_ip = xstrdup(d + 1);
>      }
> -
>      return true;
>  }
>
>  /*
> - * Returns true if a given tunnel_id contains 'chassis_id' and, if specified,
> - * the given 'encap_ip'. Returns false otherwise.
> + * Returns true if 'tunnel_id' contains 'chassis_id' and, if specified, the
> + * given 'encap_ip'. Returns false otherwise.
>   */
> -bool encaps_tunnel_id_match(const char *tunnel_id, const char *chassis_id,
> -                            const char *encap_ip)
> +bool
> +encaps_tunnel_id_match(const char *tunnel_id, const char *chassis_id,
> +                       const char *encap_ip)
>  {
> -    if (strstr(tunnel_id, chassis_id) != tunnel_id) {
> -        return false;
> -    }
> -
> -    size_t chassis_id_len = strlen(chassis_id);
> -
> -    if (tunnel_id[chassis_id_len] != OVN_MVTEP_CHASSISID_DELIM) {
> -        return false;
> -    }
> -
> -    if (encap_ip && strcmp(&tunnel_id[chassis_id_len + 1], encap_ip)) {
> -        return false;
> +    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++;
>      }
>
> -    return true;
> +    /* 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)));
>  }
>
>  static void


More information about the dev mailing list