aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv/vis.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-03-16 19:29:25 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-03-16 19:29:25 -0400
commit7a6362800cb7d1d618a697a650c7aaed3eb39320 (patch)
tree087f9bc6c13ef1fad4b392c5cf9325cd28fa8523 /net/batman-adv/vis.c
parent6445ced8670f37cfc2c5e24a9de9b413dbfc788d (diff)
parentceda86a108671294052cbf51660097b6534672f5 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6: (1480 commits) bonding: enable netpoll without checking link status xfrm: Refcount destination entry on xfrm_lookup net: introduce rx_handler results and logic around that bonding: get rid of IFF_SLAVE_INACTIVE netdev->priv_flag bonding: wrap slave state work net: get rid of multiple bond-related netdevice->priv_flags bonding: register slave pointer for rx_handler be2net: Bump up the version number be2net: Copyright notice change. Update to Emulex instead of ServerEngines e1000e: fix kconfig for crc32 dependency netfilter ebtables: fix xt_AUDIT to work with ebtables xen network backend driver bonding: Improve syslog message at device creation time bonding: Call netif_carrier_off after register_netdevice bonding: Incorrect TX queue offset net_sched: fix ip_tos2prio xfrm: fix __xfrm_route_forward() be2net: Fix UDP packet detected status in RX compl Phonet: fix aligned-mode pipe socket buffer header reserve netxen: support for GbE port settings ... Fix up conflicts in drivers/staging/brcm80211/brcmsmac/wl_mac80211.c with the staging updates.
Diffstat (limited to 'net/batman-adv/vis.c')
-rw-r--r--net/batman-adv/vis.c194
1 files changed, 111 insertions, 83 deletions
diff --git a/net/batman-adv/vis.c b/net/batman-adv/vis.c
index de1022cacaf7..f90212f42082 100644
--- a/net/batman-adv/vis.c
+++ b/net/batman-adv/vis.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) 2008-2010 B.A.T.M.A.N. contributors: 2 * Copyright (C) 2008-2011 B.A.T.M.A.N. contributors:
3 * 3 *
4 * Simon Wunderlich 4 * Simon Wunderlich
5 * 5 *
@@ -68,15 +68,16 @@ static void free_info(struct kref *ref)
68} 68}
69 69
70/* Compare two vis packets, used by the hashing algorithm */ 70/* Compare two vis packets, used by the hashing algorithm */
71static int vis_info_cmp(void *data1, void *data2) 71static int vis_info_cmp(struct hlist_node *node, void *data2)
72{ 72{
73 struct vis_info *d1, *d2; 73 struct vis_info *d1, *d2;
74 struct vis_packet *p1, *p2; 74 struct vis_packet *p1, *p2;
75 d1 = data1; 75
76 d1 = container_of(node, struct vis_info, hash_entry);
76 d2 = data2; 77 d2 = data2;
77 p1 = (struct vis_packet *)d1->skb_packet->data; 78 p1 = (struct vis_packet *)d1->skb_packet->data;
78 p2 = (struct vis_packet *)d2->skb_packet->data; 79 p2 = (struct vis_packet *)d2->skb_packet->data;
79 return compare_orig(p1->vis_orig, p2->vis_orig); 80 return compare_eth(p1->vis_orig, p2->vis_orig);
80} 81}
81 82
82/* hash function to choose an entry in a hash table of given size */ 83/* hash function to choose an entry in a hash table of given size */
@@ -104,6 +105,34 @@ static int vis_info_choose(void *data, int size)
104 return hash % size; 105 return hash % size;
105} 106}
106 107
108static struct vis_info *vis_hash_find(struct bat_priv *bat_priv,
109 void *data)
110{
111 struct hashtable_t *hash = bat_priv->vis_hash;
112 struct hlist_head *head;
113 struct hlist_node *node;
114 struct vis_info *vis_info, *vis_info_tmp = NULL;
115 int index;
116
117 if (!hash)
118 return NULL;
119
120 index = vis_info_choose(data, hash->size);
121 head = &hash->table[index];
122
123 rcu_read_lock();
124 hlist_for_each_entry_rcu(vis_info, node, head, hash_entry) {
125 if (!vis_info_cmp(node, data))
126 continue;
127
128 vis_info_tmp = vis_info;
129 break;
130 }
131 rcu_read_unlock();
132
133 return vis_info_tmp;
134}
135
107/* insert interface to the list of interfaces of one originator, if it 136/* insert interface to the list of interfaces of one originator, if it
108 * does not already exist in the list */ 137 * does not already exist in the list */
109static void vis_data_insert_interface(const uint8_t *interface, 138static void vis_data_insert_interface(const uint8_t *interface,
@@ -114,7 +143,7 @@ static void vis_data_insert_interface(const uint8_t *interface,
114 struct hlist_node *pos; 143 struct hlist_node *pos;
115 144
116 hlist_for_each_entry(entry, pos, if_list, list) { 145 hlist_for_each_entry(entry, pos, if_list, list) {
117 if (compare_orig(entry->addr, (void *)interface)) 146 if (compare_eth(entry->addr, (void *)interface))
118 return; 147 return;
119 } 148 }
120 149
@@ -166,7 +195,7 @@ static ssize_t vis_data_read_entry(char *buff, struct vis_info_entry *entry,
166 /* maximal length: max(4+17+2, 3+17+1+3+2) == 26 */ 195 /* maximal length: max(4+17+2, 3+17+1+3+2) == 26 */
167 if (primary && entry->quality == 0) 196 if (primary && entry->quality == 0)
168 return sprintf(buff, "HNA %pM, ", entry->dest); 197 return sprintf(buff, "HNA %pM, ", entry->dest);
169 else if (compare_orig(entry->src, src)) 198 else if (compare_eth(entry->src, src))
170 return sprintf(buff, "TQ %pM %d, ", entry->dest, 199 return sprintf(buff, "TQ %pM %d, ", entry->dest,
171 entry->quality); 200 entry->quality);
172 201
@@ -175,9 +204,8 @@ static ssize_t vis_data_read_entry(char *buff, struct vis_info_entry *entry,
175 204
176int vis_seq_print_text(struct seq_file *seq, void *offset) 205int vis_seq_print_text(struct seq_file *seq, void *offset)
177{ 206{
178 struct hlist_node *walk; 207 struct hlist_node *node;
179 struct hlist_head *head; 208 struct hlist_head *head;
180 struct element_t *bucket;
181 struct vis_info *info; 209 struct vis_info *info;
182 struct vis_packet *packet; 210 struct vis_packet *packet;
183 struct vis_info_entry *entries; 211 struct vis_info_entry *entries;
@@ -203,8 +231,8 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
203 for (i = 0; i < hash->size; i++) { 231 for (i = 0; i < hash->size; i++) {
204 head = &hash->table[i]; 232 head = &hash->table[i];
205 233
206 hlist_for_each_entry(bucket, walk, head, hlist) { 234 rcu_read_lock();
207 info = bucket->data; 235 hlist_for_each_entry_rcu(info, node, head, hash_entry) {
208 packet = (struct vis_packet *)info->skb_packet->data; 236 packet = (struct vis_packet *)info->skb_packet->data;
209 entries = (struct vis_info_entry *) 237 entries = (struct vis_info_entry *)
210 ((char *)packet + sizeof(struct vis_packet)); 238 ((char *)packet + sizeof(struct vis_packet));
@@ -213,7 +241,7 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
213 if (entries[j].quality == 0) 241 if (entries[j].quality == 0)
214 continue; 242 continue;
215 compare = 243 compare =
216 compare_orig(entries[j].src, packet->vis_orig); 244 compare_eth(entries[j].src, packet->vis_orig);
217 vis_data_insert_interface(entries[j].src, 245 vis_data_insert_interface(entries[j].src,
218 &vis_if_list, 246 &vis_if_list,
219 compare); 247 compare);
@@ -223,7 +251,7 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
223 buf_size += 18 + 26 * packet->entries; 251 buf_size += 18 + 26 * packet->entries;
224 252
225 /* add primary/secondary records */ 253 /* add primary/secondary records */
226 if (compare_orig(entry->addr, packet->vis_orig)) 254 if (compare_eth(entry->addr, packet->vis_orig))
227 buf_size += 255 buf_size +=
228 vis_data_count_prim_sec(&vis_if_list); 256 vis_data_count_prim_sec(&vis_if_list);
229 257
@@ -236,6 +264,7 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
236 kfree(entry); 264 kfree(entry);
237 } 265 }
238 } 266 }
267 rcu_read_unlock();
239 } 268 }
240 269
241 buff = kmalloc(buf_size, GFP_ATOMIC); 270 buff = kmalloc(buf_size, GFP_ATOMIC);
@@ -249,8 +278,8 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
249 for (i = 0; i < hash->size; i++) { 278 for (i = 0; i < hash->size; i++) {
250 head = &hash->table[i]; 279 head = &hash->table[i];
251 280
252 hlist_for_each_entry(bucket, walk, head, hlist) { 281 rcu_read_lock();
253 info = bucket->data; 282 hlist_for_each_entry_rcu(info, node, head, hash_entry) {
254 packet = (struct vis_packet *)info->skb_packet->data; 283 packet = (struct vis_packet *)info->skb_packet->data;
255 entries = (struct vis_info_entry *) 284 entries = (struct vis_info_entry *)
256 ((char *)packet + sizeof(struct vis_packet)); 285 ((char *)packet + sizeof(struct vis_packet));
@@ -259,7 +288,7 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
259 if (entries[j].quality == 0) 288 if (entries[j].quality == 0)
260 continue; 289 continue;
261 compare = 290 compare =
262 compare_orig(entries[j].src, packet->vis_orig); 291 compare_eth(entries[j].src, packet->vis_orig);
263 vis_data_insert_interface(entries[j].src, 292 vis_data_insert_interface(entries[j].src,
264 &vis_if_list, 293 &vis_if_list,
265 compare); 294 compare);
@@ -277,7 +306,7 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
277 entry->primary); 306 entry->primary);
278 307
279 /* add primary/secondary records */ 308 /* add primary/secondary records */
280 if (compare_orig(entry->addr, packet->vis_orig)) 309 if (compare_eth(entry->addr, packet->vis_orig))
281 buff_pos += 310 buff_pos +=
282 vis_data_read_prim_sec(buff + buff_pos, 311 vis_data_read_prim_sec(buff + buff_pos,
283 &vis_if_list); 312 &vis_if_list);
@@ -291,6 +320,7 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
291 kfree(entry); 320 kfree(entry);
292 } 321 }
293 } 322 }
323 rcu_read_unlock();
294 } 324 }
295 325
296 spin_unlock_bh(&bat_priv->vis_hash_lock); 326 spin_unlock_bh(&bat_priv->vis_hash_lock);
@@ -345,7 +375,7 @@ static int recv_list_is_in(struct bat_priv *bat_priv,
345 375
346 spin_lock_bh(&bat_priv->vis_list_lock); 376 spin_lock_bh(&bat_priv->vis_list_lock);
347 list_for_each_entry(entry, recv_list, list) { 377 list_for_each_entry(entry, recv_list, list) {
348 if (memcmp(entry->mac, mac, ETH_ALEN) == 0) { 378 if (compare_eth(entry->mac, mac)) {
349 spin_unlock_bh(&bat_priv->vis_list_lock); 379 spin_unlock_bh(&bat_priv->vis_list_lock);
350 return 1; 380 return 1;
351 } 381 }
@@ -381,8 +411,7 @@ static struct vis_info *add_packet(struct bat_priv *bat_priv,
381 sizeof(struct vis_packet)); 411 sizeof(struct vis_packet));
382 412
383 memcpy(search_packet->vis_orig, vis_packet->vis_orig, ETH_ALEN); 413 memcpy(search_packet->vis_orig, vis_packet->vis_orig, ETH_ALEN);
384 old_info = hash_find(bat_priv->vis_hash, vis_info_cmp, vis_info_choose, 414 old_info = vis_hash_find(bat_priv, &search_elem);
385 &search_elem);
386 kfree_skb(search_elem.skb_packet); 415 kfree_skb(search_elem.skb_packet);
387 416
388 if (old_info) { 417 if (old_info) {
@@ -442,7 +471,7 @@ static struct vis_info *add_packet(struct bat_priv *bat_priv,
442 471
443 /* try to add it */ 472 /* try to add it */
444 hash_added = hash_add(bat_priv->vis_hash, vis_info_cmp, vis_info_choose, 473 hash_added = hash_add(bat_priv->vis_hash, vis_info_cmp, vis_info_choose,
445 info); 474 info, &info->hash_entry);
446 if (hash_added < 0) { 475 if (hash_added < 0) {
447 /* did not work (for some reason) */ 476 /* did not work (for some reason) */
448 kref_put(&info->refcount, free_info); 477 kref_put(&info->refcount, free_info);
@@ -529,9 +558,8 @@ static int find_best_vis_server(struct bat_priv *bat_priv,
529 struct vis_info *info) 558 struct vis_info *info)
530{ 559{
531 struct hashtable_t *hash = bat_priv->orig_hash; 560 struct hashtable_t *hash = bat_priv->orig_hash;
532 struct hlist_node *walk; 561 struct hlist_node *node;
533 struct hlist_head *head; 562 struct hlist_head *head;
534 struct element_t *bucket;
535 struct orig_node *orig_node; 563 struct orig_node *orig_node;
536 struct vis_packet *packet; 564 struct vis_packet *packet;
537 int best_tq = -1, i; 565 int best_tq = -1, i;
@@ -541,16 +569,17 @@ static int find_best_vis_server(struct bat_priv *bat_priv,
541 for (i = 0; i < hash->size; i++) { 569 for (i = 0; i < hash->size; i++) {
542 head = &hash->table[i]; 570 head = &hash->table[i];
543 571
544 hlist_for_each_entry(bucket, walk, head, hlist) { 572 rcu_read_lock();
545 orig_node = bucket->data; 573 hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) {
546 if ((orig_node) && (orig_node->router) && 574 if ((orig_node) && (orig_node->router) &&
547 (orig_node->flags & VIS_SERVER) && 575 (orig_node->flags & VIS_SERVER) &&
548 (orig_node->router->tq_avg > best_tq)) { 576 (orig_node->router->tq_avg > best_tq)) {
549 best_tq = orig_node->router->tq_avg; 577 best_tq = orig_node->router->tq_avg;
550 memcpy(packet->target_orig, orig_node->orig, 578 memcpy(packet->target_orig, orig_node->orig,
551 ETH_ALEN); 579 ETH_ALEN);
552 } 580 }
553 } 581 }
582 rcu_read_unlock();
554 } 583 }
555 584
556 return best_tq; 585 return best_tq;
@@ -573,9 +602,8 @@ static bool vis_packet_full(struct vis_info *info)
573static int generate_vis_packet(struct bat_priv *bat_priv) 602static int generate_vis_packet(struct bat_priv *bat_priv)
574{ 603{
575 struct hashtable_t *hash = bat_priv->orig_hash; 604 struct hashtable_t *hash = bat_priv->orig_hash;
576 struct hlist_node *walk; 605 struct hlist_node *node;
577 struct hlist_head *head; 606 struct hlist_head *head;
578 struct element_t *bucket;
579 struct orig_node *orig_node; 607 struct orig_node *orig_node;
580 struct neigh_node *neigh_node; 608 struct neigh_node *neigh_node;
581 struct vis_info *info = (struct vis_info *)bat_priv->my_vis_info; 609 struct vis_info *info = (struct vis_info *)bat_priv->my_vis_info;
@@ -587,7 +615,6 @@ static int generate_vis_packet(struct bat_priv *bat_priv)
587 info->first_seen = jiffies; 615 info->first_seen = jiffies;
588 packet->vis_type = atomic_read(&bat_priv->vis_mode); 616 packet->vis_type = atomic_read(&bat_priv->vis_mode);
589 617
590 spin_lock_bh(&bat_priv->orig_hash_lock);
591 memcpy(packet->target_orig, broadcast_addr, ETH_ALEN); 618 memcpy(packet->target_orig, broadcast_addr, ETH_ALEN);
592 packet->ttl = TTL; 619 packet->ttl = TTL;
593 packet->seqno = htonl(ntohl(packet->seqno) + 1); 620 packet->seqno = htonl(ntohl(packet->seqno) + 1);
@@ -597,23 +624,21 @@ static int generate_vis_packet(struct bat_priv *bat_priv)
597 if (packet->vis_type == VIS_TYPE_CLIENT_UPDATE) { 624 if (packet->vis_type == VIS_TYPE_CLIENT_UPDATE) {
598 best_tq = find_best_vis_server(bat_priv, info); 625 best_tq = find_best_vis_server(bat_priv, info);
599 626
600 if (best_tq < 0) { 627 if (best_tq < 0)
601 spin_unlock_bh(&bat_priv->orig_hash_lock);
602 return -1; 628 return -1;
603 }
604 } 629 }
605 630
606 for (i = 0; i < hash->size; i++) { 631 for (i = 0; i < hash->size; i++) {
607 head = &hash->table[i]; 632 head = &hash->table[i];
608 633
609 hlist_for_each_entry(bucket, walk, head, hlist) { 634 rcu_read_lock();
610 orig_node = bucket->data; 635 hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) {
611 neigh_node = orig_node->router; 636 neigh_node = orig_node->router;
612 637
613 if (!neigh_node) 638 if (!neigh_node)
614 continue; 639 continue;
615 640
616 if (!compare_orig(neigh_node->addr, orig_node->orig)) 641 if (!compare_eth(neigh_node->addr, orig_node->orig))
617 continue; 642 continue;
618 643
619 if (neigh_node->if_incoming->if_status != IF_ACTIVE) 644 if (neigh_node->if_incoming->if_status != IF_ACTIVE)
@@ -632,23 +657,19 @@ static int generate_vis_packet(struct bat_priv *bat_priv)
632 entry->quality = neigh_node->tq_avg; 657 entry->quality = neigh_node->tq_avg;
633 packet->entries++; 658 packet->entries++;
634 659
635 if (vis_packet_full(info)) { 660 if (vis_packet_full(info))
636 spin_unlock_bh(&bat_priv->orig_hash_lock); 661 goto unlock;
637 return 0;
638 }
639 } 662 }
663 rcu_read_unlock();
640 } 664 }
641 665
642 spin_unlock_bh(&bat_priv->orig_hash_lock);
643
644 hash = bat_priv->hna_local_hash; 666 hash = bat_priv->hna_local_hash;
645 667
646 spin_lock_bh(&bat_priv->hna_lhash_lock); 668 spin_lock_bh(&bat_priv->hna_lhash_lock);
647 for (i = 0; i < hash->size; i++) { 669 for (i = 0; i < hash->size; i++) {
648 head = &hash->table[i]; 670 head = &hash->table[i];
649 671
650 hlist_for_each_entry(bucket, walk, head, hlist) { 672 hlist_for_each_entry(hna_local_entry, node, head, hash_entry) {
651 hna_local_entry = bucket->data;
652 entry = (struct vis_info_entry *) 673 entry = (struct vis_info_entry *)
653 skb_put(info->skb_packet, 674 skb_put(info->skb_packet,
654 sizeof(*entry)); 675 sizeof(*entry));
@@ -666,6 +687,10 @@ static int generate_vis_packet(struct bat_priv *bat_priv)
666 687
667 spin_unlock_bh(&bat_priv->hna_lhash_lock); 688 spin_unlock_bh(&bat_priv->hna_lhash_lock);
668 return 0; 689 return 0;
690
691unlock:
692 rcu_read_unlock();
693 return 0;
669} 694}
670 695
671/* free old vis packets. Must be called with this vis_hash_lock 696/* free old vis packets. Must be called with this vis_hash_lock
@@ -674,25 +699,22 @@ static void purge_vis_packets(struct bat_priv *bat_priv)
674{ 699{
675 int i; 700 int i;
676 struct hashtable_t *hash = bat_priv->vis_hash; 701 struct hashtable_t *hash = bat_priv->vis_hash;
677 struct hlist_node *walk, *safe; 702 struct hlist_node *node, *node_tmp;
678 struct hlist_head *head; 703 struct hlist_head *head;
679 struct element_t *bucket;
680 struct vis_info *info; 704 struct vis_info *info;
681 705
682 for (i = 0; i < hash->size; i++) { 706 for (i = 0; i < hash->size; i++) {
683 head = &hash->table[i]; 707 head = &hash->table[i];
684 708
685 hlist_for_each_entry_safe(bucket, walk, safe, head, hlist) { 709 hlist_for_each_entry_safe(info, node, node_tmp,
686 info = bucket->data; 710 head, hash_entry) {
687
688 /* never purge own data. */ 711 /* never purge own data. */
689 if (info == bat_priv->my_vis_info) 712 if (info == bat_priv->my_vis_info)
690 continue; 713 continue;
691 714
692 if (time_after(jiffies, 715 if (time_after(jiffies,
693 info->first_seen + VIS_TIMEOUT * HZ)) { 716 info->first_seen + VIS_TIMEOUT * HZ)) {
694 hlist_del(walk); 717 hlist_del(node);
695 kfree(bucket);
696 send_list_del(info); 718 send_list_del(info);
697 kref_put(&info->refcount, free_info); 719 kref_put(&info->refcount, free_info);
698 } 720 }
@@ -704,27 +726,24 @@ static void broadcast_vis_packet(struct bat_priv *bat_priv,
704 struct vis_info *info) 726 struct vis_info *info)
705{ 727{
706 struct hashtable_t *hash = bat_priv->orig_hash; 728 struct hashtable_t *hash = bat_priv->orig_hash;
707 struct hlist_node *walk; 729 struct hlist_node *node;
708 struct hlist_head *head; 730 struct hlist_head *head;
709 struct element_t *bucket;
710 struct orig_node *orig_node; 731 struct orig_node *orig_node;
711 struct vis_packet *packet; 732 struct vis_packet *packet;
712 struct sk_buff *skb; 733 struct sk_buff *skb;
713 struct batman_if *batman_if; 734 struct hard_iface *hard_iface;
714 uint8_t dstaddr[ETH_ALEN]; 735 uint8_t dstaddr[ETH_ALEN];
715 int i; 736 int i;
716 737
717 738
718 spin_lock_bh(&bat_priv->orig_hash_lock);
719 packet = (struct vis_packet *)info->skb_packet->data; 739 packet = (struct vis_packet *)info->skb_packet->data;
720 740
721 /* send to all routers in range. */ 741 /* send to all routers in range. */
722 for (i = 0; i < hash->size; i++) { 742 for (i = 0; i < hash->size; i++) {
723 head = &hash->table[i]; 743 head = &hash->table[i];
724 744
725 hlist_for_each_entry(bucket, walk, head, hlist) { 745 rcu_read_lock();
726 orig_node = bucket->data; 746 hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) {
727
728 /* if it's a vis server and reachable, send it. */ 747 /* if it's a vis server and reachable, send it. */
729 if ((!orig_node) || (!orig_node->router)) 748 if ((!orig_node) || (!orig_node->router))
730 continue; 749 continue;
@@ -737,54 +756,61 @@ static void broadcast_vis_packet(struct bat_priv *bat_priv,
737 continue; 756 continue;
738 757
739 memcpy(packet->target_orig, orig_node->orig, ETH_ALEN); 758 memcpy(packet->target_orig, orig_node->orig, ETH_ALEN);
740 batman_if = orig_node->router->if_incoming; 759 hard_iface = orig_node->router->if_incoming;
741 memcpy(dstaddr, orig_node->router->addr, ETH_ALEN); 760 memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
742 spin_unlock_bh(&bat_priv->orig_hash_lock);
743 761
744 skb = skb_clone(info->skb_packet, GFP_ATOMIC); 762 skb = skb_clone(info->skb_packet, GFP_ATOMIC);
745 if (skb) 763 if (skb)
746 send_skb_packet(skb, batman_if, dstaddr); 764 send_skb_packet(skb, hard_iface, dstaddr);
747 765
748 spin_lock_bh(&bat_priv->orig_hash_lock);
749 } 766 }
750 767 rcu_read_unlock();
751 } 768 }
752
753 spin_unlock_bh(&bat_priv->orig_hash_lock);
754} 769}
755 770
756static void unicast_vis_packet(struct bat_priv *bat_priv, 771static void unicast_vis_packet(struct bat_priv *bat_priv,
757 struct vis_info *info) 772 struct vis_info *info)
758{ 773{
759 struct orig_node *orig_node; 774 struct orig_node *orig_node;
775 struct neigh_node *neigh_node = NULL;
760 struct sk_buff *skb; 776 struct sk_buff *skb;
761 struct vis_packet *packet; 777 struct vis_packet *packet;
762 struct batman_if *batman_if;
763 uint8_t dstaddr[ETH_ALEN];
764 778
765 spin_lock_bh(&bat_priv->orig_hash_lock);
766 packet = (struct vis_packet *)info->skb_packet->data; 779 packet = (struct vis_packet *)info->skb_packet->data;
767 orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash,
768 compare_orig, choose_orig,
769 packet->target_orig));
770 780
771 if ((!orig_node) || (!orig_node->router)) 781 rcu_read_lock();
772 goto out; 782 orig_node = orig_hash_find(bat_priv, packet->target_orig);
773 783
774 /* don't lock while sending the packets ... we therefore 784 if (!orig_node)
775 * copy the required data before sending */ 785 goto unlock;
776 batman_if = orig_node->router->if_incoming; 786
777 memcpy(dstaddr, orig_node->router->addr, ETH_ALEN); 787 neigh_node = orig_node->router;
778 spin_unlock_bh(&bat_priv->orig_hash_lock); 788
789 if (!neigh_node)
790 goto unlock;
791
792 if (!atomic_inc_not_zero(&neigh_node->refcount)) {
793 neigh_node = NULL;
794 goto unlock;
795 }
796
797 rcu_read_unlock();
779 798
780 skb = skb_clone(info->skb_packet, GFP_ATOMIC); 799 skb = skb_clone(info->skb_packet, GFP_ATOMIC);
781 if (skb) 800 if (skb)
782 send_skb_packet(skb, batman_if, dstaddr); 801 send_skb_packet(skb, neigh_node->if_incoming,
802 neigh_node->addr);
783 803
784 return; 804 goto out;
785 805
806unlock:
807 rcu_read_unlock();
786out: 808out:
787 spin_unlock_bh(&bat_priv->orig_hash_lock); 809 if (neigh_node)
810 neigh_node_free_ref(neigh_node);
811 if (orig_node)
812 orig_node_free_ref(orig_node);
813 return;
788} 814}
789 815
790/* only send one vis packet. called from send_vis_packets() */ 816/* only send one vis packet. called from send_vis_packets() */
@@ -896,7 +922,8 @@ int vis_init(struct bat_priv *bat_priv)
896 INIT_LIST_HEAD(&bat_priv->vis_send_list); 922 INIT_LIST_HEAD(&bat_priv->vis_send_list);
897 923
898 hash_added = hash_add(bat_priv->vis_hash, vis_info_cmp, vis_info_choose, 924 hash_added = hash_add(bat_priv->vis_hash, vis_info_cmp, vis_info_choose,
899 bat_priv->my_vis_info); 925 bat_priv->my_vis_info,
926 &bat_priv->my_vis_info->hash_entry);
900 if (hash_added < 0) { 927 if (hash_added < 0) {
901 pr_err("Can't add own vis packet into hash\n"); 928 pr_err("Can't add own vis packet into hash\n");
902 /* not in hash, need to remove it manually. */ 929 /* not in hash, need to remove it manually. */
@@ -918,10 +945,11 @@ err:
918} 945}
919 946
920/* Decrease the reference count on a hash item info */ 947/* Decrease the reference count on a hash item info */
921static void free_info_ref(void *data, void *arg) 948static void free_info_ref(struct hlist_node *node, void *arg)
922{ 949{
923 struct vis_info *info = data; 950 struct vis_info *info;
924 951
952 info = container_of(node, struct vis_info, hash_entry);
925 send_list_del(info); 953 send_list_del(info);
926 kref_put(&info->refcount, free_info); 954 kref_put(&info->refcount, free_info);
927} 955}