--- zzzz-none-000/linux-5.15.111/net/bridge/br_multicast.c 2023-05-11 14:00:40.000000000 +0000 +++ puma7-atom-6670-761/linux-5.15.111/net/bridge/br_multicast.c 2024-02-07 10:23:29.000000000 +0000 @@ -5,6 +5,11 @@ * Copyright (c) 2010 Herbert Xu */ +/* + Includes MaxLinear's changes dated: 2021, 2023. + Changed portions - Copyright 2021-2023, MaxLinear, Inc. +*/ + #include #include #include @@ -32,6 +37,8 @@ #include #endif +#include + #include "br_private.h" #include "br_private_mcast_eht.h" @@ -259,8 +266,10 @@ if (p->key.port != port) return false; +#if !IS_ENABLED(CONFIG_MCAST_HELPER) if (!(port->flags & BR_MULTICAST_TO_UNICAST)) return true; +#endif return ether_addr_equal(src, p->eth_addr); } @@ -701,6 +710,12 @@ if (!mp->ports && !mp->host_joined && netif_running(br->dev)) mod_timer(&mp->timer, jiffies); + + /* Must re-learn multicast sessions because of removed port + * group, otherwise avm_pa continues to forward to that port. + */ + if (pg->key.addr.proto == htons(ETH_P_IP)) + avm_pa_flush_multicast_sessions_for_group(pg->key.addr.dst.ip4); } static void br_multicast_find_del_pg(struct net_bridge *br, @@ -1392,6 +1407,8 @@ br_mdb_notify(brmctx->br->dev, mp, p, RTM_NEWMDB); found: + if (group->proto == htons(ETH_P_IP)) + avm_pa_flush_multicast_sessions_for_group(group->dst.ip4); if (igmpv2_mldv1) mod_timer(&p->timer, now + brmctx->multicast_membership_interval); @@ -1400,7 +1417,7 @@ return p; } -static int br_multicast_add_group(struct net_bridge_mcast *brmctx, +int br_multicast_add_group(struct net_bridge_mcast *brmctx, struct net_bridge_mcast_port *pmctx, struct br_ip *group, const unsigned char *src, @@ -3413,8 +3430,7 @@ } #endif -static void -br_multicast_leave_group(struct net_bridge_mcast *brmctx, +void br_multicast_leave_group(struct net_bridge_mcast *brmctx, struct net_bridge_mcast_port *pmctx, struct br_ip *group, struct bridge_mcast_other_query *other_query, @@ -3638,10 +3654,26 @@ struct net_bridge_port *p = pmctx ? pmctx->port : NULL; const unsigned char *src; struct igmphdr *ih; + struct iphdr *iph; int err; err = ip_mc_check_igmp(skb); + iph = ip_hdr(skb); + + if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl))) { + /* Dear Apple, Inc. + * Please fix those stupid iPads sending IGMP packets with bad ip + * checksum. The checksum appears to be only calculated across the first + * 20 bytes (without RA option). As of this writing, this applies to + * iOS 9.1. We have this workaround but we'd feel better without. + * TMA 2015/11/25 */ + if (iph->ihl > 5 && iph->protocol == IPPROTO_IGMP && ip_fast_csum((u8 *)iph, 5) == 0) + ip_send_check(iph); + else + return -EINVAL; + } + if (err == -ENOMSG) { if (!ipv4_is_local_multicast(ip_hdr(skb)->daddr)) { BR_INPUT_SKB_CB(skb)->mrouters_only = 1; @@ -4181,6 +4213,8 @@ HLIST_HEAD(deleted_head); struct hlist_node *tmp; + avm_pa_flush_multicast_sessions(); + spin_lock_bh(&br->multicast_lock); hlist_for_each_entry_safe(mp, tmp, &br->mdb_list, mdb_node) br_multicast_del_mdb_entry(mp);