--- zzzz-none-000/linux-5.4.213/net/bridge/br_forward.c 2022-09-15 10:04:56.000000000 +0000 +++ miami-7690-761/linux-5.4.213/net/bridge/br_forward.c 2024-05-29 11:20:02.000000000 +0000 @@ -17,6 +17,8 @@ #include #include "br_private.h" +#include + /* Don't forward packets to originating port or forwarding disabled */ static inline int should_deliver(const struct net_bridge_port *p, const struct sk_buff *skb) @@ -24,10 +26,40 @@ struct net_bridge_vlan_group *vg; vg = nbp_vlan_group_rcu(p); + + /* QCA introduces some weird hairpin handling code here. We do not need + * that as we perfrom that configuration from userspace. So just use the + * code from the vanilla upstream kernel. For more details see MR + * linux!2159 or JZ-123646. */ +#ifdef CONFIG_AVM_ENHANCED return ((p->flags & BR_HAIRPIN_MODE) || skb->dev != p->dev) && br_allowed_egress(vg, skb) && p->state == BR_STATE_FORWARDING && nbp_switchdev_allowed_egress(p, skb) && !br_skb_isolated(p, skb); +#else + if ((skb->dev != p->dev) && + br_allowed_egress(vg, skb) && p->state == BR_STATE_FORWARDING && + nbp_switchdev_allowed_egress(p, skb) && + !br_skb_isolated(p, skb)) { + return true; + } + + if ((skb->dev == p->dev) && + (p->flags & BR_HAIRPIN_MODE) && + br_allowed_egress(vg, skb) && p->state == BR_STATE_FORWARDING) { + + /* Allow hairpin only on WLAN netdevices. + * For ethernet interfaces, hairpin not allowed + * due to issue with switchdevs. */ + if ( skb->dev->ieee80211_ptr == NULL) { + return false; + } + + return true; + } + + return false; +#endif } int br_dev_queue_push_xmit(struct net *net, struct sock *sk, struct sk_buff *skb) @@ -62,7 +94,7 @@ int br_forward_finish(struct net *net, struct sock *sk, struct sk_buff *skb) { skb->tstamp = 0; - return NF_HOOK(NFPROTO_BRIDGE, NF_BR_POST_ROUTING, + return BR_HOOK(NFPROTO_BRIDGE, NF_BR_POST_ROUTING, net, sk, skb, NULL, skb->dev, br_dev_queue_push_xmit); @@ -106,7 +138,7 @@ indev = NULL; } - NF_HOOK(NFPROTO_BRIDGE, br_hook, + BR_HOOK(NFPROTO_BRIDGE, br_hook, net, NULL, skb, indev, skb->dev, br_forward_finish); } @@ -194,6 +226,8 @@ struct net_bridge_port *prev = NULL; struct net_bridge_port *p; + avm_pa_do_not_accelerate(skb); + list_for_each_entry_rcu(p, &br->port_list, list) { /* Do not flood unicast traffic to ports that turn it off, nor * other traffic if flood off, except for traffic we originate