> 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