aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge/br_input.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/bridge/br_input.c')
-rw-r--r--net/bridge/br_input.c48
1 files changed, 22 insertions, 26 deletions
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index 6f468fc3357a..3a8a015c92e0 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -43,7 +43,7 @@ int br_handle_frame_finish(struct sk_buff *skb)
43 struct net_bridge_port *p = rcu_dereference(skb->dev->br_port); 43 struct net_bridge_port *p = rcu_dereference(skb->dev->br_port);
44 struct net_bridge *br; 44 struct net_bridge *br;
45 struct net_bridge_fdb_entry *dst; 45 struct net_bridge_fdb_entry *dst;
46 int passedup = 0; 46 struct sk_buff *skb2;
47 47
48 if (!p || p->state == BR_STATE_DISABLED) 48 if (!p || p->state == BR_STATE_DISABLED)
49 goto drop; 49 goto drop;
@@ -55,39 +55,35 @@ int br_handle_frame_finish(struct sk_buff *skb)
55 if (p->state == BR_STATE_LEARNING) 55 if (p->state == BR_STATE_LEARNING)
56 goto drop; 56 goto drop;
57 57
58 if (br->dev->flags & IFF_PROMISC) { 58 /* The packet skb2 goes to the local host (NULL to skip). */
59 struct sk_buff *skb2; 59 skb2 = NULL;
60 60
61 skb2 = skb_clone(skb, GFP_ATOMIC); 61 if (br->dev->flags & IFF_PROMISC)
62 if (skb2 != NULL) { 62 skb2 = skb;
63 passedup = 1; 63
64 br_pass_frame_up(br, skb2); 64 dst = NULL;
65 }
66 }
67 65
68 if (is_multicast_ether_addr(dest)) { 66 if (is_multicast_ether_addr(dest)) {
69 br->statistics.multicast++; 67 br->statistics.multicast++;
70 br_flood_forward(br, skb, !passedup); 68 skb2 = skb;
71 if (!passedup) 69 } else if ((dst = __br_fdb_get(br, dest)) && dst->is_local) {
72 br_pass_frame_up(br, skb); 70 skb2 = skb;
73 goto out; 71 /* Do not forward the packet since it's local. */
72 skb = NULL;
74 } 73 }
75 74
76 dst = __br_fdb_get(br, dest); 75 if (skb2 == skb)
77 if (dst != NULL && dst->is_local) { 76 skb2 = skb_clone(skb, GFP_ATOMIC);
78 if (!passedup)
79 br_pass_frame_up(br, skb);
80 else
81 kfree_skb(skb);
82 goto out;
83 }
84 77
85 if (dst != NULL) { 78 if (skb2)
86 br_forward(dst->dst, skb); 79 br_pass_frame_up(br, skb2);
87 goto out;
88 }
89 80
90 br_flood_forward(br, skb, 0); 81 if (skb) {
82 if (dst)
83 br_forward(dst->dst, skb);
84 else
85 br_flood_forward(br, skb);
86 }
91 87
92out: 88out:
93 return 0; 89 return 0;