diff options
Diffstat (limited to 'net/batman-adv/vis.c')
-rw-r--r-- | net/batman-adv/vis.c | 146 |
1 files changed, 80 insertions, 66 deletions
diff --git a/net/batman-adv/vis.c b/net/batman-adv/vis.c index f90212f42082..c39f20cc1ba6 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); |