--- zzzz-none-000/linux-3.10.107/net/bridge/br_device.c 2017-06-27 09:49:32.000000000 +0000 +++ vr9-7490-729/linux-3.10.107/net/bridge/br_device.c 2021-11-10 11:53:56.000000000 +0000 @@ -11,6 +11,12 @@ * 2 of the License, or (at your option) any later version. */ +/** + * Some part of this file is modified by Ikanos Communications. + * + * Copyright (C) 2013-2014 Ikanos Communications. + */ + #include #include #include @@ -18,10 +24,18 @@ #include #include #include +#include #include #include "br_private.h" +#if IS_ENABLED(CONFIG_FUSIV_KERNEL_IGMP_SNOOP) +void (*br_handle_mcast_frame_ptr)(struct net_bridge *br, struct sk_buff *skb) = NULL; +#endif + +#define COMMON_FEATURES (NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | \ + NETIF_F_GSO_MASK | NETIF_F_HW_CSUM) + /* net device transmit always called with BH disabled */ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) { @@ -46,35 +60,54 @@ brstats->tx_bytes += skb->len; u64_stats_update_end(&brstats->syncp); - if (!br_allowed_ingress(br, br_get_vlan_info(br), skb, &vid)) - goto out; - BR_INPUT_SKB_CB(skb)->brdev = dev; skb_reset_mac_header(skb); skb_pull(skb, ETH_HLEN); - if (is_broadcast_ether_addr(dest)) - br_flood_deliver(br, skb); + if (!br_allowed_ingress(br, br_get_vlan_info(br), skb, &vid)) + goto out; + +#if IS_ENABLED(CONFIG_FUSIV_KERNEL_IGMP_SNOOP) + if (dest[0] == 1 ||dest[0] == 0x33 ) + { + if (br->mfdb) + { + if (br_handle_mcast_frame_ptr) + br_handle_mcast_frame_ptr(br , skb); + else + { + printk("\nigmpsnoop fastpath:: br_handle_mcast_frame_ptr is not initialized\n"); + kfree_skb(skb); + } + rcu_read_unlock(); + return NETDEV_TX_OK; + } + } +#endif + + if (is_broadcast_ether_addr(dest)) + br_flood_deliver(br, skb, false); else if (is_multicast_ether_addr(dest)) { if (unlikely(netpoll_tx_running(dev))) { - br_flood_deliver(br, skb); + br_flood_deliver(br, skb, false); goto out; } - if (br_multicast_rcv(br, NULL, skb)) { + if (br_multicast_rcv(br, NULL, skb, vid)) { kfree_skb(skb); goto out; } mdst = br_mdb_get(br, skb, vid); - if (mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) + if ((mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) && + br_multicast_querier_exists(br, eth_hdr(skb))) br_multicast_deliver(mdst, skb); else - br_flood_deliver(br, skb); + br_flood_deliver(br, skb, false); } else if ((dst = __br_fdb_get(br, dest, vid)) != NULL) br_deliver(dst->dst, skb); else - br_flood_deliver(br, skb); + br_flood_deliver(br, skb, true); out: rcu_read_unlock(); @@ -176,8 +209,7 @@ spin_lock_bh(&br->lock); if (!ether_addr_equal(dev->dev_addr, addr->sa_data)) { - memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); - br_fdb_change_mac_address(br, addr->sa_data); + /* Mac address will be changed in br_stp_change_bridge_id(). */ br_stp_change_bridge_id(br, addr->sa_data); } spin_unlock_bh(&br->lock); @@ -215,8 +247,34 @@ br_netpoll_disable(p); } -static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni, - gfp_t gfp) +static int __br_netpoll_enable(struct net_bridge_port *p) +{ + struct netpoll *np; + int err; + + np = kzalloc(sizeof(*p->np), GFP_KERNEL); + if (!np) + return -ENOMEM; + + err = __netpoll_setup(np, p->dev); + if (err) { + kfree(np); + return err; + } + + p->np = np; + return err; +} + +int br_netpoll_enable(struct net_bridge_port *p) +{ + if (!p->br->dev->npinfo) + return 0; + + return __br_netpoll_enable(p); +} + +static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni) { struct net_bridge *br = netdev_priv(dev); struct net_bridge_port *p; @@ -225,7 +283,7 @@ list_for_each_entry(p, &br->port_list, list) { if (!p->dev) continue; - err = br_netpoll_enable(p, gfp); + err = __br_netpoll_enable(p); if (err) goto fail; } @@ -238,28 +296,6 @@ goto out; } -int br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp) -{ - struct netpoll *np; - int err = 0; - - np = kzalloc(sizeof(*p->np), gfp); - err = -ENOMEM; - if (!np) - goto out; - - err = __netpoll_setup(np, p->dev, gfp); - if (err) { - kfree(np); - goto out; - } - - p->np = np; - -out: - return err; -} - void br_netpoll_disable(struct net_bridge_port *p) { struct netpoll *np = p->np; @@ -346,12 +382,10 @@ dev->tx_queue_len = 0; dev->priv_flags = IFF_EBRIDGE; - dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | - NETIF_F_GSO_MASK | NETIF_F_HW_CSUM | NETIF_F_LLTX | - NETIF_F_NETNS_LOCAL | NETIF_F_HW_VLAN_CTAG_TX; - dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | - NETIF_F_GSO_MASK | NETIF_F_HW_CSUM | - NETIF_F_HW_VLAN_CTAG_TX; + dev->features = COMMON_FEATURES | NETIF_F_LLTX | NETIF_F_NETNS_LOCAL | + NETIF_F_HW_VLAN_CTAG_TX; + dev->hw_features = COMMON_FEATURES | NETIF_F_HW_VLAN_CTAG_TX; + dev->vlan_features = COMMON_FEATURES; br->dev = dev; spin_lock_init(&br->lock); @@ -361,7 +395,7 @@ br->bridge_id.prio[0] = 0x80; br->bridge_id.prio[1] = 0x00; - memcpy(br->group_addr, eth_reserved_addr_base, ETH_ALEN); + ether_addr_copy(br->group_addr, eth_reserved_addr_base); br->stp_enabled = BR_NO_STP; br->group_fwd_mask = BR_GROUPFWD_DEFAULT; @@ -373,6 +407,18 @@ br->ageing_time = 300 * HZ; br_netfilter_rtable_init(br); +#if defined(CONFIG_FUSIV_KERNEL_IGMP_SNOOP) || defined(CONFIG_FUSIV_KERNEL_IGMP_SNOOP_MODULE) + br->mfdb = NULL; //Init for IGMP Snoop +#endif +#if defined(CONFIG_FUSIV_KERNEL_AP_2_AP) || defined(CONFIG_FUSIV_KERNEL_AP_2_AP_MODULE) + br->bridgeVlanAddr = 0; +#endif + br_stp_timer_init(br); br_multicast_init(br); + br_flood_rl_setup(br); } + +#if defined(CONFIG_FUSIV_KERNEL_IGMP_SNOOP) || defined(CONFIG_FUSIV_KERNEL_IGMP_SNOOP_MODULE) +EXPORT_SYMBOL(br_handle_mcast_frame_ptr); +#endif