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, | |||
194 | { | 194 | { |
195 | /* 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 */ |
196 | if (primary && entry->quality == 0) | 196 | if (primary && entry->quality == 0) |
197 | return sprintf(buff, "HNA %pM, ", entry->dest); | 197 | return sprintf(buff, "TT %pM, ", entry->dest); |
198 | else if (compare_eth(entry->src, src)) | 198 | else if (compare_eth(entry->src, src)) |
199 | return sprintf(buff, "TQ %pM %d, ", entry->dest, | 199 | return sprintf(buff, "TQ %pM %d, ", entry->dest, |
200 | entry->quality); | 200 | entry->quality); |
@@ -204,6 +204,7 @@ static ssize_t vis_data_read_entry(char *buff, struct vis_info_entry *entry, | |||
204 | 204 | ||
205 | int vis_seq_print_text(struct seq_file *seq, void *offset) | 205 | int vis_seq_print_text(struct seq_file *seq, void *offset) |
206 | { | 206 | { |
207 | struct hard_iface *primary_if; | ||
207 | struct hlist_node *node; | 208 | struct hlist_node *node; |
208 | struct hlist_head *head; | 209 | struct hlist_head *head; |
209 | struct vis_info *info; | 210 | struct vis_info *info; |
@@ -215,15 +216,18 @@ int vis_seq_print_text(struct seq_file *seq, void *offset) | |||
215 | HLIST_HEAD(vis_if_list); | 216 | HLIST_HEAD(vis_if_list); |
216 | struct if_list_entry *entry; | 217 | struct if_list_entry *entry; |
217 | struct hlist_node *pos, *n; | 218 | struct hlist_node *pos, *n; |
218 | int i, j; | 219 | int i, j, ret = 0; |
219 | int vis_server = atomic_read(&bat_priv->vis_mode); | 220 | int vis_server = atomic_read(&bat_priv->vis_mode); |
220 | size_t buff_pos, buf_size; | 221 | size_t buff_pos, buf_size; |
221 | char *buff; | 222 | char *buff; |
222 | int compare; | 223 | int compare; |
223 | 224 | ||
224 | if ((!bat_priv->primary_if) || | 225 | primary_if = primary_if_get_selected(bat_priv); |
225 | (vis_server == VIS_TYPE_CLIENT_UPDATE)) | 226 | if (!primary_if) |
226 | return 0; | 227 | goto out; |
228 | |||
229 | if (vis_server == VIS_TYPE_CLIENT_UPDATE) | ||
230 | goto out; | ||
227 | 231 | ||
228 | buf_size = 1; | 232 | buf_size = 1; |
229 | /* Estimate length */ | 233 | /* Estimate length */ |
@@ -270,7 +274,8 @@ int vis_seq_print_text(struct seq_file *seq, void *offset) | |||
270 | buff = kmalloc(buf_size, GFP_ATOMIC); | 274 | buff = kmalloc(buf_size, GFP_ATOMIC); |
271 | if (!buff) { | 275 | if (!buff) { |
272 | spin_unlock_bh(&bat_priv->vis_hash_lock); | 276 | spin_unlock_bh(&bat_priv->vis_hash_lock); |
273 | return -ENOMEM; | 277 | ret = -ENOMEM; |
278 | goto out; | ||
274 | } | 279 | } |
275 | buff[0] = '\0'; | 280 | buff[0] = '\0'; |
276 | buff_pos = 0; | 281 | buff_pos = 0; |
@@ -328,7 +333,10 @@ int vis_seq_print_text(struct seq_file *seq, void *offset) | |||
328 | seq_printf(seq, "%s", buff); | 333 | seq_printf(seq, "%s", buff); |
329 | kfree(buff); | 334 | kfree(buff); |
330 | 335 | ||
331 | return 0; | 336 | out: |
337 | if (primary_if) | ||
338 | hardif_free_ref(primary_if); | ||
339 | return ret; | ||
332 | } | 340 | } |
333 | 341 | ||
334 | /* add the info packet to the send list, if it was not | 342 | /* 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, | |||
558 | struct vis_info *info) | 566 | struct vis_info *info) |
559 | { | 567 | { |
560 | struct hashtable_t *hash = bat_priv->orig_hash; | 568 | struct hashtable_t *hash = bat_priv->orig_hash; |
569 | struct neigh_node *router; | ||
561 | struct hlist_node *node; | 570 | struct hlist_node *node; |
562 | struct hlist_head *head; | 571 | struct hlist_head *head; |
563 | struct orig_node *orig_node; | 572 | struct orig_node *orig_node; |
@@ -571,13 +580,17 @@ static int find_best_vis_server(struct bat_priv *bat_priv, | |||
571 | 580 | ||
572 | rcu_read_lock(); | 581 | rcu_read_lock(); |
573 | hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) { | 582 | hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) { |
574 | if ((orig_node) && (orig_node->router) && | 583 | router = orig_node_get_router(orig_node); |
575 | (orig_node->flags & VIS_SERVER) && | 584 | if (!router) |
576 | (orig_node->router->tq_avg > best_tq)) { | 585 | continue; |
577 | best_tq = orig_node->router->tq_avg; | 586 | |
587 | if ((orig_node->flags & VIS_SERVER) && | ||
588 | (router->tq_avg > best_tq)) { | ||
589 | best_tq = router->tq_avg; | ||
578 | memcpy(packet->target_orig, orig_node->orig, | 590 | memcpy(packet->target_orig, orig_node->orig, |
579 | ETH_ALEN); | 591 | ETH_ALEN); |
580 | } | 592 | } |
593 | neigh_node_free_ref(router); | ||
581 | } | 594 | } |
582 | rcu_read_unlock(); | 595 | rcu_read_unlock(); |
583 | } | 596 | } |
@@ -605,11 +618,11 @@ static int generate_vis_packet(struct bat_priv *bat_priv) | |||
605 | struct hlist_node *node; | 618 | struct hlist_node *node; |
606 | struct hlist_head *head; | 619 | struct hlist_head *head; |
607 | struct orig_node *orig_node; | 620 | struct orig_node *orig_node; |
608 | struct neigh_node *neigh_node; | 621 | struct neigh_node *router; |
609 | struct vis_info *info = (struct vis_info *)bat_priv->my_vis_info; | 622 | struct vis_info *info = (struct vis_info *)bat_priv->my_vis_info; |
610 | struct vis_packet *packet = (struct vis_packet *)info->skb_packet->data; | 623 | struct vis_packet *packet = (struct vis_packet *)info->skb_packet->data; |
611 | struct vis_info_entry *entry; | 624 | struct vis_info_entry *entry; |
612 | struct hna_local_entry *hna_local_entry; | 625 | struct tt_local_entry *tt_local_entry; |
613 | int best_tq = -1, i; | 626 | int best_tq = -1, i; |
614 | 627 | ||
615 | info->first_seen = jiffies; | 628 | info->first_seen = jiffies; |
@@ -633,59 +646,61 @@ static int generate_vis_packet(struct bat_priv *bat_priv) | |||
633 | 646 | ||
634 | rcu_read_lock(); | 647 | rcu_read_lock(); |
635 | hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) { | 648 | hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) { |
636 | neigh_node = orig_node->router; | 649 | router = orig_node_get_router(orig_node); |
637 | 650 | if (!router) | |
638 | if (!neigh_node) | ||
639 | continue; | 651 | continue; |
640 | 652 | ||
641 | if (!compare_eth(neigh_node->addr, orig_node->orig)) | 653 | if (!compare_eth(router->addr, orig_node->orig)) |
642 | continue; | 654 | goto next; |
643 | 655 | ||
644 | if (neigh_node->if_incoming->if_status != IF_ACTIVE) | 656 | if (router->if_incoming->if_status != IF_ACTIVE) |
645 | continue; | 657 | goto next; |
646 | 658 | ||
647 | if (neigh_node->tq_avg < 1) | 659 | if (router->tq_avg < 1) |
648 | continue; | 660 | goto next; |
649 | 661 | ||
650 | /* fill one entry into buffer. */ | 662 | /* fill one entry into buffer. */ |
651 | entry = (struct vis_info_entry *) | 663 | entry = (struct vis_info_entry *) |
652 | skb_put(info->skb_packet, sizeof(*entry)); | 664 | skb_put(info->skb_packet, sizeof(*entry)); |
653 | memcpy(entry->src, | 665 | memcpy(entry->src, |
654 | neigh_node->if_incoming->net_dev->dev_addr, | 666 | router->if_incoming->net_dev->dev_addr, |
655 | ETH_ALEN); | 667 | ETH_ALEN); |
656 | memcpy(entry->dest, orig_node->orig, ETH_ALEN); | 668 | memcpy(entry->dest, orig_node->orig, ETH_ALEN); |
657 | entry->quality = neigh_node->tq_avg; | 669 | entry->quality = router->tq_avg; |
658 | packet->entries++; | 670 | packet->entries++; |
659 | 671 | ||
672 | next: | ||
673 | neigh_node_free_ref(router); | ||
674 | |||
660 | if (vis_packet_full(info)) | 675 | if (vis_packet_full(info)) |
661 | goto unlock; | 676 | goto unlock; |
662 | } | 677 | } |
663 | rcu_read_unlock(); | 678 | rcu_read_unlock(); |
664 | } | 679 | } |
665 | 680 | ||
666 | hash = bat_priv->hna_local_hash; | 681 | hash = bat_priv->tt_local_hash; |
667 | 682 | ||
668 | spin_lock_bh(&bat_priv->hna_lhash_lock); | 683 | spin_lock_bh(&bat_priv->tt_lhash_lock); |
669 | for (i = 0; i < hash->size; i++) { | 684 | for (i = 0; i < hash->size; i++) { |
670 | head = &hash->table[i]; | 685 | head = &hash->table[i]; |
671 | 686 | ||
672 | hlist_for_each_entry(hna_local_entry, node, head, hash_entry) { | 687 | hlist_for_each_entry(tt_local_entry, node, head, hash_entry) { |
673 | entry = (struct vis_info_entry *) | 688 | entry = (struct vis_info_entry *) |
674 | skb_put(info->skb_packet, | 689 | skb_put(info->skb_packet, |
675 | sizeof(*entry)); | 690 | sizeof(*entry)); |
676 | memset(entry->src, 0, ETH_ALEN); | 691 | memset(entry->src, 0, ETH_ALEN); |
677 | memcpy(entry->dest, hna_local_entry->addr, ETH_ALEN); | 692 | memcpy(entry->dest, tt_local_entry->addr, ETH_ALEN); |
678 | entry->quality = 0; /* 0 means HNA */ | 693 | entry->quality = 0; /* 0 means TT */ |
679 | packet->entries++; | 694 | packet->entries++; |
680 | 695 | ||
681 | if (vis_packet_full(info)) { | 696 | if (vis_packet_full(info)) { |
682 | spin_unlock_bh(&bat_priv->hna_lhash_lock); | 697 | spin_unlock_bh(&bat_priv->tt_lhash_lock); |
683 | return 0; | 698 | return 0; |
684 | } | 699 | } |
685 | } | 700 | } |
686 | } | 701 | } |
687 | 702 | ||
688 | spin_unlock_bh(&bat_priv->hna_lhash_lock); | 703 | spin_unlock_bh(&bat_priv->tt_lhash_lock); |
689 | return 0; | 704 | return 0; |
690 | 705 | ||
691 | unlock: | 706 | unlock: |
@@ -725,6 +740,7 @@ static void purge_vis_packets(struct bat_priv *bat_priv) | |||
725 | static void broadcast_vis_packet(struct bat_priv *bat_priv, | 740 | static void broadcast_vis_packet(struct bat_priv *bat_priv, |
726 | struct vis_info *info) | 741 | struct vis_info *info) |
727 | { | 742 | { |
743 | struct neigh_node *router; | ||
728 | struct hashtable_t *hash = bat_priv->orig_hash; | 744 | struct hashtable_t *hash = bat_priv->orig_hash; |
729 | struct hlist_node *node; | 745 | struct hlist_node *node; |
730 | struct hlist_head *head; | 746 | struct hlist_head *head; |
@@ -745,19 +761,26 @@ static void broadcast_vis_packet(struct bat_priv *bat_priv, | |||
745 | rcu_read_lock(); | 761 | rcu_read_lock(); |
746 | hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) { | 762 | hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) { |
747 | /* if it's a vis server and reachable, send it. */ | 763 | /* if it's a vis server and reachable, send it. */ |
748 | if ((!orig_node) || (!orig_node->router)) | ||
749 | continue; | ||
750 | if (!(orig_node->flags & VIS_SERVER)) | 764 | if (!(orig_node->flags & VIS_SERVER)) |
751 | continue; | 765 | continue; |
766 | |||
767 | router = orig_node_get_router(orig_node); | ||
768 | if (!router) | ||
769 | continue; | ||
770 | |||
752 | /* don't send it if we already received the packet from | 771 | /* don't send it if we already received the packet from |
753 | * this node. */ | 772 | * this node. */ |
754 | if (recv_list_is_in(bat_priv, &info->recv_list, | 773 | if (recv_list_is_in(bat_priv, &info->recv_list, |
755 | orig_node->orig)) | 774 | orig_node->orig)) { |
775 | neigh_node_free_ref(router); | ||
756 | continue; | 776 | continue; |
777 | } | ||
757 | 778 | ||
758 | memcpy(packet->target_orig, orig_node->orig, ETH_ALEN); | 779 | memcpy(packet->target_orig, orig_node->orig, ETH_ALEN); |
759 | hard_iface = orig_node->router->if_incoming; | 780 | hard_iface = router->if_incoming; |
760 | memcpy(dstaddr, orig_node->router->addr, ETH_ALEN); | 781 | memcpy(dstaddr, router->addr, ETH_ALEN); |
782 | |||
783 | neigh_node_free_ref(router); | ||
761 | 784 | ||
762 | skb = skb_clone(info->skb_packet, GFP_ATOMIC); | 785 | skb = skb_clone(info->skb_packet, GFP_ATOMIC); |
763 | if (skb) | 786 | if (skb) |
@@ -772,60 +795,48 @@ static void unicast_vis_packet(struct bat_priv *bat_priv, | |||
772 | struct vis_info *info) | 795 | struct vis_info *info) |
773 | { | 796 | { |
774 | struct orig_node *orig_node; | 797 | struct orig_node *orig_node; |
775 | struct neigh_node *neigh_node = NULL; | 798 | struct neigh_node *router = NULL; |
776 | struct sk_buff *skb; | 799 | struct sk_buff *skb; |
777 | struct vis_packet *packet; | 800 | struct vis_packet *packet; |
778 | 801 | ||
779 | packet = (struct vis_packet *)info->skb_packet->data; | 802 | packet = (struct vis_packet *)info->skb_packet->data; |
780 | 803 | ||
781 | rcu_read_lock(); | ||
782 | orig_node = orig_hash_find(bat_priv, packet->target_orig); | 804 | orig_node = orig_hash_find(bat_priv, packet->target_orig); |
783 | |||
784 | if (!orig_node) | 805 | if (!orig_node) |
785 | goto unlock; | 806 | goto out; |
786 | |||
787 | neigh_node = orig_node->router; | ||
788 | 807 | ||
789 | if (!neigh_node) | 808 | router = orig_node_get_router(orig_node); |
790 | goto unlock; | 809 | if (!router) |
791 | 810 | goto out; | |
792 | if (!atomic_inc_not_zero(&neigh_node->refcount)) { | ||
793 | neigh_node = NULL; | ||
794 | goto unlock; | ||
795 | } | ||
796 | |||
797 | rcu_read_unlock(); | ||
798 | 811 | ||
799 | skb = skb_clone(info->skb_packet, GFP_ATOMIC); | 812 | skb = skb_clone(info->skb_packet, GFP_ATOMIC); |
800 | if (skb) | 813 | if (skb) |
801 | send_skb_packet(skb, neigh_node->if_incoming, | 814 | send_skb_packet(skb, router->if_incoming, router->addr); |
802 | neigh_node->addr); | ||
803 | 815 | ||
804 | goto out; | ||
805 | |||
806 | unlock: | ||
807 | rcu_read_unlock(); | ||
808 | out: | 816 | out: |
809 | if (neigh_node) | 817 | if (router) |
810 | neigh_node_free_ref(neigh_node); | 818 | neigh_node_free_ref(router); |
811 | if (orig_node) | 819 | if (orig_node) |
812 | orig_node_free_ref(orig_node); | 820 | orig_node_free_ref(orig_node); |
813 | return; | ||
814 | } | 821 | } |
815 | 822 | ||
816 | /* only send one vis packet. called from send_vis_packets() */ | 823 | /* only send one vis packet. called from send_vis_packets() */ |
817 | static void send_vis_packet(struct bat_priv *bat_priv, struct vis_info *info) | 824 | static void send_vis_packet(struct bat_priv *bat_priv, struct vis_info *info) |
818 | { | 825 | { |
826 | struct hard_iface *primary_if; | ||
819 | struct vis_packet *packet; | 827 | struct vis_packet *packet; |
820 | 828 | ||
829 | primary_if = primary_if_get_selected(bat_priv); | ||
830 | if (!primary_if) | ||
831 | goto out; | ||
832 | |||
821 | packet = (struct vis_packet *)info->skb_packet->data; | 833 | packet = (struct vis_packet *)info->skb_packet->data; |
822 | if (packet->ttl < 2) { | 834 | if (packet->ttl < 2) { |
823 | pr_debug("Error - can't send vis packet: ttl exceeded\n"); | 835 | pr_debug("Error - can't send vis packet: ttl exceeded\n"); |
824 | return; | 836 | goto out; |
825 | } | 837 | } |
826 | 838 | ||
827 | memcpy(packet->sender_orig, bat_priv->primary_if->net_dev->dev_addr, | 839 | memcpy(packet->sender_orig, primary_if->net_dev->dev_addr, ETH_ALEN); |
828 | ETH_ALEN); | ||
829 | packet->ttl--; | 840 | packet->ttl--; |
830 | 841 | ||
831 | if (is_broadcast_ether_addr(packet->target_orig)) | 842 | 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) | |||
833 | else | 844 | else |
834 | unicast_vis_packet(bat_priv, info); | 845 | unicast_vis_packet(bat_priv, info); |
835 | packet->ttl++; /* restore TTL */ | 846 | packet->ttl++; /* restore TTL */ |
847 | |||
848 | out: | ||
849 | if (primary_if) | ||
850 | hardif_free_ref(primary_if); | ||
836 | } | 851 | } |
837 | 852 | ||
838 | /* called from timer; send (and maybe generate) vis packet. */ | 853 | /* called from timer; send (and maybe generate) vis packet. */ |
@@ -859,8 +874,7 @@ static void send_vis_packets(struct work_struct *work) | |||
859 | kref_get(&info->refcount); | 874 | kref_get(&info->refcount); |
860 | spin_unlock_bh(&bat_priv->vis_hash_lock); | 875 | spin_unlock_bh(&bat_priv->vis_hash_lock); |
861 | 876 | ||
862 | if (bat_priv->primary_if) | 877 | send_vis_packet(bat_priv, info); |
863 | send_vis_packet(bat_priv, info); | ||
864 | 878 | ||
865 | spin_lock_bh(&bat_priv->vis_hash_lock); | 879 | spin_lock_bh(&bat_priv->vis_hash_lock); |
866 | send_list_del(info); | 880 | send_list_del(info); |