diff options
author | David S. Miller <davem@davemloft.net> | 2011-03-07 11:37:13 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-03-07 11:37:13 +0300 |
commit | b8cec4a415e807a2f8679efa89558a040a7003de (patch) | |
tree | 1a5fc7c31c4f8b55ea850599bb7309871165f48e /net/batman-adv/unicast.c | |
parent | 5e2b61f78411be25f0b84f97d5b5d312f184dfd1 (diff) | |
parent | e44d8fe2b5c27ecc230f886d4cc49fcbd86f87a0 (diff) | |
download | linux-b8cec4a415e807a2f8679efa89558a040a7003de.tar.xz |
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, (struct unicast_frag_packet *)skb->data; *new_skb = NULL; - spin_lock_bh(&bat_priv->orig_hash_lock); - orig_node = ((struct orig_node *) - hash_find(bat_priv->orig_hash, compare_orig, choose_orig, - unicast_packet->orig)); - if (!orig_node) { - pr_debug("couldn't find originator in orig_hash\n"); + orig_node = orig_hash_find(bat_priv, unicast_packet->orig); + if (!orig_node) goto out; - } orig_node->last_frag_packet = jiffies; @@ -215,14 +210,15 @@ int frag_reassemble_skb(struct sk_buff *skb, struct bat_priv *bat_priv, /* if not, merge failed */ if (*new_skb) ret = NET_RX_SUCCESS; -out: - spin_unlock_bh(&bat_priv->orig_hash_lock); +out: + if (orig_node) + orig_node_free_ref(orig_node); return ret; } int frag_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv, - struct batman_if *batman_if, uint8_t dstaddr[]) + struct hard_iface *hard_iface, uint8_t dstaddr[]) { struct unicast_packet tmp_uc, *unicast_packet; struct sk_buff *frag_skb; @@ -267,12 +263,12 @@ int frag_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv, frag1->flags = UNI_FRAG_HEAD | large_tail; frag2->flags = large_tail; - seqno = atomic_add_return(2, &batman_if->frag_seqno); + seqno = atomic_add_return(2, &hard_iface->frag_seqno); frag1->seqno = htons(seqno - 1); frag2->seqno = htons(seqno); - send_skb_packet(skb, batman_if, dstaddr); - send_skb_packet(frag_skb, batman_if, dstaddr); + send_skb_packet(skb, hard_iface, dstaddr); + send_skb_packet(frag_skb, hard_iface, dstaddr); return NET_RX_SUCCESS; drop_frag: @@ -286,40 +282,37 @@ int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv) { struct ethhdr *ethhdr = (struct ethhdr *)skb->data; struct unicast_packet *unicast_packet; - struct orig_node *orig_node = NULL; - struct batman_if *batman_if; - struct neigh_node *router; + struct orig_node *orig_node; + struct neigh_node *neigh_node; int data_len = skb->len; - uint8_t dstaddr[6]; - - spin_lock_bh(&bat_priv->orig_hash_lock); + int ret = 1; /* get routing information */ - if (is_multicast_ether_addr(ethhdr->h_dest)) + if (is_multicast_ether_addr(ethhdr->h_dest)) { orig_node = (struct orig_node *)gw_get_selected(bat_priv); + if (orig_node) + goto find_router; + } - /* check for hna host */ - if (!orig_node) - orig_node = transtable_search(bat_priv, ethhdr->h_dest); - - router = find_router(bat_priv, orig_node, NULL); - - if (!router) - goto unlock; - - /* don't lock while sending the packets ... we therefore - * copy the required data before sending */ + /* check for hna host - increases orig_node refcount */ + orig_node = transtable_search(bat_priv, ethhdr->h_dest); - batman_if = router->if_incoming; - memcpy(dstaddr, router->addr, ETH_ALEN); +find_router: + /** + * find_router(): + * - if orig_node is NULL it returns NULL + * - increases neigh_nodes refcount if found. + */ + neigh_node = find_router(bat_priv, orig_node, NULL); - spin_unlock_bh(&bat_priv->orig_hash_lock); + if (!neigh_node) + goto out; - if (batman_if->if_status != IF_ACTIVE) - goto dropped; + if (neigh_node->if_incoming->if_status != IF_ACTIVE) + goto out; if (my_skb_head_push(skb, sizeof(struct unicast_packet)) < 0) - goto dropped; + goto out; unicast_packet = (struct unicast_packet *)skb->data; @@ -333,18 +326,24 @@ int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv) if (atomic_read(&bat_priv->fragmentation) && data_len + sizeof(struct unicast_packet) > - batman_if->net_dev->mtu) { + neigh_node->if_incoming->net_dev->mtu) { /* send frag skb decreases ttl */ unicast_packet->ttl++; - return frag_send_skb(skb, bat_priv, batman_if, - dstaddr); + ret = frag_send_skb(skb, bat_priv, + neigh_node->if_incoming, neigh_node->addr); + goto out; } - send_skb_packet(skb, batman_if, dstaddr); - return 0; -unlock: - spin_unlock_bh(&bat_priv->orig_hash_lock); -dropped: - kfree_skb(skb); - return 1; + send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); + ret = 0; + goto out; + +out: + if (neigh_node) + neigh_node_free_ref(neigh_node); + if (orig_node) + orig_node_free_ref(orig_node); + if (ret == 1) + kfree_skb(skb); + return ret; } |