modules: switch to OpenWrt master
Signed-off-by: David Bauer <mail@david-bauer.net>
This commit is contained in:
		
							parent
							
								
									979dd354fa
								
							
						
					
					
						commit
						87f2c23064
					
				
							
								
								
									
										12
									
								
								modules
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								modules
									
									
									
									
									
								
							@ -1,16 +1,16 @@
 | 
			
		||||
GLUON_FEEDS='packages routing gluon'
 | 
			
		||||
 | 
			
		||||
OPENWRT_REPO=https://github.com/openwrt/openwrt.git
 | 
			
		||||
OPENWRT_BRANCH=openwrt-22.03
 | 
			
		||||
OPENWRT_COMMIT=e500494771537b9f42f78e4d907bed18b6383606
 | 
			
		||||
OPENWRT_BRANCH=master
 | 
			
		||||
OPENWRT_COMMIT=3a6657540c3d6fc50a63caf8432e301e825ada16
 | 
			
		||||
 | 
			
		||||
PACKAGES_PACKAGES_REPO=https://github.com/openwrt/packages.git
 | 
			
		||||
PACKAGES_PACKAGES_BRANCH=openwrt-22.03
 | 
			
		||||
PACKAGES_PACKAGES_COMMIT=55eed1761207f4dfdb8e7d79138f6f65c8849b50
 | 
			
		||||
PACKAGES_PACKAGES_BRANCH=master
 | 
			
		||||
PACKAGES_PACKAGES_COMMIT=4ec0459fd3e6c3d1ef446337671b6da5bb30d006
 | 
			
		||||
 | 
			
		||||
PACKAGES_ROUTING_REPO=https://github.com/openwrt/routing.git
 | 
			
		||||
PACKAGES_ROUTING_BRANCH=openwrt-22.03
 | 
			
		||||
PACKAGES_ROUTING_COMMIT=1cc7676b9f32acc30ec47f15fcb70380d5d6ef01
 | 
			
		||||
PACKAGES_ROUTING_BRANCH=master
 | 
			
		||||
PACKAGES_ROUTING_COMMIT=c9a8f2d03226191111b95890302cb7e1ff18c11e
 | 
			
		||||
 | 
			
		||||
PACKAGES_GLUON_REPO=https://github.com/freifunk-gluon/packages.git
 | 
			
		||||
PACKAGES_GLUON_COMMIT=29912ec6308fd10b47763b4cf28a638d07f59973
 | 
			
		||||
 | 
			
		||||
@ -1,64 +0,0 @@
 | 
			
		||||
From: David Bauer <mail@david-bauer.net>
 | 
			
		||||
Date: Sun, 5 Jun 2022 23:43:38 +0200
 | 
			
		||||
Subject: ramips-mt7621: make DSA images swconfig upgradable
 | 
			
		||||
 | 
			
		||||
diff --git a/target/linux/ramips/image/mt7621.mk b/target/linux/ramips/image/mt7621.mk
 | 
			
		||||
index ab0ff95f7529aa43e69e67a4e3a303242c9b2605..4c3a38db442f06d6c1acf77fb729d93a67e2d52a 100644
 | 
			
		||||
--- a/target/linux/ramips/image/mt7621.mk
 | 
			
		||||
+++ b/target/linux/ramips/image/mt7621.mk
 | 
			
		||||
@@ -180,7 +180,6 @@ endef
 | 
			
		||||
 TARGET_DEVICES += asiarf_ap7621-nv1
 | 
			
		||||
 
 | 
			
		||||
 define Device/asus_rt-ac57u
 | 
			
		||||
-  $(Device/dsa-migration)
 | 
			
		||||
   DEVICE_VENDOR := ASUS
 | 
			
		||||
   DEVICE_MODEL := RT-AC57U
 | 
			
		||||
   DEVICE_ALT0_VENDOR := ASUS
 | 
			
		||||
@@ -1286,7 +1285,6 @@ endef
 | 
			
		||||
 TARGET_DEVICES += mts_wg430223
 | 
			
		||||
 
 | 
			
		||||
 define Device/netgear_ex6150
 | 
			
		||||
-  $(Device/dsa-migration)
 | 
			
		||||
   $(Device/uimage-lzma-loader)
 | 
			
		||||
   DEVICE_VENDOR := NETGEAR
 | 
			
		||||
   DEVICE_MODEL := EX6150
 | 
			
		||||
@@ -1299,7 +1297,6 @@ endef
 | 
			
		||||
 TARGET_DEVICES += netgear_ex6150
 | 
			
		||||
 
 | 
			
		||||
 define Device/netgear_sercomm_nand
 | 
			
		||||
-  $(Device/dsa-migration)
 | 
			
		||||
   $(Device/uimage-lzma-loader)
 | 
			
		||||
   BLOCKSIZE := 128k
 | 
			
		||||
   PAGESIZE := 2048
 | 
			
		||||
@@ -1482,7 +1479,6 @@ endef
 | 
			
		||||
 TARGET_DEVICES += netgear_wax202
 | 
			
		||||
 
 | 
			
		||||
 define Device/netgear_wndr3700-v5
 | 
			
		||||
-  $(Device/dsa-migration)
 | 
			
		||||
   $(Device/netgear_sercomm_nor)
 | 
			
		||||
   $(Device/uimage-lzma-loader)
 | 
			
		||||
   IMAGE_SIZE := 15232k
 | 
			
		||||
