kernel: bridge: Implement MLD Querier wake-up calls / Android bug workaround

Implement a configurable MLD Querier wake-up calls "feature" which
works around a widely spread Android bug in connection with IGMP/MLD
snooping.

Currently there are mobile devices (e.g. Android) which are not able
to receive and respond to MLD Queries reliably because the Wifi driver
filters a lot of ICMPv6 when the device is asleep - including
MLD. This in turn breaks IPv6 communication when MLD Snooping is
enabled. However there is one ICMPv6 type which is allowed to pass and
which can be used to wake up the mobile device: ICMPv6 Echo Requests.

If this bridge is the selected MLD Querier then setting
"multicast_wakeupcall" to a number n greater than 0 will send n
ICMPv6 Echo Requests to each host behind this port to wake
them up with each MLD Query. Upon receiving a matching ICMPv6 Echo
Reply an MLD Query with a unicast ethernet destination will be sent
to the specific host(s).

Link: https://issuetracker.google.com/issues/149630944
Link: https://github.com/freifunk-gluon/gluon/issues/1832

Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue>
This commit is contained in:
Linus Lüssing 2020-07-05 04:05:38 +02:00
parent e5b89b5511
commit b2add48d2a
2 changed files with 2662 additions and 0 deletions

View File

@ -0,0 +1,57 @@
From: Linus Lüssing <linus.luessing@c0d3.blue>
Date: Sun, 5 Jul 2020 04:02:17 +0200
Subject: batman-adv: compat: remove ip_mc_check_igmp() + ipv6_mc_check_mld()
The upstream Linux patches which reduced the number of arguments for
these functions from two to one were added to OpenWrt. Therefore compat
code for them is no more needed.
Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue>
diff --git a/batman-adv/src/compat-hacks.h b/batman-adv/src/compat-hacks.h
index d8de483a10243c77b2c5f49720a39dedb1404f01..1cbcfcf070c7dd943574612c0d13f886c88ecc25 100644
--- a/batman-adv/src/compat-hacks.h
+++ b/batman-adv/src/compat-hacks.h
@@ -53,39 +53,12 @@ int ipv6_mc_check_mld(struct sk_buff *skb);
#elif LINUX_VERSION_CODE < KERNEL_VERSION(5, 1, 0)
+#undef ip_mc_check_igmp
+#undef ipv6_mc_check_mld
+
#include_next <linux/igmp.h>
#include_next <net/addrconf.h>
-static inline int batadv_ipv6_mc_check_mld1(struct sk_buff *skb)
-{
- return ipv6_mc_check_mld(skb, NULL);
-}
-
-static inline int batadv_ipv6_mc_check_mld2(struct sk_buff *skb,
- struct sk_buff **skb_trimmed)
-{
- return ipv6_mc_check_mld(skb, skb_trimmed);
-}
-
-#define ipv6_mc_check_mld_get(_1, _2, ipv6_mc_check_mld_name, ...) ipv6_mc_check_mld_name
-#define ipv6_mc_check_mld(...) \
- ipv6_mc_check_mld_get(__VA_ARGS__, batadv_ipv6_mc_check_mld2, batadv_ipv6_mc_check_mld1)(__VA_ARGS__)
-
-static inline int batadv_ip_mc_check_igmp1(struct sk_buff *skb)
-{
- return ip_mc_check_igmp(skb, NULL);
-}
-
-static inline int batadv_ip_mc_check_igmp2(struct sk_buff *skb,
- struct sk_buff **skb_trimmed)
-{
- return ip_mc_check_igmp(skb, skb_trimmed);
-}
-
-#define ip_mc_check_igmp_get(_1, _2, ip_mc_check_igmp_name, ...) ip_mc_check_igmp_name
-#define ip_mc_check_igmp(...) \
- ip_mc_check_igmp_get(__VA_ARGS__, batadv_ip_mc_check_igmp2, batadv_ip_mc_check_igmp1)(__VA_ARGS__)
-
#endif /* < KERNEL_VERSION(4, 2, 0) */
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0)