Spelling fix: explicitly
[pandora-kernel.git] / net / bridge / br_input.c
index 5c18595..3cedd4e 100644 (file)
@@ -43,7 +43,7 @@ int br_handle_frame_finish(struct sk_buff *skb)
        struct net_bridge_port *p = rcu_dereference(skb->dev->br_port);
        struct net_bridge *br;
        struct net_bridge_fdb_entry *dst;
-       int passedup = 0;
+       struct sk_buff *skb2;
 
        if (!p || p->state == BR_STATE_DISABLED)
                goto drop;
@@ -55,39 +55,35 @@ int br_handle_frame_finish(struct sk_buff *skb)
        if (p->state == BR_STATE_LEARNING)
                goto drop;
 
-       if (br->dev->flags & IFF_PROMISC) {
-               struct sk_buff *skb2;
+       /* The packet skb2 goes to the local host (NULL to skip). */
+       skb2 = NULL;
 
-               skb2 = skb_clone(skb, GFP_ATOMIC);
-               if (skb2 != NULL) {
-                       passedup = 1;
-                       br_pass_frame_up(br, skb2);
-               }
-       }
+       if (br->dev->flags & IFF_PROMISC)
+               skb2 = skb;
+
+       dst = NULL;
 
        if (is_multicast_ether_addr(dest)) {
                br->statistics.multicast++;
-               br_flood_forward(br, skb, !passedup);
-               if (!passedup)
-                       br_pass_frame_up(br, skb);
-               goto out;
+               skb2 = skb;
+       } else if ((dst = __br_fdb_get(br, dest)) && dst->is_local) {
+               skb2 = skb;
+               /* Do not forward the packet since it's local. */
+               skb = NULL;
        }
 
-       dst = __br_fdb_get(br, dest);
-       if (dst != NULL && dst->is_local) {
-               if (!passedup)
-                       br_pass_frame_up(br, skb);
-               else
-                       kfree_skb(skb);
-               goto out;
-       }
+       if (skb2 == skb)
+               skb2 = skb_clone(skb, GFP_ATOMIC);
 
-       if (dst != NULL) {
-               br_forward(dst->dst, skb);
-               goto out;
-       }
+       if (skb2)
+               br_pass_frame_up(br, skb2);
 
-       br_flood_forward(br, skb, 0);
+       if (skb) {
+               if (dst)
+                       br_forward(dst->dst, skb);
+               else
+                       br_flood_forward(br, skb);
+       }
 
 out:
        return 0;
@@ -101,9 +97,8 @@ static int br_handle_local_finish(struct sk_buff *skb)
 {
        struct net_bridge_port *p = rcu_dereference(skb->dev->br_port);
 
-       if (p && p->state != BR_STATE_DISABLED)
+       if (p)
                br_fdb_update(p->br, p, eth_hdr(skb)->h_source);
-
        return 0;        /* process further */
 }
 
@@ -131,6 +126,10 @@ struct sk_buff *br_handle_frame(struct net_bridge_port *p, struct sk_buff *skb)
        if (!is_valid_ether_addr(eth_hdr(skb)->h_source))
                goto drop;
 
+       skb = skb_share_check(skb, GFP_ATOMIC);
+       if (!skb)
+               return NULL;
+
        if (unlikely(is_link_local(dest))) {
                /* Pause frames shouldn't be passed up by driver anyway */
                if (skb->protocol == htons(ETH_P_PAUSE))
@@ -150,7 +149,7 @@ struct sk_buff *br_handle_frame(struct net_bridge_port *p, struct sk_buff *skb)
        case BR_STATE_FORWARDING:
 
                if (br_should_route_hook) {
-                       if (br_should_route_hook(&skb))
+                       if (br_should_route_hook(skb))
                                return skb;
                        dest = eth_hdr(skb)->h_dest;
                }