On Mon, 2023-01-23 at 10:01 +0100, Lorenzo Bianconi wrote:
> Avoid learning Link-Local reserved multicast addresses if advertised in
> a MLD reports since this interferes with Slaac IPv6 address resolution
> implemented in OVN.
> 
> Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=2154930
> Tested-by: Eduardo Olivares <eoliv...@redhat.com>
> Signed-off-by: Lorenzo Bianconi <lorenzo.bianc...@redhat.com>
> ---
>  lib/mcast-snooping.c | 69 ++++++++++++++++++++++++++++++++------------
>  lib/packets.c        | 11 +++++++
>  lib/packets.h        | 13 +++++++++
>  3 files changed, 74 insertions(+), 19 deletions(-)
> 
> diff --git a/lib/mcast-snooping.c b/lib/mcast-snooping.c
> index 029ca2855..a9d2e7900 100644
> --- a/lib/mcast-snooping.c
> +++ b/lib/mcast-snooping.c
> @@ -38,6 +38,8 @@
>  COVERAGE_DEFINE(mcast_snooping_learned);
>  COVERAGE_DEFINE(mcast_snooping_expired);
>  
> +VLOG_DEFINE_THIS_MODULE(mcast_snooping);
> +
>  static struct mcast_port_bundle *
>  mcast_snooping_port_lookup(struct ovs_list *list, void *port);
>  static struct mcast_mrouter_bundle *
> @@ -489,6 +491,28 @@ mcast_snooping_add_report(struct mcast_snooping *ms,
>      return count;
>  }
>  
> +static bool
> +mcast_snooping_should_learn_mld_group(struct in6_addr *addr)
> +{
> +    /* we should learn multicast group from the following IPv6 multicast

Is this supposed to be "should *not* learn multicast group"?

Dan

> +     * groups:
> +     * - All Nodes Address       (ff02::1)
> +     * - All Router Address      (ff02::2)
> +     * - All Site Router Address (ff05::2)
> +     * - Solicited-Node Address  (ff02::1:ff00:0000/104)
> +     */
> +    if (in6_addr_is_solicited_node(addr) || ipv6_is_all_hosts(addr) ||
> +        ipv6_is_all_router(addr) || ipv6_is_all_site_router(addr)) {
> +        static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
> +        char ip_str[INET6_ADDRSTRLEN + 1];
> +
> +        ipv6_string_mapped(ip_str, addr);
> +        VLOG_DBG_RL(&rl, "Invalid Multicast group %s", ip_str);
> +        return false;
> +    }
> +    return true;
> +}
> +
>  int
>  mcast_snooping_add_mld(struct mcast_snooping *ms,
>                            const struct dp_packet *p,
> @@ -531,26 +555,33 @@ mcast_snooping_add_mld(struct mcast_snooping *ms,
>                  break;
>              }
>              /* Only consider known record types. */
> -            if (record->type >= IGMPV3_MODE_IS_INCLUDE
> -                && record->type <= IGMPV3_BLOCK_OLD_SOURCES) {
> -                struct in6_addr maddr;
> -                memcpy(maddr.s6_addr, record->maddr.be16, 16);
> -                addr = &maddr;
> -                /*
> -                 * If record is INCLUDE MODE and there are no sources, it's
> -                 * equivalent to a LEAVE.
> -                 */
> -                if (record->nsrcs == htons(0)
> -                    && (record->type == IGMPV3_MODE_IS_INCLUDE
> -                        || record->type == IGMPV3_CHANGE_TO_INCLUDE_MODE)) {
> -                    ret = mcast_snooping_leave_group(ms, addr, vlan, port);
> -                } else {
> -                    ret = mcast_snooping_add_group(ms, addr, vlan, port);
> -                }
> -                if (ret) {
> -                    count++;
> -                }
> +            if (record->type < IGMPV3_MODE_IS_INCLUDE ||
> +                record->type > IGMPV3_BLOCK_OLD_SOURCES) {
> +                goto next;
> +            }
> +
> +            struct in6_addr maddr;
> +            memcpy(maddr.s6_addr, record->maddr.be16, 16);
> +            if (!mcast_snooping_should_learn_mld_group(&maddr)) {
> +                goto next;
> +            }
> +
> +            /*
> +             * If record is INCLUDE MODE and there are no sources, it's
> +             * equivalent to a LEAVE.
> +             */
> +            addr = &maddr;
> +            if (record->nsrcs == htons(0)
> +                && (record->type == IGMPV3_MODE_IS_INCLUDE
> +                    || record->type == IGMPV3_CHANGE_TO_INCLUDE_MODE)) {
> +                ret = mcast_snooping_leave_group(ms, addr, vlan, port);
> +            } else {
> +                ret = mcast_snooping_add_group(ms, addr, vlan, port);
> +            }
> +            if (ret) {
> +                count++;
>              }
> +next:
>              offset += sizeof(*record)
>                        + ntohs(record->nsrcs) * sizeof(struct in6_addr)
>                        + record->aux_len;
> diff --git a/lib/packets.c b/lib/packets.c
> index 06f516cb1..b43f78bc1 100644
> --- a/lib/packets.c
> +++ b/lib/packets.c
> @@ -38,6 +38,7 @@
>  const struct in6_addr in6addr_exact = IN6ADDR_EXACT_INIT;
>  const struct in6_addr in6addr_all_hosts = IN6ADDR_ALL_HOSTS_INIT;
>  const struct in6_addr in6addr_all_routers = IN6ADDR_ALL_ROUTERS_INIT;
> +const struct in6_addr in6addr_all_site_routers = 
> IN6ADDR_ALL_SITE_ROUTERS_INIT;
>  
>  struct in6_addr
>  flow_tnl_dst(const struct flow_tnl *tnl)
> @@ -605,6 +606,16 @@ in6_addr_solicited_node(struct in6_addr *addr, const 
> struct in6_addr *ip6)
>      memcpy(&addr->s6_addr[13], &ip6->s6_addr[13], 3);
>  }
>  
> +bool
> +in6_addr_is_solicited_node(struct in6_addr *addr)
> +{
> +    union ovs_16aligned_in6_addr *taddr =
> +        (union ovs_16aligned_in6_addr *) addr;
> +    return taddr->be16[0] ==  htons(0xff02) &&
> +           taddr->be16[5] ==  htons(0x1) &&
> +           taddr->be16[6] ==  htons(0xff00);
> +}
> +
>  /*
>   * Generates ipv6 EUI64 address from the given eth addr
>   * and prefix and stores it in 'lla'
> diff --git a/lib/packets.h b/lib/packets.h
> index 8626aac8d..e88753456 100644
> --- a/lib/packets.h
> +++ b/lib/packets.h
> @@ -1146,6 +1146,10 @@ extern const struct in6_addr in6addr_all_routers;
>  #define IN6ADDR_ALL_ROUTERS_INIT { { { 
> 0xff,0x02,0x00,0x00,0x00,0x00,0x00,0x00, \
>                                         
> 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02 } } }
>  
> +extern const struct in6_addr in6addr_all_site_routers;
> +#define IN6ADDR_ALL_SITE_ROUTERS_INIT { { { 
> 0xff,0x05,0x00,0x00,0x00,0x00,0x00,0x00, \
> +                                            
> 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02 } } }
> +
>  static inline bool ipv6_addr_equals(const struct in6_addr *a,
>                                      const struct in6_addr *b)
>  {
> @@ -1169,6 +1173,14 @@ static inline bool ipv6_is_all_hosts(const struct 
> in6_addr *addr) {
>      return ipv6_addr_equals(addr, &in6addr_all_hosts);
>  }
>  
> +static inline bool ipv6_is_all_router(const struct in6_addr *addr) {
> +    return ipv6_addr_equals(addr, &in6addr_all_routers);
> +}
> +
> +static inline bool ipv6_is_all_site_router(const struct in6_addr *addr) {
> +    return ipv6_addr_equals(addr, &in6addr_all_site_routers);
> +}
> +
>  static inline bool ipv6_addr_is_set(const struct in6_addr *addr) {
>      return !ipv6_addr_equals(addr, &in6addr_any);
>  }
> @@ -1207,6 +1219,7 @@ in6_addr_get_mapped_ipv4(const struct in6_addr *addr)
>  
>  void in6_addr_solicited_node(struct in6_addr *addr,
>                               const struct in6_addr *ip6);
> +bool in6_addr_is_solicited_node(struct in6_addr *addr);
>  
>  void in6_generate_eui64(struct eth_addr ea, const struct in6_addr *prefix,
>                          struct in6_addr *lla);

_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to