diff options
Diffstat (limited to 'net/batman-adv/vis.c')
-rw-r--r-- | net/batman-adv/vis.c | 104 |
1 files changed, 43 insertions, 61 deletions
diff --git a/net/batman-adv/vis.c b/net/batman-adv/vis.c index c39f20cc1ba..8a1b98589d7 100644 --- a/net/batman-adv/vis.c +++ b/net/batman-adv/vis.c | |||
@@ -30,22 +30,6 @@ | |||
30 | 30 | ||
31 | #define MAX_VIS_PACKET_SIZE 1000 | 31 | #define MAX_VIS_PACKET_SIZE 1000 |
32 | 32 | ||
33 | /* Returns the smallest signed integer in two's complement with the sizeof x */ | ||
34 | #define smallest_signed_int(x) (1u << (7u + 8u * (sizeof(x) - 1u))) | ||
35 | |||
36 | /* Checks if a sequence number x is a predecessor/successor of y. | ||
37 | * they handle overflows/underflows and can correctly check for a | ||
38 | * predecessor/successor unless the variable sequence number has grown by | ||
39 | * more then 2**(bitwidth(x)-1)-1. | ||
40 | * This means that for a uint8_t with the maximum value 255, it would think: | ||
41 | * - when adding nothing - it is neither a predecessor nor a successor | ||
42 | * - before adding more than 127 to the starting value - it is a predecessor, | ||
43 | * - when adding 128 - it is neither a predecessor nor a successor, | ||
44 | * - after adding more than 127 to the starting value - it is a successor */ | ||
45 | #define seq_before(x, y) ({typeof(x) _dummy = (x - y); \ | ||
46 | _dummy > smallest_signed_int(_dummy); }) | ||
47 | #define seq_after(x, y) seq_before(y, x) | ||
48 | |||
49 | static void start_vis_timer(struct bat_priv *bat_priv); | 33 | static void start_vis_timer(struct bat_priv *bat_priv); |
50 | 34 | ||
51 | /* free the info */ | 35 | /* free the info */ |
@@ -68,10 +52,10 @@ static void free_info(struct kref *ref) | |||
68 | } | 52 | } |
69 | 53 | ||
70 | /* Compare two vis packets, used by the hashing algorithm */ | 54 | /* Compare two vis packets, used by the hashing algorithm */ |
71 | static int vis_info_cmp(struct hlist_node *node, void *data2) | 55 | static int vis_info_cmp(const struct hlist_node *node, const void *data2) |
72 | { | 56 | { |
73 | struct vis_info *d1, *d2; | 57 | const struct vis_info *d1, *d2; |
74 | struct vis_packet *p1, *p2; | 58 | const struct vis_packet *p1, *p2; |
75 | 59 | ||
76 | d1 = container_of(node, struct vis_info, hash_entry); | 60 | d1 = container_of(node, struct vis_info, hash_entry); |
77 | d2 = data2; | 61 | d2 = data2; |
@@ -82,11 +66,11 @@ static int vis_info_cmp(struct hlist_node *node, void *data2) | |||
82 | 66 | ||
83 | /* hash function to choose an entry in a hash table of given size */ | 67 | /* hash function to choose an entry in a hash table of given size */ |
84 | /* hash algorithm from http://en.wikipedia.org/wiki/Hash_table */ | 68 | /* hash algorithm from http://en.wikipedia.org/wiki/Hash_table */ |
85 | static int vis_info_choose(void *data, int size) | 69 | static int vis_info_choose(const void *data, int size) |
86 | { | 70 | { |
87 | struct vis_info *vis_info = data; | 71 | const struct vis_info *vis_info = data; |
88 | struct vis_packet *packet; | 72 | const struct vis_packet *packet; |
89 | unsigned char *key; | 73 | const unsigned char *key; |
90 | uint32_t hash = 0; | 74 | uint32_t hash = 0; |
91 | size_t i; | 75 | size_t i; |
92 | 76 | ||
@@ -106,7 +90,7 @@ static int vis_info_choose(void *data, int size) | |||
106 | } | 90 | } |
107 | 91 | ||
108 | static struct vis_info *vis_hash_find(struct bat_priv *bat_priv, | 92 | static struct vis_info *vis_hash_find(struct bat_priv *bat_priv, |
109 | void *data) | 93 | const void *data) |
110 | { | 94 | { |
111 | struct hashtable_t *hash = bat_priv->vis_hash; | 95 | struct hashtable_t *hash = bat_priv->vis_hash; |
112 | struct hlist_head *head; | 96 | struct hlist_head *head; |
@@ -143,7 +127,7 @@ static void vis_data_insert_interface(const uint8_t *interface, | |||
143 | struct hlist_node *pos; | 127 | struct hlist_node *pos; |
144 | 128 | ||
145 | hlist_for_each_entry(entry, pos, if_list, list) { | 129 | hlist_for_each_entry(entry, pos, if_list, list) { |
146 | if (compare_eth(entry->addr, (void *)interface)) | 130 | if (compare_eth(entry->addr, interface)) |
147 | return; | 131 | return; |
148 | } | 132 | } |
149 | 133 | ||
@@ -156,7 +140,8 @@ static void vis_data_insert_interface(const uint8_t *interface, | |||
156 | hlist_add_head(&entry->list, if_list); | 140 | hlist_add_head(&entry->list, if_list); |
157 | } | 141 | } |
158 | 142 | ||
159 | static ssize_t vis_data_read_prim_sec(char *buff, struct hlist_head *if_list) | 143 | static ssize_t vis_data_read_prim_sec(char *buff, |
144 | const struct hlist_head *if_list) | ||
160 | { | 145 | { |
161 | struct if_list_entry *entry; | 146 | struct if_list_entry *entry; |
162 | struct hlist_node *pos; | 147 | struct hlist_node *pos; |
@@ -189,8 +174,9 @@ static size_t vis_data_count_prim_sec(struct hlist_head *if_list) | |||
189 | } | 174 | } |
190 | 175 | ||
191 | /* read an entry */ | 176 | /* read an entry */ |
192 | static ssize_t vis_data_read_entry(char *buff, struct vis_info_entry *entry, | 177 | static ssize_t vis_data_read_entry(char *buff, |
193 | uint8_t *src, bool primary) | 178 | const struct vis_info_entry *entry, |
179 | const uint8_t *src, bool primary) | ||
194 | { | 180 | { |
195 | /* maximal length: max(4+17+2, 3+17+1+3+2) == 26 */ | 181 | /* maximal length: max(4+17+2, 3+17+1+3+2) == 26 */ |
196 | if (primary && entry->quality == 0) | 182 | if (primary && entry->quality == 0) |
@@ -239,7 +225,7 @@ int vis_seq_print_text(struct seq_file *seq, void *offset) | |||
239 | hlist_for_each_entry_rcu(info, node, head, hash_entry) { | 225 | hlist_for_each_entry_rcu(info, node, head, hash_entry) { |
240 | packet = (struct vis_packet *)info->skb_packet->data; | 226 | packet = (struct vis_packet *)info->skb_packet->data; |
241 | entries = (struct vis_info_entry *) | 227 | entries = (struct vis_info_entry *) |
242 | ((char *)packet + sizeof(struct vis_packet)); | 228 | ((char *)packet + sizeof(*packet)); |
243 | 229 | ||
244 | for (j = 0; j < packet->entries; j++) { | 230 | for (j = 0; j < packet->entries; j++) { |
245 | if (entries[j].quality == 0) | 231 | if (entries[j].quality == 0) |
@@ -287,7 +273,7 @@ int vis_seq_print_text(struct seq_file *seq, void *offset) | |||
287 | hlist_for_each_entry_rcu(info, node, head, hash_entry) { | 273 | hlist_for_each_entry_rcu(info, node, head, hash_entry) { |
288 | packet = (struct vis_packet *)info->skb_packet->data; | 274 | packet = (struct vis_packet *)info->skb_packet->data; |
289 | entries = (struct vis_info_entry *) | 275 | entries = (struct vis_info_entry *) |
290 | ((char *)packet + sizeof(struct vis_packet)); | 276 | ((char *)packet + sizeof(*packet)); |
291 | 277 | ||
292 | for (j = 0; j < packet->entries; j++) { | 278 | for (j = 0; j < packet->entries; j++) { |
293 | if (entries[j].quality == 0) | 279 | if (entries[j].quality == 0) |
@@ -361,11 +347,11 @@ static void send_list_del(struct vis_info *info) | |||
361 | 347 | ||
362 | /* tries to add one entry to the receive list. */ | 348 | /* tries to add one entry to the receive list. */ |
363 | static void recv_list_add(struct bat_priv *bat_priv, | 349 | static void recv_list_add(struct bat_priv *bat_priv, |
364 | struct list_head *recv_list, char *mac) | 350 | struct list_head *recv_list, const char *mac) |
365 | { | 351 | { |
366 | struct recvlist_node *entry; | 352 | struct recvlist_node *entry; |
367 | 353 | ||
368 | entry = kmalloc(sizeof(struct recvlist_node), GFP_ATOMIC); | 354 | entry = kmalloc(sizeof(*entry), GFP_ATOMIC); |
369 | if (!entry) | 355 | if (!entry) |
370 | return; | 356 | return; |
371 | 357 | ||
@@ -377,9 +363,9 @@ static void recv_list_add(struct bat_priv *bat_priv, | |||
377 | 363 | ||
378 | /* returns 1 if this mac is in the recv_list */ | 364 | /* returns 1 if this mac is in the recv_list */ |
379 | static int recv_list_is_in(struct bat_priv *bat_priv, | 365 | static int recv_list_is_in(struct bat_priv *bat_priv, |
380 | struct list_head *recv_list, char *mac) | 366 | const struct list_head *recv_list, const char *mac) |
381 | { | 367 | { |
382 | struct recvlist_node *entry; | 368 | const struct recvlist_node *entry; |
383 | 369 | ||
384 | spin_lock_bh(&bat_priv->vis_list_lock); | 370 | spin_lock_bh(&bat_priv->vis_list_lock); |
385 | list_for_each_entry(entry, recv_list, list) { | 371 | list_for_each_entry(entry, recv_list, list) { |
@@ -412,11 +398,11 @@ static struct vis_info *add_packet(struct bat_priv *bat_priv, | |||
412 | return NULL; | 398 | return NULL; |
413 | 399 | ||
414 | /* see if the packet is already in vis_hash */ | 400 | /* see if the packet is already in vis_hash */ |
415 | search_elem.skb_packet = dev_alloc_skb(sizeof(struct vis_packet)); | 401 | search_elem.skb_packet = dev_alloc_skb(sizeof(*search_packet)); |
416 | if (!search_elem.skb_packet) | 402 | if (!search_elem.skb_packet) |
417 | return NULL; | 403 | return NULL; |
418 | search_packet = (struct vis_packet *)skb_put(search_elem.skb_packet, | 404 | search_packet = (struct vis_packet *)skb_put(search_elem.skb_packet, |
419 | sizeof(struct vis_packet)); | 405 | sizeof(*search_packet)); |
420 | 406 | ||
421 | memcpy(search_packet->vis_orig, vis_packet->vis_orig, ETH_ALEN); | 407 | memcpy(search_packet->vis_orig, vis_packet->vis_orig, ETH_ALEN); |
422 | old_info = vis_hash_find(bat_priv, &search_elem); | 408 | old_info = vis_hash_find(bat_priv, &search_elem); |
@@ -442,27 +428,26 @@ static struct vis_info *add_packet(struct bat_priv *bat_priv, | |||
442 | kref_put(&old_info->refcount, free_info); | 428 | kref_put(&old_info->refcount, free_info); |
443 | } | 429 | } |
444 | 430 | ||
445 | info = kmalloc(sizeof(struct vis_info), GFP_ATOMIC); | 431 | info = kmalloc(sizeof(*info), GFP_ATOMIC); |
446 | if (!info) | 432 | if (!info) |
447 | return NULL; | 433 | return NULL; |
448 | 434 | ||
449 | info->skb_packet = dev_alloc_skb(sizeof(struct vis_packet) + | 435 | info->skb_packet = dev_alloc_skb(sizeof(*packet) + vis_info_len + |
450 | vis_info_len + sizeof(struct ethhdr)); | 436 | sizeof(struct ethhdr)); |
451 | if (!info->skb_packet) { | 437 | if (!info->skb_packet) { |
452 | kfree(info); | 438 | kfree(info); |
453 | return NULL; | 439 | return NULL; |
454 | } | 440 | } |
455 | skb_reserve(info->skb_packet, sizeof(struct ethhdr)); | 441 | skb_reserve(info->skb_packet, sizeof(struct ethhdr)); |
456 | packet = (struct vis_packet *)skb_put(info->skb_packet, | 442 | packet = (struct vis_packet *)skb_put(info->skb_packet, sizeof(*packet) |
457 | sizeof(struct vis_packet) + | 443 | + vis_info_len); |
458 | vis_info_len); | ||
459 | 444 | ||
460 | kref_init(&info->refcount); | 445 | kref_init(&info->refcount); |
461 | INIT_LIST_HEAD(&info->send_list); | 446 | INIT_LIST_HEAD(&info->send_list); |
462 | INIT_LIST_HEAD(&info->recv_list); | 447 | INIT_LIST_HEAD(&info->recv_list); |
463 | info->first_seen = jiffies; | 448 | info->first_seen = jiffies; |
464 | info->bat_priv = bat_priv; | 449 | info->bat_priv = bat_priv; |
465 | memcpy(packet, vis_packet, sizeof(struct vis_packet) + vis_info_len); | 450 | memcpy(packet, vis_packet, sizeof(*packet) + vis_info_len); |
466 | 451 | ||
467 | /* initialize and add new packet. */ | 452 | /* initialize and add new packet. */ |
468 | *is_new = 1; | 453 | *is_new = 1; |
@@ -599,9 +584,9 @@ static int find_best_vis_server(struct bat_priv *bat_priv, | |||
599 | } | 584 | } |
600 | 585 | ||
601 | /* Return true if the vis packet is full. */ | 586 | /* Return true if the vis packet is full. */ |
602 | static bool vis_packet_full(struct vis_info *info) | 587 | static bool vis_packet_full(const struct vis_info *info) |
603 | { | 588 | { |
604 | struct vis_packet *packet; | 589 | const struct vis_packet *packet; |
605 | packet = (struct vis_packet *)info->skb_packet->data; | 590 | packet = (struct vis_packet *)info->skb_packet->data; |
606 | 591 | ||
607 | if (MAX_VIS_PACKET_SIZE / sizeof(struct vis_info_entry) | 592 | if (MAX_VIS_PACKET_SIZE / sizeof(struct vis_info_entry) |
@@ -619,7 +604,7 @@ static int generate_vis_packet(struct bat_priv *bat_priv) | |||
619 | struct hlist_head *head; | 604 | struct hlist_head *head; |
620 | struct orig_node *orig_node; | 605 | struct orig_node *orig_node; |
621 | struct neigh_node *router; | 606 | struct neigh_node *router; |
622 | struct vis_info *info = (struct vis_info *)bat_priv->my_vis_info; | 607 | struct vis_info *info = bat_priv->my_vis_info; |
623 | struct vis_packet *packet = (struct vis_packet *)info->skb_packet->data; | 608 | struct vis_packet *packet = (struct vis_packet *)info->skb_packet->data; |
624 | struct vis_info_entry *entry; | 609 | struct vis_info_entry *entry; |
625 | struct tt_local_entry *tt_local_entry; | 610 | struct tt_local_entry *tt_local_entry; |
@@ -632,7 +617,7 @@ static int generate_vis_packet(struct bat_priv *bat_priv) | |||
632 | packet->ttl = TTL; | 617 | packet->ttl = TTL; |
633 | packet->seqno = htonl(ntohl(packet->seqno) + 1); | 618 | packet->seqno = htonl(ntohl(packet->seqno) + 1); |
634 | packet->entries = 0; | 619 | packet->entries = 0; |
635 | skb_trim(info->skb_packet, sizeof(struct vis_packet)); | 620 | skb_trim(info->skb_packet, sizeof(*packet)); |
636 | 621 | ||
637 | if (packet->vis_type == VIS_TYPE_CLIENT_UPDATE) { | 622 | if (packet->vis_type == VIS_TYPE_CLIENT_UPDATE) { |
638 | best_tq = find_best_vis_server(bat_priv, info); | 623 | best_tq = find_best_vis_server(bat_priv, info); |
@@ -680,11 +665,12 @@ next: | |||
680 | 665 | ||
681 | hash = bat_priv->tt_local_hash; | 666 | hash = bat_priv->tt_local_hash; |
682 | 667 | ||
683 | spin_lock_bh(&bat_priv->tt_lhash_lock); | ||
684 | for (i = 0; i < hash->size; i++) { | 668 | for (i = 0; i < hash->size; i++) { |
685 | head = &hash->table[i]; | 669 | head = &hash->table[i]; |
686 | 670 | ||
687 | hlist_for_each_entry(tt_local_entry, node, head, hash_entry) { | 671 | rcu_read_lock(); |
672 | hlist_for_each_entry_rcu(tt_local_entry, node, head, | ||
673 | hash_entry) { | ||
688 | entry = (struct vis_info_entry *) | 674 | entry = (struct vis_info_entry *) |
689 | skb_put(info->skb_packet, | 675 | skb_put(info->skb_packet, |
690 | sizeof(*entry)); | 676 | sizeof(*entry)); |
@@ -693,14 +679,12 @@ next: | |||
693 | entry->quality = 0; /* 0 means TT */ | 679 | entry->quality = 0; /* 0 means TT */ |
694 | packet->entries++; | 680 | packet->entries++; |
695 | 681 | ||
696 | if (vis_packet_full(info)) { | 682 | if (vis_packet_full(info)) |
697 | spin_unlock_bh(&bat_priv->tt_lhash_lock); | 683 | goto unlock; |
698 | return 0; | ||
699 | } | ||
700 | } | 684 | } |
685 | rcu_read_unlock(); | ||
701 | } | 686 | } |
702 | 687 | ||
703 | spin_unlock_bh(&bat_priv->tt_lhash_lock); | ||
704 | return 0; | 688 | return 0; |
705 | 689 | ||
706 | unlock: | 690 | unlock: |
@@ -908,17 +892,15 @@ int vis_init(struct bat_priv *bat_priv) | |||
908 | goto err; | 892 | goto err; |
909 | } | 893 | } |
910 | 894 | ||
911 | bat_priv->my_vis_info->skb_packet = dev_alloc_skb( | 895 | bat_priv->my_vis_info->skb_packet = dev_alloc_skb(sizeof(*packet) + |
912 | sizeof(struct vis_packet) + | 896 | MAX_VIS_PACKET_SIZE + |
913 | MAX_VIS_PACKET_SIZE + | 897 | sizeof(struct ethhdr)); |
914 | sizeof(struct ethhdr)); | ||
915 | if (!bat_priv->my_vis_info->skb_packet) | 898 | if (!bat_priv->my_vis_info->skb_packet) |
916 | goto free_info; | 899 | goto free_info; |
917 | 900 | ||
918 | skb_reserve(bat_priv->my_vis_info->skb_packet, sizeof(struct ethhdr)); | 901 | skb_reserve(bat_priv->my_vis_info->skb_packet, sizeof(struct ethhdr)); |
919 | packet = (struct vis_packet *)skb_put( | 902 | packet = (struct vis_packet *)skb_put(bat_priv->my_vis_info->skb_packet, |
920 | bat_priv->my_vis_info->skb_packet, | 903 | sizeof(*packet)); |
921 | sizeof(struct vis_packet)); | ||
922 | 904 | ||
923 | /* prefill the vis info */ | 905 | /* prefill the vis info */ |
924 | bat_priv->my_vis_info->first_seen = jiffies - | 906 | bat_priv->my_vis_info->first_seen = jiffies - |