On 30/06/2016 17:05, Daniel Danzberger wrote: > This patch is a backport for current LEDE 4.4 Kernels. > It is already upstream, for linux-next and stable. > The initial commit message is below: > > The bridge is falsly dropping ipv6 mulitcast packets if there is: > 1. No ipv6 address assigned on the brigde. > 2. No external mld querier present. > 3. The internal querier enabled. > > When the bridge fails to build mld queries, because it has no > ipv6 address, it slilently returns, but keeps the local querier enabled. > This specific case causes confusing packet loss. > > Ipv6 multicast snooping can only work if: > a) An external querier is present > OR > b) The bridge has an ipv6 address an is capable of sending own queries > > Otherwise it has to forward/flood the ipv6 multicast traffic, > because snooping cannot work. > > This patch fixes the issue by adding a flag to the bridge struct that > indicates that there is currently no ipv6 address assinged to the bridge > and returns a false state for the local querier in > __br_multicast_querier_exists(). > > Special thanks to Linus Lüssing. > > Signed-off-by: Daniel Danzberger <dan...@dd-wrt.com>
Hi Daniel, can you please use the full annotated upstream patch ? it would be best if 646-bridge_fix_ipv6_mc_snooping_if_bridge_has_no_ipv6_address.patch contained the original description and SoB line John > --- > ...mc_snooping_if_bridge_has_no_ipv6_address.patch | 76 > ++++++++++++++++++++++ > 1 file changed, 76 insertions(+) > create mode 100644 > target/linux/generic/patches-4.4/646-bridge_fix_ipv6_mc_snooping_if_bridge_has_no_ipv6_address.patch > > diff --git > a/target/linux/generic/patches-4.4/646-bridge_fix_ipv6_mc_snooping_if_bridge_has_no_ipv6_address.patch > > b/target/linux/generic/patches-4.4/646-bridge_fix_ipv6_mc_snooping_if_bridge_has_no_ipv6_address.patch > new file mode 100644 > index 0000000..e0bdbae > --- /dev/null > +++ > b/target/linux/generic/patches-4.4/646-bridge_fix_ipv6_mc_snooping_if_bridge_has_no_ipv6_address.patch > @@ -0,0 +1,76 @@ > +diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c > +index c8c2a8a..d063a10 100644 > +--- a/net/bridge/br_multicast.c > ++++ b/net/bridge/br_multicast.c > +@@ -465,8 +465,11 @@ static struct sk_buff > *br_ip6_multicast_alloc_query(struct net_bridge *br, > + if (ipv6_dev_get_saddr(dev_net(br->dev), br->dev, &ip6h->daddr, 0, > + &ip6h->saddr)) { > + kfree_skb(skb); > ++ br->has_ipv6_addr = 0; > + return NULL; > + } > ++ > ++ br->has_ipv6_addr = 1; > + ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest); > + > + hopopt = (u8 *)(ip6h + 1); > +@@ -1768,6 +1771,7 @@ void br_multicast_init(struct net_bridge *br) > + br->ip6_other_query.delay_time = 0; > + br->ip6_querier.port = NULL; > + #endif > ++ br->has_ipv6_addr = 1; > + > + spin_lock_init(&br->multicast_lock); > + setup_timer(&br->multicast_router_timer, > +diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h > +index e24abfd..3dd7e2c 100644 > +--- a/net/bridge/br_private.h > ++++ b/net/bridge/br_private.h > +@@ -303,6 +303,7 @@ struct net_bridge > + u8 multicast_disabled:1; > + u8 multicast_querier:1; > + u8 multicast_query_use_ifaddr:1; > ++ u8 has_ipv6_addr:1; > + > + u32 hash_elasticity; > + u32 hash_max; > +@@ -577,10 +578,22 @@ static inline bool br_multicast_is_router(struct > net_bridge *br) > + > + static inline bool > + __br_multicast_querier_exists(struct net_bridge *br, > +- struct bridge_mcast_other_query *querier) > ++ struct bridge_mcast_other_query *querier, > ++ const bool is_ipv6) > + { > ++ bool own_querier_enabled; > ++ > ++ if (br->multicast_querier) { > ++ if (is_ipv6 && !br->has_ipv6_addr) > ++ own_querier_enabled = false; > ++ else > ++ own_querier_enabled = true; > ++ } else { > ++ own_querier_enabled = false; > ++ } > ++ > + return time_is_before_jiffies(querier->delay_time) && > +- (br->multicast_querier || timer_pending(&querier->timer)); > ++ (own_querier_enabled || timer_pending(&querier->timer)); > + } > + > + static inline bool br_multicast_querier_exists(struct net_bridge *br, > +@@ -588,10 +601,12 @@ static inline bool br_multicast_querier_exists(struct > net_bridge *br, > + { > + switch (eth->h_proto) { > + case (htons(ETH_P_IP)): > +- return __br_multicast_querier_exists(br, &br->ip4_other_query); > ++ return __br_multicast_querier_exists(br, > ++ &br->ip4_other_query, false); > + #if IS_ENABLED(CONFIG_IPV6) > + case (htons(ETH_P_IPV6)): > +- return __br_multicast_querier_exists(br, &br->ip6_other_query); > ++ return __br_multicast_querier_exists(br, > ++ &br->ip6_other_query, true); > + #endif > + default: > + return false; > _______________________________________________ Lede-dev mailing list Lede-dev@lists.infradead.org http://lists.infradead.org/mailman/listinfo/lede-dev