diff options
Diffstat (limited to 'net/bridge/br_input.c')
| -rw-r--r-- | net/bridge/br_input.c | 48 | 
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 | ||
| 92 | out: | 88 | out: | 
| 93 | return 0; | 89 | return 0; | 
