diff options
| -rw-r--r-- | net/bridge/br_device.c | 4 | ||||
| -rw-r--r-- | net/bridge/br_forward.c | 21 | ||||
| -rw-r--r-- | net/bridge/br_input.c | 48 | ||||
| -rw-r--r-- | net/bridge/br_private.h | 8 |
4 files changed, 31 insertions, 50 deletions
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 0eded176ce99..99292e8e1d0f 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c | |||
| @@ -41,11 +41,11 @@ int br_dev_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 41 | skb_pull(skb, ETH_HLEN); | 41 | skb_pull(skb, ETH_HLEN); |
| 42 | 42 | ||
| 43 | if (dest[0] & 1) | 43 | if (dest[0] & 1) |
| 44 | br_flood_deliver(br, skb, 0); | 44 | br_flood_deliver(br, skb); |
| 45 | else if ((dst = __br_fdb_get(br, dest)) != NULL) | 45 | else if ((dst = __br_fdb_get(br, dest)) != NULL) |
| 46 | br_deliver(dst->dst, skb); | 46 | br_deliver(dst->dst, skb); |
| 47 | else | 47 | else |
| 48 | br_flood_deliver(br, skb, 0); | 48 | br_flood_deliver(br, skb); |
| 49 | 49 | ||
| 50 | return 0; | 50 | return 0; |
| 51 | } | 51 | } |
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index ada7f495445c..bdd7c35c3c7b 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c | |||
| @@ -100,24 +100,13 @@ void br_forward(const struct net_bridge_port *to, struct sk_buff *skb) | |||
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | /* called under bridge lock */ | 102 | /* called under bridge lock */ |
| 103 | static void br_flood(struct net_bridge *br, struct sk_buff *skb, int clone, | 103 | static void br_flood(struct net_bridge *br, struct sk_buff *skb, |
| 104 | void (*__packet_hook)(const struct net_bridge_port *p, | 104 | void (*__packet_hook)(const struct net_bridge_port *p, |
| 105 | struct sk_buff *skb)) | 105 | struct sk_buff *skb)) |
| 106 | { | 106 | { |
| 107 | struct net_bridge_port *p; | 107 | struct net_bridge_port *p; |
| 108 | struct net_bridge_port *prev; | 108 | struct net_bridge_port *prev; |
| 109 | 109 | ||
| 110 | if (clone) { | ||
| 111 | struct sk_buff *skb2; | ||
| 112 | |||
| 113 | if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL) { | ||
| 114 | br->statistics.tx_dropped++; | ||
| 115 | return; | ||
| 116 | } | ||
| 117 | |||
| 118 | skb = skb2; | ||
| 119 | } | ||
| 120 | |||
| 121 | prev = NULL; | 110 | prev = NULL; |
| 122 | 111 | ||
| 123 | list_for_each_entry_rcu(p, &br->port_list, list) { | 112 | list_for_each_entry_rcu(p, &br->port_list, list) { |
| @@ -148,13 +137,13 @@ static void br_flood(struct net_bridge *br, struct sk_buff *skb, int clone, | |||
| 148 | 137 | ||
| 149 | 138 | ||
| 150 | /* called with rcu_read_lock */ | 139 | /* called with rcu_read_lock */ |
| 151 | void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb, int clone) | 140 | void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb) |
| 152 | { | 141 | { |
| 153 | br_flood(br, skb, clone, __br_deliver); | 142 | br_flood(br, skb, __br_deliver); |
| 154 | } | 143 | } |
| 155 | 144 | ||
| 156 | /* called under bridge lock */ | 145 | /* called under bridge lock */ |
| 157 | void br_flood_forward(struct net_bridge *br, struct sk_buff *skb, int clone) | 146 | void br_flood_forward(struct net_bridge *br, struct sk_buff *skb) |
| 158 | { | 147 | { |
| 159 | br_flood(br, skb, clone, __br_forward); | 148 | br_flood(br, skb, __br_forward); |
| 160 | } | 149 | } |
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; |
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 21bf3a9a03fd..e6dc6f52990d 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
| @@ -170,12 +170,8 @@ extern int br_dev_queue_push_xmit(struct sk_buff *skb); | |||
| 170 | extern void br_forward(const struct net_bridge_port *to, | 170 | extern void br_forward(const struct net_bridge_port *to, |
| 171 | struct sk_buff *skb); | 171 | struct sk_buff *skb); |
| 172 | extern int br_forward_finish(struct sk_buff *skb); | 172 | extern int br_forward_finish(struct sk_buff *skb); |
| 173 | extern void br_flood_deliver(struct net_bridge *br, | 173 | extern void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb); |
| 174 | struct sk_buff *skb, | 174 | extern void br_flood_forward(struct net_bridge *br, struct sk_buff *skb); |
| 175 | int clone); | ||
| 176 | extern void br_flood_forward(struct net_bridge *br, | ||
| 177 | struct sk_buff *skb, | ||
| 178 | int clone); | ||
| 179 | 175 | ||
| 180 | /* br_if.c */ | 176 | /* br_if.c */ |
| 181 | extern void br_port_carrier_check(struct net_bridge_port *p); | 177 | extern void br_port_carrier_check(struct net_bridge_port *p); |
