summaryrefslogtreecommitdiffstats
path: root/net/batman-adv/vis.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/batman-adv/vis.c')
-rw-r--r--net/batman-adv/vis.c146
1 files changed, 80 insertions, 66 deletions
diff --git a/net/batman-adv/vis.c b/net/batman-adv/vis.c
index f90212f..c39f20c 100644
--- a/net/batman-adv/vis.c
+++ b/net/batman-adv/vis.c
@@ -194,7 +194,7 @@ static ssize_t vis_data_read_entry(char *buff, struct vis_info_entry *entry,
{
/* maximal length: max(4+17+2, 3+17+1+3+2) == 26 */
if (primary && entry->quality == 0)
- return sprintf(buff, "HNA %pM, ", entry->dest);
+ return sprintf(buff, "TT %pM, ", entry->dest);
else if (compare_eth(entry->src, src))
return sprintf(buff, "TQ %pM %d, ", entry->dest,
entry->quality);
@@ -204,6 +204,7 @@ static ssize_t vis_data_read_entry(char *buff, struct vis_info_entry *entry,
int vis_seq_print_text(struct seq_file *seq, void *offset)
{
+ struct hard_iface *primary_if;
struct hlist_node *node;
struct hlist_head *head;
struct vis_info *info;
@@ -215,15 +216,18 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
HLIST_HEAD(vis_if_list);
struct if_list_entry *entry;
struct hlist_node *pos, *n;
- int i, j;
+ int i, j, ret = 0;
int vis_server = atomic_read(&bat_priv->vis_mode);
size_t buff_pos, buf_size;
char *buff;
int compare;
- if ((!bat_priv->primary_if) ||
- (vis_server == VIS_TYPE_CLIENT_UPDATE))
- return 0;
+ primary_if = primary_if_get_selected(bat_priv);
+ if (!primary_if)
+ goto out;
+
+ if (vis_server == VIS_TYPE_CLIENT_UPDATE)
+ goto out;
buf_size = 1;
/* Estimate length */
@@ -270,7 +274,8 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
buff = kmalloc(buf_size, GFP_ATOMIC);
if (!buff) {
spin_unlock_bh(&bat_priv->vis_hash_lock);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto out;
}
buff[0] = '\0';
buff_pos = 0;
@@ -328,7 +333,10 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
seq_printf(seq, "%s", buff);
kfree(buff);
- return 0;
+out:
+ if (primary_if)
+ hardif_free_ref(primary_if);
+ return ret;
}
/* add the info packet to the send list, if it was not
@@ -558,6 +566,7 @@ static int find_best_vis_server(struct bat_priv *bat_priv,
struct vis_info *info)
{
struct hashtable_t *hash = bat_priv->orig_hash;
+ struct neigh_node *router;
struct hlist_node *node;
struct hlist_head *head;
struct orig_node *orig_node;
@@ -571,13 +580,17 @@ static int find_best_vis_server(struct bat_priv *bat_priv,
rcu_read_lock();
hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) {
- if ((orig_node) && (orig_node->router) &&
- (orig_node->flags & VIS_SERVER) &&
- (orig_node->router->tq_avg > best_tq)) {
- best_tq = orig_node->router->tq_avg;
+ router = orig_node_get_router(orig_node);
+ if (!router)
+ continue;
+
+ if ((orig_node->flags & VIS_SERVER) &&
+ (router->tq_avg > best_tq)) {
+ best_tq = router->tq_avg;
memcpy(packet->target_orig, orig_node->orig,
ETH_ALEN);
}
+ neigh_node_free_ref(router);
}
rcu_read_unlock();
}
@@ -605,11 +618,11 @@ static int generate_vis_packet(struct bat_priv *bat_priv)
struct hlist_node *node;
struct hlist_head *head;
struct orig_node *orig_node;
- struct neigh_node *neigh_node;
+ struct neigh_node *router;
struct vis_info *info = (struct vis_info *)bat_priv->my_vis_info;
struct vis_packet *packet = (struct vis_packet *)info->skb_packet->data;
struct vis_info_entry *entry;
- struct hna_local_entry *hna_local_entry;
+ struct tt_local_entry *tt_local_entry;
int best_tq = -1, i;
info->first_seen = jiffies;
@@ -633,59 +646,61 @@ static int generate_vis_packet(struct bat_priv *bat_priv)
rcu_read_lock();
hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) {
- neigh_node = orig_node->router;
-
- if (!neigh_node)
+ router = orig_node_get_router(orig_node);
+ if (!router)
continue;
- if (!compare_eth(neigh_node->addr, orig_node->orig))
- continue;
+ if (!compare_eth(router->addr, orig_node->orig))
+ goto next;
- if (neigh_node->if_incoming->if_status != IF_ACTIVE)
- continue;
+ if (router->if_incoming->if_status != IF_ACTIVE)
+ goto next;
- if (neigh_node->tq_avg < 1)
- continue;
+ if (router->tq_avg < 1)
+ goto next;
/* fill one entry into buffer. */
entry = (struct vis_info_entry *)
skb_put(info->skb_packet, sizeof(*entry));
memcpy(entry->src,
- neigh_node->if_incoming->net_dev->dev_addr,
+ router->if_incoming->net_dev->dev_addr,
ETH_ALEN);
memcpy(entry->dest, orig_node->orig, ETH_ALEN);
- entry->quality = neigh_node->tq_avg;
+ entry->quality = router->tq_avg;
packet->entries++;
+next:
+ neigh_node_free_ref(router);
+
if (vis_packet_full(info))
goto unlock;
}
rcu_read_unlock();
}
- hash = bat_priv->hna_local_hash;
+ hash = bat_priv->tt_local_hash;
- spin_lock_bh(&bat_priv->hna_lhash_lock);
+ spin_lock_bh(&bat_priv->tt_lhash_lock);
for (i = 0; i < hash->size; i++) {
head = &hash->table[i];
- hlist_for_each_entry(hna_local_entry, node, head, hash_entry) {
+ hlist_for_each_entry(tt_local_entry, node, head, hash_entry) {
entry = (struct vis_info_entry *)
skb_put(info->skb_packet,
sizeof(*entry));
memset(entry->src, 0, ETH_ALEN);
- memcpy(entry->dest, hna_local_entry->addr, ETH_ALEN);
- entry->quality = 0; /* 0 means HNA */
+ memcpy(entry->dest, tt_local_entry->addr, ETH_ALEN);
+ entry->quality = 0; /* 0 means TT */
packet->entries++;
if (vis_packet_full(info)) {
- spin_unlock_bh(&bat_priv->hna_lhash_lock);
+ spin_unlock_bh(&bat_priv->tt_lhash_lock);
return 0;
}
}
}
- spin_unlock_bh(&bat_priv->hna_lhash_lock);
+ spin_unlock_bh(&bat_priv->tt_lhash_lock);
return 0;
unlock:
@@ -725,6 +740,7 @@ static void purge_vis_packets(struct bat_priv *bat_priv)
static void broadcast_vis_packet(struct bat_priv *bat_priv,
struct vis_info *info)
{
+ struct neigh_node *router;
struct hashtable_t *hash = bat_priv->orig_hash;
struct hlist_node *node;
struct hlist_head *head;
@@ -745,19 +761,26 @@ static void broadcast_vis_packet(struct bat_priv *bat_priv,
rcu_read_lock();
hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) {
/* if it's a vis server and reachable, send it. */
- if ((!orig_node) || (!orig_node->router))
- continue;
if (!(orig_node->flags & VIS_SERVER))
continue;
+
+ router = orig_node_get_router(orig_node);
+ if (!router)
+ continue;
+
/* don't send it if we already received the packet from
- * this node. */
+ * this node. */
if (recv_list_is_in(bat_priv, &info->recv_list,
- orig_node->orig))
+ orig_node->orig)) {
+ neigh_node_free_ref(router);
continue;
+ }
memcpy(packet->target_orig, orig_node->orig, ETH_ALEN);
- hard_iface = orig_node->router->if_incoming;
- memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
+ hard_iface = router->if_incoming;
+ memcpy(dstaddr, router->addr, ETH_ALEN);
+
+ neigh_node_free_ref(router);
skb = skb_clone(info->skb_packet, GFP_ATOMIC);
if (skb)
@@ -772,60 +795,48 @@ static void unicast_vis_packet(struct bat_priv *bat_priv,
struct vis_info *info)
{
struct orig_node *orig_node;
- struct neigh_node *neigh_node = NULL;
+ struct neigh_node *router = NULL;
struct sk_buff *skb;
struct vis_packet *packet;
packet = (struct vis_packet *)info->skb_packet->data;
- rcu_read_lock();
orig_node = orig_hash_find(bat_priv, packet->target_orig);
-
if (!orig_node)
- goto unlock;
-
- neigh_node = orig_node->router;
+ goto out;
- if (!neigh_node)
- goto unlock;
-
- if (!atomic_inc_not_zero(&neigh_node->refcount)) {
- neigh_node = NULL;
- goto unlock;
- }
-
- rcu_read_unlock();
+ router = orig_node_get_router(orig_node);
+ if (!router)
+ goto out;
skb = skb_clone(info->skb_packet, GFP_ATOMIC);
if (skb)
- send_skb_packet(skb, neigh_node->if_incoming,
- neigh_node->addr);
+ send_skb_packet(skb, router->if_incoming, router->addr);
- goto out;
-
-unlock:
- rcu_read_unlock();
out:
- if (neigh_node)
- neigh_node_free_ref(neigh_node);
+ if (router)
+ neigh_node_free_ref(router);
if (orig_node)
orig_node_free_ref(orig_node);
- return;
}
/* only send one vis packet. called from send_vis_packets() */
static void send_vis_packet(struct bat_priv *bat_priv, struct vis_info *info)
{
+ struct hard_iface *primary_if;
struct vis_packet *packet;
+ primary_if = primary_if_get_selected(bat_priv);
+ if (!primary_if)
+ goto out;
+
packet = (struct vis_packet *)info->skb_packet->data;
if (packet->ttl < 2) {
pr_debug("Error - can't send vis packet: ttl exceeded\n");
- return;
+ goto out;
}
- memcpy(packet->sender_orig, bat_priv->primary_if->net_dev->dev_addr,
- ETH_ALEN);
+ memcpy(packet->sender_orig, primary_if->net_dev->dev_addr, ETH_ALEN);
packet->ttl--;
if (is_broadcast_ether_addr(packet->target_orig))
@@ -833,6 +844,10 @@ static void send_vis_packet(struct bat_priv *bat_priv, struct vis_info *info)
else
unicast_vis_packet(bat_priv, info);
packet->ttl++; /* restore TTL */
+
+out:
+ if (primary_if)
+ hardif_free_ref(primary_if);
}
/* called from timer; send (and maybe generate) vis packet. */
@@ -859,8 +874,7 @@ static void send_vis_packets(struct work_struct *work)
kref_get(&info->refcount);
spin_unlock_bh(&bat_priv->vis_hash_lock);
- if (bat_priv->primary_if)
- send_vis_packet(bat_priv, info);
+ send_vis_packet(bat_priv, info);
spin_lock_bh(&bat_priv->vis_hash_lock);
send_list_del(info);
OpenPOWER on IntegriCloud