summaryrefslogtreecommitdiffstats
path: root/net/batman-adv/unicast.c
diff options
context:
space:
mode:
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,
(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;
}