@@ -1819,7 +1815,6 @@ endef
 | 
			
		||||
 TARGET_DEVICES += tplink_tl-wpa8631p-v3
 | 
			
		||||
 
 | 
			
		||||
 define Device/ubnt_edgerouter_common
 | 
			
		||||
-  $(Device/dsa-migration)
 | 
			
		||||
   $(Device/uimage-lzma-loader)
 | 
			
		||||
   DEVICE_VENDOR := Ubiquiti
 | 
			
		||||
   IMAGE_SIZE := 256768k
 | 
			
		||||
@@ -2235,7 +2230,6 @@ endef
 | 
			
		||||
 TARGET_DEVICES += zbtlink_zbt-wg2626
 | 
			
		||||
 
 | 
			
		||||
 define Device/zbtlink_zbt-wg3526-16m
 | 
			
		||||
-  $(Device/dsa-migration)
 | 
			
		||||
   $(Device/uimage-lzma-loader)
 | 
			
		||||
   IMAGE_SIZE := 16064k
 | 
			
		||||
   DEVICE_VENDOR := Zbtlink
 | 
			
		||||
@@ -2248,7 +2242,6 @@ endef
 | 
			
		||||
 TARGET_DEVICES += zbtlink_zbt-wg3526-16m
 | 
			
		||||
 
 | 
			
		||||
 define Device/zbtlink_zbt-wg3526-32m
 | 
			
		||||
-  $(Device/dsa-migration)
 | 
			
		||||
   $(Device/uimage-lzma-loader)
 | 
			
		||||
   IMAGE_SIZE := 32448k
 | 
			
		||||
   DEVICE_VENDOR := Zbtlink
 | 
			
		||||
@ -1,53 +0,0 @@
 | 
			
		||||
From: David Bauer <mail@david-bauer.net>
 | 
			
		||||
Date: Sat, 18 Jun 2022 02:37:56 +0200
 | 
			
		||||
Subject: ramips: add MT7621 WiFi devpath migration
 | 
			
		||||
 | 
			
		||||
Add a migration script to migrate the device path of PCIe WiFi hardware
 | 
			
		||||
from OpenWrt 19.07 to the one used with OpenWrt 21.02+.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: David Bauer <mail@david-bauer.net>
 | 
			
		||||
 | 
			
		||||
diff --git a/target/linux/ramips/mt7621/base-files/etc/hotplug.d/ieee80211/00-wifi-migration b/target/linux/ramips/mt7621/base-files/etc/hotplug.d/ieee80211/00-wifi-migration
 | 
			
		||||
new file mode 100644
 | 
			
		||||
index 0000000000000000000000000000000000000000..17fd4a58ff2d56694743e149292746c136b6f27a
 | 
			
		||||
--- /dev/null
 | 
			
		||||
+++ b/target/linux/ramips/mt7621/base-files/etc/hotplug.d/ieee80211/00-wifi-migration
 | 
			
		||||
@@ -0,0 +1,38 @@
 | 
			
		||||
+#!/bin/sh
 | 
			
		||||
+
 | 
			
		||||
+# Migrate WiFi path from 19.07 to 21.02+
 | 
			
		||||
+
 | 
			
		||||
+WIFI_PATH_CHANGED=0
 | 
			
		||||
+
 | 
			
		||||
+. /lib/functions.sh
 | 
			
		||||
+
 | 
			
		||||
+migrate_wifi_path() {
 | 
			
		||||
+	local section="$1"
 | 
			
		||||
+	local path
 | 
			
		||||
+
 | 
			
		||||
+	config_get path ${section} path
 | 
			
		||||
+	case ${path} in
 | 
			
		||||
+		"pci0000:00/0000:00:00.0/0000:01:00.0")
 | 
			
		||||
+			path="1e140000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0"
 | 
			
		||||
+			WIFI_PATH_CHANGED=1
 | 
			
		||||
+		;;
 | 
			
		||||
+		"pci0000:00/0000:00:01.0/0000:02:00.0")
 | 
			
		||||
+			path="1e140000.pcie/pci0000:00/0000:00:01.0/0000:02:00.0"
 | 
			
		||||
+			WIFI_PATH_CHANGED=1
 | 
			
		||||
+		;;
 | 
			
		||||
+		*)
 | 
			
		||||
+			return 0
 | 
			
		||||
+		;;
 | 
			
		||||
+	esac
 | 
			
		||||
+
 | 
			
		||||
+	uci set wireless.${section}.path=${path}
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+[ "${ACTION}" = "add" ] && {
 | 
			
		||||
+	[ ! -e /etc/config/wireless ] && return 0
 | 
			
		||||
+
 | 
			
		||||
+	config_load wireless
 | 
			
		||||
+	config_foreach migrate_wifi_path wifi-device
 | 
			
		||||
+
 | 
			
		||||
+	[ "${WIFI_PATH_CHANGED}" = "1" ] && uci commit wireless
 | 
			
		||||
+}
 | 
			
		||||
@ -1,30 +0,0 @@
 | 
			
		||||
From: David Bauer <mail@david-bauer.net>
 | 
			
		||||
Date: Tue, 5 Jul 2022 23:49:31 +0200
 | 
			
		||||
Subject: lantiq-xrx200: make DSA images swconfig upgradable
 | 
			
		||||
 | 
			
		||||
diff --git a/target/linux/lantiq/image/tp-link.mk b/target/linux/lantiq/image/tp-link.mk
 | 
			
		||||
