diff options
author | David S. Miller <davem@davemloft.net> | 2011-03-07 03:37:13 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-03-07 03:37:13 -0500 |
commit | b8cec4a415e807a2f8679efa89558a040a7003de (patch) | |
tree | 1a5fc7c31c4f8b55ea850599bb7309871165f48e /net/batman-adv/unicast.c | |
parent | 5e2b61f78411be25f0b84f97d5b5d312f184dfd1 (diff) | |
parent | e44d8fe2b5c27ecc230f886d4cc49fcbd86f87a0 (diff) |
Merge branch 'batman-adv/next' of git://git.open-mesh.org/ecsv/linux-merge
Diffstat (limited to 'net/batman-adv/unicast.c')
-rw-r--r-- | net/batman-adv/unicast.c | 93 |
1 files changed, 46 insertions, 47 deletions
diff --git a/net/batman-adv/unicast.c b/net/batman-adv/unicast.c index 121b11d2a23d..19f84bd443af 100644 --- a/net/batman-adv/unicast.c +++ b/net/batman-adv/unicast.c | |||
@@ -183,15 +183,10 @@ int frag_reassemble_skb(struct sk_buff *skb, struct bat_priv *bat_priv, | |||
183 | (struct unicast_frag_packet *)skb->data; | 183 | (struct unicast_frag_packet *)skb->data; |
184 | 184 | ||
185 | *new_skb = NULL; | 185 | *new_skb = NULL; |
186 | spin_lock_bh(&bat_priv->orig_hash_lock); | ||
187 | orig_node = ((struct orig_node *) | ||
188 | hash_find(bat_priv->orig_hash, compare_orig, choose_orig, | ||
189 | unicast_packet->orig)); | ||
190 | 186 | ||
191 | if (!orig_node) { | 187 | orig_node = orig_hash_find(bat_priv, unicast_packet->orig); |
192 | pr_debug("couldn't find originator in orig_hash\n"); | 188 | if (!orig_node) |
193 | goto out; | 189 | goto out; |
194 | } | ||
195 | 190 | ||
196 | orig_node->last_frag_packet = jiffies; | 191 | orig_node->last_frag_packet = jiffies; |
197 | 192 | ||
@@ -215,14 +210,15 @@ int frag_reassemble_skb(struct sk_buff *skb, struct bat_priv *bat_priv, | |||
215 | /* if not, merge failed */ | 210 | /* if not, merge failed */ |
216 | if (*new_skb) | 211 | if (*new_skb) |
217 | ret = NET_RX_SUCCESS; | 212 | ret = NET_RX_SUCCESS; |
218 | out: | ||
219 | spin_unlock_bh(&bat_priv->orig_hash_lock); | ||
220 | 213 | ||
214 | out: | ||
215 | if (orig_node) | ||
216 | orig_node_free_ref(orig_node); | ||
221 | return ret; | 217 | return ret; |
222 | } | 218 | } |
223 | 219 | ||
224 | int frag_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv, | 220 | int frag_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv, |
225 | struct batman_if *batman_if, uint8_t dstaddr[]) | 221 | struct hard_iface *hard_iface, uint8_t dstaddr[]) |
226 | { | 222 | { |
227 | struct unicast_packet tmp_uc, *unicast_packet; | 223 | struct unicast_packet tmp_uc, *unicast_packet; |
228 | struct sk_buff *frag_skb; | 224 | struct sk_buff *frag_skb; |
@@ -267,12 +263,12 @@ int frag_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv, | |||
267 | frag1->flags = UNI_FRAG_HEAD | large_tail; | 263 | frag1->flags = UNI_FRAG_HEAD | large_tail; |
268 | frag2->flags = large_tail; | 264 | frag2->flags = large_tail; |
269 | 265 | ||
270 | seqno = atomic_add_return(2, &batman_if->frag_seqno); | 266 | seqno = atomic_add_return(2, &hard_iface->frag_seqno); |
271 | frag1->seqno = htons(seqno - 1); | 267 | frag1->seqno = htons(seqno - 1); |
272 | frag2->seqno = htons(seqno); | 268 | frag2->seqno = htons(seqno); |
273 | 269 | ||
274 | send_skb_packet(skb, batman_if, dstaddr); | 270 | send_skb_packet(skb, hard_iface, dstaddr); |
275 | send_skb_packet(frag_skb, batman_if, dstaddr); | 271 | send_skb_packet(frag_skb, hard_iface, dstaddr); |
276 | return NET_RX_SUCCESS; | 272 | return NET_RX_SUCCESS; |
277 | 273 | ||
278 | drop_frag: | 274 | drop_frag: |
@@ -286,40 +282,37 @@ int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv) | |||
286 | { | 282 | { |
287 | struct ethhdr *ethhdr = (struct ethhdr *)skb->data; | 283 | struct ethhdr *ethhdr = (struct ethhdr *)skb->data; |
288 | struct unicast_packet *unicast_packet; | 284 | struct unicast_packet *unicast_packet; |
289 | struct orig_node *orig_node = NULL; | 285 | struct orig_node *orig_node; |
290 | struct batman_if *batman_if; | 286 | struct neigh_node *neigh_node; |
291 | struct neigh_node *router; | ||
292 | int data_len = skb->len; | 287 | int data_len = skb->len; |
293 | uint8_t dstaddr[6]; | 288 | int ret = 1; |
294 | |||
295 | spin_lock_bh(&bat_priv->orig_hash_lock); | ||
296 | 289 | ||
297 | /* get routing information */ | 290 | /* get routing information */ |
298 | if (is_multicast_ether_addr(ethhdr->h_dest)) | 291 | if (is_multicast_ether_addr(ethhdr->h_dest)) { |
299 | orig_node = (struct orig_node *)gw_get_selected(bat_priv); | 292 | orig_node = (struct orig_node *)gw_get_selected(bat_priv); |
293 | if (orig_node) | ||
294 | goto find_router; | ||
295 | } | ||
300 | 296 | ||
301 | /* check for hna host */ | 297 | /* check for hna host - increases orig_node refcount */ |
302 | if (!orig_node) | 298 | orig_node = transtable_search(bat_priv, ethhdr->h_dest); |
303 | orig_node = transtable_search(bat_priv, ethhdr->h_dest); | ||
304 | |||
305 | router = find_router(bat_priv, orig_node, NULL); | ||
306 | |||
307 | if (!router) | ||
308 | goto unlock; | ||
309 | |||
310 | /* don't lock while sending the packets ... we therefore | ||
311 | * copy the required data before sending */ | ||
312 | 299 | ||
313 | batman_if = router->if_incoming; | 300 | find_router: |
314 | memcpy(dstaddr, router->addr, ETH_ALEN); | 301 | /** |
302 | * find_router(): | ||
303 | * - if orig_node is NULL it returns NULL | ||
304 | * - increases neigh_nodes refcount if found. | ||
305 | */ | ||
306 | neigh_node = find_router(bat_priv, orig_node, NULL); | ||
315 | 307 | ||
316 | spin_unlock_bh(&bat_priv->orig_hash_lock); | 308 | if (!neigh_node) |
309 | goto out; | ||
317 | 310 | ||
318 | if (batman_if->if_status != IF_ACTIVE) | 311 | if (neigh_node->if_incoming->if_status != IF_ACTIVE) |
319 | goto dropped; | 312 | goto out; |
320 | 313 | ||
321 | if (my_skb_head_push(skb, sizeof(struct unicast_packet)) < 0) | 314 | if (my_skb_head_push(skb, sizeof(struct unicast_packet)) < 0) |
322 | goto dropped; | 315 | goto out; |
323 | 316 | ||
324 | unicast_packet = (struct unicast_packet *)skb->data; | 317 | unicast_packet = (struct unicast_packet *)skb->data; |
325 | 318 | ||
@@ -333,18 +326,24 @@ int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv) | |||
333 | 326 | ||
334 | if (atomic_read(&bat_priv->fragmentation) && | 327 | if (atomic_read(&bat_priv->fragmentation) && |
335 | data_len + sizeof(struct unicast_packet) > | 328 | data_len + sizeof(struct unicast_packet) > |
336 | batman_if->net_dev->mtu) { | 329 | neigh_node->if_incoming->net_dev->mtu) { |
337 | /* send frag skb decreases ttl */ | 330 | /* send frag skb decreases ttl */ |
338 | unicast_packet->ttl++; | 331 | unicast_packet->ttl++; |
339 | return frag_send_skb(skb, bat_priv, batman_if, | 332 | ret = frag_send_skb(skb, bat_priv, |
340 | dstaddr); | 333 | neigh_node->if_incoming, neigh_node->addr); |
334 | goto out; | ||
341 | } | 335 | } |
342 | send_skb_packet(skb, batman_if, dstaddr); | ||
343 | return 0; | ||
344 | 336 | ||
345 | unlock: | 337 | send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); |
346 | spin_unlock_bh(&bat_priv->orig_hash_lock); | 338 | ret = 0; |
347 | dropped: | 339 | goto out; |
348 | kfree_skb(skb); | 340 | |
349 | return 1; | 341 | out: |
342 | if (neigh_node) | ||
343 | neigh_node_free_ref(neigh_node); | ||
344 | if (orig_node) | ||
345 | orig_node_free_ref(orig_node); | ||
346 | if (ret == 1) | ||
347 | kfree_skb(skb); | ||
348 | return ret; | ||
350 | } | 349 | } |