b85a9c54d5
6c3e16055a kernel: backport ksmbd security fix ZDI-22-1690 275c51bf40 Revert "image-commands.mk: Be consistent in command invocation" fec4fb3a56 sunxi: remove frequency for NanoPi R1 51a763ab0f arm-trusted-firmware-sunxi: drop CPE ID 377d805887 trusted-firmware-a.mk: use correct CPE ID f30414c56d kernel: bump 5.10 to 5.10.160 47ac52a7c4 ath79: image: don't depend on other COMPILE targets da79da3ac1 image: fix device profile specific COMPILE targets 9aa95bbebb rules: fix broken commitcount on alpine system fcff234fd8 image-commands.mk: Be consistent in command invocation be7b97d873 sunxi: fix typo in device packages for MarsBoard A10 709351bf32 kernel: Make KERNEL_MAKEOPTS recursively expanded 3b066a6581 lantiq: vr9: include usb driver for fritz 7430 39dcfcd987 wolfssl: fix build with /dev/crypto e51f3a22aa toolchain: Update glibc 2.34 to recent HEAD 298d2d0412 Revert "mbedtls: import patch to fix illegal instruction on mpc85xx" 3de4572ed3 tools/ccache: fix build with musl and gcc 12 8e43a44f08 rpcd: update to latest Git HEAD f43ceb60d5 iwinfo: update to latest Git HEAD 31baecb70e iwinfo: update to the latest version f34c4a950e iwinfo: update to the latest version 9b7a3e1a5e iwinfo: update to the latest version ce881873c0 kernel: add missing dependency to KERNEL_RPI_AXIPERF 7ccb4c6651 kernel: add missing symbol for bcm27xx b18a0d0b92 generic: add support for EON EN25QX128A spi nor flash d909fb1d3b kernel: bump 5.10 to 5.10.159 e5cec69484 kernel: bump 5.10 to 5.10.158 3a58bda06b kernel: bump 5.10 to 5.10.157 ee2341cac6 kernel: add symbol in generic config for 5.10.157 bc64ca15d4 kernel: kmod-net-rtl8192su: Remove package b1204ce28c umbim: Allow roaming and partner connections 15bc6b23c7 kernel: further cleanup of xfrm[4|6]_mode* 6e396eff1a kernel: remove handling of xfrm[4|6]_mode_* modules 78fc12ddd0 kernel: fix typo for tegra crypto-sha1 module 4408f7d564 kernel: add kmod-btsdio package 6b2c445b88 kernel: remove CONFIG_MMC_BLOCK_BOUNCE aef33ab13a ath79: fix Teltonika RUT230 v1 MAC assignment 6cd1035d8d ramips: add support for Wavlink WS-WN572HP3 4G 3f7ce4bd40 comgt-ncm: add support for quectel modem EC200T-EU 03ab5a60da realtek: update GPIO bindings for DGS-1210-10P 63fde4607c ustream-ssl: update to Git version 2022-12-07 1c174fe0ba CI: kernel: don't checkout and install feeds 385f78780c CI: build: skip sdk adapt to external toolchain on cache hit 8be50c369b CI: build: fix use of sdk as toolchain 1af58a2d39 ramips: mt7621: enable lzma-loader for ZyXEL WAP6805 8fbf03690e ramips: mt7621: enable lzma-loader for netis WF2881 282dd271ad kernel: ca8210: Fix crash by zero initializing data 1a0f2c3a3e e2fsprogs: Fix CVE-2022-1304 1285938d2c bcm4908: Refresh kernel patches eb639e54fc ucode: update to latest Git HEAD 9b6dcf322b mvebu: disable also wrt32x due to broken switch 69ed96fba8 kernel: netconsole: add network console logging support 1f9bf1ee82 kernel: kmod-isdn4linux: Remove package a3dee42206 kernel: kmod-w1-slave-ds2760: Remove package 2a1bf860f3 kernel: kmod-rtc-pt7c4338: Remove package a0bae2fef8 mvebu: cortexa9: disable devices using broken mv88e6176 switch 309a6f22ba CI: trigger check also on build and check-kernel-patches workflow change ec9ca325c0 CI: build: fix matching for openwrt release branch for toolchain parsing 63a2ea5470 CI: fix matching for openwrt release branch for container selection 9db78a7e86 CI: build: add support to fallback to sdk for external toolchain 47519a574c CI: build: add support for external toolchains from stable branch 05c3ee608f CI: build: add support for per branch tools container f3cb0cfdf9 CI: tools: support per branch tools container 5fc4182f1e CI: Build all boards and testing kernel 31fb360f57 CI: Allow building with internal toolchain e74479d559 CI: Extract the OpenWrt building to own sub workflow b7e2e14912 CI: Simplify if conditions 8ac2cf6de9 CI: packages.yml: Fix usage of pre-build tools db347be0b3 CI: packages: Add github CI job to build all packages 99524d49b4 CI: kernel: fix deprecation of set-output de29c8bda7 ci: kernel: trigger build check on changes in kernel.mk as well b93a59352f CI: kernel: check if patch are refreshed for each target d070707379 CI: bump actions/download,upload-artifact action to v3 69414201ae CI: bump actions/checkout action to v3 8c4e39eb08 CI: kernel: generate ccache cache on kernel push 6c3e16055a kernel: backport ksmbd security fix ZDI-22-1690 275c51bf40 Revert "image-commands.mk: Be consistent in command invocation" fec4fb3a56 sunxi: remove frequency for NanoPi R1 51a763ab0f arm-trusted-firmware-sunxi: drop CPE ID 377d805887 trusted-firmware-a.mk: use correct CPE ID f30414c56d kernel: bump 5.10 to 5.10.160 47ac52a7c4 ath79: image: don't depend on other COMPILE targets da79da3ac1 image: fix device profile specific COMPILE targets 9aa95bbebb rules: fix broken commitcount on alpine system fcff234fd8 image-commands.mk: Be consistent in command invocation be7b97d873 sunxi: fix typo in device packages for MarsBoard A10 709351bf32 kernel: Make KERNEL_MAKEOPTS recursively expanded 3b066a6581 lantiq: vr9: include usb driver for fritz 7430 39dcfcd987 wolfssl: fix build with /dev/crypto e51f3a22aa toolchain: Update glibc 2.34 to recent HEAD 298d2d0412 Revert "mbedtls: import patch to fix illegal instruction on mpc85xx" 3de4572ed3 tools/ccache: fix build with musl and gcc 12 8e43a44f08 rpcd: update to latest Git HEAD f43ceb60d5 iwinfo: update to latest Git HEAD 31baecb70e iwinfo: update to the latest version f34c4a950e iwinfo: update to the latest version 9b7a3e1a5e iwinfo: update to the latest version ce881873c0 kernel: add missing dependency to KERNEL_RPI_AXIPERF 7ccb4c6651 kernel: add missing symbol for bcm27xx b18a0d0b92 generic: add support for EON EN25QX128A spi nor flash d909fb1d3b kernel: bump 5.10 to 5.10.159 e5cec69484 kernel: bump 5.10 to 5.10.158 3a58bda06b kernel: bump 5.10 to 5.10.157 ee2341cac6 kernel: add symbol in generic config for 5.10.157 bc64ca15d4 kernel: kmod-net-rtl8192su: Remove package b1204ce28c umbim: Allow roaming and partner connections 15bc6b23c7 kernel: further cleanup of xfrm[4|6]_mode* 6e396eff1a kernel: remove handling of xfrm[4|6]_mode_* modules 78fc12ddd0 kernel: fix typo for tegra crypto-sha1 module 4408f7d564 kernel: add kmod-btsdio package 6b2c445b88 kernel: remove CONFIG_MMC_BLOCK_BOUNCE aef33ab13a ath79: fix Teltonika RUT230 v1 MAC assignment 6cd1035d8d ramips: add support for Wavlink WS-WN572HP3 4G 3f7ce4bd40 comgt-ncm: add support for quectel modem EC200T-EU 03ab5a60da realtek: update GPIO bindings for DGS-1210-10P 63fde4607c ustream-ssl: update to Git version 2022-12-07 1c174fe0ba CI: kernel: don't checkout and install feeds 385f78780c CI: build: skip sdk adapt to external toolchain on cache hit 8be50c369b CI: build: fix use of sdk as toolchain 1af58a2d39 ramips: mt7621: enable lzma-loader for ZyXEL WAP6805 8fbf03690e ramips: mt7621: enable lzma-loader for netis WF2881 282dd271ad kernel: ca8210: Fix crash by zero initializing data 1a0f2c3a3e e2fsprogs: Fix CVE-2022-1304 1285938d2c bcm4908: Refresh kernel patches eb639e54fc ucode: update to latest Git HEAD 9b6dcf322b mvebu: disable also wrt32x due to broken switch 69ed96fba8 kernel: netconsole: add network console logging support 1f9bf1ee82 kernel: kmod-isdn4linux: Remove package a3dee42206 kernel: kmod-w1-slave-ds2760: Remove package 2a1bf860f3 kernel: kmod-rtc-pt7c4338: Remove package a0bae2fef8 mvebu: cortexa9: disable devices using broken mv88e6176 switch 309a6f22ba CI: trigger check also on build and check-kernel-patches workflow change ec9ca325c0 CI: build: fix matching for openwrt release branch for toolchain parsing 63a2ea5470 CI: fix matching for openwrt release branch for container selection 9db78a7e86 CI: build: add support to fallback to sdk for external toolchain 47519a574c CI: build: add support for external toolchains from stable branch 05c3ee608f CI: build: add support for per branch tools container f3cb0cfdf9 CI: tools: support per branch tools container 5fc4182f1e CI: Build all boards and testing kernel 31fb360f57 CI: Allow building with internal toolchain e74479d559 CI: Extract the OpenWrt building to own sub workflow b7e2e14912 CI: Simplify if conditions 8ac2cf6de9 CI: packages.yml: Fix usage of pre-build tools db347be0b3 CI: packages: Add github CI job to build all packages 99524d49b4 CI: kernel: fix deprecation of set-output de29c8bda7 ci: kernel: trigger build check on changes in kernel.mk as well b93a59352f CI: kernel: check if patch are refreshed for each target d070707379 CI: bump actions/download,upload-artifact action to v3 69414201ae CI: bump actions/checkout action to v3 8c4e39eb08 CI: kernel: generate ccache cache on kernel push 303b784cc8 build: harden GitHub workflow permissions b3e8d58151 Revert "build: harden GitHub workflow permissions" 431875b3df CI: kernel: use ccache to speedup workflow 8bbaa486cb CI: tools: compile tools with ccache support for tools container c2df98c49c CI: Add workaround for github uppercase usernames daeb367dc1 CI: use tools:latest container to speedup kernel workflow fccf42cb05 CI: create Docker container containing compiled tools 047e68adb1 CI: use buildbot container for building a69b9a8962 ci: show build failures directly in job log output f2fb3ffd71 ci: move scripts into separate directory 7ff1477b3d CI: package kmods in kernel workflow 2f9b35624d CI: kernel: Cache external toolchain 1f13c8cd24 CI: kernel: Build all kernel modules c3ed9f36ee CI: kernel: Checkout feeds from github 0987df4af1 CI: kernel: Show used OpenWrt configuration f7affcd614 CI: kernel: Use downloads.cdn.openwrt.org 0f71cf7ab6 CI: kernel: Trigger workflow for more directories 586be47078 CI: run inside the buildbot docker container 0e46907ff5 CI: add Kernel compile tests 119c6573c4 CI: usability improvements for tools ac7b1c8e94 build: handle directory with whitespace in AUTOREMOVE clean 439e19de96 scripts/ext-tools: introduce new script to install prebuilt tools d419136ad5 build: make find_md5 reproducible with AUTOREMOVE be2da47ced ath79: expand rootfs for DIR-825-B1 with unused space 087a2a4691 mac80211: Update to version 5.15.81 83c70346ac base-files: support "metric" in board.json 5167bcf2fc kernel: update U-Boot nvmem driver to v6.2 release version bf1c4f1eba bcm4908: update DTS files with the latest changes 44fad4b1f6 bcm4908: fix Asus GT-AX6000 image c45f44165b bcm4908: use upstream patches for Asus GT-AC5300 LEDs 7d63c39bf4 CI: labeler: fix wrong label for pr targeting stable branch e516c31e14 CI: add support to tag pr targeting stable branch 8b95e14e32 Revert "CI: Add release/22.03 label to all pull requests" ce1de42096 layerscape: Fix SPI-NOR issues with vendor patches a704216259 mt76: move the mt7921 firmware to its own package e7497d1083 CI: Add release/22.03 label to all pull requests c43b5e71b8 CI: labeler: target major version of labeler action 008e9a335d build: harden GitHub workflow permissions c7757810fc CI: include automatic Pull Request Labeler 2b5154214c ipq40xx: luma_wrtq-acn329: swap ethernet MAC addresses 68add5f364 ath79: mikrotik: use OpenWrt loader for initram image a907c20340 kernel: add kmod-hwmon-sht3x support a4af427d80 procd: service: pass all arguments to service 106fedd9ed ath79: fix MAC address assigment for TP-Link TL-WR740N/TL-WR741ND v4 8040f74f8d tools/patch: apply patch for EACCES on xattr copy eda395a5e0 wolfssl: update to v5.5.3 0b22e87db0 ath79: D-Link DIR-825 B1 add factory.bin recipe de6c3cca4d mbedtls: import patch to fix illegal instruction on mpc85xx 302ef2137d mt76: add firmware package for mt7916 844de50b7b ath79: disable image building for Ubiquiti EdgeSwitch 8XP af0c128368 lantiq: add 6.1 tag to upstream patch a4e8ff5ab4 lantiq: enable interrupts on second VPEs dca73263a4 lantiq: xrx200: backport upstream network fixes 078bdc1856 kernel: bump 5.10 to 5.10.156 b7388191a5 kernel: bump 5.10 to 5.10.155 61e1f6541d kernel: modules: package Marvell gigE PHY driver 64da7c8af7 bcm27xx: fix CI build after config refresh 3564c22e46 bcm27xx: disable duplicate sdhost driver 353e468f47 kernel: support "linux,rootfs" DT property for splitting rootfs b66037f53b bcm53xx: update DTS files with the latest changes 58a73b1135 kernel: improve description of NTFS kernel packages 932378aeb6 kernel: backport support for "linux,rootfs" in DT af20d9d03b kernel: split out mtd hack for CONFIG_FIT_PARTITION + rootfs 8c1f8f9978 ipq40xx: ZTE MF286D: fix DEVICE_PACKAGES 54dc60e71d generic: fix unset symbol c837fc9cdb kernel: bump 5.10 to 5.10.154 bbad2ee4de kernel: bump 5.10 to 5.10.153 d2ae7613b5 ramips: improve compatibility for Youku YK-L2 and YK-L1 series 9155d40513 ramips: gl-mt1300: downclock SPI to 50MHz ca124d2e4b ramips: mt7621: use seama-lzma-loader for D-Link DIR-860L B1 fafc9448ae ramips: rt3883: use seama-lzma-loader for D-Link DIR-645 292d3f00c7 ramips: define lzma-loader recipe for SEAMA devices d25e1a3bde ath79: fix MAC address assignment for TP-Link ar7241 devices 7fa6351310 tools/expat: update to 2.5.0 8122aa92fd ath79: add support for Linksys EA4500 v3 1133a8f805 ath79: add support to TrendNet TEW-673GRU 5725b773b4 qoriq: fix typo in FEATURES 615dbec223 mac80211: fix mesh airtime link metric estimation a26f7e61e8 mac80211: fix issues with receiving small STP packets bfeffb8aed mac80211: fix decap offload for stations on AP_VLAN interfaces 88c43b5887 hostapd: remove invalid dtim_period option processing 4628e7ae4d ramips: backport TP-Link RE200 v3/v4 LED fix 1d095c1d43 strace: replace PKG_CPE_ID d84cf62000 strace: update to 5.19 8650f77314 strace: add nls.mk 0b80a7da58 strace: update to 5.18 faf9d20a21 strace: update to 5.17 e95b359eaa kernel: netsupport: Add FQ-PIE as an optional sched kmod and extract PIE 051c24c69a kernel: extract kmod-sched-act-ipt from kmod-sched 23ccc71c61 kernel: netsupport: Extract act_police 3ca45248fd kernel: netsupport: Add kmod-sched-act-sample 7ee55d82fc kernel: netsupport: Extract sched-prio and sched-red 31fd96bdbd kernel: netsupport: Add kmod-sched-drr c61ed09228 kernel: netsupport: kmod-sched: Reorder packages 26b58991b0 ipq40xx: fix ZTE MF289F port mapping 71178a8506 ipq40xx: Fix wrong GPIO for internal status LED on ZTE MF289F 3e15a54bb0 ipq40xx: Add ZTE MF289F 7a77aacb31 uboot-envtools: Fix format of autogenerated sectors b3b3428a0e openssl: bump to 1.1.1s e313cd8d15 uboot-layerscape: adjust LS1012A-IOT config and env 77522d4eb7 dnsmasq: Backport DHCPv6 server fix (CVE-2022-0934) 13bd217821 busybox: awk: fix use after free (CVE-2022-30065) fe5cd3c9d9 util-linux: Update to version 2.37.4 84b3eafe39 bcm4908: backport upstream BQL support for bcm4908_enet 0ff3adfa11 kernel: bump 5.10 to 5.10.152 0abcea19d7 kernel: bump 5.10 to 5.10.151 0667688a40 kernel: bump 5.10 to 5.10.150 fe58ee9057 ramips: Correct Unielec 01 and 06 dts wan macaddr byte location 6c5313d77c bcm4908: backport bcm4908_enet fix for NULL dereference 91e4a74fff bcm4908: optimize Ethernet driver by using build_skb() b4bc9eb837 kernel: mtd: backport SafeLoader parser 18c77387c5 kernel: mtd: backport extended dynamic partitions support
915 lines
32 KiB
Diff
915 lines
32 KiB
Diff
From: Linus Lüssing <linus.luessing@c0d3.blue>
|
|
Date: Sat, 1 Jan 2022 10:09:13 +0100
|
|
Subject: 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>
|
|
|
|
diff --git a/package/network/config/netifd/patches/0001-bridge-Add-multicast_wakeupcall-option.patch b/package/network/config/netifd/patches/0001-bridge-Add-multicast_wakeupcall-option.patch
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..e3da684dc950ea4c226705d27b23b0470499d54b
|
|
--- /dev/null
|
|
+++ b/package/network/config/netifd/patches/0001-bridge-Add-multicast_wakeupcall-option.patch
|
|
@@ -0,0 +1,176 @@
|
|
+From 6db5050d9e046a486260ea23a77118db4f8a6672 Mon Sep 17 00:00:00 2001
|
|
+From: =?UTF-8?q?Linus=20L=C3=BCssing?= <linus.luessing@c0d3.blue>
|
|
+Date: Sun, 5 Jul 2020 23:33:51 +0200
|
|
+Subject: [PATCH] bridge: Add multicast_wakeupcall option
|
|
+MIME-Version: 1.0
|
|
+Content-Type: text/plain; charset=UTF-8
|
|
+Content-Transfer-Encoding: 8bit
|
|
+
|
|
+This makes the new per bridge port multicast_wakeupcall feature
|
|
+for the Linux bridge configurable for wireless interfaces and enables it
|
|
+by default for an AP interface.
|
|
+
|
|
+The MLD Querier wake-up calls "feature" 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>
|
|
+---
|
|
+ device.c | 9 +++++++++
|
|
+ device.h | 37 ++++++++++++++++++++-----------------
|
|
+ system-linux.c | 13 +++++++++++++
|
|
+ 3 files changed, 42 insertions(+), 17 deletions(-)
|
|
+
|
|
+--- a/device.c
|
|
++++ b/device.c
|
|
+@@ -47,6 +47,7 @@ static const struct blobmsg_policy dev_a
|
|
+ [DEV_ATTR_NEIGHGCSTALETIME] = { .name = "neighgcstaletime", .type = BLOBMSG_TYPE_INT32 },
|
|
+ [DEV_ATTR_DADTRANSMITS] = { .name = "dadtransmits", .type = BLOBMSG_TYPE_INT32 },
|
|
+ [DEV_ATTR_MULTICAST_TO_UNICAST] = { .name = "multicast_to_unicast", .type = BLOBMSG_TYPE_BOOL },
|
|
++ [DEV_ATTR_MULTICAST_WAKEUPCALL] = { .name = "multicast_wakeupcall", .type = BLOBMSG_TYPE_INT32 },
|
|
+ [DEV_ATTR_MULTICAST_ROUTER] = { .name = "multicast_router", .type = BLOBMSG_TYPE_INT32 },
|
|
+ [DEV_ATTR_MULTICAST_FAST_LEAVE] = { .name = "multicast_fast_leave", . type = BLOBMSG_TYPE_BOOL },
|
|
+ [DEV_ATTR_MULTICAST] = { .name ="multicast", .type = BLOBMSG_TYPE_BOOL },
|
|
+@@ -261,6 +262,7 @@ device_merge_settings(struct device *dev
|
|
+ n->multicast = s->flags & DEV_OPT_MULTICAST ?
|
|
+ s->multicast : os->multicast;
|
|
+ n->multicast_to_unicast = s->multicast_to_unicast;
|
|
++ n->multicast_wakeupcall = s->multicast_wakeupcall;
|
|
+ n->multicast_router = s->multicast_router;
|
|
+ n->multicast_fast_leave = s->multicast_fast_leave;
|
|
+ n->learning = s->learning;
|
|
+@@ -386,6 +388,11 @@ device_init_settings(struct device *dev,
|
|
+ s->flags |= DEV_OPT_MULTICAST_TO_UNICAST;
|
|
+ }
|
|
+
|
|
++ if ((cur = tb[DEV_ATTR_MULTICAST_WAKEUPCALL])) {
|
|
++ s->multicast_wakeupcall = blobmsg_get_u32(cur);
|
|
++ s->flags |= DEV_OPT_MULTICAST_WAKEUPCALL;
|
|
++ }
|
|
++
|
|
+ if ((cur = tb[DEV_ATTR_MULTICAST_ROUTER])) {
|
|
+ s->multicast_router = blobmsg_get_u32(cur);
|
|
+ if (s->multicast_router <= 2)
|
|
+@@ -1186,6 +1193,8 @@ device_dump_status(struct blob_buf *b, s
|
|
+ blobmsg_add_u32(b, "dadtransmits", st.dadtransmits);
|
|
+ if (st.flags & DEV_OPT_MULTICAST_TO_UNICAST)
|
|
+ blobmsg_add_u8(b, "multicast_to_unicast", st.multicast_to_unicast);
|
|
++ if (st.flags & DEV_OPT_MULTICAST_WAKEUPCALL)
|
|
++ blobmsg_add_u32(b, "multicast_wakeupcall", st.multicast_wakeupcall);
|
|
+ if (st.flags & DEV_OPT_MULTICAST_ROUTER)
|
|
+ blobmsg_add_u32(b, "multicast_router", st.multicast_router);
|
|
+ if (st.flags & DEV_OPT_MULTICAST_FAST_LEAVE)
|
|
+--- a/device.h
|
|
++++ b/device.h
|
|
+@@ -44,6 +44,7 @@ enum {
|
|
+ DEV_ATTR_NEIGHREACHABLETIME,
|
|
+ DEV_ATTR_DADTRANSMITS,
|
|
+ DEV_ATTR_MULTICAST_TO_UNICAST,
|
|
++ DEV_ATTR_MULTICAST_WAKEUPCALL,
|
|
+ DEV_ATTR_MULTICAST_ROUTER,
|
|
+ DEV_ATTR_MULTICAST_FAST_LEAVE,
|
|
+ DEV_ATTR_MULTICAST,
|
|
+@@ -109,23 +110,24 @@ enum {
|
|
+ DEV_OPT_MTU6 = (1ULL << 12),
|
|
+ DEV_OPT_DADTRANSMITS = (1ULL << 13),
|
|
+ DEV_OPT_MULTICAST_TO_UNICAST = (1ULL << 14),
|
|
+- DEV_OPT_MULTICAST_ROUTER = (1ULL << 15),
|
|
+- DEV_OPT_MULTICAST = (1ULL << 16),
|
|
+- DEV_OPT_LEARNING = (1ULL << 17),
|
|
+- DEV_OPT_UNICAST_FLOOD = (1ULL << 18),
|
|
+- DEV_OPT_NEIGHGCSTALETIME = (1ULL << 19),
|
|
+- DEV_OPT_MULTICAST_FAST_LEAVE = (1ULL << 20),
|
|
+- DEV_OPT_SENDREDIRECTS = (1ULL << 21),
|
|
+- DEV_OPT_NEIGHLOCKTIME = (1ULL << 22),
|
|
+- DEV_OPT_ISOLATE = (1ULL << 23),
|
|
+- DEV_OPT_IP6SEGMENTROUTING = (1ULL << 24),
|
|
+- DEV_OPT_DROP_V4_UNICAST_IN_L2_MULTICAST = (1ULL << 25),
|
|
+- DEV_OPT_DROP_V6_UNICAST_IN_L2_MULTICAST = (1ULL << 26),
|
|
+- DEV_OPT_DROP_GRATUITOUS_ARP = (1ULL << 27),
|
|
+- DEV_OPT_DROP_UNSOLICITED_NA = (1ULL << 28),
|
|
+- DEV_OPT_ARP_ACCEPT = (1ULL << 29),
|
|
+- DEV_OPT_SPEED = (1ULL << 30),
|
|
+- DEV_OPT_DUPLEX = (1ULL << 31),
|
|
++ DEV_OPT_MULTICAST_WAKEUPCALL = (1ULL << 15),
|
|
++ DEV_OPT_MULTICAST_ROUTER = (1ULL << 16),
|
|
++ DEV_OPT_MULTICAST = (1ULL << 17),
|
|
++ DEV_OPT_LEARNING = (1ULL << 18),
|
|
++ DEV_OPT_UNICAST_FLOOD = (1ULL << 19),
|
|
++ DEV_OPT_NEIGHGCSTALETIME = (1ULL << 20),
|
|
++ DEV_OPT_MULTICAST_FAST_LEAVE = (1ULL << 21),
|
|
++ DEV_OPT_SENDREDIRECTS = (1ULL << 22),
|
|
++ DEV_OPT_NEIGHLOCKTIME = (1ULL << 23),
|
|
++ DEV_OPT_ISOLATE = (1ULL << 24),
|
|
++ DEV_OPT_IP6SEGMENTROUTING = (1ULL << 25),
|
|
++ DEV_OPT_DROP_V4_UNICAST_IN_L2_MULTICAST = (1ULL << 26),
|
|
++ DEV_OPT_DROP_V6_UNICAST_IN_L2_MULTICAST = (1ULL << 27),
|
|
++ DEV_OPT_DROP_GRATUITOUS_ARP = (1ULL << 28),
|
|
++ DEV_OPT_DROP_UNSOLICITED_NA = (1ULL << 29),
|
|
++ DEV_OPT_ARP_ACCEPT = (1ULL << 30),
|
|
++ DEV_OPT_SPEED = (1ULL << 31),
|
|
++ DEV_OPT_DUPLEX = (1ULL << 32),
|
|
+ };
|
|
+
|
|
+ /* events broadcasted to all users of a device */
|
|
+@@ -187,6 +189,7 @@ struct device_settings {
|
|
+ int neigh4locktime;
|
|
+ unsigned int dadtransmits;
|
|
+ bool multicast_to_unicast;
|
|
++ unsigned int multicast_wakeupcall;
|
|
+ unsigned int multicast_router;
|
|
+ bool multicast_fast_leave;
|
|
+ bool multicast;
|
|
+--- a/system-linux.c
|
|
++++ b/system-linux.c
|
|
+@@ -465,6 +465,11 @@ static void system_bridge_set_multicast_
|
|
+ system_set_dev_sysfs("brport/multicast_to_unicast", dev->ifname, val);
|
|
+ }
|
|
+
|
|
++static void system_bridge_set_multicast_wakeupcall(struct device *dev, const char *val)
|
|
++{
|
|
++ system_set_dev_sysfs("brport/multicast_wakeupcall", dev->ifname, val);
|
|
++}
|
|
++
|
|
+ static void system_bridge_set_multicast_fast_leave(struct device *dev, const char *val)
|
|
+ {
|
|
+ system_set_dev_sysfs("brport/multicast_fast_leave", dev->ifname, val);
|
|
+@@ -844,8 +849,10 @@ static char *system_get_bridge(const cha
|
|
+ static void
|
|
+ system_bridge_set_wireless(struct device *bridge, struct device *dev)
|
|
+ {
|
|
++ unsigned int mcast_wakeupcall = dev->wireless_ap ? 2 : 0;
|
|
+ bool mcast_to_ucast = dev->wireless_ap;
|
|
+ bool hairpin;
|
|
++ char buf[64];
|
|
+
|
|
+ if (bridge->settings.flags & DEV_OPT_MULTICAST_TO_UNICAST &&
|
|
+ !bridge->settings.multicast_to_unicast)
|
|
+@@ -858,6 +865,12 @@ system_bridge_set_wireless(struct device
|
|
+ system_bridge_set_multicast_to_unicast(dev, mcast_to_ucast ? "1" : "0");
|
|
+ system_bridge_set_hairpin_mode(dev, hairpin ? "1" : "0");
|
|
+ system_bridge_set_proxyarp_wifi(dev, dev->wireless_proxyarp ? "1" : "0");
|
|
++
|
|
++ if (bridge->settings.flags & DEV_OPT_MULTICAST_WAKEUPCALL)
|
|
++ mcast_wakeupcall = dev->settings.multicast_wakeupcall;
|
|
++
|
|
++ snprintf(buf, sizeof(buf), "%u", mcast_wakeupcall);
|
|
++ system_bridge_set_multicast_wakeupcall(dev, buf);
|
|
+ }
|
|
+
|
|
+ int system_bridge_addif(struct device *bridge, struct device *dev)
|
|
diff --git a/target/linux/generic/config-5.10 b/target/linux/generic/config-5.10
|
|
index efc0861f1c99eedb29d40ea0e6f52a26008c901b..a99c836e2f9413936f010ef53f1f3d3c82d46dff 100644
|
|
--- a/target/linux/generic/config-5.10
|
|
+++ b/target/linux/generic/config-5.10
|
|
@@ -737,6 +737,7 @@ CONFIG_BRIDGE=y
|
|
# CONFIG_BRIDGE_EBT_T_NAT is not set
|
|
# CONFIG_BRIDGE_EBT_VLAN is not set
|
|
CONFIG_BRIDGE_IGMP_SNOOPING=y
|
|
+CONFIG_BRIDGE_IGMP_SNOOPING_WAKEUPCALLS=y
|
|
# CONFIG_BRIDGE_MRP is not set
|
|
# CONFIG_BRIDGE_NETFILTER is not set
|
|
# CONFIG_BRIDGE_NF_EBTABLES is not set
|
|
diff --git a/target/linux/generic/hack-5.10/601-bridge-Implement-MLD-Querier-wake-up-calls-Android-b.patch b/target/linux/generic/hack-5.10/601-bridge-Implement-MLD-Querier-wake-up-calls-Android-b.patch
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..17df35fe4a812b5b5118beb9239bf825be7b67ed
|
|
--- /dev/null
|
|
+++ b/target/linux/generic/hack-5.10/601-bridge-Implement-MLD-Querier-wake-up-calls-Android-b.patch
|
|
@@ -0,0 +1,687 @@
|
|
+From e0fd3ecf9b4f6825ad0380b759baf88ef508bed5 Mon Sep 17 00:00:00 2001
|
|
+From: =?UTF-8?q?Linus=20L=C3=BCssing?= <linus.luessing@c0d3.blue>
|
|
+Date: Mon, 29 Jun 2020 19:04:05 +0200
|
|
+Subject: [PATCH] bridge: Implement MLD Querier wake-up calls / Android bug
|
|
+ workaround
|
|
+MIME-Version: 1.0
|
|
+Content-Type: text/plain; charset=UTF-8
|
|
+Content-Transfer-Encoding: 8bit
|
|
+
|
|
+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>
|
|
+---
|
|
+ include/linux/if_bridge.h | 1 +
|
|
+ include/net/addrconf.h | 1 +
|
|
+ include/uapi/linux/if_link.h | 1 +
|
|
+ net/bridge/Kconfig | 26 ++++
|
|
+ net/bridge/br_fdb.c | 10 ++
|
|
+ net/bridge/br_input.c | 4 +-
|
|
+ net/bridge/br_multicast.c | 289 ++++++++++++++++++++++++++++++++++-
|
|
+ net/bridge/br_netlink.c | 19 +++
|
|
+ net/bridge/br_private.h | 19 +++
|
|
+ net/bridge/br_sysfs_if.c | 18 +++
|
|
+ net/core/rtnetlink.c | 2 +-
|
|
+ net/ipv6/mcast_snoop.c | 3 +-
|
|
+ 12 files changed, 383 insertions(+), 10 deletions(-)
|
|
+
|
|
+diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h
|
|
+index ea1c7d151f46..d7714f60b88a 100644
|
|
+--- a/include/linux/if_bridge.h
|
|
++++ b/include/linux/if_bridge.h
|
|
+@@ -58,6 +58,7 @@ struct br_ip_list {
|
|
+ #define BR_MRP_LOST_IN_CONT BIT(19)
|
|
+ #define BR_BPDU_FILTER BIT(20)
|
|
+ #define BR_OFFLOAD BIT(21)
|
|
++#define BR_MULTICAST_WAKEUPCALL BIT(22)
|
|
+
|
|
+ #define BR_DEFAULT_AGEING_TIME (300 * HZ)
|
|
+
|
|
+diff --git a/include/net/addrconf.h b/include/net/addrconf.h
|
|
+index e7ce719838b5..af8f153e1b5f 100644
|
|
+--- a/include/net/addrconf.h
|
|
++++ b/include/net/addrconf.h
|
|
+@@ -235,6 +235,7 @@ void ipv6_mc_unmap(struct inet6_dev *idev);
|
|
+ void ipv6_mc_remap(struct inet6_dev *idev);
|
|
+ void ipv6_mc_init_dev(struct inet6_dev *idev);
|
|
+ void ipv6_mc_destroy_dev(struct inet6_dev *idev);
|
|
++int ipv6_mc_check_icmpv6(struct sk_buff *skb);
|
|
+ int ipv6_mc_check_mld(struct sk_buff *skb);
|
|
+ void addrconf_dad_failure(struct sk_buff *skb, struct inet6_ifaddr *ifp);
|
|
+
|
|
+diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
|
|
+index ffeb05c061d2..1956ab99e97d 100644
|
|
+--- a/include/uapi/linux/if_link.h
|
|
++++ b/include/uapi/linux/if_link.h
|
|
+@@ -525,6 +525,7 @@ enum {
|
|
+ IFLA_BRPORT_MRP_RING_OPEN,
|
|
+ IFLA_BRPORT_MRP_IN_OPEN,
|
|
+ IFLA_BRPORT_BPDU_FILTER,
|
|
++ IFLA_BRPORT_MCAST_WAKEUPCALL,
|
|
+ __IFLA_BRPORT_MAX
|
|
+ };
|
|
+ #define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1)
|
|
+diff --git a/net/bridge/Kconfig b/net/bridge/Kconfig
|
|
+index 80879196560c..056e80bf00c4 100644
|
|
+--- a/net/bridge/Kconfig
|
|
++++ b/net/bridge/Kconfig
|
|
+@@ -48,6 +48,32 @@ config BRIDGE_IGMP_SNOOPING
|
|
+
|
|
+ If unsure, say Y.
|
|
+
|
|
++config BRIDGE_IGMP_SNOOPING_WAKEUPCALLS
|
|
++ bool "MLD Querier wake-up calls"
|
|
++ depends on BRIDGE_IGMP_SNOOPING
|
|
++ depends on IPV6
|
|
++ help
|
|
++ If you say Y here, then the MLD Snooping Querier will be built
|
|
++ with a per bridge port wake-up call "feature"/workaround.
|
|
++
|
|
++ 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).
|
|
++
|
|
++ Say N to exclude this support and reduce the binary size.
|
|
++
|
|
++ If unsure, say N.
|
|
++
|
|
+ config BRIDGE_VLAN_FILTERING
|
|
+ bool "VLAN filtering"
|
|
+ depends on BRIDGE
|
|
+diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
|
|
+index bc6c8d5cd1e1..98ca86b7ca42 100644
|
|
+--- a/net/bridge/br_fdb.c
|
|
++++ b/net/bridge/br_fdb.c
|
|
+@@ -85,6 +85,10 @@ static void fdb_rcu_free(struct rcu_head *head)
|
|
+ {
|
|
+ struct net_bridge_fdb_entry *ent
|
|
+ = container_of(head, struct net_bridge_fdb_entry, rcu);
|
|
++
|
|
++#ifdef CONFIG_BRIDGE_IGMP_SNOOPING_WAKEUPCALLS
|
|
++ del_timer_sync(&ent->wakeupcall_timer);
|
|
++#endif
|
|
+ kmem_cache_free(br_fdb_cache, ent);
|
|
+ }
|
|
+
|
|
+@@ -516,6 +520,12 @@ static struct net_bridge_fdb_entry *fdb_create(struct net_bridge *br,
|
|
+ fdb->updated = fdb->used = jiffies;
|
|
+ INIT_HLIST_HEAD(&fdb->offload_in);
|
|
+ INIT_HLIST_HEAD(&fdb->offload_out);
|
|
++
|
|
++#ifdef CONFIG_BRIDGE_IGMP_SNOOPING_WAKEUPCALLS
|
|
++ timer_setup(&fdb->wakeupcall_timer,
|
|
++ br_multicast_send_wakeupcall, 0);
|
|
++#endif
|
|
++
|
|
+ if (rhashtable_lookup_insert_fast(&br->fdb_hash_tbl,
|
|
+ &fdb->rhnode,
|
|
+ br_fdb_rht_params)) {
|
|
+diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
|
|
+index 64f3eaa3879d..a449a1f60f1b 100644
|
|
+--- a/net/bridge/br_input.c
|
|
++++ b/net/bridge/br_input.c
|
|
+@@ -163,8 +163,10 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
|
|
+ if (dst) {
|
|
+ unsigned long now = jiffies;
|
|
+
|
|
+- if (test_bit(BR_FDB_LOCAL, &dst->flags))
|
|
++ if (test_bit(BR_FDB_LOCAL, &dst->flags)) {
|
|
++ br_multicast_wakeupcall_rcv(br, p, skb, vid);
|
|
+ return br_pass_frame_up(skb);
|
|
++ }
|
|
+
|
|
+ if (now != dst->used)
|
|
+ dst->used = now;
|
|
+diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
|
|
+index e5328a2777ec..a2f45bd523ab 100644
|
|
+--- a/net/bridge/br_multicast.c
|
|
++++ b/net/bridge/br_multicast.c
|
|
+@@ -833,15 +833,16 @@ static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge *br,
|
|
+ const struct in6_addr *group,
|
|
+ bool with_srcs, bool over_llqt,
|
|
+ u8 sflag, u8 *igmp_type,
|
|
+- bool *need_rexmit)
|
|
++ bool *need_rexmit,
|
|
++ bool delay)
|
|
+ {
|
|
+ struct net_bridge_port *p = pg ? pg->key.port : NULL;
|
|
+ struct net_bridge_group_src *ent;
|
|
+ size_t pkt_size, mld_hdr_size;
|
|
+ unsigned long now = jiffies;
|
|
++ unsigned long interval = 0;
|
|
+ struct mld2_query *mld2q;
|
|
+ void *csum_start = NULL;
|
|
+- unsigned long interval;
|
|
+ __sum16 *csum = NULL;
|
|
+ struct ipv6hdr *ip6h;
|
|
+ struct mld_msg *mldq;
|
|
+@@ -922,9 +923,13 @@ static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge *br,
|
|
+
|
|
+ /* ICMPv6 */
|
|
+ skb_set_transport_header(skb, skb->len);
|
|
+- interval = ipv6_addr_any(group) ?
|
|
+- br->multicast_query_response_interval :
|
|
+- br->multicast_last_member_interval;
|
|
++ if (delay) {
|
|
++ interval = ipv6_addr_any(group) ?
|
|
++ br->multicast_query_response_interval :
|
|
++ br->multicast_last_member_interval;
|
|
++ interval = jiffies_to_msecs(interval);
|
|
++ }
|
|
++
|
|
+ *igmp_type = ICMPV6_MGM_QUERY;
|
|
+ switch (br->multicast_mld_version) {
|
|
+ case 1:
|
|
+@@ -932,7 +937,7 @@ static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge *br,
|
|
+ mldq->mld_type = ICMPV6_MGM_QUERY;
|
|
+ mldq->mld_code = 0;
|
|
+ mldq->mld_cksum = 0;
|
|
+- mldq->mld_maxdelay = htons((u16)jiffies_to_msecs(interval));
|
|
++ mldq->mld_maxdelay = htons((u16)interval);
|
|
+ mldq->mld_reserved = 0;
|
|
+ mldq->mld_mca = *group;
|
|
+ csum = &mldq->mld_cksum;
|
|
+@@ -1022,7 +1027,7 @@ static struct sk_buff *br_multicast_alloc_query(struct net_bridge *br,
|
|
+ &ip6_dst, &group->dst.ip6,
|
|
+ with_srcs, over_lmqt,
|
|
+ sflag, igmp_type,
|
|
+- need_rexmit);
|
|
++ need_rexmit, true);
|
|
+ }
|
|
+ #endif
|
|
+ }
|
|
+@@ -1427,6 +1432,168 @@ static void br_multicast_select_own_querier(struct net_bridge *br,
|
|
+ #endif
|
|
+ }
|
|
+
|
|
++#ifdef CONFIG_BRIDGE_IGMP_SNOOPING_WAKEUPCALLS
|
|
++
|
|
++#define BR_MC_WAKEUP_ID htons(0xEC6B) /* random identifier */
|
|
++#define BR_MC_ETH_ZERO { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
|
|
++#define BR_MC_IN6_ZERO \
|
|
++{ \
|
|
++ .s6_addr32[0] = 0, .s6_addr32[1] = 0, \
|
|
++ .s6_addr32[2] = 0, .s6_addr32[3] = 0, \
|
|
++}
|
|
++
|
|
++#define BR_MC_IN6_FE80 \
|
|
++{ \
|
|
++ .s6_addr32[0] = htonl(0xfe800000), \
|
|
++ .s6_addr32[1] = 0, \
|
|
++ .s6_addr32[2] = htonl(0x000000ff), \
|
|
++ .s6_addr32[3] = htonl(0xfe000000), \
|
|
++}
|
|
++
|
|
++#define BR_MC_ECHO_LEN sizeof(pkt->echohdr)
|
|
++
|
|
++static struct sk_buff *br_multicast_alloc_wakeupcall(struct net_bridge *br,
|
|
++ struct net_bridge_port *port,
|
|
++ u8 *eth_dst)
|
|
++{
|
|
++ struct in6_addr ip6_src, ip6_dst = BR_MC_IN6_FE80;
|
|
++ struct sk_buff *skb;
|
|
++ __wsum csum_part;
|
|
++ __sum16 csum;
|
|
++
|
|
++ struct wakeupcall_pkt {
|
|
++ struct ethhdr ethhdr;
|
|
++ struct ipv6hdr ip6hdr;
|
|
++ struct icmp6hdr echohdr;
|
|
++ } __packed;
|
|
++
|
|
++ struct wakeupcall_pkt *pkt;
|
|
++
|
|
++ static const struct wakeupcall_pkt __pkt_template = {
|
|
++ .ethhdr = {
|
|
++ .h_dest = BR_MC_ETH_ZERO, // update
|
|
++ .h_source = BR_MC_ETH_ZERO, // update
|
|
++ .h_proto = htons(ETH_P_IPV6),
|
|
++ },
|
|
++ .ip6hdr = {
|
|
++ .priority = 0,
|
|
++ .version = 0x6,
|
|
++ .flow_lbl = { 0x00, 0x00, 0x00 },
|
|
++ .payload_len = htons(BR_MC_ECHO_LEN),
|
|
++ .nexthdr = IPPROTO_ICMPV6,
|
|
++ .hop_limit = 1,
|
|
++ .saddr = BR_MC_IN6_ZERO, // update
|
|
++ .daddr = BR_MC_IN6_ZERO, // update
|
|
++ },
|
|
++ .echohdr = {
|
|
++ .icmp6_type = ICMPV6_ECHO_REQUEST,
|
|
++ .icmp6_code = 0,
|
|
++ .icmp6_cksum = 0, // update
|
|
++ .icmp6_dataun.u_echo = {
|
|
++ .identifier = BR_MC_WAKEUP_ID,
|
|
++ .sequence = 0,
|
|
++ },
|
|
++ },
|
|
++ };
|
|
++
|
|
++ memcpy(&ip6_dst.s6_addr32[2], ð_dst[0], ETH_ALEN / 2);
|
|
++ memcpy(&ip6_dst.s6_addr[13], ð_dst[3], ETH_ALEN / 2);
|
|
++ ip6_dst.s6_addr[8] ^= 0x02;
|
|
++ if (ipv6_dev_get_saddr(dev_net(br->dev), br->dev, &ip6_dst, 0,
|
|
++ &ip6_src))
|
|
++ return NULL;
|
|
++
|
|
++ skb = netdev_alloc_skb_ip_align(br->dev, sizeof(*pkt));
|
|
++ if (!skb)
|
|
++ return NULL;
|
|
++
|
|
++ skb->protocol = htons(ETH_P_IPV6);
|
|
++ skb->dev = port->dev;
|
|
++
|
|
++ pkt = (struct wakeupcall_pkt *)skb->data;
|
|
++ *pkt = __pkt_template;
|
|
++
|
|
++ ether_addr_copy(pkt->ethhdr.h_source, br->dev->dev_addr);
|
|
++ ether_addr_copy(pkt->ethhdr.h_dest, eth_dst);
|
|
++
|
|
++ pkt->ip6hdr.saddr = ip6_src;
|
|
++ pkt->ip6hdr.daddr = ip6_dst;
|
|
++
|
|
++ csum_part = csum_partial(&pkt->echohdr, sizeof(pkt->echohdr), 0);
|
|
++ csum = csum_ipv6_magic(&ip6_src, &ip6_dst, sizeof(pkt->echohdr),
|
|
++ IPPROTO_ICMPV6, csum_part);
|
|
++ pkt->echohdr.icmp6_cksum = csum;
|
|
++
|
|
++ skb_reset_mac_header(skb);
|
|
++ skb_set_network_header(skb, offsetof(struct wakeupcall_pkt, ip6hdr));
|
|
++ skb_set_transport_header(skb, offsetof(struct wakeupcall_pkt, echohdr));
|
|
++ skb_put(skb, sizeof(*pkt));
|
|
++ __skb_pull(skb, sizeof(pkt->ethhdr));
|
|
++
|
|
++ return skb;
|
|
++}
|
|
++
|
|
++void br_multicast_send_wakeupcall(struct timer_list *t)
|
|
++{
|
|
++ struct net_bridge_fdb_entry *fdb = from_timer(fdb, t, wakeupcall_timer);
|
|
++ struct net_bridge_port *port = fdb->dst;
|
|
++ struct net_bridge *br = port->br;
|
|
++ struct sk_buff *skb, *skb0;
|
|
++ int i;
|
|
++
|
|
++ skb0 = br_multicast_alloc_wakeupcall(br, port, fdb->key.addr.addr);
|
|
++ if (!skb0)
|
|
++ return;
|
|
++
|
|
++ for (i = port->wakeupcall_num_rings; i > 0; i--) {
|
|
++ if (i > 1) {
|
|
++ skb = skb_clone(skb0, GFP_ATOMIC);
|
|
++ if (!skb) {
|
|
++ kfree_skb(skb0);
|
|
++ break;
|
|
++ }
|
|
++ } else {
|
|
++ skb = skb0;
|
|
++ }
|
|
++
|
|
++ NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT,
|
|
++ dev_net(port->dev), NULL, skb, NULL, skb->dev,
|
|
++ br_dev_queue_push_xmit);
|
|
++ }
|
|
++}
|
|
++
|
|
++static void br_multicast_schedule_wakeupcalls(struct net_bridge *br,
|
|
++ struct net_bridge_port *port,
|
|
++ const struct in6_addr *group)
|
|
++{
|
|
++ struct net_bridge_fdb_entry *fdb;
|
|
++ unsigned long delay;
|
|
++
|
|
++ rcu_read_lock();
|
|
++ hlist_for_each_entry_rcu(fdb, &br->fdb_list, fdb_node) {
|
|
++ if (!fdb->dst || fdb->dst->dev != port->dev)
|
|
++ continue;
|
|
++
|
|
++ /* Wake-up calls to VLANs unsupported for now */
|
|
++ if (fdb->key.vlan_id)
|
|
++ continue;
|
|
++
|
|
++ /* Spread the ICMPv6 Echo Requests to avoid congestion.
|
|
++ * We then won't use a max response delay for the queries later,
|
|
++ * as that would be redundant. Spread randomly by a little less
|
|
++ * than max response delay to anticipate the extra round trip.
|
|
++ */
|
|
++ delay = ipv6_addr_any(group) ?
|
|
++ br->multicast_query_response_interval :
|
|
++ br->multicast_last_member_interval;
|
|
++ delay = prandom_u32() % (3 * delay / 4);
|
|
++
|
|
++ timer_reduce(&fdb->wakeupcall_timer, jiffies + delay);
|
|
++ }
|
|
++ rcu_read_unlock();
|
|
++}
|
|
++#endif /* CONFIG_BRIDGE_IGMP_SNOOPING_WAKEUPCALLS */
|
|
++
|
|
+ static void __br_multicast_send_query(struct net_bridge *br,
|
|
+ struct net_bridge_port *port,
|
|
+ struct net_bridge_port_group *pg,
|
|
+@@ -1455,6 +1622,13 @@ static void __br_multicast_send_query(struct net_bridge *br,
|
|
+ dev_net(port->dev), NULL, skb, NULL, skb->dev,
|
|
+ br_dev_queue_push_xmit);
|
|
+
|
|
++#ifdef CONFIG_BRIDGE_IGMP_SNOOPING_WAKEUPCALLS
|
|
++ if (port->wakeupcall_num_rings &&
|
|
++ group->proto == htons(ETH_P_IPV6))
|
|
++ br_multicast_schedule_wakeupcalls(br, port,
|
|
++ &group->dst.ip6);
|
|
++#endif
|
|
++
|
|
+ if (over_lmqt && with_srcs && sflag) {
|
|
+ over_lmqt = false;
|
|
+ goto again_under_lmqt;
|
|
+@@ -3164,6 +3338,98 @@ int br_multicast_rcv(struct net_bridge *br, struct net_bridge_port *port,
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
++#ifdef CONFIG_BRIDGE_IGMP_SNOOPING_WAKEUPCALLS
|
|
++
|
|
++static bool br_multicast_wakeupcall_check(struct net_bridge *br,
|
|
++ struct net_bridge_port *port,
|
|
++ struct sk_buff *skb, u16 vid)
|
|
++{
|
|
++ struct ethhdr *eth = eth_hdr(skb);
|
|
++ const struct ipv6hdr *ip6h;
|
|
++ unsigned int offset, len;
|
|
++ struct icmp6hdr *icmp6h;
|
|
++
|
|
++ /* Wake-up calls to VLANs unsupported for now */
|
|
++ if (!port->wakeupcall_num_rings || vid ||
|
|
++ eth->h_proto != htons(ETH_P_IPV6))
|
|
++ return false;
|
|
++
|
|
++ if (!ether_addr_equal(eth->h_dest, br->dev->dev_addr) ||
|
|
++ is_multicast_ether_addr(eth->h_source) ||
|
|
++ is_zero_ether_addr(eth->h_source))
|
|
++ return false;
|
|
++
|
|
++ offset = skb_network_offset(skb) + sizeof(*ip6h);
|
|
++ if (!pskb_may_pull(skb, offset))
|
|
++ return false;
|
|
++
|
|
++ ip6h = ipv6_hdr(skb);
|
|
++
|
|
++ if (ip6h->version != 6)
|
|
++ return false;
|
|
++
|
|
++ len = offset + ntohs(ip6h->payload_len);
|
|
++ if (skb->len < len || len <= offset)
|
|
++ return false;
|
|
++
|
|
++ if (ip6h->nexthdr != IPPROTO_ICMPV6)
|
|
++ return false;
|
|
++
|
|
++ skb_set_transport_header(skb, offset);
|
|
++
|
|
++ if (ipv6_mc_check_icmpv6(skb) < 0)
|
|
++ return false;
|
|
++
|
|
++ icmp6h = (struct icmp6hdr *)skb_transport_header(skb);
|
|
++ if (icmp6h->icmp6_type != ICMPV6_ECHO_REPLY ||
|
|
++ icmp6h->icmp6_dataun.u_echo.identifier != BR_MC_WAKEUP_ID)
|
|
++ return false;
|
|
++
|
|
++ return true;
|
|
++}
|
|
++
|
|
++static void br_multicast_wakeupcall_send_mldq(struct net_bridge *br,
|
|
++ struct net_bridge_port *port,
|
|
++ const u8 *eth_dst)
|
|
++{
|
|
++ const struct in6_addr group = BR_MC_IN6_ZERO;
|
|
++ struct in6_addr ip6_dst;
|
|
++ struct sk_buff *skb;
|
|
++ u8 igmp_type;
|
|
++
|
|
++ /* we might have been triggered by multicast-address-specific query
|
|
++ * but reply with a general MLD query for now to keep things simple
|
|
++ */
|
|
++ ipv6_addr_set(&ip6_dst, htonl(0xff020000), 0, 0, htonl(1));
|
|
++
|
|
++ skb = br_ip6_multicast_alloc_query(br, NULL, &ip6_dst, &group, false,
|
|
++ false, false, &igmp_type, NULL,
|
|
++ false);
|
|
++ if (!skb)
|
|
++ return;
|
|
++
|
|
++ skb->dev = port->dev;
|
|
++ ether_addr_copy(eth_hdr(skb)->h_dest, eth_dst);
|
|
++
|
|
++ br_multicast_count(br, port, skb, igmp_type,
|
|
++ BR_MCAST_DIR_TX);
|
|
++ NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT,
|
|
++ dev_net(port->dev), NULL, skb, NULL, skb->dev,
|
|
++ br_dev_queue_push_xmit);
|
|
++}
|
|
++
|
|
++void br_multicast_wakeupcall_rcv(struct net_bridge *br,
|
|
++ struct net_bridge_port *port,
|
|
++ struct sk_buff *skb, u16 vid)
|
|
++{
|
|
++ if (!br_multicast_wakeupcall_check(br, port, skb, vid))
|
|
++ return;
|
|
++
|
|
++ br_multicast_wakeupcall_send_mldq(br, port, eth_hdr(skb)->h_source);
|
|
++}
|
|
++
|
|
++#endif /* CONFIG_BRIDGE_IGMP_SNOOPING_WAKEUPCALLS */
|
|
++
|
|
+ static void br_multicast_query_expired(struct net_bridge *br,
|
|
+ struct bridge_mcast_own_query *query,
|
|
+ struct bridge_mcast_querier *querier)
|
|
+@@ -3444,6 +3710,15 @@ int br_multicast_set_port_router(struct net_bridge_port *p, unsigned long val)
|
|
+ return err;
|
|
+ }
|
|
+
|
|
++int br_multicast_set_wakeupcall(struct net_bridge_port *p, unsigned long val)
|
|
++{
|
|
++ if (val > U8_MAX)
|
|
++ return -EINVAL;
|
|
++
|
|
++ p->wakeupcall_num_rings = val;
|
|
++ return 0;
|
|
++}
|
|
++
|
|
+ static void br_multicast_start_querier(struct net_bridge *br,
|
|
+ struct bridge_mcast_own_query *query)
|
|
+ {
|
|
+diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
|
|
+index e8116a4438b9..b544889fb7fe 100644
|
|
+--- a/net/bridge/br_netlink.c
|
|
++++ b/net/bridge/br_netlink.c
|
|
+@@ -151,6 +151,9 @@ static inline size_t br_port_info_size(void)
|
|
+ + nla_total_size_64bit(sizeof(u64)) /* IFLA_BRPORT_HOLD_TIMER */
|
|
+ #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
|
|
+ + nla_total_size(sizeof(u8)) /* IFLA_BRPORT_MULTICAST_ROUTER */
|
|
++#endif
|
|
++#ifdef CONFIG_BRIDGE_IGMP_SNOOPING_WAKEUPCALLS
|
|
++ + nla_total_size(sizeof(u8)) /* IFLA_BRPORT_MCAST_WAKEUPCALL */
|
|
+ #endif
|
|
+ + nla_total_size(sizeof(u16)) /* IFLA_BRPORT_GROUP_FWD_MASK */
|
|
+ + nla_total_size(sizeof(u8)) /* IFLA_BRPORT_MRP_RING_OPEN */
|
|
+@@ -243,6 +246,11 @@ static int br_port_fill_attrs(struct sk_buff *skb,
|
|
+ p->multicast_router))
|
|
+ return -EMSGSIZE;
|
|
+ #endif
|
|
++#ifdef CONFIG_BRIDGE_IGMP_SNOOPING_WAKEUPCALLS
|
|
++ if (nla_put_u8(skb, IFLA_BRPORT_MCAST_WAKEUPCALL,
|
|
++ p->wakeupcall_num_rings))
|
|
++ return -EMSGSIZE;
|
|
++#endif
|
|
+
|
|
+ /* we might be called only with br->lock */
|
|
+ rcu_read_lock();
|
|
+@@ -723,6 +731,7 @@ static const struct nla_policy br_port_policy[IFLA_BRPORT_MAX + 1] = {
|
|
+ [IFLA_BRPORT_PROXYARP_WIFI] = { .type = NLA_U8 },
|
|
+ [IFLA_BRPORT_MULTICAST_ROUTER] = { .type = NLA_U8 },
|
|
+ [IFLA_BRPORT_MCAST_TO_UCAST] = { .type = NLA_U8 },
|
|
++ [IFLA_BRPORT_MCAST_WAKEUPCALL] = { .type = NLA_U8 },
|
|
+ [IFLA_BRPORT_MCAST_FLOOD] = { .type = NLA_U8 },
|
|
+ [IFLA_BRPORT_BCAST_FLOOD] = { .type = NLA_U8 },
|
|
+ [IFLA_BRPORT_VLAN_TUNNEL] = { .type = NLA_U8 },
|
|
+@@ -872,6 +881,16 @@ static int br_setport(struct net_bridge_port *p, struct nlattr *tb[])
|
|
+ }
|
|
+ #endif
|
|
+
|
|
++#ifdef CONFIG_BRIDGE_IGMP_SNOOPING_WAKEUPCALLS
|
|
++ if (tb[IFLA_BRPORT_MCAST_WAKEUPCALL]) {
|
|
++ u8 wakeupcall = nla_get_u8(tb[IFLA_BRPORT_MCAST_WAKEUPCALL]);
|
|
++
|
|
++ err = br_multicast_set_wakeupcall(p, wakeupcall);
|
|
++ if (err)
|
|
++ return err;
|
|
++ }
|
|
++#endif
|
|
++
|
|
+ if (tb[IFLA_BRPORT_GROUP_FWD_MASK]) {
|
|
+ u16 fwd_mask = nla_get_u16(tb[IFLA_BRPORT_GROUP_FWD_MASK]);
|
|
+
|
|
+diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
|
|
+index 61b5b81b6828..6390d2fe88f6 100644
|
|
+--- a/net/bridge/br_private.h
|
|
++++ b/net/bridge/br_private.h
|
|
+@@ -214,6 +214,10 @@ struct net_bridge_fdb_entry {
|
|
+ };
|
|
+ struct rcu_head rcu;
|
|
+ };
|
|
++
|
|
++#ifdef CONFIG_BRIDGE_IGMP_SNOOPING_WAKEUPCALLS
|
|
++ struct timer_list wakeupcall_timer;
|
|
++#endif
|
|
+ };
|
|
+
|
|
+ #define MDB_PG_FLAGS_PERMANENT BIT(0)
|
|
+@@ -333,6 +337,7 @@ struct net_bridge_port {
|
|
+ struct timer_list multicast_router_timer;
|
|
+ struct hlist_head mglist;
|
|
+ struct hlist_node rlist;
|
|
++ u8 wakeupcall_num_rings;
|
|
+ #endif
|
|
+
|
|
+ #ifdef CONFIG_SYSFS
|
|
+@@ -1065,6 +1070,20 @@ static inline int br_multicast_igmp_type(const struct sk_buff *skb)
|
|
+ }
|
|
+ #endif
|
|
+
|
|
++#ifdef CONFIG_BRIDGE_IGMP_SNOOPING_WAKEUPCALLS
|
|
++void br_multicast_wakeupcall_rcv(struct net_bridge *br,
|
|
++ struct net_bridge_port *port,
|
|
++ struct sk_buff *skb, u16 vid);
|
|
++void br_multicast_send_wakeupcall(struct timer_list *t);
|
|
++int br_multicast_set_wakeupcall(struct net_bridge_port *p, unsigned long val);
|
|
++#else
|
|
++static inline void br_multicast_wakeupcall_rcv(struct net_bridge *br,
|
|
++ struct net_bridge_port *port,
|
|
++ struct sk_buff *skb, u16 vid)
|
|
++{
|
|
++}
|
|
++#endif /* CONFIG_BRIDGE_IGMP_SNOOPING_WAKEUPCALLS */
|
|
++
|
|
+ /* br_vlan.c */
|
|
+ #ifdef CONFIG_BRIDGE_VLAN_FILTERING
|
|
+ bool br_allowed_ingress(const struct net_bridge *br,
|
|
+diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c
|
|
+index 969eb6ca0776..88b74a5a7ccb 100644
|
|
+--- a/net/bridge/br_sysfs_if.c
|
|
++++ b/net/bridge/br_sysfs_if.c
|
|
+@@ -254,6 +254,21 @@ BRPORT_ATTR_FLAG(multicast_fast_leave, BR_MULTICAST_FAST_LEAVE);
|
|
+ BRPORT_ATTR_FLAG(multicast_to_unicast, BR_MULTICAST_TO_UNICAST);
|
|
+ #endif
|
|
+
|
|
++#ifdef CONFIG_BRIDGE_IGMP_SNOOPING_WAKEUPCALLS
|
|
++static ssize_t show_multicast_wakeupcall(struct net_bridge_port *p, char *buf)
|
|
++{
|
|
++ return sprintf(buf, "%d\n", p->wakeupcall_num_rings);
|
|
++}
|
|
++
|
|
++static int store_multicast_wakeupcall(struct net_bridge_port *p,
|
|
++ unsigned long v)
|
|
++{
|
|
++ return br_multicast_set_wakeupcall(p, v);
|
|
++}
|
|
++static BRPORT_ATTR(multicast_wakeupcall, 0644, show_multicast_wakeupcall,
|
|
++ store_multicast_wakeupcall);
|
|
++#endif
|
|
++
|
|
+ static const struct brport_attribute *brport_attrs[] = {
|
|
+ &brport_attr_path_cost,
|
|
+ &brport_attr_priority,
|
|
+@@ -279,6 +294,9 @@ static const struct brport_attribute *brport_attrs[] = {
|
|
+ &brport_attr_multicast_router,
|
|
+ &brport_attr_multicast_fast_leave,
|
|
+ &brport_attr_multicast_to_unicast,
|
|
++#endif
|
|
++#ifdef CONFIG_BRIDGE_IGMP_SNOOPING_WAKEUPCALLS
|
|
++ &brport_attr_multicast_wakeupcall,
|
|
+ #endif
|
|
+ &brport_attr_proxyarp,
|
|
+ &brport_attr_proxyarp_wifi,
|
|
+diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
|
|
+index ccb62f7d1054..3b269aafd3b5 100644
|
|
+--- a/net/core/rtnetlink.c
|
|
++++ b/net/core/rtnetlink.c
|
|
+@@ -55,7 +55,7 @@
|
|
+ #include <net/net_namespace.h>
|
|
+
|
|
+ #define RTNL_MAX_TYPE 50
|
|
+-#define RTNL_SLAVE_MAX_TYPE 37
|
|
++#define RTNL_SLAVE_MAX_TYPE 38
|
|
+
|
|
+ struct rtnl_link {
|
|
+ rtnl_doit_func doit;
|
|
+diff --git a/net/ipv6/mcast_snoop.c b/net/ipv6/mcast_snoop.c
|
|
+index 04d5fcdfa6e0..9a5061edbaf3 100644
|
|
+--- a/net/ipv6/mcast_snoop.c
|
|
++++ b/net/ipv6/mcast_snoop.c
|
|
+@@ -131,7 +131,7 @@ static inline __sum16 ipv6_mc_validate_checksum(struct sk_buff *skb)
|
|
+ return skb_checksum_validate(skb, IPPROTO_ICMPV6, ip6_compute_pseudo);
|
|
+ }
|
|
+
|
|
+-static int ipv6_mc_check_icmpv6(struct sk_buff *skb)
|
|
++int ipv6_mc_check_icmpv6(struct sk_buff *skb)
|
|
+ {
|
|
+ unsigned int len = skb_transport_offset(skb) + sizeof(struct icmp6hdr);
|
|
+ unsigned int transport_len = ipv6_transport_len(skb);
|
|
+@@ -150,6 +150,7 @@ static int ipv6_mc_check_icmpv6(struct sk_buff *skb)
|
|
+
|
|
+ return 0;
|
|
+ }
|
|
++EXPORT_SYMBOL(ipv6_mc_check_icmpv6);
|
|
+
|
|
+ /**
|
|
+ * ipv6_mc_check_mld - checks whether this is a sane MLD packet
|
|
+--
|
|
+2.36.1
|
|
+
|