index 756105b94c7f844439132ab57837c9ac87d231ca..5563968de9ab3f491fa89d755fcc6e6fff79948f 100644
 | 
			
		||||
--- a/target/linux/lantiq/image/tp-link.mk
 | 
			
		||||
+++ b/target/linux/lantiq/image/tp-link.mk
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
 DEVICE_VARS += TPLINK_FLASHLAYOUT TPLINK_HWID TPLINK_HWREV TPLINK_HWREVADD TPLINK_HVERSION
 | 
			
		||||
 
 | 
			
		||||
 define Device/dsa-migration
 | 
			
		||||
-  DEVICE_COMPAT_VERSION := 1.1
 | 
			
		||||
+  DEVICE_COMPAT_VERSION := 1.0
 | 
			
		||||
   DEVICE_COMPAT_MESSAGE := Config cannot be migrated from swconfig to DSA
 | 
			
		||||
 endef
 | 
			
		||||
 
 | 
			
		||||
diff --git a/target/linux/lantiq/image/vr9.mk b/target/linux/lantiq/image/vr9.mk
 | 
			
		||||
index deea3996670fcef6d2a546373425c4ca5d92734b..d23b80e94e5548ccb19738f22c29c75fa19ab1e7 100644
 | 
			
		||||
--- a/target/linux/lantiq/image/vr9.mk
 | 
			
		||||
+++ b/target/linux/lantiq/image/vr9.mk
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
 DEVICE_VARS += NETGEAR_BOARD_ID NETGEAR_HW_ID
 | 
			
		||||
 
 | 
			
		||||
 define Device/dsa-migration
 | 
			
		||||
-  DEVICE_COMPAT_VERSION := 1.1
 | 
			
		||||
+  DEVICE_COMPAT_VERSION := 1.0
 | 
			
		||||
   DEVICE_COMPAT_MESSAGE := Config cannot be migrated from swconfig to DSA
 | 
			
		||||
 endef
 | 
			
		||||
 
 | 
			
		||||
@ -1,914 +0,0 @@
 | 
			
		||||
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 a348d4821ecef796c8c2b983a969b7becb7ae334..dad7baabe69f53ca9afeff8e9392397dd9dc35aa 100644
 | 
			
		||||
--- a/target/linux/generic/config-5.10
 | 
			
		||||
+++ b/target/linux/generic/config-5.10
 | 
			
		||||
@@ -738,6 +738,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
 | 
			
		||||
+
 | 
			
		||||
@ -1,74 +0,0 @@
 | 
			
		||||
From: David Bauer <mail@david-bauer.net>
 | 
			
		||||
Date: Sat, 10 Sep 2022 01:06:02 +0200
 | 
			
		||||
Subject: hostapd: don't select indoor channel on outdoor operation
 | 
			
		||||
 | 
			
		||||
Don't select channels designated for exclusive-indoor use when the
 | 
			
		||||
country3 element is set on outdoor operation.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: David Bauer <mail@david-bauer.net>
 | 
			
		||||
(cherry picked from commit 5110cf7ebdd5af57f98fe4581ce4c5ddb0a2bf86)
 | 
			
		||||
 | 
			
		||||
diff --git a/package/network/services/hostapd/patches/800-acs-don-t-select-indoor-channel-on-outdoor-operation.patch b/package/network/services/hostapd/patches/800-acs-don-t-select-indoor-channel-on-outdoor-operation.patch
 | 
			
		||||
new file mode 100644
 | 
			
		||||
index 0000000000000000000000000000000000000000..96ebdefae9e710a350fa44a359896071b142af67
 | 
			
		||||
--- /dev/null
 | 
			
		||||
+++ b/package/network/services/hostapd/patches/800-acs-don-t-select-indoor-channel-on-outdoor-operation.patch
 | 
			
		||||
@@ -0,0 +1,58 @@
 | 
			
		||||
+From 37528a5205cb0b9e2238b7d97fb2ff5457448f1c Mon Sep 17 00:00:00 2001
 | 
			
		||||
+From: David Bauer <mail@david-bauer.net>
 | 
			
		||||
+Date: Thu, 8 Sep 2022 01:45:41 +0200
 | 
			
		||||
+Subject: [PATCH] acs: don't select indoor channel on outdoor operation
 | 
			
		||||
+
 | 
			
		||||
+Don't select channels designated for exclusive-indoor use when the
 | 
			
		||||
+country3 element is set on outdoor operation.
 | 
			
		||||
+
 | 
			
		||||
+Signed-off-by: David Bauer <mail@david-bauer.net>
 | 
			
		||||
+---
 | 
			
		||||
+ src/ap/acs.c | 9 +++++++++
 | 
			
		||||
+ src/ap/dfs.c | 3 +++
 | 
			
		||||
+ 2 files changed, 12 insertions(+)
 | 
			
		||||
+
 | 
			
		||||
+--- a/src/ap/acs.c
 | 
			
		||||
++++ b/src/ap/acs.c
 | 
			
		||||
+@@ -552,6 +552,9 @@ static void acs_survey_mode_interference
 | 
			
		||||
+ 		if (chan->max_tx_power < iface->conf->min_tx_power)
 | 
			
		||||
+ 			continue;
 | 
			
		||||
+ 
 | 
			
		||||
++		if (chan->flag & HOSTAPD_CHAN_INDOOR_ONLY && iface->conf->country[2] == 0x4f)
 | 
			
		||||
++			continue;
 | 
			
		||||
++
 | 
			
		||||
