]> Pileus Git - ~andy/linux/blobdiff - net/bridge/br_input.c
bridge: Add a flag to control unicast packet flood.
[~andy/linux] / net / bridge / br_input.c
index 828e2bcc1f525570809b652c98e1c011b2850940..1b8b8b824cd766b05665e1d89f0e1394abdfbe2f 100644 (file)
@@ -65,6 +65,7 @@ int br_handle_frame_finish(struct sk_buff *skb)
        struct net_bridge_fdb_entry *dst;
        struct net_bridge_mdb_entry *mdst;
        struct sk_buff *skb2;
+       bool unicast = true;
        u16 vid = 0;
 
        if (!p || p->state == BR_STATE_DISABLED)
@@ -75,7 +76,8 @@ int br_handle_frame_finish(struct sk_buff *skb)
 
        /* insert into forwarding database after filtering to avoid spoofing */
        br = p->br;
-       br_fdb_update(br, p, eth_hdr(skb)->h_source, vid);
+       if (p->flags & BR_LEARNING)
+               br_fdb_update(br, p, eth_hdr(skb)->h_source, vid);
 
        if (!is_broadcast_ether_addr(dest) && is_multicast_ether_addr(dest) &&
            br_multicast_rcv(br, p, skb))
@@ -94,9 +96,10 @@ int br_handle_frame_finish(struct sk_buff *skb)
 
        dst = NULL;
 
-       if (is_broadcast_ether_addr(dest))
+       if (is_broadcast_ether_addr(dest)) {
                skb2 = skb;
-       else if (is_multicast_ether_addr(dest)) {
+               unicast = false;
+       } else if (is_multicast_ether_addr(dest)) {
                mdst = br_mdb_get(br, skb, vid);
                if (mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) {
                        if ((mdst && mdst->mglist) ||
@@ -109,6 +112,7 @@ int br_handle_frame_finish(struct sk_buff *skb)
                } else
                        skb2 = skb;
 
+               unicast = false;
                br->dev->stats.multicast++;
        } else if ((dst = __br_fdb_get(br, dest, vid)) &&
                        dst->is_local) {
@@ -122,7 +126,7 @@ int br_handle_frame_finish(struct sk_buff *skb)
                        dst->used = jiffies;
                        br_forward(dst->dst, skb, skb2);
                } else
-                       br_flood_forward(br, skb, skb2);
+                       br_flood_forward(br, skb, skb2, unicast);
        }
 
        if (skb2)
@@ -142,7 +146,8 @@ static int br_handle_local_finish(struct sk_buff *skb)
        u16 vid = 0;
 
        br_vlan_get_tag(skb, &vid);
-       br_fdb_update(p->br, p, eth_hdr(skb)->h_source, vid);
+       if (p->flags & BR_LEARNING)
+               br_fdb_update(p->br, p, eth_hdr(skb)->h_source, vid);
        return 0;        /* process further */
 }