aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv/unicast.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2011-03-07 03:37:13 -0500
committerDavid S. Miller <davem@davemloft.net>2011-03-07 03:37:13 -0500
commitb8cec4a415e807a2f8679efa89558a040a7003de (patch)
tree1a5fc7c31c4f8b55ea850599bb7309871165f48e /net/batman-adv/unicast.c
parent5e2b61f78411be25f0b84f97d5b5d312f184dfd1 (diff)
parente44d8fe2b5c27ecc230f886d4cc49fcbd86f87a0 (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.c93
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;
218out:
219 spin_unlock_bh(&bat_priv->orig_hash_lock);
220 213
214out:
215 if (orig_node)
216 orig_node_free_ref(orig_node);
221 return ret; 217 return ret;
222} 218}
223 219
224int frag_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv, 220int 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
278drop_frag: 274drop_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; 300find_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
345unlock: 337 send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
346 spin_unlock_bh(&bat_priv->orig_hash_lock); 338 ret = 0;
347dropped: 339 goto out;
348 kfree_skb(skb); 340
349 return 1; 341out:
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}