diff options
Diffstat (limited to 'net/bridge/br_input.c')
-rw-r--r-- | net/bridge/br_input.c | 32 |
1 files changed, 19 insertions, 13 deletions
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index 88e4aa9cb1f9..f3ac1e858ee1 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c | |||
@@ -98,9 +98,10 @@ int br_handle_frame_finish(struct sk_buff *skb) | |||
98 | } | 98 | } |
99 | 99 | ||
100 | if (skb) { | 100 | if (skb) { |
101 | if (dst) | 101 | if (dst) { |
102 | dst->used = jiffies; | ||
102 | br_forward(dst->dst, skb, skb2); | 103 | br_forward(dst->dst, skb, skb2); |
103 | else | 104 | } else |
104 | br_flood_forward(br, skb, skb2); | 105 | br_flood_forward(br, skb, skb2); |
105 | } | 106 | } |
106 | 107 | ||
@@ -139,21 +140,22 @@ static inline int is_link_local(const unsigned char *dest) | |||
139 | * Return NULL if skb is handled | 140 | * Return NULL if skb is handled |
140 | * note: already called with rcu_read_lock | 141 | * note: already called with rcu_read_lock |
141 | */ | 142 | */ |
142 | struct sk_buff *br_handle_frame(struct sk_buff *skb) | 143 | rx_handler_result_t br_handle_frame(struct sk_buff **pskb) |
143 | { | 144 | { |
144 | struct net_bridge_port *p; | 145 | struct net_bridge_port *p; |
146 | struct sk_buff *skb = *pskb; | ||
145 | const unsigned char *dest = eth_hdr(skb)->h_dest; | 147 | const unsigned char *dest = eth_hdr(skb)->h_dest; |
146 | br_should_route_hook_t *rhook; | 148 | br_should_route_hook_t *rhook; |
147 | 149 | ||
148 | if (unlikely(skb->pkt_type == PACKET_LOOPBACK)) | 150 | if (unlikely(skb->pkt_type == PACKET_LOOPBACK)) |
149 | return skb; | 151 | return RX_HANDLER_PASS; |
150 | 152 | ||
151 | if (!is_valid_ether_addr(eth_hdr(skb)->h_source)) | 153 | if (!is_valid_ether_addr(eth_hdr(skb)->h_source)) |
152 | goto drop; | 154 | goto drop; |
153 | 155 | ||
154 | skb = skb_share_check(skb, GFP_ATOMIC); | 156 | skb = skb_share_check(skb, GFP_ATOMIC); |
155 | if (!skb) | 157 | if (!skb) |
156 | return NULL; | 158 | return RX_HANDLER_CONSUMED; |
157 | 159 | ||
158 | p = br_port_get_rcu(skb->dev); | 160 | p = br_port_get_rcu(skb->dev); |
159 | 161 | ||
@@ -163,14 +165,16 @@ struct sk_buff *br_handle_frame(struct sk_buff *skb) | |||
163 | goto drop; | 165 | goto drop; |
164 | 166 | ||
165 | /* If STP is turned off, then forward */ | 167 | /* If STP is turned off, then forward */ |
166 | if (p->br->stp_enabled == BR_NO_STP) | 168 | if (p->br->stp_enabled == BR_NO_STP && dest[5] == 0) |
167 | goto forward; | 169 | goto forward; |
168 | 170 | ||
169 | if (NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev, | 171 | if (NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev, |
170 | NULL, br_handle_local_finish)) | 172 | NULL, br_handle_local_finish)) { |
171 | return NULL; /* frame consumed by filter */ | 173 | return RX_HANDLER_CONSUMED; /* consumed by filter */ |
172 | else | 174 | } else { |
173 | return skb; /* continue processing */ | 175 | *pskb = skb; |
176 | return RX_HANDLER_PASS; /* continue processing */ | ||
177 | } | ||
174 | } | 178 | } |
175 | 179 | ||
176 | forward: | 180 | forward: |
@@ -178,8 +182,10 @@ forward: | |||
178 | case BR_STATE_FORWARDING: | 182 | case BR_STATE_FORWARDING: |
179 | rhook = rcu_dereference(br_should_route_hook); | 183 | rhook = rcu_dereference(br_should_route_hook); |
180 | if (rhook) { | 184 | if (rhook) { |
181 | if ((*rhook)(skb)) | 185 | if ((*rhook)(skb)) { |
182 | return skb; | 186 | *pskb = skb; |
187 | return RX_HANDLER_PASS; | ||
188 | } | ||
183 | dest = eth_hdr(skb)->h_dest; | 189 | dest = eth_hdr(skb)->h_dest; |
184 | } | 190 | } |
185 | /* fall through */ | 191 | /* fall through */ |
@@ -194,5 +200,5 @@ forward: | |||
194 | drop: | 200 | drop: |
195 | kfree_skb(skb); | 201 | kfree_skb(skb); |
196 | } | 202 | } |
197 | return NULL; | 203 | return RX_HANDLER_CONSUMED; |
198 | } | 204 | } |