--- zzzz-none-000/linux-4.9.279/net/bridge/br_forward.c 2021-08-08 06:38:54.000000000 +0000 +++ puma7-atom-6591-750/linux-4.9.279/net/bridge/br_forward.c 2023-02-08 11:43:43.000000000 +0000 @@ -19,8 +19,22 @@ #include #include #include +#include #include "br_private.h" +#include + +#ifdef CONFIG_LTQ_MCAST_SNOOPING +#define IS_MCAST_ADDR 0x1 +#endif + +#if IS_ENABLED(CONFIG_LANTIQ_MCAST_HELPER) +void (*five_tuple_br_info_ptr)(struct sk_buff *skb) = NULL; +EXPORT_SYMBOL(five_tuple_br_info_ptr); +int mch_br_capture_pkt=0; +EXPORT_SYMBOL(mch_br_capture_pkt); +#endif + /* 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) @@ -30,9 +44,11 @@ vg = nbp_vlan_group_rcu(p); 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); + nbp_switchdev_allowed_egress(p, skb) && + !br_skb_isolated(p, skb); } + int br_dev_queue_push_xmit(struct net *net, struct sock *sk, struct sk_buff *skb) { skb_push(skb, ETH_HLEN); @@ -84,6 +100,16 @@ if (!skb) return; +#if IS_ENABLED(CONFIG_LANTIQ_MCAST_HELPER) + /* Send five tuple info to mcast helper */ + if(mch_br_capture_pkt == 1) { + if(ip_hdr(skb)->protocol == 17) { + if(five_tuple_br_info_ptr != NULL) { + five_tuple_br_info_ptr(skb); + } + } + } +#endif indev = skb->dev; skb->dev = to->dev; if (!local_orig) { @@ -162,6 +188,15 @@ if (!should_deliver(p, skb)) return prev; +#ifdef CONFIG_LTQ_MCAST_SNOOPING + if ((bridge_igmp_snooping || bridge_mld_snooping) && + p->br->this_br_snooping_enabled && + (eth_hdr(skb)->h_dest[0] & IS_MCAST_ADDR) && + (br_selective_flood(p, skb) == 0)) { + return prev; + } +#endif + if (!prev) goto out; @@ -181,14 +216,33 @@ struct net_bridge_port *prev = NULL; struct net_bridge_port *p; +#ifdef CONFIG_TI_PACKET_PROCESSOR + ti_hil_pp_event (TI_BRIDGE_PACKET_FLOODED, (void*)skb); +#endif// CONFIG_TI_PACKET_PROCESSOR + + if (!local_orig && !br_flood_rl(br, skb, skb->dev)) + goto out; + + 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 */ - if (pkt_type == BR_PKT_UNICAST && !(p->flags & BR_FLOOD)) - continue; - /* Do not flood if mc off, except for traffic we originate */ - if (pkt_type == BR_PKT_MULTICAST && - !(p->flags & BR_MCAST_FLOOD) && skb->dev != br->dev) - continue; + /* Do not flood unicast traffic to ports that turn it off, nor + * other traffic if flood off, except for traffic we originate + */ + switch (pkt_type) { + case BR_PKT_UNICAST: + if (!(p->flags & BR_FLOOD)) + continue; + break; + case BR_PKT_MULTICAST: + if (!(p->flags & BR_MCAST_FLOOD) && skb->dev != br->dev) + continue; + break; + case BR_PKT_BROADCAST: + if (!(p->flags & BR_BCAST_FLOOD) && skb->dev != br->dev) + continue; + break; + } /* Do not flood to ports that enable proxy ARP */ if (p->flags & BR_PROXYARP) @@ -220,6 +274,31 @@ } #ifdef CONFIG_BRIDGE_IGMP_SNOOPING +static void maybe_deliver_addr(struct net_bridge_port *p, struct sk_buff *skb, + const unsigned char *addr, bool local_orig) +{ + struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev; + const unsigned char *src = eth_hdr(skb)->h_source; + + if (!should_deliver(p, skb)) + return; + + /* Even with hairpin, no soliloquies - prevent breaking IPv6 DAD */ + if (skb->dev == p->dev && ether_addr_equal(src, addr)) + return; + + skb = skb_copy(skb, GFP_ATOMIC); + if (!skb) { + dev->stats.tx_dropped++; + return; + } + + if (!is_broadcast_ether_addr(addr)) + memcpy(eth_hdr(skb)->h_dest, addr, ETH_ALEN); + + __br_forward(p, skb, local_orig); +} + /* called with rcu_read_lock */ void br_multicast_flood(struct net_bridge_mdb_entry *mdst, struct sk_buff *skb, @@ -234,6 +313,7 @@ rp = rcu_dereference(hlist_first_rcu(&br->router_list)); p = mdst ? rcu_dereference(mdst->ports) : NULL; + while (p || rp) { struct net_bridge_port *port, *lport, *rport; @@ -241,10 +321,20 @@ rport = rp ? hlist_entry(rp, struct net_bridge_port, rlist) : NULL; - port = (unsigned long)lport > (unsigned long)rport ? - lport : rport; + if ((unsigned long)lport > (unsigned long)rport) { + port = lport; + + if (port->flags & BR_MULTICAST_TO_UNICAST) { + maybe_deliver_addr(lport, skb, p->eth_addr, + local_orig); + goto delivered; + } + } else { + port = rport; + } prev = maybe_deliver(prev, port, skb, local_orig); +delivered: if (IS_ERR(prev)) goto out; if (prev == port)