> 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"?

yes, sorry :)

Regards,
Lorenzo

> 
> 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