diff --git a/modules b/modules index e5f7861d4f..72af9296e2 100644 --- a/modules +++ b/modules @@ -1,16 +1,16 @@ GLUON_FEEDS='gluon packages routing' OPENWRT_REPO=https://github.com/openwrt/openwrt.git -OPENWRT_BRANCH=openwrt-23.05 -OPENWRT_COMMIT=1efcdb2446602c3b120b265c1d189039fdb9c0e7 +OPENWRT_BRANCH=openwrt-24.10 +OPENWRT_COMMIT=05b3adc0dbfd888f2a91c675146db5b62cdce0dc PACKAGES_GLUON_REPO=https://github.com/freifunk-gluon/packages.git PACKAGES_GLUON_COMMIT=3d08b0fee8dc5d96d8bcdb985fad1d5564de4022 PACKAGES_PACKAGES_REPO=https://github.com/openwrt/packages.git -PACKAGES_PACKAGES_BRANCH=openwrt-23.05 -PACKAGES_PACKAGES_COMMIT=c691e6f4c7ea2b40909270e4523b0fa6dcfbb9ae +PACKAGES_PACKAGES_BRANCH=openwrt-24.10 +PACKAGES_PACKAGES_COMMIT=ceda7c95ffcc296442f2e0b9249c66219e0deb80 PACKAGES_ROUTING_REPO=https://github.com/openwrt/routing.git -PACKAGES_ROUTING_BRANCH=openwrt-23.05 -PACKAGES_ROUTING_COMMIT=e351d1e623e9ef2ab78f28cb1ce8d271d28c902d +PACKAGES_ROUTING_BRANCH=openwrt-24.10 +PACKAGES_ROUTING_COMMIT=0ff4ab0506f2ab09b829699bef6b8be8bf8f87f1 diff --git a/patches/openwrt/0005-kernel-bridge-Implement-MLD-Querier-wake-up-calls-Android-bug-workaround.patch b/patches/openwrt/0005-kernel-bridge-Implement-MLD-Querier-wake-up-calls-Android-bug-workaround.patch deleted file mode 100644 index 23235feed7..0000000000 --- a/patches/openwrt/0005-kernel-bridge-Implement-MLD-Querier-wake-up-calls-Android-bug-workaround.patch +++ /dev/null @@ -1,856 +0,0 @@ -From: Linus Lüssing -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 - -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..077a563b6066cd1d3aee4b1e82328e8cc5e042ea ---- /dev/null -+++ b/package/network/config/netifd/patches/0001-bridge-Add-multicast_wakeupcall-option.patch -@@ -0,0 +1,142 @@ -+From d23a49e6542dc068b12fbc7b6a4520f9fb3626f9 Mon Sep 17 00:00:00 2001 -+From: =?UTF-8?q?Linus=20L=C3=BCssing?= -+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 -+--- -+ device.c | 9 +++++++++ -+ device.h | 3 +++ -+ system-linux.c | 13 +++++++++++++ -+ 3 files changed, 25 insertions(+) -+ -+--- a/device.c -++++ b/device.c -+@@ -49,6 +49,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 }, -+@@ -275,6 +276,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; -+@@ -449,6 +451,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) -+@@ -1372,6 +1379,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, -+@@ -144,6 +145,7 @@ enum { -+ DEV_OPT_GRO = (1ULL << 37), -+ DEV_OPT_MASTER = (1ULL << 38), -+ DEV_OPT_EEE = (1ULL << 39), -++ DEV_OPT_MULTICAST_WAKEUPCALL = (1ULL << 63), -+ }; -+ -+ /* events broadcasted to all users of a device */ -+@@ -205,6 +207,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 -+@@ -536,6 +536,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); -+@@ -923,8 +928,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 (dev->settings.flags & DEV_OPT_MULTICAST_TO_UNICAST) -+ mcast_to_ucast = dev->settings.multicast_to_unicast; -+@@ -939,6 +946,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.15 b/target/linux/generic/config-5.15 -index 4b059cb53f4fe1b7132675d15b66a175a0d44a60..ed36acdb8dc055bef60709191ad0950520f9cb57 100644 ---- a/target/linux/generic/config-5.15 -+++ b/target/linux/generic/config-5.15 -@@ -762,6 +762,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.15/602-bridge-Implement-MLD-Querier-wake-up-calls-Android-b.patch b/target/linux/generic/hack-5.15/602-bridge-Implement-MLD-Querier-wake-up-calls-Android-b.patch -new file mode 100644 -index 0000000000000000000000000000000000000000..91dd13e51549f40aa11a01d53e11be1a70f25d86 ---- /dev/null -+++ b/target/linux/generic/hack-5.15/602-bridge-Implement-MLD-Querier-wake-up-calls-Android-b.patch -@@ -0,0 +1,663 @@ -+From 4529dcf18d4c5e05d30cd2d6fabfbae201e6c347 Mon Sep 17 00:00:00 2001 -+From: =?UTF-8?q?Linus=20L=C3=BCssing?= -+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 -+--- -+ 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 | 291 ++++++++++++++++++++++++++++++++++- -+ net/bridge/br_netlink.c | 19 +++ -+ net/bridge/br_private.h | 20 +++ -+ net/bridge/br_sysfs_if.c | 18 +++ -+ net/core/rtnetlink.c | 2 +- -+ net/ipv6/mcast_snoop.c | 3 +- -+ 12 files changed, 386 insertions(+), 10 deletions(-) -+ -+--- a/include/linux/if_bridge.h -++++ b/include/linux/if_bridge.h -+@@ -59,6 +59,7 @@ struct br_ip_list { -+ #define BR_MRP_LOST_IN_CONT BIT(19) -+ #define BR_TX_FWD_OFFLOAD BIT(20) -+ #define BR_BPDU_FILTER BIT(21) -++#define BR_MULTICAST_WAKEUPCALL BIT(22) -+ -+ #define BR_DEFAULT_AGEING_TIME (300 * HZ) -+ -+--- a/include/net/addrconf.h -++++ b/include/net/addrconf.h -+@@ -241,6 +241,7 @@ void ipv6_mc_unmap(struct inet6_dev *ide -+ 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); -+ -+--- a/include/uapi/linux/if_link.h -++++ b/include/uapi/linux/if_link.h -+@@ -537,6 +537,7 @@ enum { -+ IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT, -+ IFLA_BRPORT_MCAST_EHT_HOSTS_CNT, -+ IFLA_BRPORT_BPDU_FILTER, -++ IFLA_BRPORT_MCAST_WAKEUPCALL, -+ __IFLA_BRPORT_MAX -+ }; -+ #define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1) -+--- 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 -+--- a/net/bridge/br_fdb.c -++++ b/net/bridge/br_fdb.c -+@@ -84,6 +84,10 @@ static void fdb_rcu_free(struct rcu_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); -+ } -+ -+@@ -518,6 +522,12 @@ static struct net_bridge_fdb_entry *fdb_ -+ fdb->key.vlan_id = vid; -+ fdb->flags = flags; -+ fdb->updated = fdb->used = jiffies; -++ -++#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)) { -+--- a/net/bridge/br_input.c -++++ b/net/bridge/br_input.c -+@@ -169,8 +169,10 @@ int br_handle_frame_finish(struct net *n -+ 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(brmctx, pmctx, skb, vid); -+ return br_pass_frame_up(skb, false); -++ } -+ -+ if (now != dst->used) -+ dst->used = now; -+--- a/net/bridge/br_multicast.c -++++ b/net/bridge/br_multicast.c -+@@ -950,15 +950,16 @@ static struct sk_buff *br_ip6_multicast_ -+ 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; -+@@ -1040,9 +1041,13 @@ static struct sk_buff *br_ip6_multicast_ -+ -+ /* ICMPv6 */ -+ skb_set_transport_header(skb, skb->len); -+- interval = ipv6_addr_any(group) ? -+- brmctx->multicast_query_response_interval : -+- brmctx->multicast_last_member_interval; -++ if (delay) { -++ interval = ipv6_addr_any(group) ? -++ brmctx->multicast_query_response_interval : -++ brmctx->multicast_last_member_interval; -++ interval = jiffies_to_msecs(interval); -++ } -++ -+ *igmp_type = ICMPV6_MGM_QUERY; -+ switch (brmctx->multicast_mld_version) { -+ case 1: -+@@ -1050,7 +1055,7 @@ static struct sk_buff *br_ip6_multicast_ -+ 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; -+@@ -1141,7 +1146,7 @@ static struct sk_buff *br_multicast_allo -+ &ip6_dst, &group->dst.ip6, -+ with_srcs, over_lmqt, -+ sflag, igmp_type, -+- need_rexmit); -++ need_rexmit, true); -+ } -+ #endif -+ } -+@@ -1623,6 +1628,169 @@ static void br_multicast_select_own_quer -+ #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_mcast *brmctx, -++ struct net_bridge_mcast_port *pmctx, -++ const struct in6_addr *group) -++{ -++ struct net_bridge_fdb_entry *fdb; -++ unsigned long delay; -++ -++ rcu_read_lock(); -++ hlist_for_each_entry_rcu(fdb, &brmctx->br->fdb_list, fdb_node) { -++ if (!fdb->dst || fdb->dst->dev != pmctx->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) ? -++ brmctx->multicast_query_response_interval : -++ brmctx->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_mcast *brmctx, -+ struct net_bridge_mcast_port *pmctx, -+ struct net_bridge_port_group *pg, -+@@ -1655,6 +1823,13 @@ again_under_lmqt: -+ dev_net(pmctx->port->dev), NULL, skb, NULL, skb->dev, -+ br_dev_queue_push_xmit); -+ -++#ifdef CONFIG_BRIDGE_IGMP_SNOOPING_WAKEUPCALLS -++ if (pmctx->port->wakeupcall_num_rings && -++ group->proto == htons(ETH_P_IPV6)) -++ br_multicast_schedule_wakeupcalls(brmctx, pmctx, -++ &group->dst.ip6); -++#endif -++ -+ if (over_lmqt && with_srcs && sflag) { -+ over_lmqt = false; -+ goto again_under_lmqt; -+@@ -3805,6 +3980,99 @@ int br_multicast_rcv(struct net_bridge_m -+ 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_mcast *brmctx, -++ struct net_bridge_mcast_port *pmctx, -++ 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(brmctx, pmctx, NULL, &ip6_dst, -++ &group, false, false, false, -++ &igmp_type, NULL, false); -++ if (!skb) -++ return; -++ -++ skb->dev = pmctx->port->dev; -++ ether_addr_copy(eth_hdr(skb)->h_dest, eth_dst); -++ -++ br_multicast_count(brmctx->br, pmctx->port, skb, igmp_type, -++ BR_MCAST_DIR_TX); -++ NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, -++ dev_net(pmctx->port->dev), NULL, skb, NULL, skb->dev, -++ br_dev_queue_push_xmit); -++} -++ -++void br_multicast_wakeupcall_rcv(struct net_bridge_mcast *brmctx, -++ struct net_bridge_mcast_port *pmctx, -++ struct sk_buff *skb, u16 vid) -++{ -++ if (!br_multicast_wakeupcall_check(brmctx->br, pmctx->port, skb, vid)) -++ return; -++ -++ br_multicast_wakeupcall_send_mldq(brmctx, pmctx, -++ eth_hdr(skb)->h_source); -++} -++ -++#endif /* CONFIG_BRIDGE_IGMP_SNOOPING_WAKEUPCALLS */ -++ -+ static void br_multicast_query_expired(struct net_bridge_mcast *brmctx, -+ struct bridge_mcast_own_query *query, -+ struct bridge_mcast_querier *querier) -+@@ -4333,6 +4601,15 @@ int br_multicast_set_vlan_router(struct -+ 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_mcast *brmctx, -+ struct bridge_mcast_own_query *query) -+ { -+--- a/net/bridge/br_netlink.c -++++ b/net/bridge/br_netlink.c -+@@ -199,6 +199,9 @@ static inline size_t br_port_info_size(v -+ #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 */ -+ + nla_total_size(sizeof(u8)) /* IFLA_BRPORT_MRP_IN_OPEN */ -+@@ -296,6 +299,11 @@ static int br_port_fill_attrs(struct sk_ -+ p->multicast_eht_hosts_cnt)) -+ 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(); -+@@ -823,6 +831,7 @@ static const struct nla_policy br_port_p -+ [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 }, -+@@ -950,6 +959,16 @@ static int br_setport(struct net_bridge_ -+ if (err) -+ return err; -+ } -++#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]) { -+--- a/net/bridge/br_private.h -++++ b/net/bridge/br_private.h -+@@ -269,6 +269,10 @@ struct net_bridge_fdb_entry { -+ unsigned long used; -+ -+ struct rcu_head rcu; -++ -++#ifdef CONFIG_BRIDGE_IGMP_SNOOPING_WAKEUPCALLS -++ struct timer_list wakeupcall_timer; -++#endif -+ }; -+ -+ #define MDB_PG_FLAGS_PERMANENT BIT(0) -+@@ -382,6 +386,7 @@ struct net_bridge_port { -+ u32 multicast_eht_hosts_limit; -+ u32 multicast_eht_hosts_cnt; -+ struct hlist_head mglist; -++ u8 wakeupcall_num_rings; -+ #endif -+ -+ #ifdef CONFIG_SYSFS -+@@ -1419,6 +1424,21 @@ br_multicast_ctx_options_equal(const str -+ } -+ #endif -+ -++#ifdef CONFIG_BRIDGE_IGMP_SNOOPING_WAKEUPCALLS -++void br_multicast_wakeupcall_rcv(struct net_bridge_mcast *brmctx, -++ struct net_bridge_mcast_port *pmctx, -++ 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_mcast *brmctx, -++ struct net_bridge_mcast_port *pmctx, -++ 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, -+--- a/net/bridge/br_sysfs_if.c -++++ b/net/bridge/br_sysfs_if.c -+@@ -260,6 +260,21 @@ BRPORT_ATTR_FLAG(multicast_fast_leave, B -+ 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, -+@@ -286,6 +301,9 @@ static const struct brport_attribute *br -+ &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, -+ &brport_attr_multicast_flood, -+--- a/net/core/rtnetlink.c -++++ b/net/core/rtnetlink.c -+@@ -55,7 +55,7 @@ -+ #include -+ -+ #define RTNL_MAX_TYPE 50 -+-#define RTNL_SLAVE_MAX_TYPE 41 -++#define RTNL_SLAVE_MAX_TYPE 42 -+ -+ struct rtnl_link { -+ rtnl_doit_func doit; -+--- a/net/ipv6/mcast_snoop.c -++++ b/net/ipv6/mcast_snoop.c -+@@ -131,7 +131,7 @@ static inline __sum16 ipv6_mc_validate_c -+ 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 s -+ -+ return 0; -+ } -++EXPORT_SYMBOL(ipv6_mc_check_icmpv6); -+ -+ /** -+ * ipv6_mc_check_mld - checks whether this is a sane MLD packet diff --git a/patches/openwrt/0007-mac80211-silence-warning-for-missing-rate-information.patch b/patches/openwrt/0005-mac80211-silence-warning-for-missing-rate-information.patch similarity index 100% rename from patches/openwrt/0007-mac80211-silence-warning-for-missing-rate-information.patch rename to patches/openwrt/0005-mac80211-silence-warning-for-missing-rate-information.patch diff --git a/patches/openwrt/0006-ath79-don-t-create-DIR-825-B1-factory-image.patch b/patches/openwrt/0006-ath79-don-t-create-DIR-825-B1-factory-image.patch deleted file mode 100644 index 4530f838dc..0000000000 --- a/patches/openwrt/0006-ath79-don-t-create-DIR-825-B1-factory-image.patch +++ /dev/null @@ -1,29 +0,0 @@ -From: David Bauer -Date: Mon, 21 Aug 2023 23:16:14 +0200 -Subject: ath79: don't create DIR-825 B1 factory image - -Currently the build fails for the D-Link DIR-825 B1. THis is due to the -factory image being size-constrained. The sysupgrade image is not -affected, as OpenWrt now uses a concatenated firmware partition. - -To newly install such a device, please use the latest OpenWrt 22.03 -factory image and install a Gluon sysupgrade. - -Signed-off-by: David Bauer - -diff --git a/target/linux/ath79/image/generic.mk b/target/linux/ath79/image/generic.mk -index f264c14314ca862e39c71e821621a81f8f1957fa..d3e2a9ccd7ae3cb03e35bb4b68a2360bb4d4f84c 100644 ---- a/target/linux/ath79/image/generic.mk -+++ b/target/linux/ath79/image/generic.mk -@@ -1073,11 +1073,6 @@ define Device/dlink_dir-825-b1 - DEVICE_PACKAGES := kmod-usb-ohci kmod-usb2 kmod-usb-ledtrig-usbport \ - kmod-leds-reset kmod-owl-loader kmod-switch-rtl8366s - IMAGE_SIZE := 7808k -- FACTORY_SIZE := 6144k -- IMAGES += factory.bin -- IMAGE/factory.bin = append-kernel | pad-to $$$$(BLOCKSIZE) | append-rootfs | \ -- pad-rootfs | check-size $$$$(FACTORY_SIZE) | pad-to $$$$(FACTORY_SIZE) | \ -- append-string 01AP94-AR7161-RT-080619-00 - endef - TARGET_DEVICES += dlink_dir-825-b1 - diff --git a/patches/openwrt/0009-mt76-include-fixes-for-MT7603-MT7612.patch b/patches/openwrt/0006-mt76-include-fixes-for-MT7603-MT7612.patch similarity index 100% rename from patches/openwrt/0009-mt76-include-fixes-for-MT7603-MT7612.patch rename to patches/openwrt/0006-mt76-include-fixes-for-MT7603-MT7612.patch diff --git a/patches/openwrt/0008-mac80211-add-AQL-support-for-broadcast-multicast-packets.patch b/patches/openwrt/0008-mac80211-add-AQL-support-for-broadcast-multicast-packets.patch deleted file mode 100644 index a8f810850a..0000000000 --- a/patches/openwrt/0008-mac80211-add-AQL-support-for-broadcast-multicast-packets.patch +++ /dev/null @@ -1,317 +0,0 @@ -From: Felix Fietkau -Date: Fri, 9 Feb 2024 20:47:39 +0100 -Subject: mac80211: add AQL support for broadcast/multicast packets - -Should improve performance/reliability with lots of mcast packets - -Signed-off-by: Felix Fietkau -(cherry picked from commit 95e633efbd1b4ffbbfc2d8abba2b05291f6e9903) - -diff --git a/package/kernel/mac80211/patches/subsys/330-mac80211-add-AQL-support-for-broadcast-packets.patch b/package/kernel/mac80211/patches/subsys/330-mac80211-add-AQL-support-for-broadcast-packets.patch -new file mode 100644 -index 0000000000000000000000000000000000000000..5f6754e5024f90f7ba6833c3702fe3ce425c50bb ---- /dev/null -+++ b/package/kernel/mac80211/patches/subsys/330-mac80211-add-AQL-support-for-broadcast-packets.patch -@@ -0,0 +1,302 @@ -+From: Felix Fietkau -+Date: Fri, 9 Feb 2024 19:43:40 +0100 -+Subject: [PATCH] mac80211: add AQL support for broadcast packets -+ -+Excessive broadcast traffic with little competing unicast traffic can easily -+flood hardware queues, leading to throughput issues. Additionally, filling -+the hardware queues with too many packets breaks FQ for broadcast data. -+Fix this by enabling AQL for broadcast packets. -+ -+Signed-off-by: Felix Fietkau -+--- -+ -+--- a/include/net/cfg80211.h -++++ b/include/net/cfg80211.h -+@@ -3158,6 +3158,7 @@ enum wiphy_params_flags { -+ /* The per TXQ device queue limit in airtime */ -+ #define IEEE80211_DEFAULT_AQL_TXQ_LIMIT_L 5000 -+ #define IEEE80211_DEFAULT_AQL_TXQ_LIMIT_H 12000 -++#define IEEE80211_DEFAULT_AQL_TXQ_LIMIT_BC 50000 -+ -+ /* The per interface airtime threshold to switch to lower queue limit */ -+ #define IEEE80211_AQL_THRESHOLD 24000 -+--- a/net/mac80211/debugfs.c -++++ b/net/mac80211/debugfs.c -+@@ -215,11 +215,13 @@ static ssize_t aql_pending_read(struct f -+ "VI %u us\n" -+ "BE %u us\n" -+ "BK %u us\n" -++ "BC/MC %u us\n" -+ "total %u us\n", -+ atomic_read(&local->aql_ac_pending_airtime[IEEE80211_AC_VO]), -+ atomic_read(&local->aql_ac_pending_airtime[IEEE80211_AC_VI]), -+ atomic_read(&local->aql_ac_pending_airtime[IEEE80211_AC_BE]), -+ atomic_read(&local->aql_ac_pending_airtime[IEEE80211_AC_BK]), -++ atomic_read(&local->aql_bc_pending_airtime), -+ atomic_read(&local->aql_total_pending_airtime)); -+ return simple_read_from_buffer(user_buf, count, ppos, -+ buf, len); -+@@ -245,7 +247,8 @@ static ssize_t aql_txq_limit_read(struct -+ "VO %u %u\n" -+ "VI %u %u\n" -+ "BE %u %u\n" -+- "BK %u %u\n", -++ "BK %u %u\n" -++ "BC/MC %u\n", -+ local->aql_txq_limit_low[IEEE80211_AC_VO], -+ local->aql_txq_limit_high[IEEE80211_AC_VO], -+ local->aql_txq_limit_low[IEEE80211_AC_VI], -+@@ -253,7 +256,8 @@ static ssize_t aql_txq_limit_read(struct -+ local->aql_txq_limit_low[IEEE80211_AC_BE], -+ local->aql_txq_limit_high[IEEE80211_AC_BE], -+ local->aql_txq_limit_low[IEEE80211_AC_BK], -+- local->aql_txq_limit_high[IEEE80211_AC_BK]); -++ local->aql_txq_limit_high[IEEE80211_AC_BK], -++ local->aql_txq_limit_bc); -+ return simple_read_from_buffer(user_buf, count, ppos, -+ buf, len); -+ } -+@@ -279,6 +283,11 @@ static ssize_t aql_txq_limit_write(struc -+ else -+ buf[count] = '\0'; -+ -++ if (sscanf(buf, "mcast %u", &q_limit_low) == 1) { -++ local->aql_txq_limit_bc = q_limit_low; -++ return count; -++ } -++ -+ if (sscanf(buf, "%u %u %u", &ac, &q_limit_low, &q_limit_high) != 3) -+ return -EINVAL; -+ -+--- a/net/mac80211/ieee80211_i.h -++++ b/net/mac80211/ieee80211_i.h -+@@ -1300,10 +1300,12 @@ struct ieee80211_local { -+ u16 schedule_round[IEEE80211_NUM_ACS]; -+ -+ u16 airtime_flags; -++ u32 aql_txq_limit_bc; -+ u32 aql_txq_limit_low[IEEE80211_NUM_ACS]; -+ u32 aql_txq_limit_high[IEEE80211_NUM_ACS]; -+ u32 aql_threshold; -+ atomic_t aql_total_pending_airtime; -++ atomic_t aql_bc_pending_airtime; -+ atomic_t aql_ac_pending_airtime[IEEE80211_NUM_ACS]; -+ -+ const struct ieee80211_ops *ops; -+--- a/net/mac80211/main.c -++++ b/net/mac80211/main.c -+@@ -789,6 +789,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_ -+ spin_lock_init(&local->rx_path_lock); -+ spin_lock_init(&local->queue_stop_reason_lock); -+ -++ local->aql_txq_limit_bc = IEEE80211_DEFAULT_AQL_TXQ_LIMIT_BC; -+ for (i = 0; i < IEEE80211_NUM_ACS; i++) { -+ INIT_LIST_HEAD(&local->active_txqs[i]); -+ spin_lock_init(&local->active_txq_lock[i]); -+--- a/net/mac80211/sta_info.c -++++ b/net/mac80211/sta_info.c -+@@ -2164,13 +2164,28 @@ EXPORT_SYMBOL(ieee80211_sta_recalc_aggre -+ -+ void ieee80211_sta_update_pending_airtime(struct ieee80211_local *local, -+ struct sta_info *sta, u8 ac, -+- u16 tx_airtime, bool tx_completed) -++ u16 tx_airtime, bool tx_completed, -++ bool mcast) -+ { -+ int tx_pending; -+ -+ if (!wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) -+ return; -+ -++ if (mcast) { -++ if (!tx_completed) { -++ atomic_add(tx_airtime, &local->aql_bc_pending_airtime); -++ return; -++ } -++ -++ tx_pending = atomic_sub_return(tx_airtime, -++ &local->aql_bc_pending_airtime); -++ if (tx_pending < 0) -++ atomic_cmpxchg(&local->aql_bc_pending_airtime, -++ tx_pending, 0); -++ return; -++ } -++ -+ if (!tx_completed) { -+ if (sta) -+ atomic_add(tx_airtime, -+--- a/net/mac80211/tx.c -++++ b/net/mac80211/tx.c -+@@ -2553,7 +2553,7 @@ static u16 ieee80211_store_ack_skb(struc -+ -+ spin_lock_irqsave(&local->ack_status_lock, flags); -+ id = idr_alloc(&local->ack_status_frames, ack_skb, -+- 1, 0x2000, GFP_ATOMIC); -++ 1, 0x1000, GFP_ATOMIC); -+ spin_unlock_irqrestore(&local->ack_status_lock, flags); -+ -+ if (id >= 0) { -+@@ -3957,20 +3957,20 @@ begin: -+ encap_out: -+ IEEE80211_SKB_CB(skb)->control.vif = vif; -+ -+- if (tx.sta && -+- wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) { -+- bool ampdu = txq->ac != IEEE80211_AC_VO; -++ if (wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) { -++ bool ampdu = txq->sta && txq->ac != IEEE80211_AC_VO; -+ u32 airtime; -+ -+ airtime = ieee80211_calc_expected_tx_airtime(hw, vif, txq->sta, -+ skb->len, ampdu); -+- if (airtime) { -+- airtime = ieee80211_info_set_tx_time_est(info, airtime); -+- ieee80211_sta_update_pending_airtime(local, tx.sta, -+- txq->ac, -+- airtime, -+- false); -+- } -++ if (!airtime) -++ return skb; -++ -++ airtime = ieee80211_info_set_tx_time_est(info, airtime); -++ info->tx_time_mc = !tx.sta; -++ ieee80211_sta_update_pending_airtime(local, tx.sta, txq->ac, -++ airtime, false, -++ info->tx_time_mc); -+ } -+ -+ return skb; -+@@ -4025,6 +4025,7 @@ struct ieee80211_txq *ieee80211_next_txq -+ struct ieee80211_txq *ret = NULL; -+ struct txq_info *txqi = NULL, *head = NULL; -+ bool found_eligible_txq = false; -++ bool aql_check; -+ -+ spin_lock_bh(&local->active_txq_lock[ac]); -+ -+@@ -4048,26 +4049,26 @@ struct ieee80211_txq *ieee80211_next_txq -+ if (!head) -+ head = txqi; -+ -++ aql_check = ieee80211_txq_airtime_check(hw, &txqi->txq); -++ if (aql_check) -++ found_eligible_txq = true; -++ -+ if (txqi->txq.sta) { -+ struct sta_info *sta = container_of(txqi->txq.sta, -+ struct sta_info, sta); -+- bool aql_check = ieee80211_txq_airtime_check(hw, &txqi->txq); -+- s32 deficit = ieee80211_sta_deficit(sta, txqi->txq.ac); -+- -+- if (aql_check) -+- found_eligible_txq = true; -+- -+- if (deficit < 0) -++ if (ieee80211_sta_deficit(sta, txqi->txq.ac) < 0) { -+ sta->airtime[txqi->txq.ac].deficit += -+ sta->airtime_weight << AIRTIME_QUANTUM_SHIFT; -+- -+- if (deficit < 0 || !aql_check) { -+- list_move_tail(&txqi->schedule_order, -+- &local->active_txqs[txqi->txq.ac]); -+- goto begin; -++ aql_check = false; -+ } -+ } -+ -++ if (!aql_check) { -++ list_move_tail(&txqi->schedule_order, -++ &local->active_txqs[txqi->txq.ac]); -++ goto begin; -++ } -++ -+ if (txqi->schedule_round == local->schedule_round[ac]) -+ goto out; -+ -+@@ -4132,7 +4133,8 @@ bool ieee80211_txq_airtime_check(struct -+ return true; -+ -+ if (!txq->sta) -+- return true; -++ return atomic_read(&local->aql_bc_pending_airtime) < -++ local->aql_txq_limit_bc; -+ -+ if (unlikely(txq->tid == IEEE80211_NUM_TIDS)) -+ return true; -+@@ -4181,15 +4183,15 @@ bool ieee80211_txq_may_transmit(struct i -+ -+ spin_lock_bh(&local->active_txq_lock[ac]); -+ -+- if (!txqi->txq.sta) -+- goto out; -+- -+ if (list_empty(&txqi->schedule_order)) -+ goto out; -+ -+ if (!ieee80211_txq_schedule_airtime_check(local, ac)) -+ goto out; -+ -++ if (!txqi->txq.sta) -++ goto out; -++ -+ list_for_each_entry_safe(iter, tmp, &local->active_txqs[ac], -+ schedule_order) { -+ if (iter == txqi) -+--- a/include/net/mac80211.h -++++ b/include/net/mac80211.h -+@@ -1092,6 +1092,7 @@ ieee80211_rate_get_vht_nss(const struct -+ * link the frame will be transmitted on -+ * @hw_queue: HW queue to put the frame on, skb_get_queue_mapping() gives the AC -+ * @ack_frame_id: internal frame ID for TX status, used internally -++ * @tx_time_mc: TX time is for a multicast packet -+ * @tx_time_est: TX time estimate in units of 4us, used internally -+ * @control: union part for control data -+ * @control.rates: TX rates array to try -+@@ -1131,8 +1132,9 @@ struct ieee80211_tx_info { -+ /* common information */ -+ u32 flags; -+ u32 band:3, -+- ack_frame_id:13, -++ ack_frame_id:12, -+ hw_queue:4, -++ tx_time_mc:1, -+ tx_time_est:10; -+ /* 2 free bits */ -+ -+--- a/net/mac80211/sta_info.h -++++ b/net/mac80211/sta_info.h -+@@ -147,7 +147,8 @@ struct airtime_info { -+ -+ void ieee80211_sta_update_pending_airtime(struct ieee80211_local *local, -+ struct sta_info *sta, u8 ac, -+- u16 tx_airtime, bool tx_completed); -++ u16 tx_airtime, bool tx_completed, -++ bool mcast); -+ -+ struct sta_info; -+ -+--- a/net/mac80211/status.c -++++ b/net/mac80211/status.c -+@@ -716,7 +716,7 @@ static void ieee80211_report_used_skb(st -+ ieee80211_sta_update_pending_airtime(local, sta, -+ skb_get_queue_mapping(skb), -+ tx_time_est, -+- true); -++ true, info->tx_time_mc); -+ rcu_read_unlock(); -+ } -+ -+@@ -1127,10 +1127,11 @@ void ieee80211_tx_status_ext(struct ieee -+ /* Do this here to avoid the expensive lookup of the sta -+ * in ieee80211_report_used_skb(). -+ */ -++ bool mcast = IEEE80211_SKB_CB(skb)->tx_time_mc; -+ ieee80211_sta_update_pending_airtime(local, sta, -+ skb_get_queue_mapping(skb), -+ tx_time_est, -+- true); -++ true, mcast); -+ ieee80211_info_set_tx_time_est(IEEE80211_SKB_CB(skb), 0); -+ } -+ diff --git a/patches/packages/packages/0001-perl-don-t-build-in-parallel-and-bump-release.patch b/patches/packages/packages/0001-perl-don-t-build-in-parallel-and-bump-release.patch index 2cf958edfc..de66e902b4 100644 --- a/patches/packages/packages/0001-perl-don-t-build-in-parallel-and-bump-release.patch +++ b/patches/packages/packages/0001-perl-don-t-build-in-parallel-and-bump-release.patch @@ -8,10 +8,10 @@ https://github.com/openwrt/packages/issues/8238 https://github.com/openwrt/packages/pull/17274 diff --git a/lang/perl/Makefile b/lang/perl/Makefile -index 2763de2777f8e3e60db9917ad64da7d5d127ba8f..7468e6db8ea561a6285b77990c8786ef3d46967f 100644 +index 6a6dd5ea86798e7e95e3657a94cca829dbd0924b..a0ffd0e982b59b871e683f745231579404a206c3 100644 --- a/lang/perl/Makefile +++ b/lang/perl/Makefile -@@ -34,8 +34,8 @@ PKG_BUILD_DIR:=$(BUILD_DIR)/perl/$(PKG_NAME)-$(PKG_VERSION) +@@ -27,8 +27,8 @@ PKG_BUILD_DIR:=$(BUILD_DIR)/perl/$(PKG_NAME)-$(PKG_VERSION) HOST_BUILD_DIR:=$(BUILD_DIR_HOST)/perl/$(PKG_NAME)-$(PKG_VERSION) PKG_INSTALL:=1 PKG_BUILD_DEPENDS:=perl/host