--- zzzz-none-000/linux-5.15.111/net/bridge/br_forward.c 2023-05-11 14:00:40.000000000 +0000 +++ puma7-atom-6670-761/linux-5.15.111/net/bridge/br_forward.c 2024-02-07 10:23:29.000000000 +0000 @@ -7,6 +7,11 @@ * Lennert Buytenhek */ +/* + * Includes MaxLinear's changes dated: 2021, 2022, 2023. + * Changed portions - Copyright 2021-2023, MaxLinear, Inc. +*/ + #include #include #include @@ -15,8 +20,51 @@ #include #include #include +#include #include "br_private.h" +#include + +struct net_bridge_port *(*ovs_port_get_rcu)(const struct net_device *dev) = NULL; +EXPORT_SYMBOL(ovs_port_get_rcu); + +#if IS_ENABLED(CONFIG_MCAST_HELPER) && IS_ENABLED(CONFIG_BRIDGE_IGMP_SNOOPING) +void (*mcast_helper_br_learning_hook)(struct sk_buff *skb, + struct net_device *mem_dev, + unsigned long flags, u8 *mac) = NULL; +EXPORT_SYMBOL(mcast_helper_br_learning_hook); + +/* Helper learning - called only from bridge flood path */ +void mcast_helper_learning(struct sk_buff *skb, + struct net_device *mem_dev, u8 *host_mac) +{ + struct net_bridge_port *iif_port; + unsigned long port_flag = 0; + + if (!mcast_helper_br_learning_hook) + return; + + /* XXX: broadcast MAC indicates mdb not added from JOIN */ + if (!mem_dev || !host_mac || is_broadcast_ether_addr(host_mac)) + return; + + if (netif_is_any_bridge_port(skb->dev)) { + iif_port = br_port_get_rcu(skb->dev); + if (iif_port) + port_flag = iif_port->flags; + } + + /* Send five tuple & host info to mcast helper for learning */ + if ((skb->protocol == htons(ETH_P_IP) && + (ip_hdr(skb)->protocol == IPPROTO_UDP)) || + ((skb->protocol == htons(ETH_P_IPV6)) && + (ipv6_hdr(skb)->nexthdr == IPPROTO_UDP))) { + mcast_helper_br_learning_hook(skb, mem_dev, port_flag, host_mac); + } +} +EXPORT_SYMBOL(mcast_helper_learning); +#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) @@ -202,6 +250,15 @@ 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, nor * other traffic if flood off, except for traffic we originate @@ -283,6 +340,10 @@ struct net_bridge_port_group *p; bool allow_mode_include = true; struct hlist_node *rp; +#if IS_ENABLED(CONFIG_MCAST_HELPER) + u8 igmp_type = br_multicast_igmp_type(skb); + u8 *host_mac = NULL; +#endif rp = br_multicast_get_first_rport_node(brmctx, skb); @@ -317,9 +378,26 @@ port = rport; } +#if IS_ENABLED(CONFIG_MCAST_HELPER) + /* For each host - learn and assign GID if deliverable */ + if (!igmp_type && prev && host_mac) + mcast_helper_learning(skb, prev->dev, host_mac); +#endif + prev = maybe_deliver(prev, port, skb, local_orig); if (IS_ERR(prev)) goto out; +#if IS_ENABLED(CONFIG_MCAST_HELPER) + /* If not delivered, prev != port. Same way multicast stats + * not collected above. So, stop learning when not delivered. + */ + if (p && (prev == port) && + ((unsigned long)lport >= (unsigned long)rport)) + host_mac = p->eth_addr; + else + host_mac = NULL; +#endif + delivered: if ((unsigned long)lport >= (unsigned long)port) p = rcu_dereference(p->next); @@ -330,6 +408,12 @@ if (!prev) goto out; +#if IS_ENABLED(CONFIG_MCAST_HELPER) + /* For each host - learn and assign GID before delivery */ + if (!igmp_type && host_mac) + mcast_helper_learning(skb, prev->dev, host_mac); +#endif + if (local_rcv) deliver_clone(prev, skb, local_orig); else