+ 		wpa_printf(MSG_DEBUG, "ACS: Survey analysis for channel %d (%d MHz)",
 | 
			
		||||
+ 			   chan->chan, chan->freq);
 | 
			
		||||
+ 
 | 
			
		||||
+@@ -686,6 +689,9 @@ acs_find_ideal_chan_mode(struct hostapd_
 | 
			
		||||
+ 		if (chan->max_tx_power < iface->conf->min_tx_power)
 | 
			
		||||
+ 			continue;
 | 
			
		||||
+ 
 | 
			
		||||
++		if (chan->flag & HOSTAPD_CHAN_INDOOR_ONLY && iface->conf->country[2] == 0x4f)
 | 
			
		||||
++			continue;
 | 
			
		||||
++
 | 
			
		||||
+ 		if (!chan_bw_allowed(chan, bw, 1, 1)) {
 | 
			
		||||
+ 			wpa_printf(MSG_DEBUG,
 | 
			
		||||
+ 				   "ACS: Channel %d: BW %u is not supported",
 | 
			
		||||
+@@ -1065,6 +1071,9 @@ static int * acs_request_scan_add_freqs(
 | 
			
		||||
+ 		if (chan->max_tx_power < iface->conf->min_tx_power)
 | 
			
		||||
+ 			continue;
 | 
			
		||||
+ 
 | 
			
		||||
++		if (chan->flag & HOSTAPD_CHAN_INDOOR_ONLY && iface->conf->country[2] == 0x4f)
 | 
			
		||||
++			continue;
 | 
			
		||||
++
 | 
			
		||||
+ 		*freq++ = chan->freq;
 | 
			
		||||
+ 	}
 | 
			
		||||
+ 
 | 
			
		||||
+--- a/src/ap/dfs.c
 | 
			
		||||
++++ b/src/ap/dfs.c
 | 
			
		||||
+@@ -282,6 +282,9 @@ static int dfs_find_channel(struct hosta
 | 
			
		||||
+ 		if (chan->max_tx_power < iface->conf->min_tx_power)
 | 
			
		||||
+ 			continue;
 | 
			
		||||
+ 
 | 
			
		||||
++		if (chan->flag & HOSTAPD_CHAN_INDOOR_ONLY && iface->conf->country[2] == 0x4f)
 | 
			
		||||
++			continue;
 | 
			
		||||
++
 | 
			
		||||
+ 		if (ret_chan && idx == channel_idx) {
 | 
			
		||||
+ 			wpa_printf(MSG_DEBUG, "Selected channel %d (%d)",
 | 
			
		||||
+ 				   chan->freq, chan->chan);
 | 
			
		||||
@ -1,81 +0,0 @@
 | 
			
		||||
From: Grische <github@grische.xyz>
 | 
			
		||||
Date: Sun, 18 Sep 2022 14:03:16 +0200
 | 
			
		||||
Subject: xrx200: migrate fritz7360-v2 using incorrect image
 | 
			
		||||
 | 
			
		||||
Migrate AVM FRITZ!Box 7360 v2 boards flashed with the incorrect v1 image to use
 | 
			
		||||
the newly added v2 target image during the next upgrade.
 | 
			
		||||
Using the v2 target image allows the boards to read the TFFS partition, which
 | 
			
		||||
is misaligned when using the v1 image.
 | 
			
		||||
 | 
			
		||||
Ref: https://github.com/freifunk-gluon/gluon/pull/2648
 | 
			
		||||
 | 
			
		||||
Co-authored-by: Jan-Niklas Burfeind <git@aiyionpri.me>
 | 
			
		||||
 | 
			
		||||
diff --git a/target/linux/lantiq/xrx200/base-files/lib/preinit/01_sysinfo.sh b/target/linux/lantiq/xrx200/base-files/lib/preinit/01_sysinfo.sh
 | 
			
		||||
new file mode 100644
 | 
			
		||||
index 0000000000000000000000000000000000000000..fab50d708e872f819c643cea79327e4f438de524
 | 
			
		||||
--- /dev/null
 | 
			
		||||
+++ b/target/linux/lantiq/xrx200/base-files/lib/preinit/01_sysinfo.sh
 | 
			
		||||
@@ -0,0 +1,62 @@
 | 
			
		||||
+set_sysinfo_xrx200_for_fritz7360_model() {
 | 
			
		||||
+    local board_name=$1
 | 
			
		||||
+    local model
 | 
			
		||||
+    local urlader_version urlader_memsize urlader_flashsize
 | 
			
		||||
+    local hexdump_format='4/1 "%02x""\n"'
 | 
			
		||||
+
 | 
			
		||||
+    # Values are based on urlader-parser-py
 | 
			
		||||
+    # https://github.com/grische/urlader-parser-py/blob/42970bf8dec7962317df4ff734c57ebf36df8905/parser.py#L77-L84
 | 
			
		||||
+    urlader_version="$(dd if=/dev/mtd0ro bs=1 skip=$((0x580+0x0)) count=4 | hexdump -e "${hexdump_format}")"
 | 
			
		||||
+    if [ "${urlader_version}" != "00000003" ]; then
 | 
			
		||||
+        logger -s -p warn -t sysinfo-xrx200 "unexpected urlader version found: ${urlader_version}"
 | 
			
		||||
+        return
 | 
			
		||||
+    fi
 | 
			
		||||
+
 | 
			
		||||
+    urlader_memsize="$(dd if=/dev/mtd0ro bs=1 skip=$((0x580+0x4)) count=4 | hexdump -e "${hexdump_format}")"
 | 
			
		||||
+    if [ "${urlader_memsize}" != "08000000" ]; then
 | 
			
		||||
+        logger -s -p warn -t sysinfo-xrx200 "unexpected memsize found: ${urlader_memsize}"
 | 
			
		||||
+        return
 | 
			
		||||
+    fi
 | 
			
		||||
+
 | 
			
		||||
+    urlader_flashsize="$(dd if=/dev/mtd0ro bs=1 skip=$((0x580+0x8)) count=4 | hexdump -e "${hexdump_format}")"
 | 
			
		||||
+    case "${urlader_flashsize}" in
 | 
			
		||||
+        "02000000")    # 32MB
 | 
			
		||||
+            # see vr9_avm_fritz7360-v2.dts
 | 
			
		||||
+            board_name="avm,fritz7360-v2"
 | 
			
		||||
+            model="AVM FRITZ!Box 7360 V2"
 | 
			
		||||
+            ;;
 | 
			
		||||
+        "01000000")    # 16MB
 | 
			
		||||
+            return
 | 
			
		||||
+            ;;
 | 
			
		||||
+        *)
 | 
			
		||||
+            logger -s -p warn -t sysinfo-xrx200 "unexpected flashsize found: ${urlader_flashsize}"
 | 
			
		||||
+            return
 | 
			
		||||
+            ;;
 | 
			
		||||
+    esac
 | 
			
		||||
+
 | 
			
		||||
+    logger -s -p notice -t sysinfo-xrx200 "detected ${board_name} from urlader partition /dev/mtd0ro. Enforcing model ${model}."
 | 
			
		||||
+    echo "${board_name}" > /tmp/sysinfo/board_name
 | 
			
		||||
+    echo "${model}" > /tmp/sysinfo/model
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+do_sysinfo_xrx200() {
 | 
			
		||||
+    local reported_board board_name model
 | 
			
		||||
+
 | 
			
		||||
+    [ -d /proc/device-tree ] || return
 | 
			
		||||
+    reported_board="$(strings /proc/device-tree/compatible | head -1)"
 | 
			
		||||
+
 | 
			
		||||
+    mkdir -p /tmp/sysinfo
 | 
			
		||||
+    # 7360 is notoriously known for not writing "v2" on their labels and many
 | 
			
		||||
+    # routers have flashed the wrong firmware with the wrong flash layout.
 | 
			
		||||
+    # We ensure that the underlying hardware is reported correctly, so that
 | 
			
		||||
+    # future upgrades will use the correct flash layout.
 | 
			
		||||
+    # Using 7360v2 hardware, an upgrade from a 7360v1/sl firmware to a 7360v2
 | 
			
		||||
+    # is working.
 | 
			
		||||
+    case "${reported_board}" in
 | 
			
		||||
+        avm,fritz7360sl)
 | 
			
		||||
+            set_sysinfo_xrx200_for_fritz7360_model "${reported_board}"
 | 
			
		||||
+            ;;
 | 
			
		||||
+    esac
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+boot_hook_add preinit_main do_sysinfo_xrx200
 | 
			
		||||
@ -1,75 +0,0 @@
 | 
			
		||||
From: David Bauer <mail@david-bauer.net>
 | 
			
		||||
Date: Fri, 11 Nov 2022 13:37:07 +0100
 | 
			
		||||
Subject: kconfig: abort configuration on unset symbol
 | 
			
		||||
 | 
			
		||||
This fixes the initial patch to cover all cases where unset symbols are
 | 
			
		||||
handled in the code.
 | 
			
		||||
 | 
			
		||||
Fixes commit eaa9c94c7574 ("generic: Kconfig: exit on unset symbol")
 | 
			
		||||
 | 
			
		||||
Signed-off-by: David Bauer <mail@david-bauer.net>
 | 
			
		||||
 | 
			
		||||
diff --git a/target/linux/generic/hack-5.10/205-kconfig-abort-configuration-on-unset-symbol.patch b/target/linux/generic/hack-5.10/205-kconfig-abort-configuration-on-unset-symbol.patch
 | 
			
		||||
new file mode 100644
 | 
			
		||||
index 0000000000000000000000000000000000000000..bd5c54d4b8b73b36c9f5b809447a8e76fce19e5d
 | 
			
		||||
--- /dev/null
 | 
			
		||||
+++ b/target/linux/generic/hack-5.10/205-kconfig-abort-configuration-on-unset-symbol.patch
 | 
			
		||||
@@ -0,0 +1,41 @@
 | 
			
		||||
+From 310e8e04a05d9eb43fa9dd7f00143300afcaa37a Mon Sep 17 00:00:00 2001
 | 
			
		||||
+From: David Bauer <mail@david-bauer.net>
 | 
			
		||||
+Date: Fri, 11 Nov 2022 13:33:44 +0100
 | 
			
		||||
+Subject: [PATCH] kconfig: abort configuration on unset symbol
 | 
			
		||||
+
 | 
			
		||||
+When a target configuration has unset Kconfig symbols, the build will
 | 
			
		||||
+fail when OpenWrt is compiled with V=s and stdin is connected to a tty.
 | 
			
		||||
+
 | 
			
		||||
+In case OpenWrt is compiled without either of these preconditions, the
 | 
			
		||||
+build will succeed with the symbols in question being unset.
 | 
			
		||||
+
 | 
			
		||||
+Modify the kernel configuration in a way it fails on unset symbols
 | 
			
		||||
+regardless of the aforementioned preconditions.
 | 
			
		||||
+
 | 
			
		||||
+Signed-off-by: David Bauer <mail@david-bauer.net>
 | 
			
		||||
+---
 | 
			
		||||
+ scripts/kconfig/conf.c | 6 ++++++
 | 
			
		||||
+ 1 file changed, 6 insertions(+)
 | 
			
		||||
+
 | 
			
		||||
+--- a/scripts/kconfig/conf.c
 | 
			
		||||
++++ b/scripts/kconfig/conf.c
 | 
			
		||||
+@@ -109,6 +109,9 @@ static int conf_askvalue(struct symbol *
 | 
			
		||||
+ 		}
 | 
			
		||||
+ 		/* fall through */
 | 
			
		||||
+ 	case oldaskconfig:
 | 
			
		||||
++		if (!tty_stdio && getenv("FAIL_ON_UNCONFIGURED")) {
 | 
			
		||||
++			exit(1);
 | 
			
		||||
++		}
 | 
			
		||||
+ 		fflush(stdout);
 | 
			
		||||
+ 		xfgets(line, sizeof(line), stdin);
 | 
			
		||||
+ 		return 1;
 | 
			
		||||
+@@ -303,6 +306,9 @@ static int conf_choice(struct menu *menu
 | 
			
		||||
+ 			}
 | 
			
		||||
+ 			/* fall through */
 | 
			
		||||
+ 		case oldaskconfig:
 | 
			
		||||
++			if (!tty_stdio && getenv("FAIL_ON_UNCONFIGURED")) {
 | 
			
		||||
++				exit(1);
 | 
			
		||||
++			}
 | 
			
		||||
+ 			fflush(stdout);
 | 
			
		||||
+ 			xfgets(line, sizeof(line), stdin);
 | 
			
		||||
+ 			strip(line);
 | 
			
		||||
diff --git a/target/linux/generic/hack-5.10/205-kconfig-exit.patch b/target/linux/generic/hack-5.10/205-kconfig-exit.patch
 | 
			
		||||
deleted file mode 100644
 | 
			
		||||
index c3fb7a1f999e56da34b0a15565ce36098cfba7fb..0000000000000000000000000000000000000000
 | 
			
		||||
--- a/target/linux/generic/hack-5.10/205-kconfig-exit.patch
 | 
			
		||||
+++ /dev/null
 | 
			
		||||
@@ -1,11 +0,0 @@
 | 
			
		||||
---- a/scripts/kconfig/conf.c
 | 
			
		||||
-+++ b/scripts/kconfig/conf.c
 | 
			
		||||
-@@ -215,6 +215,8 @@ static int conf_sym(struct menu *menu)
 | 
			
		||||
- 				break;
 | 
			
		||||
- 			continue;
 | 
			
		||||
- 		case 0:
 | 
			
		||||
-+			if (!sym_has_value(sym) && !tty_stdio && getenv("FAIL_ON_UNCONFIGURED"))
 | 
			
		||||
-+				exit(1);
 | 
			
		||||
- 			newval = oldval;
 | 
			
		||||
- 			break;
 | 
			
		||||
- 		case '?':
 | 
			
		||||
@ -1,115 +0,0 @@
 | 
			
		||||
From: David Bauer <mail@david-bauer.net>
 | 
			
		||||
Date: Tue, 15 Nov 2022 15:25:40 +0100
 | 
			
		||||
Subject: ath79: combine OCEDO dual firmware-partitions
 | 
			
		||||
 | 
			
		||||
In order to maximize the available space on OCEDO boards using a
 | 
			
		||||
dual-image partition layout, combine the two OS partitions into a single
 | 
			
		||||
partition.
 | 
			
		||||
 | 
			
		||||
This allows users to access more usable space for additional packages.
 | 
			
		||||
 | 
			
		||||
Don't limit the usable image size to the size of a single OS partition.
 | 
			
		||||
The initial installation has to be done with an older version of OpenWrt
 | 
			
		||||
in case the generated image exceeds the space of a single OS
 | 
			
		||||
partition in the future.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: David Bauer <mail@david-bauer.net>
 | 
			
		||||
(cherry picked from commit eded295cd7fd53bfa5afcb67a1b91cfda0523ba6)
 | 
			
		||||
 | 
			
		||||
diff --git a/target/linux/ath79/dts/ar9344_ocedo_raccoon.dts b/target/linux/ath79/dts/ar9344_ocedo_raccoon.dts
 | 
			
		||||
index 0bbeb2b533b3fbbdcce53e094412d459ee762d85..3ecd20e2aa8fe04164cddbc84e0eb800e049c011 100644
 | 
			
		||||
--- a/target/linux/ath79/dts/ar9344_ocedo_raccoon.dts
 | 
			
		||||
+++ b/target/linux/ath79/dts/ar9344_ocedo_raccoon.dts
 | 
			
		||||
@@ -91,15 +91,10 @@
 | 
			
		||||
 			};
 | 
			
		||||
 
 | 
			
		||||
 			partition@50000 {
 | 
			
		||||
+				/* Dual-Flash layout combined */
 | 
			
		||||
 				compatible = "denx,uimage";
 | 
			
		||||
 				label = "firmware";
 | 
			
		||||
-				reg = <0x050000 0x740000>;
 | 
			
		||||
-			};
 | 
			
		||||
-
 | 
			
		||||
-			partition@790000 {
 | 
			
		||||
-				label = "vendor";
 | 
			
		||||
-				reg = <0x790000 0x740000>;
 | 
			
		||||
-				read-only;
 | 
			
		||||
+				reg = <0x050000 0xe80000>;
 | 
			
		||||
 			};
 | 
			
		||||
 
 | 
			
		||||
 			partition@ed0000 {
 | 
			
		||||
diff --git a/target/linux/ath79/dts/qca9558_ocedo_koala.dts b/target/linux/ath79/dts/qca9558_ocedo_koala.dts
 | 
			
		||||
index 66f8c6589b20221edc41a2f882b28229ff8633b9..de9e1bc19c4d03707f5b921ee5e9fe7422f461bb 100644
 | 
			
		||||
--- a/target/linux/ath79/dts/qca9558_ocedo_koala.dts
 | 
			
		||||
+++ b/target/linux/ath79/dts/qca9558_ocedo_koala.dts
 | 
			
		||||
@@ -88,15 +88,10 @@
 | 
			
		||||
 			};
 | 
			
		||||
 
 | 
			
		||||
 			partition@50000 {
 | 
			
		||||
+				/* Dual-Flash layout combined */
 | 
			
		||||
 				compatible = "denx,uimage";
 | 
			
		||||
 				label = "firmware";
 | 
			
		||||
-				reg = <0x050000 0x740000>;
 | 
			
		||||
-			};
 | 
			
		||||
-
 | 
			
		||||
-			partition@790000 {
 | 
			
		||||
-				label = "vendor";
 | 
			
		||||
-				reg = <0x790000 0x740000>;
 | 
			
		||||
-				read-only;
 | 
			
		||||
+				reg = <0x050000 0xe80000>;
 | 
			
		||||
 			};
 | 
			
		||||
 
 | 
			
		||||
 			partition@ed0000 {
 | 
			
		||||
diff --git a/target/linux/ath79/dts/qca9558_ocedo_ursus.dts b/target/linux/ath79/dts/qca9558_ocedo_ursus.dts
 | 
			
		||||
index 2dc4c07e918c50eb522100eb7f72c8804d5ba5fb..f8b3681bb7f143a498d5cb64897af335b970c43b 100644
 | 
			
		||||
--- a/target/linux/ath79/dts/qca9558_ocedo_ursus.dts
 | 
			
		||||
+++ b/target/linux/ath79/dts/qca9558_ocedo_ursus.dts
 | 
			
		||||
@@ -59,15 +59,10 @@
 | 
			
		||||
 			};
 | 
			
		||||
 
 | 
			
		||||
 			partition@50000 {
 | 
			
		||||
+				/* Dual-Flash layout combined */
 | 
			
		||||
 				compatible = "denx,uimage";
 | 
			
		||||
 				label = "firmware";
 | 
			
		||||
-				reg = <0x050000 0x740000>;
 | 
			
		||||
-			};
 | 
			
		||||
-
 | 
			
		||||
-			partition@790000 {
 | 
			
		||||
-				label = "vendor";
 | 
			
		||||
-				reg = <0x790000 0x740000>;
 | 
			
		||||
-				read-only;
 | 
			
		||||
+				reg = <0x050000 0xe80000>;
 | 
			
		||||
 			};
 | 
			
		||||
 
 | 
			
		||||
 			partition@ed0000 {
 | 
			
		||||
diff --git a/target/linux/ath79/image/generic.mk b/target/linux/ath79/image/generic.mk
 | 
			
		||||
index f1542e4e38f7540dd9facf4c40f0b271b9ea1e45..87d01a42eda274f9197f3382d955b87ecf615f7d 100644
 | 
			
		||||
--- a/target/linux/ath79/image/generic.mk
 | 
			
		||||
+++ b/target/linux/ath79/image/generic.mk
 | 
			
		||||
@@ -1803,7 +1803,7 @@ define Device/ocedo_koala
 | 
			
		||||
   DEVICE_MODEL := Koala
 | 
			
		||||
   DEVICE_PACKAGES := kmod-ath10k-ct ath10k-firmware-qca988x-ct
 | 
			
		||||
   SUPPORTED_DEVICES += koala
 | 
			
		||||
-  IMAGE_SIZE := 7424k
 | 
			
		||||
+  IMAGE_SIZE := 14848k
 | 
			
		||||
 endef
 | 
			
		||||
 TARGET_DEVICES += ocedo_koala
 | 
			
		||||
 
 | 
			
		||||
@@ -1811,7 +1811,7 @@ define Device/ocedo_raccoon
 | 
			
		||||
   SOC := ar9344
 | 
			
		||||
   DEVICE_VENDOR := Ocedo
 | 
			
		||||
   DEVICE_MODEL := Raccoon
 | 
			
		||||
-  IMAGE_SIZE := 7424k
 | 
			
		||||
+  IMAGE_SIZE := 14848k
 | 
			
		||||
 endef
 | 
			
		||||
 TARGET_DEVICES += ocedo_raccoon
 | 
			
		||||
 
 | 
			
		||||
@@ -1820,7 +1820,7 @@ define Device/ocedo_ursus
 | 
			
		||||
   DEVICE_VENDOR := Ocedo
 | 
			
		||||
   DEVICE_MODEL := Ursus
 | 
			
		||||
   DEVICE_PACKAGES := kmod-ath10k-ct ath10k-firmware-qca988x-ct
 | 
			
		||||
-  IMAGE_SIZE := 7424k
 | 
			
		||||
+  IMAGE_SIZE := 14848k
 | 
			
		||||
 endef
 | 
			
		||||
 TARGET_DEVICES += ocedo_ursus
 | 
			
		||||
 
 | 
			
		||||
@ -1,55 +0,0 @@
 | 
			
		||||
From: David Bauer <mail@david-bauer.net>
 | 
			
		||||
Date: Thu, 17 Nov 2022 22:53:33 +0100
 | 
			
		||||
Subject: ath79: combine UniFi AC dual firmware-partitions
 | 
			
		||||
 | 
			
		||||
In order to maximize the available space on UniFi AC boards using a
 | 
			
		||||
dual-image partition layout, combine the two OS partitions into a single
 | 
			
		||||
partition.
 | 
			
		||||
 | 
			
		||||
This allows users to access more usable space for additional packages.
 | 
			
		||||
 | 
			
		||||
Don't limit the usable image size to the size of a single OS partition.
 | 
			
		||||
The initial installation has to be done with an older version of OpenWrt
 | 
			
		||||
in case the generated image exceeds the space of a single kernel
 | 
			
		||||
partition in the future.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: David Bauer <mail@david-bauer.net>
 | 
			
		||||
(cherry picked from commit e4a76673ff4f655ba0698d9edb9efbacd0f82fff)
 | 
			
		||||
 | 
			
		||||
diff --git a/target/linux/ath79/dts/qca9563_ubnt_unifiac.dtsi b/target/linux/ath79/dts/qca9563_ubnt_unifiac.dtsi
 | 
			
		||||
index 2e407c348642cf5145f79c15288856fa141b0512..6704ec983b0beed5421a59f663cf8db6d650f559 100644
 | 
			
		||||
--- a/target/linux/ath79/dts/qca9563_ubnt_unifiac.dtsi
 | 
			
		||||
+++ b/target/linux/ath79/dts/qca9563_ubnt_unifiac.dtsi
 | 
			
		||||
@@ -69,17 +69,12 @@
 | 
			
		||||
 			};
 | 
			
		||||
 
 | 
			
		||||
 			partition@70000 {
 | 
			
		||||
+				/* Combine kernel0 & kernel1 */
 | 
			
		||||
 				label = "firmware";
 | 
			
		||||
-				reg = <0x070000 0x790000>;
 | 
			
		||||
+				reg = <0x070000 0xf20000>;
 | 
			
		||||
 				compatible = "denx,uimage";
 | 
			
		||||
 			};
 | 
			
		||||
 
 | 
			
		||||
-			partition@800000 {
 | 
			
		||||
-				label = "kernel1";
 | 
			
		||||
-				reg = <0x800000 0x790000>;
 | 
			
		||||
-				read-only;
 | 
			
		||||
-			};
 | 
			
		||||
-
 | 
			
		||||
 			partition@f90000 {
 | 
			
		||||
 				label = "bs";
 | 
			
		||||
 				reg = <0xf90000 0x020000>;
 | 
			
		||||
diff --git a/target/linux/ath79/image/generic-ubnt.mk b/target/linux/ath79/image/generic-ubnt.mk
 | 
			
		||||
index 7642c59e02848741996d6f9dcaf923d5dbaf6880..d6898c79d6b4d51d19813781e086db8086537318 100644
 | 
			
		||||
--- a/target/linux/ath79/image/generic-ubnt.mk
 | 
			
		||||
+++ b/target/linux/ath79/image/generic-ubnt.mk
 | 
			
		||||
@@ -221,7 +221,7 @@ TARGET_DEVICES += ubnt_unifi
 | 
			
		||||
 define Device/ubnt_unifiac
 | 
			
		||||
   DEVICE_VENDOR := Ubiquiti
 | 
			
		||||
   SOC := qca9563
 | 
			
		||||
-  IMAGE_SIZE := 7744k
 | 
			
		||||
+  IMAGE_SIZE := 15488k
 | 
			
		||||
   DEVICE_PACKAGES := kmod-ath10k-ct ath10k-firmware-qca988x-ct
 | 
			
		||||
 endef
 | 
			
		||||
 
 | 
			
		||||
@ -1,20 +0,0 @@
 | 
			
		||||
From: Maciej Krüger <mkg20001@gmail.com>
 | 
			
		||||
Date: Sun, 10 Apr 2022 01:58:41 +0200
 | 
			
		||||
Subject: oonf-olsrd2: add support to check if service is running
 | 
			
		||||
 | 
			
		||||
diff --git a/oonf-olsrd2/files/olsrd2.init b/oonf-olsrd2/files/olsrd2.init
 | 
			
		||||
index debae9883258b821a5ea0aecebe879ddc84e29eb..b6c1e9a5522788005db850ceaf6699aa1eee6877 100755
 | 
			
		||||
--- a/oonf-olsrd2/files/olsrd2.init
 | 
			
		||||
+++ b/oonf-olsrd2/files/olsrd2.init
 | 
			
		||||
@@ -3,4 +3,11 @@
 | 
			
		||||
 START=82
 | 
			
		||||
 DAEMON='olsrd2'
 | 
			
		||||
 
 | 
			
		||||
+running() {
 | 
			
		||||
+  test -e "/tmp/run/olsrd2.pid" && test -e "/proc/$(cat "/tmp/run/olsrd2.pid")" && return 0
 | 
			
		||||
+  return 1
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+extra_command "running" "Check if service is running"
 | 
			
		||||
+
 | 
			
		||||
 . /lib/functions/oonf_init.sh
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user