--- zzzz-none-000/linux-4.4.60/net/bridge/br_device.c 2017-04-08 07:53:53.000000000 +0000 +++ dragonfly-4020-701/linux-4.4.60/net/bridge/br_device.c 2018-11-08 13:36:17.000000000 +0000 @@ -40,6 +40,8 @@ struct pcpu_sw_netstats *brstats = this_cpu_ptr(br->stats); const struct nf_br_ops *nf_ops; u16 vid = 0; + struct net_bridge_port *pdst; + br_get_dst_hook_t *get_dst_hook; rcu_read_lock(); nf_ops = rcu_dereference(nf_br_ops); @@ -61,9 +63,16 @@ if (!br_allowed_ingress(br, br_vlan_group_rcu(br), skb, &vid)) goto out; + get_dst_hook = rcu_dereference(br_get_dst_hook); + if (is_broadcast_ether_addr(dest)) br_flood_deliver(br, skb, false); else if (is_multicast_ether_addr(dest)) { + br_multicast_handle_hook_t *multicast_handle_hook = + rcu_dereference(br_multicast_handle_hook); + if (!__br_get(multicast_handle_hook, true, NULL, skb)) + goto out; + if (unlikely(netpoll_tx_running(dev))) { br_flood_deliver(br, skb, false); goto out; @@ -79,10 +88,20 @@ br_multicast_deliver(mdst, skb); else 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, true); + } else { + pdst = __br_get(get_dst_hook, NULL, NULL, &skb); + if (pdst) { + if (!skb) + goto out; + br_deliver(pdst, skb); + } else { + dst = __br_fdb_get(br, dest, vid); + if (dst) + br_deliver(dst->dst, skb); + else + br_flood_deliver(br, skb, true); + } + } out: rcu_read_unlock(); @@ -404,4 +423,5 @@ br_netfilter_rtable_init(br); br_stp_timer_init(br); br_multicast_init(br); + br_flood_rl_setup(br); }