diff options
Diffstat (limited to 'net/batman-adv')
-rw-r--r-- | net/batman-adv/bat_sysfs.c | 4 | ||||
-rw-r--r-- | net/batman-adv/bitarray.c | 2 | ||||
-rw-r--r-- | net/batman-adv/gateway_client.c | 153 | ||||
-rw-r--r-- | net/batman-adv/gateway_client.h | 5 | ||||
-rw-r--r-- | net/batman-adv/gateway_common.c | 4 | ||||
-rw-r--r-- | net/batman-adv/hash.c | 4 | ||||
-rw-r--r-- | net/batman-adv/hash.h | 13 | ||||
-rw-r--r-- | net/batman-adv/icmp_socket.c | 14 | ||||
-rw-r--r-- | net/batman-adv/main.h | 2 | ||||
-rw-r--r-- | net/batman-adv/originator.c | 13 | ||||
-rw-r--r-- | net/batman-adv/originator.h | 2 | ||||
-rw-r--r-- | net/batman-adv/routing.c | 21 | ||||
-rw-r--r-- | net/batman-adv/soft-interface.c | 45 | ||||
-rw-r--r-- | net/batman-adv/translation-table.c | 437 | ||||
-rw-r--r-- | net/batman-adv/types.h | 14 | ||||
-rw-r--r-- | net/batman-adv/vis.c | 23 |
16 files changed, 411 insertions, 345 deletions
diff --git a/net/batman-adv/bat_sysfs.c b/net/batman-adv/bat_sysfs.c index b8a7414c3571..c25492f7d665 100644 --- a/net/batman-adv/bat_sysfs.c +++ b/net/batman-adv/bat_sysfs.c | |||
@@ -174,7 +174,7 @@ static int store_uint_attr(const char *buff, size_t count, | |||
174 | unsigned long uint_val; | 174 | unsigned long uint_val; |
175 | int ret; | 175 | int ret; |
176 | 176 | ||
177 | ret = strict_strtoul(buff, 10, &uint_val); | 177 | ret = kstrtoul(buff, 10, &uint_val); |
178 | if (ret) { | 178 | if (ret) { |
179 | bat_info(net_dev, | 179 | bat_info(net_dev, |
180 | "%s: Invalid parameter received: %s\n", | 180 | "%s: Invalid parameter received: %s\n", |
@@ -239,7 +239,7 @@ static ssize_t store_vis_mode(struct kobject *kobj, struct attribute *attr, | |||
239 | unsigned long val; | 239 | unsigned long val; |
240 | int ret, vis_mode_tmp = -1; | 240 | int ret, vis_mode_tmp = -1; |
241 | 241 | ||
242 | ret = strict_strtoul(buff, 10, &val); | 242 | ret = kstrtoul(buff, 10, &val); |
243 | 243 | ||
244 | if (((count == 2) && (!ret) && (val == VIS_TYPE_CLIENT_UPDATE)) || | 244 | if (((count == 2) && (!ret) && (val == VIS_TYPE_CLIENT_UPDATE)) || |
245 | (strncmp(buff, "client", 6) == 0) || | 245 | (strncmp(buff, "client", 6) == 0) || |
diff --git a/net/batman-adv/bitarray.c b/net/batman-adv/bitarray.c index 0be9ff346fa0..9bc63b209b3f 100644 --- a/net/batman-adv/bitarray.c +++ b/net/batman-adv/bitarray.c | |||
@@ -155,7 +155,7 @@ int bit_get_packet(void *priv, unsigned long *seq_bits, | |||
155 | /* sequence number is much newer, probably missed a lot of packets */ | 155 | /* sequence number is much newer, probably missed a lot of packets */ |
156 | 156 | ||
157 | if ((seq_num_diff >= TQ_LOCAL_WINDOW_SIZE) | 157 | if ((seq_num_diff >= TQ_LOCAL_WINDOW_SIZE) |
158 | || (seq_num_diff < EXPECTED_SEQNO_RANGE)) { | 158 | && (seq_num_diff < EXPECTED_SEQNO_RANGE)) { |
159 | bat_dbg(DBG_BATMAN, bat_priv, | 159 | bat_dbg(DBG_BATMAN, bat_priv, |
160 | "We missed a lot of packets (%i) !\n", | 160 | "We missed a lot of packets (%i) !\n", |
161 | seq_num_diff - 1); | 161 | seq_num_diff - 1); |
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index 619fb73b3b76..24403a7350f7 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include "gateway_common.h" | 25 | #include "gateway_common.h" |
26 | #include "hard-interface.h" | 26 | #include "hard-interface.h" |
27 | #include "originator.h" | 27 | #include "originator.h" |
28 | #include "translation-table.h" | ||
28 | #include "routing.h" | 29 | #include "routing.h" |
29 | #include <linux/ip.h> | 30 | #include <linux/ip.h> |
30 | #include <linux/ipv6.h> | 31 | #include <linux/ipv6.h> |
@@ -572,108 +573,142 @@ out: | |||
572 | return ret; | 573 | return ret; |
573 | } | 574 | } |
574 | 575 | ||
575 | int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb, | 576 | bool gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len) |
576 | struct orig_node *old_gw) | ||
577 | { | 577 | { |
578 | struct ethhdr *ethhdr; | 578 | struct ethhdr *ethhdr; |
579 | struct iphdr *iphdr; | 579 | struct iphdr *iphdr; |
580 | struct ipv6hdr *ipv6hdr; | 580 | struct ipv6hdr *ipv6hdr; |
581 | struct udphdr *udphdr; | 581 | struct udphdr *udphdr; |
582 | struct gw_node *curr_gw; | ||
583 | struct neigh_node *neigh_curr = NULL, *neigh_old = NULL; | ||
584 | unsigned int header_len = 0; | ||
585 | int ret = 1; | ||
586 | |||
587 | if (atomic_read(&bat_priv->gw_mode) == GW_MODE_OFF) | ||
588 | return 0; | ||
589 | 582 | ||
590 | /* check for ethernet header */ | 583 | /* check for ethernet header */ |
591 | if (!pskb_may_pull(skb, header_len + ETH_HLEN)) | 584 | if (!pskb_may_pull(skb, *header_len + ETH_HLEN)) |
592 | return 0; | 585 | return false; |
593 | ethhdr = (struct ethhdr *)skb->data; | 586 | ethhdr = (struct ethhdr *)skb->data; |
594 | header_len += ETH_HLEN; | 587 | *header_len += ETH_HLEN; |
595 | 588 | ||
596 | /* check for initial vlan header */ | 589 | /* check for initial vlan header */ |
597 | if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) { | 590 | if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) { |
598 | if (!pskb_may_pull(skb, header_len + VLAN_HLEN)) | 591 | if (!pskb_may_pull(skb, *header_len + VLAN_HLEN)) |
599 | return 0; | 592 | return false; |
600 | ethhdr = (struct ethhdr *)(skb->data + VLAN_HLEN); | 593 | ethhdr = (struct ethhdr *)(skb->data + VLAN_HLEN); |
601 | header_len += VLAN_HLEN; | 594 | *header_len += VLAN_HLEN; |
602 | } | 595 | } |
603 | 596 | ||
604 | /* check for ip header */ | 597 | /* check for ip header */ |
605 | switch (ntohs(ethhdr->h_proto)) { | 598 | switch (ntohs(ethhdr->h_proto)) { |
606 | case ETH_P_IP: | 599 | case ETH_P_IP: |
607 | if (!pskb_may_pull(skb, header_len + sizeof(*iphdr))) | 600 | if (!pskb_may_pull(skb, *header_len + sizeof(*iphdr))) |
608 | return 0; | 601 | return false; |
609 | iphdr = (struct iphdr *)(skb->data + header_len); | 602 | iphdr = (struct iphdr *)(skb->data + *header_len); |
610 | header_len += iphdr->ihl * 4; | 603 | *header_len += iphdr->ihl * 4; |
611 | 604 | ||
612 | /* check for udp header */ | 605 | /* check for udp header */ |
613 | if (iphdr->protocol != IPPROTO_UDP) | 606 | if (iphdr->protocol != IPPROTO_UDP) |
614 | return 0; | 607 | return false; |
615 | 608 | ||
616 | break; | 609 | break; |
617 | case ETH_P_IPV6: | 610 | case ETH_P_IPV6: |
618 | if (!pskb_may_pull(skb, header_len + sizeof(*ipv6hdr))) | 611 | if (!pskb_may_pull(skb, *header_len + sizeof(*ipv6hdr))) |
619 | return 0; | 612 | return false; |
620 | ipv6hdr = (struct ipv6hdr *)(skb->data + header_len); | 613 | ipv6hdr = (struct ipv6hdr *)(skb->data + *header_len); |
621 | header_len += sizeof(*ipv6hdr); | 614 | *header_len += sizeof(*ipv6hdr); |
622 | 615 | ||
623 | /* check for udp header */ | 616 | /* check for udp header */ |
624 | if (ipv6hdr->nexthdr != IPPROTO_UDP) | 617 | if (ipv6hdr->nexthdr != IPPROTO_UDP) |
625 | return 0; | 618 | return false; |
626 | 619 | ||
627 | break; | 620 | break; |
628 | default: | 621 | default: |
629 | return 0; | 622 | return false; |
630 | } | 623 | } |
631 | 624 | ||
632 | if (!pskb_may_pull(skb, header_len + sizeof(*udphdr))) | 625 | if (!pskb_may_pull(skb, *header_len + sizeof(*udphdr))) |
633 | return 0; | 626 | return false; |
634 | udphdr = (struct udphdr *)(skb->data + header_len); | 627 | udphdr = (struct udphdr *)(skb->data + *header_len); |
635 | header_len += sizeof(*udphdr); | 628 | *header_len += sizeof(*udphdr); |
636 | 629 | ||
637 | /* check for bootp port */ | 630 | /* check for bootp port */ |
638 | if ((ntohs(ethhdr->h_proto) == ETH_P_IP) && | 631 | if ((ntohs(ethhdr->h_proto) == ETH_P_IP) && |
639 | (ntohs(udphdr->dest) != 67)) | 632 | (ntohs(udphdr->dest) != 67)) |
640 | return 0; | 633 | return false; |
641 | 634 | ||
642 | if ((ntohs(ethhdr->h_proto) == ETH_P_IPV6) && | 635 | if ((ntohs(ethhdr->h_proto) == ETH_P_IPV6) && |
643 | (ntohs(udphdr->dest) != 547)) | 636 | (ntohs(udphdr->dest) != 547)) |
644 | return 0; | 637 | return false; |
645 | 638 | ||
646 | if (atomic_read(&bat_priv->gw_mode) == GW_MODE_SERVER) | 639 | return true; |
647 | return -1; | 640 | } |
648 | 641 | ||
649 | curr_gw = gw_get_selected_gw_node(bat_priv); | 642 | bool gw_out_of_range(struct bat_priv *bat_priv, |
650 | if (!curr_gw) | 643 | struct sk_buff *skb, struct ethhdr *ethhdr) |
651 | return 0; | 644 | { |
652 | 645 | struct neigh_node *neigh_curr = NULL, *neigh_old = NULL; | |
653 | /* If old_gw != NULL then this packet is unicast. | 646 | struct orig_node *orig_dst_node = NULL; |
654 | * So, at this point we have to check the message type: if it is a | 647 | struct gw_node *curr_gw = NULL; |
655 | * DHCPREQUEST we have to decide whether to drop it or not */ | 648 | bool ret, out_of_range = false; |
656 | if (old_gw && curr_gw->orig_node != old_gw) { | 649 | unsigned int header_len = 0; |
657 | if (is_type_dhcprequest(skb, header_len)) { | 650 | uint8_t curr_tq_avg; |
658 | /* If the dhcp packet has been sent to a different gw, | 651 | |
659 | * we have to evaluate whether the old gw is still | 652 | ret = gw_is_dhcp_target(skb, &header_len); |
660 | * reliable enough */ | 653 | if (!ret) |
661 | neigh_curr = find_router(bat_priv, curr_gw->orig_node, | 654 | goto out; |
662 | NULL); | 655 | |
663 | neigh_old = find_router(bat_priv, old_gw, NULL); | 656 | orig_dst_node = transtable_search(bat_priv, ethhdr->h_source, |
664 | if (!neigh_curr || !neigh_old) | 657 | ethhdr->h_dest); |
665 | goto free_neigh; | 658 | if (!orig_dst_node) |
666 | if (neigh_curr->tq_avg - neigh_old->tq_avg < | 659 | goto out; |
667 | GW_THRESHOLD) | 660 | |
668 | ret = -1; | 661 | if (!orig_dst_node->gw_flags) |
669 | } | 662 | goto out; |
663 | |||
664 | ret = is_type_dhcprequest(skb, header_len); | ||
665 | if (!ret) | ||
666 | goto out; | ||
667 | |||
668 | switch (atomic_read(&bat_priv->gw_mode)) { | ||
669 | case GW_MODE_SERVER: | ||
670 | /* If we are a GW then we are our best GW. We can artificially | ||
671 | * set the tq towards ourself as the maximum value */ | ||
672 | curr_tq_avg = TQ_MAX_VALUE; | ||
673 | break; | ||
674 | case GW_MODE_CLIENT: | ||
675 | curr_gw = gw_get_selected_gw_node(bat_priv); | ||
676 | if (!curr_gw) | ||
677 | goto out; | ||
678 | |||
679 | /* packet is going to our gateway */ | ||
680 | if (curr_gw->orig_node == orig_dst_node) | ||
681 | goto out; | ||
682 | |||
683 | /* If the dhcp packet has been sent to a different gw, | ||
684 | * we have to evaluate whether the old gw is still | ||
685 | * reliable enough */ | ||
686 | neigh_curr = find_router(bat_priv, curr_gw->orig_node, NULL); | ||
687 | if (!neigh_curr) | ||
688 | goto out; | ||
689 | |||
690 | curr_tq_avg = neigh_curr->tq_avg; | ||
691 | break; | ||
692 | case GW_MODE_OFF: | ||
693 | default: | ||
694 | goto out; | ||
670 | } | 695 | } |
671 | free_neigh: | 696 | |
697 | neigh_old = find_router(bat_priv, orig_dst_node, NULL); | ||
698 | if (!neigh_old) | ||
699 | goto out; | ||
700 | |||
701 | if (curr_tq_avg - neigh_old->tq_avg > GW_THRESHOLD) | ||
702 | out_of_range = true; | ||
703 | |||
704 | out: | ||
705 | if (orig_dst_node) | ||
706 | orig_node_free_ref(orig_dst_node); | ||
707 | if (curr_gw) | ||
708 | gw_node_free_ref(curr_gw); | ||
672 | if (neigh_old) | 709 | if (neigh_old) |
673 | neigh_node_free_ref(neigh_old); | 710 | neigh_node_free_ref(neigh_old); |
674 | if (neigh_curr) | 711 | if (neigh_curr) |
675 | neigh_node_free_ref(neigh_curr); | 712 | neigh_node_free_ref(neigh_curr); |
676 | if (curr_gw) | 713 | return out_of_range; |
677 | gw_node_free_ref(curr_gw); | ||
678 | return ret; | ||
679 | } | 714 | } |
diff --git a/net/batman-adv/gateway_client.h b/net/batman-adv/gateway_client.h index b9b983c07feb..e1edba08eb1d 100644 --- a/net/batman-adv/gateway_client.h +++ b/net/batman-adv/gateway_client.h | |||
@@ -31,7 +31,8 @@ void gw_node_update(struct bat_priv *bat_priv, | |||
31 | void gw_node_delete(struct bat_priv *bat_priv, struct orig_node *orig_node); | 31 | void gw_node_delete(struct bat_priv *bat_priv, struct orig_node *orig_node); |
32 | void gw_node_purge(struct bat_priv *bat_priv); | 32 | void gw_node_purge(struct bat_priv *bat_priv); |
33 | int gw_client_seq_print_text(struct seq_file *seq, void *offset); | 33 | int gw_client_seq_print_text(struct seq_file *seq, void *offset); |
34 | int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb, | 34 | bool gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len); |
35 | struct orig_node *old_gw); | 35 | bool gw_out_of_range(struct bat_priv *bat_priv, |
36 | struct sk_buff *skb, struct ethhdr *ethhdr); | ||
36 | 37 | ||
37 | #endif /* _NET_BATMAN_ADV_GATEWAY_CLIENT_H_ */ | 38 | #endif /* _NET_BATMAN_ADV_GATEWAY_CLIENT_H_ */ |
diff --git a/net/batman-adv/gateway_common.c b/net/batman-adv/gateway_common.c index 18661af0bc3b..c4ac7b0a2a63 100644 --- a/net/batman-adv/gateway_common.c +++ b/net/batman-adv/gateway_common.c | |||
@@ -97,7 +97,7 @@ static bool parse_gw_bandwidth(struct net_device *net_dev, char *buff, | |||
97 | *tmp_ptr = '\0'; | 97 | *tmp_ptr = '\0'; |
98 | } | 98 | } |
99 | 99 | ||
100 | ret = strict_strtol(buff, 10, &ldown); | 100 | ret = kstrtol(buff, 10, &ldown); |
101 | if (ret) { | 101 | if (ret) { |
102 | bat_err(net_dev, | 102 | bat_err(net_dev, |
103 | "Download speed of gateway mode invalid: %s\n", | 103 | "Download speed of gateway mode invalid: %s\n", |
@@ -122,7 +122,7 @@ static bool parse_gw_bandwidth(struct net_device *net_dev, char *buff, | |||
122 | *tmp_ptr = '\0'; | 122 | *tmp_ptr = '\0'; |
123 | } | 123 | } |
124 | 124 | ||
125 | ret = strict_strtol(slash_ptr + 1, 10, &lup); | 125 | ret = kstrtol(slash_ptr + 1, 10, &lup); |
126 | if (ret) { | 126 | if (ret) { |
127 | bat_err(net_dev, | 127 | bat_err(net_dev, |
128 | "Upload speed of gateway mode invalid: " | 128 | "Upload speed of gateway mode invalid: " |
diff --git a/net/batman-adv/hash.c b/net/batman-adv/hash.c index 2a172505f513..d1da29da333b 100644 --- a/net/batman-adv/hash.c +++ b/net/batman-adv/hash.c | |||
@@ -25,7 +25,7 @@ | |||
25 | /* clears the hash */ | 25 | /* clears the hash */ |
26 | static void hash_init(struct hashtable_t *hash) | 26 | static void hash_init(struct hashtable_t *hash) |
27 | { | 27 | { |
28 | int i; | 28 | uint32_t i; |
29 | 29 | ||
30 | for (i = 0 ; i < hash->size; i++) { | 30 | for (i = 0 ; i < hash->size; i++) { |
31 | INIT_HLIST_HEAD(&hash->table[i]); | 31 | INIT_HLIST_HEAD(&hash->table[i]); |
@@ -42,7 +42,7 @@ void hash_destroy(struct hashtable_t *hash) | |||
42 | } | 42 | } |
43 | 43 | ||
44 | /* allocates and clears the hash */ | 44 | /* allocates and clears the hash */ |
45 | struct hashtable_t *hash_new(int size) | 45 | struct hashtable_t *hash_new(uint32_t size) |
46 | { | 46 | { |
47 | struct hashtable_t *hash; | 47 | struct hashtable_t *hash; |
48 | 48 | ||
diff --git a/net/batman-adv/hash.h b/net/batman-adv/hash.h index d20aa71ba1e8..4768717f07f9 100644 --- a/net/batman-adv/hash.h +++ b/net/batman-adv/hash.h | |||
@@ -33,17 +33,17 @@ typedef int (*hashdata_compare_cb)(const struct hlist_node *, const void *); | |||
33 | /* the hashfunction, should return an index | 33 | /* the hashfunction, should return an index |
34 | * based on the key in the data of the first | 34 | * based on the key in the data of the first |
35 | * argument and the size the second */ | 35 | * argument and the size the second */ |
36 | typedef int (*hashdata_choose_cb)(const void *, int); | 36 | typedef uint32_t (*hashdata_choose_cb)(const void *, uint32_t); |
37 | typedef void (*hashdata_free_cb)(struct hlist_node *, void *); | 37 | typedef void (*hashdata_free_cb)(struct hlist_node *, void *); |
38 | 38 | ||
39 | struct hashtable_t { | 39 | struct hashtable_t { |
40 | struct hlist_head *table; /* the hashtable itself with the buckets */ | 40 | struct hlist_head *table; /* the hashtable itself with the buckets */ |
41 | spinlock_t *list_locks; /* spinlock for each hash list entry */ | 41 | spinlock_t *list_locks; /* spinlock for each hash list entry */ |
42 | int size; /* size of hashtable */ | 42 | uint32_t size; /* size of hashtable */ |
43 | }; | 43 | }; |
44 | 44 | ||
45 | /* allocates and clears the hash */ | 45 | /* allocates and clears the hash */ |
46 | struct hashtable_t *hash_new(int size); | 46 | struct hashtable_t *hash_new(uint32_t size); |
47 | 47 | ||
48 | /* free only the hashtable and the hash itself. */ | 48 | /* free only the hashtable and the hash itself. */ |
49 | void hash_destroy(struct hashtable_t *hash); | 49 | void hash_destroy(struct hashtable_t *hash); |
@@ -57,7 +57,7 @@ static inline void hash_delete(struct hashtable_t *hash, | |||
57 | struct hlist_head *head; | 57 | struct hlist_head *head; |
58 | struct hlist_node *node, *node_tmp; | 58 | struct hlist_node *node, *node_tmp; |
59 | spinlock_t *list_lock; /* spinlock to protect write access */ | 59 | spinlock_t *list_lock; /* spinlock to protect write access */ |
60 | int i; | 60 | uint32_t i; |
61 | 61 | ||
62 | for (i = 0; i < hash->size; i++) { | 62 | for (i = 0; i < hash->size; i++) { |
63 | head = &hash->table[i]; | 63 | head = &hash->table[i]; |
@@ -93,7 +93,8 @@ static inline int hash_add(struct hashtable_t *hash, | |||
93 | hashdata_choose_cb choose, | 93 | hashdata_choose_cb choose, |
94 | const void *data, struct hlist_node *data_node) | 94 | const void *data, struct hlist_node *data_node) |
95 | { | 95 | { |
96 | int index, ret = -1; | 96 | uint32_t index; |
97 | int ret = -1; | ||
97 | struct hlist_head *head; | 98 | struct hlist_head *head; |
98 | struct hlist_node *node; | 99 | struct hlist_node *node; |
99 | spinlock_t *list_lock; /* spinlock to protect write access */ | 100 | spinlock_t *list_lock; /* spinlock to protect write access */ |
@@ -137,7 +138,7 @@ static inline void *hash_remove(struct hashtable_t *hash, | |||
137 | hashdata_compare_cb compare, | 138 | hashdata_compare_cb compare, |
138 | hashdata_choose_cb choose, void *data) | 139 | hashdata_choose_cb choose, void *data) |
139 | { | 140 | { |
140 | size_t index; | 141 | uint32_t index; |
141 | struct hlist_node *node; | 142 | struct hlist_node *node; |
142 | struct hlist_head *head; | 143 | struct hlist_head *head; |
143 | void *data_save = NULL; | 144 | void *data_save = NULL; |
diff --git a/net/batman-adv/icmp_socket.c b/net/batman-adv/icmp_socket.c index ac3520e057c0..d9c1e7bb7fbf 100644 --- a/net/batman-adv/icmp_socket.c +++ b/net/batman-adv/icmp_socket.c | |||
@@ -136,10 +136,9 @@ static ssize_t bat_socket_read(struct file *file, char __user *buf, | |||
136 | 136 | ||
137 | spin_unlock_bh(&socket_client->lock); | 137 | spin_unlock_bh(&socket_client->lock); |
138 | 138 | ||
139 | error = __copy_to_user(buf, &socket_packet->icmp_packet, | 139 | packet_len = min(count, socket_packet->icmp_len); |
140 | socket_packet->icmp_len); | 140 | error = copy_to_user(buf, &socket_packet->icmp_packet, packet_len); |
141 | 141 | ||
142 | packet_len = socket_packet->icmp_len; | ||
143 | kfree(socket_packet); | 142 | kfree(socket_packet); |
144 | 143 | ||
145 | if (error) | 144 | if (error) |
@@ -187,12 +186,7 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, | |||
187 | skb_reserve(skb, sizeof(struct ethhdr)); | 186 | skb_reserve(skb, sizeof(struct ethhdr)); |
188 | icmp_packet = (struct icmp_packet_rr *)skb_put(skb, packet_len); | 187 | icmp_packet = (struct icmp_packet_rr *)skb_put(skb, packet_len); |
189 | 188 | ||
190 | if (!access_ok(VERIFY_READ, buff, packet_len)) { | 189 | if (copy_from_user(icmp_packet, buff, packet_len)) { |
191 | len = -EFAULT; | ||
192 | goto free_skb; | ||
193 | } | ||
194 | |||
195 | if (__copy_from_user(icmp_packet, buff, packet_len)) { | ||
196 | len = -EFAULT; | 190 | len = -EFAULT; |
197 | goto free_skb; | 191 | goto free_skb; |
198 | } | 192 | } |
@@ -217,7 +211,7 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, | |||
217 | 211 | ||
218 | if (icmp_packet->version != COMPAT_VERSION) { | 212 | if (icmp_packet->version != COMPAT_VERSION) { |
219 | icmp_packet->msg_type = PARAMETER_PROBLEM; | 213 | icmp_packet->msg_type = PARAMETER_PROBLEM; |
220 | icmp_packet->ttl = COMPAT_VERSION; | 214 | icmp_packet->version = COMPAT_VERSION; |
221 | bat_socket_add_packet(socket_client, icmp_packet, packet_len); | 215 | bat_socket_add_packet(socket_client, icmp_packet, packet_len); |
222 | goto free_skb; | 216 | goto free_skb; |
223 | } | 217 | } |
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h index 964ad4d8ba33..86354e06eb48 100644 --- a/net/batman-adv/main.h +++ b/net/batman-adv/main.h | |||
@@ -28,7 +28,7 @@ | |||
28 | #define DRIVER_DEVICE "batman-adv" | 28 | #define DRIVER_DEVICE "batman-adv" |
29 | 29 | ||
30 | #ifndef SOURCE_VERSION | 30 | #ifndef SOURCE_VERSION |
31 | #define SOURCE_VERSION "2011.4.0" | 31 | #define SOURCE_VERSION "2012.0.0" |
32 | #endif | 32 | #endif |
33 | 33 | ||
34 | /* B.A.T.M.A.N. parameters */ | 34 | /* B.A.T.M.A.N. parameters */ |
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index 0e5b77255d99..0bc2045a2f2e 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c | |||
@@ -164,7 +164,7 @@ void originator_free(struct bat_priv *bat_priv) | |||
164 | struct hlist_head *head; | 164 | struct hlist_head *head; |
165 | spinlock_t *list_lock; /* spinlock to protect write access */ | 165 | spinlock_t *list_lock; /* spinlock to protect write access */ |
166 | struct orig_node *orig_node; | 166 | struct orig_node *orig_node; |
167 | int i; | 167 | uint32_t i; |
168 | 168 | ||
169 | if (!hash) | 169 | if (!hash) |
170 | return; | 170 | return; |
@@ -350,7 +350,7 @@ static void _purge_orig(struct bat_priv *bat_priv) | |||
350 | struct hlist_head *head; | 350 | struct hlist_head *head; |
351 | spinlock_t *list_lock; /* spinlock to protect write access */ | 351 | spinlock_t *list_lock; /* spinlock to protect write access */ |
352 | struct orig_node *orig_node; | 352 | struct orig_node *orig_node; |
353 | int i; | 353 | uint32_t i; |
354 | 354 | ||
355 | if (!hash) | 355 | if (!hash) |
356 | return; | 356 | return; |
@@ -413,7 +413,8 @@ int orig_seq_print_text(struct seq_file *seq, void *offset) | |||
413 | int batman_count = 0; | 413 | int batman_count = 0; |
414 | int last_seen_secs; | 414 | int last_seen_secs; |
415 | int last_seen_msecs; | 415 | int last_seen_msecs; |
416 | int i, ret = 0; | 416 | uint32_t i; |
417 | int ret = 0; | ||
417 | 418 | ||
418 | primary_if = primary_if_get_selected(bat_priv); | 419 | primary_if = primary_if_get_selected(bat_priv); |
419 | 420 | ||
@@ -519,7 +520,8 @@ int orig_hash_add_if(struct hard_iface *hard_iface, int max_if_num) | |||
519 | struct hlist_node *node; | 520 | struct hlist_node *node; |
520 | struct hlist_head *head; | 521 | struct hlist_head *head; |
521 | struct orig_node *orig_node; | 522 | struct orig_node *orig_node; |
522 | int i, ret; | 523 | uint32_t i; |
524 | int ret; | ||
523 | 525 | ||
524 | /* resize all orig nodes because orig_node->bcast_own(_sum) depend on | 526 | /* resize all orig nodes because orig_node->bcast_own(_sum) depend on |
525 | * if_num */ | 527 | * if_num */ |
@@ -601,7 +603,8 @@ int orig_hash_del_if(struct hard_iface *hard_iface, int max_if_num) | |||
601 | struct hlist_head *head; | 603 | struct hlist_head *head; |
602 | struct hard_iface *hard_iface_tmp; | 604 | struct hard_iface *hard_iface_tmp; |
603 | struct orig_node *orig_node; | 605 | struct orig_node *orig_node; |
604 | int i, ret; | 606 | uint32_t i; |
607 | int ret; | ||
605 | 608 | ||
606 | /* resize all orig nodes because orig_node->bcast_own(_sum) depend on | 609 | /* resize all orig nodes because orig_node->bcast_own(_sum) depend on |
607 | * if_num */ | 610 | * if_num */ |
diff --git a/net/batman-adv/originator.h b/net/batman-adv/originator.h index cfc1f60a96a1..67765ffef731 100644 --- a/net/batman-adv/originator.h +++ b/net/batman-adv/originator.h | |||
@@ -42,7 +42,7 @@ int orig_hash_del_if(struct hard_iface *hard_iface, int max_if_num); | |||
42 | 42 | ||
43 | /* hashfunction to choose an entry in a hash table of given size */ | 43 | /* hashfunction to choose an entry in a hash table of given size */ |
44 | /* hash algorithm from http://en.wikipedia.org/wiki/Hash_table */ | 44 | /* hash algorithm from http://en.wikipedia.org/wiki/Hash_table */ |
45 | static inline int choose_orig(const void *data, int32_t size) | 45 | static inline uint32_t choose_orig(const void *data, uint32_t size) |
46 | { | 46 | { |
47 | const unsigned char *key = data; | 47 | const unsigned char *key = data; |
48 | uint32_t hash = 0; | 48 | uint32_t hash = 0; |
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index f961cc5eade5..773e606f9702 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c | |||
@@ -39,7 +39,7 @@ void slide_own_bcast_window(struct hard_iface *hard_iface) | |||
39 | struct hlist_head *head; | 39 | struct hlist_head *head; |
40 | struct orig_node *orig_node; | 40 | struct orig_node *orig_node; |
41 | unsigned long *word; | 41 | unsigned long *word; |
42 | int i; | 42 | uint32_t i; |
43 | size_t word_index; | 43 | size_t word_index; |
44 | 44 | ||
45 | for (i = 0; i < hash->size; i++) { | 45 | for (i = 0; i < hash->size; i++) { |
@@ -578,6 +578,7 @@ int recv_tt_query(struct sk_buff *skb, struct hard_iface *recv_if) | |||
578 | { | 578 | { |
579 | struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface); | 579 | struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface); |
580 | struct tt_query_packet *tt_query; | 580 | struct tt_query_packet *tt_query; |
581 | uint16_t tt_len; | ||
581 | struct ethhdr *ethhdr; | 582 | struct ethhdr *ethhdr; |
582 | 583 | ||
583 | /* drop packet if it has not necessary minimum size */ | 584 | /* drop packet if it has not necessary minimum size */ |
@@ -616,13 +617,21 @@ int recv_tt_query(struct sk_buff *skb, struct hard_iface *recv_if) | |||
616 | } | 617 | } |
617 | break; | 618 | break; |
618 | case TT_RESPONSE: | 619 | case TT_RESPONSE: |
619 | /* packet needs to be linearized to access the TT changes */ | 620 | if (is_my_mac(tt_query->dst)) { |
620 | if (skb_linearize(skb) < 0) | 621 | /* packet needs to be linearized to access the TT |
621 | goto out; | 622 | * changes */ |
623 | if (skb_linearize(skb) < 0) | ||
624 | goto out; | ||
625 | |||
626 | tt_len = tt_query->tt_data * sizeof(struct tt_change); | ||
627 | |||
628 | /* Ensure we have all the claimed data */ | ||
629 | if (unlikely(skb_headlen(skb) < | ||
630 | sizeof(struct tt_query_packet) + tt_len)) | ||
631 | goto out; | ||
622 | 632 | ||
623 | if (is_my_mac(tt_query->dst)) | ||
624 | handle_tt_response(bat_priv, tt_query); | 633 | handle_tt_response(bat_priv, tt_query); |
625 | else { | 634 | } else { |
626 | bat_dbg(DBG_TT, bat_priv, | 635 | bat_dbg(DBG_TT, bat_priv, |
627 | "Routing TT_RESPONSE to %pM [%c]\n", | 636 | "Routing TT_RESPONSE to %pM [%c]\n", |
628 | tt_query->dst, | 637 | tt_query->dst, |
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index f9cc95728989..987c75a775f9 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c | |||
@@ -563,10 +563,10 @@ static int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) | |||
563 | struct bcast_packet *bcast_packet; | 563 | struct bcast_packet *bcast_packet; |
564 | struct vlan_ethhdr *vhdr; | 564 | struct vlan_ethhdr *vhdr; |
565 | struct softif_neigh *curr_softif_neigh = NULL; | 565 | struct softif_neigh *curr_softif_neigh = NULL; |
566 | struct orig_node *orig_node = NULL; | 566 | unsigned int header_len = 0; |
567 | int data_len = skb->len, ret; | 567 | int data_len = skb->len, ret; |
568 | short vid = -1; | 568 | short vid = -1; |
569 | bool do_bcast; | 569 | bool do_bcast = false; |
570 | 570 | ||
571 | if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE) | 571 | if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE) |
572 | goto dropped; | 572 | goto dropped; |
@@ -598,17 +598,28 @@ static int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) | |||
598 | /* Register the client MAC in the transtable */ | 598 | /* Register the client MAC in the transtable */ |
599 | tt_local_add(soft_iface, ethhdr->h_source, skb->skb_iif); | 599 | tt_local_add(soft_iface, ethhdr->h_source, skb->skb_iif); |
600 | 600 | ||
601 | orig_node = transtable_search(bat_priv, ethhdr->h_source, | 601 | if (is_multicast_ether_addr(ethhdr->h_dest)) { |
602 | ethhdr->h_dest); | 602 | do_bcast = true; |
603 | do_bcast = is_multicast_ether_addr(ethhdr->h_dest); | ||
604 | if (do_bcast || (orig_node && orig_node->gw_flags)) { | ||
605 | ret = gw_is_target(bat_priv, skb, orig_node); | ||
606 | 603 | ||
607 | if (ret < 0) | 604 | switch (atomic_read(&bat_priv->gw_mode)) { |
608 | goto dropped; | 605 | case GW_MODE_SERVER: |
609 | 606 | /* gateway servers should not send dhcp | |
610 | if (ret) | 607 | * requests into the mesh */ |
611 | do_bcast = false; | 608 | ret = gw_is_dhcp_target(skb, &header_len); |
609 | if (ret) | ||
610 | goto dropped; | ||
611 | break; | ||
612 | case GW_MODE_CLIENT: | ||
613 | /* gateway clients should send dhcp requests | ||
614 | * via unicast to their gateway */ | ||
615 | ret = gw_is_dhcp_target(skb, &header_len); | ||
616 | if (ret) | ||
617 | do_bcast = false; | ||
618 | break; | ||
619 | case GW_MODE_OFF: | ||
620 | default: | ||
621 | break; | ||
622 | } | ||
612 | } | 623 | } |
613 | 624 | ||
614 | /* ethernet packet should be broadcasted */ | 625 | /* ethernet packet should be broadcasted */ |
@@ -644,6 +655,12 @@ static int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) | |||
644 | 655 | ||
645 | /* unicast packet */ | 656 | /* unicast packet */ |
646 | } else { | 657 | } else { |
658 | if (atomic_read(&bat_priv->gw_mode) != GW_MODE_OFF) { | ||
659 | ret = gw_out_of_range(bat_priv, skb, ethhdr); | ||
660 | if (ret) | ||
661 | goto dropped; | ||
662 | } | ||
663 | |||
647 | ret = unicast_send_skb(skb, bat_priv); | 664 | ret = unicast_send_skb(skb, bat_priv); |
648 | if (ret != 0) | 665 | if (ret != 0) |
649 | goto dropped_freed; | 666 | goto dropped_freed; |
@@ -662,8 +679,6 @@ end: | |||
662 | softif_neigh_free_ref(curr_softif_neigh); | 679 | softif_neigh_free_ref(curr_softif_neigh); |
663 | if (primary_if) | 680 | if (primary_if) |
664 | hardif_free_ref(primary_if); | 681 | hardif_free_ref(primary_if); |
665 | if (orig_node) | ||
666 | orig_node_free_ref(orig_node); | ||
667 | return NETDEV_TX_OK; | 682 | return NETDEV_TX_OK; |
668 | } | 683 | } |
669 | 684 | ||
@@ -859,7 +874,7 @@ unreg_debugfs: | |||
859 | unreg_sysfs: | 874 | unreg_sysfs: |
860 | sysfs_del_meshif(soft_iface); | 875 | sysfs_del_meshif(soft_iface); |
861 | unreg_soft_iface: | 876 | unreg_soft_iface: |
862 | unregister_netdev(soft_iface); | 877 | unregister_netdevice(soft_iface); |
863 | return NULL; | 878 | return NULL; |
864 | 879 | ||
865 | free_soft_iface: | 880 | free_soft_iface: |
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index 5f09a578d49d..ab8dea8b0b2e 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c | |||
@@ -36,18 +36,9 @@ static void _tt_global_del(struct bat_priv *bat_priv, | |||
36 | static void tt_purge(struct work_struct *work); | 36 | static void tt_purge(struct work_struct *work); |
37 | 37 | ||
38 | /* returns 1 if they are the same mac addr */ | 38 | /* returns 1 if they are the same mac addr */ |
39 | static int compare_ltt(const struct hlist_node *node, const void *data2) | 39 | static int compare_tt(const struct hlist_node *node, const void *data2) |
40 | { | 40 | { |
41 | const void *data1 = container_of(node, struct tt_local_entry, | 41 | const void *data1 = container_of(node, struct tt_common_entry, |
42 | hash_entry); | ||
43 | |||
44 | return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0); | ||
45 | } | ||
46 | |||
47 | /* returns 1 if they are the same mac addr */ | ||
48 | static int compare_gtt(const struct hlist_node *node, const void *data2) | ||
49 | { | ||
50 | const void *data1 = container_of(node, struct tt_global_entry, | ||
51 | hash_entry); | 42 | hash_entry); |
52 | 43 | ||
53 | return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0); | 44 | return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0); |
@@ -60,14 +51,13 @@ static void tt_start_timer(struct bat_priv *bat_priv) | |||
60 | msecs_to_jiffies(5000)); | 51 | msecs_to_jiffies(5000)); |
61 | } | 52 | } |
62 | 53 | ||
63 | static struct tt_local_entry *tt_local_hash_find(struct bat_priv *bat_priv, | 54 | static struct tt_common_entry *tt_hash_find(struct hashtable_t *hash, |
64 | const void *data) | 55 | const void *data) |
65 | { | 56 | { |
66 | struct hashtable_t *hash = bat_priv->tt_local_hash; | ||
67 | struct hlist_head *head; | 57 | struct hlist_head *head; |
68 | struct hlist_node *node; | 58 | struct hlist_node *node; |
69 | struct tt_local_entry *tt_local_entry, *tt_local_entry_tmp = NULL; | 59 | struct tt_common_entry *tt_common_entry, *tt_common_entry_tmp = NULL; |
70 | int index; | 60 | uint32_t index; |
71 | 61 | ||
72 | if (!hash) | 62 | if (!hash) |
73 | return NULL; | 63 | return NULL; |
@@ -76,51 +66,46 @@ static struct tt_local_entry *tt_local_hash_find(struct bat_priv *bat_priv, | |||
76 | head = &hash->table[index]; | 66 | head = &hash->table[index]; |
77 | 67 | ||
78 | rcu_read_lock(); | 68 | rcu_read_lock(); |
79 | hlist_for_each_entry_rcu(tt_local_entry, node, head, hash_entry) { | 69 | hlist_for_each_entry_rcu(tt_common_entry, node, head, hash_entry) { |
80 | if (!compare_eth(tt_local_entry, data)) | 70 | if (!compare_eth(tt_common_entry, data)) |
81 | continue; | 71 | continue; |
82 | 72 | ||
83 | if (!atomic_inc_not_zero(&tt_local_entry->refcount)) | 73 | if (!atomic_inc_not_zero(&tt_common_entry->refcount)) |
84 | continue; | 74 | continue; |
85 | 75 | ||
86 | tt_local_entry_tmp = tt_local_entry; | 76 | tt_common_entry_tmp = tt_common_entry; |
87 | break; | 77 | break; |
88 | } | 78 | } |
89 | rcu_read_unlock(); | 79 | rcu_read_unlock(); |
90 | 80 | ||
91 | return tt_local_entry_tmp; | 81 | return tt_common_entry_tmp; |
92 | } | 82 | } |
93 | 83 | ||
94 | static struct tt_global_entry *tt_global_hash_find(struct bat_priv *bat_priv, | 84 | static struct tt_local_entry *tt_local_hash_find(struct bat_priv *bat_priv, |
95 | const void *data) | 85 | const void *data) |
96 | { | 86 | { |
97 | struct hashtable_t *hash = bat_priv->tt_global_hash; | 87 | struct tt_common_entry *tt_common_entry; |
98 | struct hlist_head *head; | 88 | struct tt_local_entry *tt_local_entry = NULL; |
99 | struct hlist_node *node; | ||
100 | struct tt_global_entry *tt_global_entry; | ||
101 | struct tt_global_entry *tt_global_entry_tmp = NULL; | ||
102 | int index; | ||
103 | |||
104 | if (!hash) | ||
105 | return NULL; | ||
106 | |||
107 | index = choose_orig(data, hash->size); | ||
108 | head = &hash->table[index]; | ||
109 | 89 | ||
110 | rcu_read_lock(); | 90 | tt_common_entry = tt_hash_find(bat_priv->tt_local_hash, data); |
111 | hlist_for_each_entry_rcu(tt_global_entry, node, head, hash_entry) { | 91 | if (tt_common_entry) |
112 | if (!compare_eth(tt_global_entry, data)) | 92 | tt_local_entry = container_of(tt_common_entry, |
113 | continue; | 93 | struct tt_local_entry, common); |
94 | return tt_local_entry; | ||
95 | } | ||
114 | 96 | ||
115 | if (!atomic_inc_not_zero(&tt_global_entry->refcount)) | 97 | static struct tt_global_entry *tt_global_hash_find(struct bat_priv *bat_priv, |
116 | continue; | 98 | const void *data) |
99 | { | ||
100 | struct tt_common_entry *tt_common_entry; | ||
101 | struct tt_global_entry *tt_global_entry = NULL; | ||
117 | 102 | ||
118 | tt_global_entry_tmp = tt_global_entry; | 103 | tt_common_entry = tt_hash_find(bat_priv->tt_global_hash, data); |
119 | break; | 104 | if (tt_common_entry) |
120 | } | 105 | tt_global_entry = container_of(tt_common_entry, |
121 | rcu_read_unlock(); | 106 | struct tt_global_entry, common); |
107 | return tt_global_entry; | ||
122 | 108 | ||
123 | return tt_global_entry_tmp; | ||
124 | } | 109 | } |
125 | 110 | ||
126 | static bool is_out_of_time(unsigned long starting_time, unsigned long timeout) | 111 | static bool is_out_of_time(unsigned long starting_time, unsigned long timeout) |
@@ -133,15 +118,18 @@ static bool is_out_of_time(unsigned long starting_time, unsigned long timeout) | |||
133 | 118 | ||
134 | static void tt_local_entry_free_ref(struct tt_local_entry *tt_local_entry) | 119 | static void tt_local_entry_free_ref(struct tt_local_entry *tt_local_entry) |
135 | { | 120 | { |
136 | if (atomic_dec_and_test(&tt_local_entry->refcount)) | 121 | if (atomic_dec_and_test(&tt_local_entry->common.refcount)) |
137 | kfree_rcu(tt_local_entry, rcu); | 122 | kfree_rcu(tt_local_entry, common.rcu); |
138 | } | 123 | } |
139 | 124 | ||
140 | static void tt_global_entry_free_rcu(struct rcu_head *rcu) | 125 | static void tt_global_entry_free_rcu(struct rcu_head *rcu) |
141 | { | 126 | { |
127 | struct tt_common_entry *tt_common_entry; | ||
142 | struct tt_global_entry *tt_global_entry; | 128 | struct tt_global_entry *tt_global_entry; |
143 | 129 | ||
144 | tt_global_entry = container_of(rcu, struct tt_global_entry, rcu); | 130 | tt_common_entry = container_of(rcu, struct tt_common_entry, rcu); |
131 | tt_global_entry = container_of(tt_common_entry, struct tt_global_entry, | ||
132 | common); | ||
145 | 133 | ||
146 | if (tt_global_entry->orig_node) | 134 | if (tt_global_entry->orig_node) |
147 | orig_node_free_ref(tt_global_entry->orig_node); | 135 | orig_node_free_ref(tt_global_entry->orig_node); |
@@ -151,8 +139,9 @@ static void tt_global_entry_free_rcu(struct rcu_head *rcu) | |||
151 | 139 | ||
152 | static void tt_global_entry_free_ref(struct tt_global_entry *tt_global_entry) | 140 | static void tt_global_entry_free_ref(struct tt_global_entry *tt_global_entry) |
153 | { | 141 | { |
154 | if (atomic_dec_and_test(&tt_global_entry->refcount)) | 142 | if (atomic_dec_and_test(&tt_global_entry->common.refcount)) |
155 | call_rcu(&tt_global_entry->rcu, tt_global_entry_free_rcu); | 143 | call_rcu(&tt_global_entry->common.rcu, |
144 | tt_global_entry_free_rcu); | ||
156 | } | 145 | } |
157 | 146 | ||
158 | static void tt_local_event(struct bat_priv *bat_priv, const uint8_t *addr, | 147 | static void tt_local_event(struct bat_priv *bat_priv, const uint8_t *addr, |
@@ -201,6 +190,7 @@ void tt_local_add(struct net_device *soft_iface, const uint8_t *addr, | |||
201 | struct bat_priv *bat_priv = netdev_priv(soft_iface); | 190 | struct bat_priv *bat_priv = netdev_priv(soft_iface); |
202 | struct tt_local_entry *tt_local_entry = NULL; | 191 | struct tt_local_entry *tt_local_entry = NULL; |
203 | struct tt_global_entry *tt_global_entry = NULL; | 192 | struct tt_global_entry *tt_global_entry = NULL; |
193 | int hash_added; | ||
204 | 194 | ||
205 | tt_local_entry = tt_local_hash_find(bat_priv, addr); | 195 | tt_local_entry = tt_local_hash_find(bat_priv, addr); |
206 | 196 | ||
@@ -217,26 +207,33 @@ void tt_local_add(struct net_device *soft_iface, const uint8_t *addr, | |||
217 | "Creating new local tt entry: %pM (ttvn: %d)\n", addr, | 207 | "Creating new local tt entry: %pM (ttvn: %d)\n", addr, |
218 | (uint8_t)atomic_read(&bat_priv->ttvn)); | 208 | (uint8_t)atomic_read(&bat_priv->ttvn)); |
219 | 209 | ||
220 | memcpy(tt_local_entry->addr, addr, ETH_ALEN); | 210 | memcpy(tt_local_entry->common.addr, addr, ETH_ALEN); |
221 | tt_local_entry->last_seen = jiffies; | 211 | tt_local_entry->common.flags = NO_FLAGS; |
222 | tt_local_entry->flags = NO_FLAGS; | ||
223 | if (is_wifi_iface(ifindex)) | 212 | if (is_wifi_iface(ifindex)) |
224 | tt_local_entry->flags |= TT_CLIENT_WIFI; | 213 | tt_local_entry->common.flags |= TT_CLIENT_WIFI; |
225 | atomic_set(&tt_local_entry->refcount, 2); | 214 | atomic_set(&tt_local_entry->common.refcount, 2); |
215 | tt_local_entry->last_seen = jiffies; | ||
226 | 216 | ||
227 | /* the batman interface mac address should never be purged */ | 217 | /* the batman interface mac address should never be purged */ |
228 | if (compare_eth(addr, soft_iface->dev_addr)) | 218 | if (compare_eth(addr, soft_iface->dev_addr)) |
229 | tt_local_entry->flags |= TT_CLIENT_NOPURGE; | 219 | tt_local_entry->common.flags |= TT_CLIENT_NOPURGE; |
220 | |||
221 | hash_added = hash_add(bat_priv->tt_local_hash, compare_tt, choose_orig, | ||
222 | &tt_local_entry->common, | ||
223 | &tt_local_entry->common.hash_entry); | ||
224 | |||
225 | if (unlikely(hash_added != 0)) { | ||
226 | /* remove the reference for the hash */ | ||
227 | tt_local_entry_free_ref(tt_local_entry); | ||
228 | goto out; | ||
229 | } | ||
230 | 230 | ||
231 | tt_local_event(bat_priv, addr, tt_local_entry->flags); | 231 | tt_local_event(bat_priv, addr, tt_local_entry->common.flags); |
232 | 232 | ||
233 | /* The local entry has to be marked as NEW to avoid to send it in | 233 | /* The local entry has to be marked as NEW to avoid to send it in |
234 | * a full table response going out before the next ttvn increment | 234 | * a full table response going out before the next ttvn increment |
235 | * (consistency check) */ | 235 | * (consistency check) */ |
236 | tt_local_entry->flags |= TT_CLIENT_NEW; | 236 | tt_local_entry->common.flags |= TT_CLIENT_NEW; |
237 | |||
238 | hash_add(bat_priv->tt_local_hash, compare_ltt, choose_orig, | ||
239 | tt_local_entry, &tt_local_entry->hash_entry); | ||
240 | 237 | ||
241 | /* remove address from global hash if present */ | 238 | /* remove address from global hash if present */ |
242 | tt_global_entry = tt_global_hash_find(bat_priv, addr); | 239 | tt_global_entry = tt_global_hash_find(bat_priv, addr); |
@@ -247,10 +244,9 @@ void tt_local_add(struct net_device *soft_iface, const uint8_t *addr, | |||
247 | tt_global_entry->orig_node->tt_poss_change = true; | 244 | tt_global_entry->orig_node->tt_poss_change = true; |
248 | /* The global entry has to be marked as ROAMING and has to be | 245 | /* The global entry has to be marked as ROAMING and has to be |
249 | * kept for consistency purpose */ | 246 | * kept for consistency purpose */ |
250 | tt_global_entry->flags |= TT_CLIENT_ROAM; | 247 | tt_global_entry->common.flags |= TT_CLIENT_ROAM; |
251 | tt_global_entry->roam_at = jiffies; | 248 | tt_global_entry->roam_at = jiffies; |
252 | 249 | send_roam_adv(bat_priv, tt_global_entry->common.addr, | |
253 | send_roam_adv(bat_priv, tt_global_entry->addr, | ||
254 | tt_global_entry->orig_node); | 250 | tt_global_entry->orig_node); |
255 | } | 251 | } |
256 | out: | 252 | out: |
@@ -312,13 +308,12 @@ int tt_local_seq_print_text(struct seq_file *seq, void *offset) | |||
312 | struct net_device *net_dev = (struct net_device *)seq->private; | 308 | struct net_device *net_dev = (struct net_device *)seq->private; |
313 | struct bat_priv *bat_priv = netdev_priv(net_dev); | 309 | struct bat_priv *bat_priv = netdev_priv(net_dev); |
314 | struct hashtable_t *hash = bat_priv->tt_local_hash; | 310 | struct hashtable_t *hash = bat_priv->tt_local_hash; |
315 | struct tt_local_entry *tt_local_entry; | 311 | struct tt_common_entry *tt_common_entry; |
316 | struct hard_iface *primary_if; | 312 | struct hard_iface *primary_if; |
317 | struct hlist_node *node; | 313 | struct hlist_node *node; |
318 | struct hlist_head *head; | 314 | struct hlist_head *head; |
319 | size_t buf_size, pos; | 315 | uint32_t i; |
320 | char *buff; | 316 | int ret = 0; |
321 | int i, ret = 0; | ||
322 | 317 | ||
323 | primary_if = primary_if_get_selected(bat_priv); | 318 | primary_if = primary_if_get_selected(bat_priv); |
324 | if (!primary_if) { | 319 | if (!primary_if) { |
@@ -339,51 +334,27 @@ int tt_local_seq_print_text(struct seq_file *seq, void *offset) | |||
339 | "announced via TT (TTVN: %u):\n", | 334 | "announced via TT (TTVN: %u):\n", |
340 | net_dev->name, (uint8_t)atomic_read(&bat_priv->ttvn)); | 335 | net_dev->name, (uint8_t)atomic_read(&bat_priv->ttvn)); |
341 | 336 | ||
342 | buf_size = 1; | ||
343 | /* Estimate length for: " * xx:xx:xx:xx:xx:xx\n" */ | ||
344 | for (i = 0; i < hash->size; i++) { | 337 | for (i = 0; i < hash->size; i++) { |
345 | head = &hash->table[i]; | 338 | head = &hash->table[i]; |
346 | 339 | ||
347 | rcu_read_lock(); | 340 | rcu_read_lock(); |
348 | __hlist_for_each_rcu(node, head) | 341 | hlist_for_each_entry_rcu(tt_common_entry, node, |
349 | buf_size += 29; | ||
350 | rcu_read_unlock(); | ||
351 | } | ||
352 | |||
353 | buff = kmalloc(buf_size, GFP_ATOMIC); | ||
354 | if (!buff) { | ||
355 | ret = -ENOMEM; | ||
356 | goto out; | ||
357 | } | ||
358 | |||
359 | buff[0] = '\0'; | ||
360 | pos = 0; | ||
361 | |||
362 | for (i = 0; i < hash->size; i++) { | ||
363 | head = &hash->table[i]; | ||
364 | |||
365 | rcu_read_lock(); | ||
366 | hlist_for_each_entry_rcu(tt_local_entry, node, | ||
367 | head, hash_entry) { | 342 | head, hash_entry) { |
368 | pos += snprintf(buff + pos, 30, " * %pM " | 343 | seq_printf(seq, " * %pM [%c%c%c%c%c]\n", |
369 | "[%c%c%c%c%c]\n", | 344 | tt_common_entry->addr, |
370 | tt_local_entry->addr, | 345 | (tt_common_entry->flags & |
371 | (tt_local_entry->flags & | ||
372 | TT_CLIENT_ROAM ? 'R' : '.'), | 346 | TT_CLIENT_ROAM ? 'R' : '.'), |
373 | (tt_local_entry->flags & | 347 | (tt_common_entry->flags & |
374 | TT_CLIENT_NOPURGE ? 'P' : '.'), | 348 | TT_CLIENT_NOPURGE ? 'P' : '.'), |
375 | (tt_local_entry->flags & | 349 | (tt_common_entry->flags & |
376 | TT_CLIENT_NEW ? 'N' : '.'), | 350 | TT_CLIENT_NEW ? 'N' : '.'), |
377 | (tt_local_entry->flags & | 351 | (tt_common_entry->flags & |
378 | TT_CLIENT_PENDING ? 'X' : '.'), | 352 | TT_CLIENT_PENDING ? 'X' : '.'), |
379 | (tt_local_entry->flags & | 353 | (tt_common_entry->flags & |
380 | TT_CLIENT_WIFI ? 'W' : '.')); | 354 | TT_CLIENT_WIFI ? 'W' : '.')); |
381 | } | 355 | } |
382 | rcu_read_unlock(); | 356 | rcu_read_unlock(); |
383 | } | 357 | } |
384 | |||
385 | seq_printf(seq, "%s", buff); | ||
386 | kfree(buff); | ||
387 | out: | 358 | out: |
388 | if (primary_if) | 359 | if (primary_if) |
389 | hardif_free_ref(primary_if); | 360 | hardif_free_ref(primary_if); |
@@ -394,13 +365,13 @@ static void tt_local_set_pending(struct bat_priv *bat_priv, | |||
394 | struct tt_local_entry *tt_local_entry, | 365 | struct tt_local_entry *tt_local_entry, |
395 | uint16_t flags) | 366 | uint16_t flags) |
396 | { | 367 | { |
397 | tt_local_event(bat_priv, tt_local_entry->addr, | 368 | tt_local_event(bat_priv, tt_local_entry->common.addr, |
398 | tt_local_entry->flags | flags); | 369 | tt_local_entry->common.flags | flags); |
399 | 370 | ||
400 | /* The local client has to be marked as "pending to be removed" but has | 371 | /* The local client has to be marked as "pending to be removed" but has |
401 | * to be kept in the table in order to send it in a full table | 372 | * to be kept in the table in order to send it in a full table |
402 | * response issued before the net ttvn increment (consistency check) */ | 373 | * response issued before the net ttvn increment (consistency check) */ |
403 | tt_local_entry->flags |= TT_CLIENT_PENDING; | 374 | tt_local_entry->common.flags |= TT_CLIENT_PENDING; |
404 | } | 375 | } |
405 | 376 | ||
406 | void tt_local_remove(struct bat_priv *bat_priv, const uint8_t *addr, | 377 | void tt_local_remove(struct bat_priv *bat_priv, const uint8_t *addr, |
@@ -416,7 +387,7 @@ void tt_local_remove(struct bat_priv *bat_priv, const uint8_t *addr, | |||
416 | (roaming ? TT_CLIENT_ROAM : NO_FLAGS)); | 387 | (roaming ? TT_CLIENT_ROAM : NO_FLAGS)); |
417 | 388 | ||
418 | bat_dbg(DBG_TT, bat_priv, "Local tt entry (%pM) pending to be removed: " | 389 | bat_dbg(DBG_TT, bat_priv, "Local tt entry (%pM) pending to be removed: " |
419 | "%s\n", tt_local_entry->addr, message); | 390 | "%s\n", tt_local_entry->common.addr, message); |
420 | out: | 391 | out: |
421 | if (tt_local_entry) | 392 | if (tt_local_entry) |
422 | tt_local_entry_free_ref(tt_local_entry); | 393 | tt_local_entry_free_ref(tt_local_entry); |
@@ -426,23 +397,27 @@ static void tt_local_purge(struct bat_priv *bat_priv) | |||
426 | { | 397 | { |
427 | struct hashtable_t *hash = bat_priv->tt_local_hash; | 398 | struct hashtable_t *hash = bat_priv->tt_local_hash; |
428 | struct tt_local_entry *tt_local_entry; | 399 | struct tt_local_entry *tt_local_entry; |
400 | struct tt_common_entry *tt_common_entry; | ||
429 | struct hlist_node *node, *node_tmp; | 401 | struct hlist_node *node, *node_tmp; |
430 | struct hlist_head *head; | 402 | struct hlist_head *head; |
431 | spinlock_t *list_lock; /* protects write access to the hash lists */ | 403 | spinlock_t *list_lock; /* protects write access to the hash lists */ |
432 | int i; | 404 | uint32_t i; |
433 | 405 | ||
434 | for (i = 0; i < hash->size; i++) { | 406 | for (i = 0; i < hash->size; i++) { |
435 | head = &hash->table[i]; | 407 | head = &hash->table[i]; |
436 | list_lock = &hash->list_locks[i]; | 408 | list_lock = &hash->list_locks[i]; |
437 | 409 | ||
438 | spin_lock_bh(list_lock); | 410 | spin_lock_bh(list_lock); |
439 | hlist_for_each_entry_safe(tt_local_entry, node, node_tmp, | 411 | hlist_for_each_entry_safe(tt_common_entry, node, node_tmp, |
440 | head, hash_entry) { | 412 | head, hash_entry) { |
441 | if (tt_local_entry->flags & TT_CLIENT_NOPURGE) | 413 | tt_local_entry = container_of(tt_common_entry, |
414 | struct tt_local_entry, | ||
415 | common); | ||
416 | if (tt_local_entry->common.flags & TT_CLIENT_NOPURGE) | ||
442 | continue; | 417 | continue; |
443 | 418 | ||
444 | /* entry already marked for deletion */ | 419 | /* entry already marked for deletion */ |
445 | if (tt_local_entry->flags & TT_CLIENT_PENDING) | 420 | if (tt_local_entry->common.flags & TT_CLIENT_PENDING) |
446 | continue; | 421 | continue; |
447 | 422 | ||
448 | if (!is_out_of_time(tt_local_entry->last_seen, | 423 | if (!is_out_of_time(tt_local_entry->last_seen, |
@@ -453,7 +428,7 @@ static void tt_local_purge(struct bat_priv *bat_priv) | |||
453 | TT_CLIENT_DEL); | 428 | TT_CLIENT_DEL); |
454 | bat_dbg(DBG_TT, bat_priv, "Local tt entry (%pM) " | 429 | bat_dbg(DBG_TT, bat_priv, "Local tt entry (%pM) " |
455 | "pending to be removed: timed out\n", | 430 | "pending to be removed: timed out\n", |
456 | tt_local_entry->addr); | 431 | tt_local_entry->common.addr); |
457 | } | 432 | } |
458 | spin_unlock_bh(list_lock); | 433 | spin_unlock_bh(list_lock); |
459 | } | 434 | } |
@@ -464,10 +439,11 @@ static void tt_local_table_free(struct bat_priv *bat_priv) | |||
464 | { | 439 | { |
465 | struct hashtable_t *hash; | 440 | struct hashtable_t *hash; |
466 | spinlock_t *list_lock; /* protects write access to the hash lists */ | 441 | spinlock_t *list_lock; /* protects write access to the hash lists */ |
442 | struct tt_common_entry *tt_common_entry; | ||
467 | struct tt_local_entry *tt_local_entry; | 443 | struct tt_local_entry *tt_local_entry; |
468 | struct hlist_node *node, *node_tmp; | 444 | struct hlist_node *node, *node_tmp; |
469 | struct hlist_head *head; | 445 | struct hlist_head *head; |
470 | int i; | 446 | uint32_t i; |
471 | 447 | ||
472 | if (!bat_priv->tt_local_hash) | 448 | if (!bat_priv->tt_local_hash) |
473 | return; | 449 | return; |
@@ -479,9 +455,12 @@ static void tt_local_table_free(struct bat_priv *bat_priv) | |||
479 | list_lock = &hash->list_locks[i]; | 455 | list_lock = &hash->list_locks[i]; |
480 | 456 | ||
481 | spin_lock_bh(list_lock); | 457 | spin_lock_bh(list_lock); |
482 | hlist_for_each_entry_safe(tt_local_entry, node, node_tmp, | 458 | hlist_for_each_entry_safe(tt_common_entry, node, node_tmp, |
483 | head, hash_entry) { | 459 | head, hash_entry) { |
484 | hlist_del_rcu(node); | 460 | hlist_del_rcu(node); |
461 | tt_local_entry = container_of(tt_common_entry, | ||
462 | struct tt_local_entry, | ||
463 | common); | ||
485 | tt_local_entry_free_ref(tt_local_entry); | 464 | tt_local_entry_free_ref(tt_local_entry); |
486 | } | 465 | } |
487 | spin_unlock_bh(list_lock); | 466 | spin_unlock_bh(list_lock); |
@@ -529,6 +508,7 @@ int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node, | |||
529 | struct tt_global_entry *tt_global_entry; | 508 | struct tt_global_entry *tt_global_entry; |
530 | struct orig_node *orig_node_tmp; | 509 | struct orig_node *orig_node_tmp; |
531 | int ret = 0; | 510 | int ret = 0; |
511 | int hash_added; | ||
532 | 512 | ||
533 | tt_global_entry = tt_global_hash_find(bat_priv, tt_addr); | 513 | tt_global_entry = tt_global_hash_find(bat_priv, tt_addr); |
534 | 514 | ||
@@ -539,18 +519,24 @@ int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node, | |||
539 | if (!tt_global_entry) | 519 | if (!tt_global_entry) |
540 | goto out; | 520 | goto out; |
541 | 521 | ||
542 | memcpy(tt_global_entry->addr, tt_addr, ETH_ALEN); | 522 | memcpy(tt_global_entry->common.addr, tt_addr, ETH_ALEN); |
523 | tt_global_entry->common.flags = NO_FLAGS; | ||
524 | atomic_set(&tt_global_entry->common.refcount, 2); | ||
543 | /* Assign the new orig_node */ | 525 | /* Assign the new orig_node */ |
544 | atomic_inc(&orig_node->refcount); | 526 | atomic_inc(&orig_node->refcount); |
545 | tt_global_entry->orig_node = orig_node; | 527 | tt_global_entry->orig_node = orig_node; |
546 | tt_global_entry->ttvn = ttvn; | 528 | tt_global_entry->ttvn = ttvn; |
547 | tt_global_entry->flags = NO_FLAGS; | ||
548 | tt_global_entry->roam_at = 0; | 529 | tt_global_entry->roam_at = 0; |
549 | atomic_set(&tt_global_entry->refcount, 2); | ||
550 | 530 | ||
551 | hash_add(bat_priv->tt_global_hash, compare_gtt, | 531 | hash_added = hash_add(bat_priv->tt_global_hash, compare_tt, |
552 | choose_orig, tt_global_entry, | 532 | choose_orig, &tt_global_entry->common, |
553 | &tt_global_entry->hash_entry); | 533 | &tt_global_entry->common.hash_entry); |
534 | |||
535 | if (unlikely(hash_added != 0)) { | ||
536 | /* remove the reference for the hash */ | ||
537 | tt_global_entry_free_ref(tt_global_entry); | ||
538 | goto out_remove; | ||
539 | } | ||
554 | atomic_inc(&orig_node->tt_size); | 540 | atomic_inc(&orig_node->tt_size); |
555 | } else { | 541 | } else { |
556 | if (tt_global_entry->orig_node != orig_node) { | 542 | if (tt_global_entry->orig_node != orig_node) { |
@@ -561,20 +547,21 @@ int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node, | |||
561 | orig_node_free_ref(orig_node_tmp); | 547 | orig_node_free_ref(orig_node_tmp); |
562 | atomic_inc(&orig_node->tt_size); | 548 | atomic_inc(&orig_node->tt_size); |
563 | } | 549 | } |
550 | tt_global_entry->common.flags = NO_FLAGS; | ||
564 | tt_global_entry->ttvn = ttvn; | 551 | tt_global_entry->ttvn = ttvn; |
565 | tt_global_entry->flags = NO_FLAGS; | ||
566 | tt_global_entry->roam_at = 0; | 552 | tt_global_entry->roam_at = 0; |
567 | } | 553 | } |
568 | 554 | ||
569 | if (wifi) | 555 | if (wifi) |
570 | tt_global_entry->flags |= TT_CLIENT_WIFI; | 556 | tt_global_entry->common.flags |= TT_CLIENT_WIFI; |
571 | 557 | ||
572 | bat_dbg(DBG_TT, bat_priv, | 558 | bat_dbg(DBG_TT, bat_priv, |
573 | "Creating new global tt entry: %pM (via %pM)\n", | 559 | "Creating new global tt entry: %pM (via %pM)\n", |
574 | tt_global_entry->addr, orig_node->orig); | 560 | tt_global_entry->common.addr, orig_node->orig); |
575 | 561 | ||
562 | out_remove: | ||
576 | /* remove address from local hash if present */ | 563 | /* remove address from local hash if present */ |
577 | tt_local_remove(bat_priv, tt_global_entry->addr, | 564 | tt_local_remove(bat_priv, tt_global_entry->common.addr, |
578 | "global tt received", roaming); | 565 | "global tt received", roaming); |
579 | ret = 1; | 566 | ret = 1; |
580 | out: | 567 | out: |
@@ -588,13 +575,13 @@ int tt_global_seq_print_text(struct seq_file *seq, void *offset) | |||
588 | struct net_device *net_dev = (struct net_device *)seq->private; | 575 | struct net_device *net_dev = (struct net_device *)seq->private; |
589 | struct bat_priv *bat_priv = netdev_priv(net_dev); | 576 | struct bat_priv *bat_priv = netdev_priv(net_dev); |
590 | struct hashtable_t *hash = bat_priv->tt_global_hash; | 577 | struct hashtable_t *hash = bat_priv->tt_global_hash; |
578 | struct tt_common_entry *tt_common_entry; | ||
591 | struct tt_global_entry *tt_global_entry; | 579 | struct tt_global_entry *tt_global_entry; |
592 | struct hard_iface *primary_if; | 580 | struct hard_iface *primary_if; |
593 | struct hlist_node *node; | 581 | struct hlist_node *node; |
594 | struct hlist_head *head; | 582 | struct hlist_head *head; |
595 | size_t buf_size, pos; | 583 | uint32_t i; |
596 | char *buff; | 584 | int ret = 0; |
597 | int i, ret = 0; | ||
598 | 585 | ||
599 | primary_if = primary_if_get_selected(bat_priv); | 586 | primary_if = primary_if_get_selected(bat_priv); |
600 | if (!primary_if) { | 587 | if (!primary_if) { |
@@ -617,53 +604,32 @@ int tt_global_seq_print_text(struct seq_file *seq, void *offset) | |||
617 | seq_printf(seq, " %-13s %s %-15s %s %s\n", | 604 | seq_printf(seq, " %-13s %s %-15s %s %s\n", |
618 | "Client", "(TTVN)", "Originator", "(Curr TTVN)", "Flags"); | 605 | "Client", "(TTVN)", "Originator", "(Curr TTVN)", "Flags"); |
619 | 606 | ||
620 | buf_size = 1; | ||
621 | /* Estimate length for: " * xx:xx:xx:xx:xx:xx (ttvn) via | ||
622 | * xx:xx:xx:xx:xx:xx (cur_ttvn)\n"*/ | ||
623 | for (i = 0; i < hash->size; i++) { | ||
624 | head = &hash->table[i]; | ||
625 | |||
626 | rcu_read_lock(); | ||
627 | __hlist_for_each_rcu(node, head) | ||
628 | buf_size += 67; | ||
629 | rcu_read_unlock(); | ||
630 | } | ||
631 | |||
632 | buff = kmalloc(buf_size, GFP_ATOMIC); | ||
633 | if (!buff) { | ||
634 | ret = -ENOMEM; | ||
635 | goto out; | ||
636 | } | ||
637 | |||
638 | buff[0] = '\0'; | ||
639 | pos = 0; | ||
640 | |||
641 | for (i = 0; i < hash->size; i++) { | 607 | for (i = 0; i < hash->size; i++) { |
642 | head = &hash->table[i]; | 608 | head = &hash->table[i]; |
643 | 609 | ||
644 | rcu_read_lock(); | 610 | rcu_read_lock(); |
645 | hlist_for_each_entry_rcu(tt_global_entry, node, | 611 | hlist_for_each_entry_rcu(tt_common_entry, node, |
646 | head, hash_entry) { | 612 | head, hash_entry) { |
647 | pos += snprintf(buff + pos, 69, | 613 | tt_global_entry = container_of(tt_common_entry, |
648 | " * %pM (%3u) via %pM (%3u) " | 614 | struct tt_global_entry, |
649 | "[%c%c%c]\n", tt_global_entry->addr, | 615 | common); |
616 | seq_printf(seq, " * %pM (%3u) via %pM (%3u) " | ||
617 | "[%c%c%c]\n", | ||
618 | tt_global_entry->common.addr, | ||
650 | tt_global_entry->ttvn, | 619 | tt_global_entry->ttvn, |
651 | tt_global_entry->orig_node->orig, | 620 | tt_global_entry->orig_node->orig, |
652 | (uint8_t) atomic_read( | 621 | (uint8_t) atomic_read( |
653 | &tt_global_entry->orig_node-> | 622 | &tt_global_entry->orig_node-> |
654 | last_ttvn), | 623 | last_ttvn), |
655 | (tt_global_entry->flags & | 624 | (tt_global_entry->common.flags & |
656 | TT_CLIENT_ROAM ? 'R' : '.'), | 625 | TT_CLIENT_ROAM ? 'R' : '.'), |
657 | (tt_global_entry->flags & | 626 | (tt_global_entry->common.flags & |
658 | TT_CLIENT_PENDING ? 'X' : '.'), | 627 | TT_CLIENT_PENDING ? 'X' : '.'), |
659 | (tt_global_entry->flags & | 628 | (tt_global_entry->common.flags & |
660 | TT_CLIENT_WIFI ? 'W' : '.')); | 629 | TT_CLIENT_WIFI ? 'W' : '.')); |
661 | } | 630 | } |
662 | rcu_read_unlock(); | 631 | rcu_read_unlock(); |
663 | } | 632 | } |
664 | |||
665 | seq_printf(seq, "%s", buff); | ||
666 | kfree(buff); | ||
667 | out: | 633 | out: |
668 | if (primary_if) | 634 | if (primary_if) |
669 | hardif_free_ref(primary_if); | 635 | hardif_free_ref(primary_if); |
@@ -679,13 +645,13 @@ static void _tt_global_del(struct bat_priv *bat_priv, | |||
679 | 645 | ||
680 | bat_dbg(DBG_TT, bat_priv, | 646 | bat_dbg(DBG_TT, bat_priv, |
681 | "Deleting global tt entry %pM (via %pM): %s\n", | 647 | "Deleting global tt entry %pM (via %pM): %s\n", |
682 | tt_global_entry->addr, tt_global_entry->orig_node->orig, | 648 | tt_global_entry->common.addr, tt_global_entry->orig_node->orig, |
683 | message); | 649 | message); |
684 | 650 | ||
685 | atomic_dec(&tt_global_entry->orig_node->tt_size); | 651 | atomic_dec(&tt_global_entry->orig_node->tt_size); |
686 | 652 | ||
687 | hash_remove(bat_priv->tt_global_hash, compare_gtt, choose_orig, | 653 | hash_remove(bat_priv->tt_global_hash, compare_tt, choose_orig, |
688 | tt_global_entry->addr); | 654 | tt_global_entry->common.addr); |
689 | out: | 655 | out: |
690 | if (tt_global_entry) | 656 | if (tt_global_entry) |
691 | tt_global_entry_free_ref(tt_global_entry); | 657 | tt_global_entry_free_ref(tt_global_entry); |
@@ -713,9 +679,9 @@ void tt_global_del(struct bat_priv *bat_priv, | |||
713 | * 2) the client roamed to us => we can directly delete | 679 | * 2) the client roamed to us => we can directly delete |
714 | * the global entry, since it is useless now. */ | 680 | * the global entry, since it is useless now. */ |
715 | tt_local_entry = tt_local_hash_find(bat_priv, | 681 | tt_local_entry = tt_local_hash_find(bat_priv, |
716 | tt_global_entry->addr); | 682 | tt_global_entry->common.addr); |
717 | if (!tt_local_entry) { | 683 | if (!tt_local_entry) { |
718 | tt_global_entry->flags |= TT_CLIENT_ROAM; | 684 | tt_global_entry->common.flags |= TT_CLIENT_ROAM; |
719 | tt_global_entry->roam_at = jiffies; | 685 | tt_global_entry->roam_at = jiffies; |
720 | goto out; | 686 | goto out; |
721 | } | 687 | } |
@@ -733,7 +699,8 @@ void tt_global_del_orig(struct bat_priv *bat_priv, | |||
733 | struct orig_node *orig_node, const char *message) | 699 | struct orig_node *orig_node, const char *message) |
734 | { | 700 | { |
735 | struct tt_global_entry *tt_global_entry; | 701 | struct tt_global_entry *tt_global_entry; |
736 | int i; | 702 | struct tt_common_entry *tt_common_entry; |
703 | uint32_t i; | ||
737 | struct hashtable_t *hash = bat_priv->tt_global_hash; | 704 | struct hashtable_t *hash = bat_priv->tt_global_hash; |
738 | struct hlist_node *node, *safe; | 705 | struct hlist_node *node, *safe; |
739 | struct hlist_head *head; | 706 | struct hlist_head *head; |
@@ -747,14 +714,18 @@ void tt_global_del_orig(struct bat_priv *bat_priv, | |||
747 | list_lock = &hash->list_locks[i]; | 714 | list_lock = &hash->list_locks[i]; |
748 | 715 | ||
749 | spin_lock_bh(list_lock); | 716 | spin_lock_bh(list_lock); |
750 | hlist_for_each_entry_safe(tt_global_entry, node, safe, | 717 | hlist_for_each_entry_safe(tt_common_entry, node, safe, |
751 | head, hash_entry) { | 718 | head, hash_entry) { |
719 | tt_global_entry = container_of(tt_common_entry, | ||
720 | struct tt_global_entry, | ||
721 | common); | ||
752 | if (tt_global_entry->orig_node == orig_node) { | 722 | if (tt_global_entry->orig_node == orig_node) { |
753 | bat_dbg(DBG_TT, bat_priv, | 723 | bat_dbg(DBG_TT, bat_priv, |
754 | "Deleting global tt entry %pM " | 724 | "Deleting global tt entry %pM " |
755 | "(via %pM): originator time out\n", | 725 | "(via %pM): %s\n", |
756 | tt_global_entry->addr, | 726 | tt_global_entry->common.addr, |
757 | tt_global_entry->orig_node->orig); | 727 | tt_global_entry->orig_node->orig, |
728 | message); | ||
758 | hlist_del_rcu(node); | 729 | hlist_del_rcu(node); |
759 | tt_global_entry_free_ref(tt_global_entry); | 730 | tt_global_entry_free_ref(tt_global_entry); |
760 | } | 731 | } |
@@ -767,20 +738,24 @@ void tt_global_del_orig(struct bat_priv *bat_priv, | |||
767 | static void tt_global_roam_purge(struct bat_priv *bat_priv) | 738 | static void tt_global_roam_purge(struct bat_priv *bat_priv) |
768 | { | 739 | { |
769 | struct hashtable_t *hash = bat_priv->tt_global_hash; | 740 | struct hashtable_t *hash = bat_priv->tt_global_hash; |
741 | struct tt_common_entry *tt_common_entry; | ||
770 | struct tt_global_entry *tt_global_entry; | 742 | struct tt_global_entry *tt_global_entry; |
771 | struct hlist_node *node, *node_tmp; | 743 | struct hlist_node *node, *node_tmp; |
772 | struct hlist_head *head; | 744 | struct hlist_head *head; |
773 | spinlock_t *list_lock; /* protects write access to the hash lists */ | 745 | spinlock_t *list_lock; /* protects write access to the hash lists */ |
774 | int i; | 746 | uint32_t i; |
775 | 747 | ||
776 | for (i = 0; i < hash->size; i++) { | 748 | for (i = 0; i < hash->size; i++) { |
777 | head = &hash->table[i]; | 749 | head = &hash->table[i]; |
778 | list_lock = &hash->list_locks[i]; | 750 | list_lock = &hash->list_locks[i]; |
779 | 751 | ||
780 | spin_lock_bh(list_lock); | 752 | spin_lock_bh(list_lock); |
781 | hlist_for_each_entry_safe(tt_global_entry, node, node_tmp, | 753 | hlist_for_each_entry_safe(tt_common_entry, node, node_tmp, |
782 | head, hash_entry) { | 754 | head, hash_entry) { |
783 | if (!(tt_global_entry->flags & TT_CLIENT_ROAM)) | 755 | tt_global_entry = container_of(tt_common_entry, |
756 | struct tt_global_entry, | ||
757 | common); | ||
758 | if (!(tt_global_entry->common.flags & TT_CLIENT_ROAM)) | ||
784 | continue; | 759 | continue; |
785 | if (!is_out_of_time(tt_global_entry->roam_at, | 760 | if (!is_out_of_time(tt_global_entry->roam_at, |
786 | TT_CLIENT_ROAM_TIMEOUT * 1000)) | 761 | TT_CLIENT_ROAM_TIMEOUT * 1000)) |
@@ -788,7 +763,7 @@ static void tt_global_roam_purge(struct bat_priv *bat_priv) | |||
788 | 763 | ||
789 | bat_dbg(DBG_TT, bat_priv, "Deleting global " | 764 | bat_dbg(DBG_TT, bat_priv, "Deleting global " |
790 | "tt entry (%pM): Roaming timeout\n", | 765 | "tt entry (%pM): Roaming timeout\n", |
791 | tt_global_entry->addr); | 766 | tt_global_entry->common.addr); |
792 | atomic_dec(&tt_global_entry->orig_node->tt_size); | 767 | atomic_dec(&tt_global_entry->orig_node->tt_size); |
793 | hlist_del_rcu(node); | 768 | hlist_del_rcu(node); |
794 | tt_global_entry_free_ref(tt_global_entry); | 769 | tt_global_entry_free_ref(tt_global_entry); |
@@ -802,10 +777,11 @@ static void tt_global_table_free(struct bat_priv *bat_priv) | |||
802 | { | 777 | { |
803 | struct hashtable_t *hash; | 778 | struct hashtable_t *hash; |
804 | spinlock_t *list_lock; /* protects write access to the hash lists */ | 779 | spinlock_t *list_lock; /* protects write access to the hash lists */ |
780 | struct tt_common_entry *tt_common_entry; | ||
805 | struct tt_global_entry *tt_global_entry; | 781 | struct tt_global_entry *tt_global_entry; |
806 | struct hlist_node *node, *node_tmp; | 782 | struct hlist_node *node, *node_tmp; |
807 | struct hlist_head *head; | 783 | struct hlist_head *head; |
808 | int i; | 784 | uint32_t i; |
809 | 785 | ||
810 | if (!bat_priv->tt_global_hash) | 786 | if (!bat_priv->tt_global_hash) |
811 | return; | 787 | return; |
@@ -817,9 +793,12 @@ static void tt_global_table_free(struct bat_priv *bat_priv) | |||
817 | list_lock = &hash->list_locks[i]; | 793 | list_lock = &hash->list_locks[i]; |
818 | 794 | ||
819 | spin_lock_bh(list_lock); | 795 | spin_lock_bh(list_lock); |
820 | hlist_for_each_entry_safe(tt_global_entry, node, node_tmp, | 796 | hlist_for_each_entry_safe(tt_common_entry, node, node_tmp, |
821 | head, hash_entry) { | 797 | head, hash_entry) { |
822 | hlist_del_rcu(node); | 798 | hlist_del_rcu(node); |
799 | tt_global_entry = container_of(tt_common_entry, | ||
800 | struct tt_global_entry, | ||
801 | common); | ||
823 | tt_global_entry_free_ref(tt_global_entry); | 802 | tt_global_entry_free_ref(tt_global_entry); |
824 | } | 803 | } |
825 | spin_unlock_bh(list_lock); | 804 | spin_unlock_bh(list_lock); |
@@ -835,8 +814,8 @@ static bool _is_ap_isolated(struct tt_local_entry *tt_local_entry, | |||
835 | { | 814 | { |
836 | bool ret = false; | 815 | bool ret = false; |
837 | 816 | ||
838 | if (tt_local_entry->flags & TT_CLIENT_WIFI && | 817 | if (tt_local_entry->common.flags & TT_CLIENT_WIFI && |
839 | tt_global_entry->flags & TT_CLIENT_WIFI) | 818 | tt_global_entry->common.flags & TT_CLIENT_WIFI) |
840 | ret = true; | 819 | ret = true; |
841 | 820 | ||
842 | return ret; | 821 | return ret; |
@@ -869,7 +848,7 @@ struct orig_node *transtable_search(struct bat_priv *bat_priv, | |||
869 | 848 | ||
870 | /* A global client marked as PENDING has already moved from that | 849 | /* A global client marked as PENDING has already moved from that |
871 | * originator */ | 850 | * originator */ |
872 | if (tt_global_entry->flags & TT_CLIENT_PENDING) | 851 | if (tt_global_entry->common.flags & TT_CLIENT_PENDING) |
873 | goto out; | 852 | goto out; |
874 | 853 | ||
875 | orig_node = tt_global_entry->orig_node; | 854 | orig_node = tt_global_entry->orig_node; |
@@ -888,29 +867,34 @@ uint16_t tt_global_crc(struct bat_priv *bat_priv, struct orig_node *orig_node) | |||
888 | { | 867 | { |
889 | uint16_t total = 0, total_one; | 868 | uint16_t total = 0, total_one; |
890 | struct hashtable_t *hash = bat_priv->tt_global_hash; | 869 | struct hashtable_t *hash = bat_priv->tt_global_hash; |
870 | struct tt_common_entry *tt_common_entry; | ||
891 | struct tt_global_entry *tt_global_entry; | 871 | struct tt_global_entry *tt_global_entry; |
892 | struct hlist_node *node; | 872 | struct hlist_node *node; |
893 | struct hlist_head *head; | 873 | struct hlist_head *head; |
894 | int i, j; | 874 | uint32_t i; |
875 | int j; | ||
895 | 876 | ||
896 | for (i = 0; i < hash->size; i++) { | 877 | for (i = 0; i < hash->size; i++) { |
897 | head = &hash->table[i]; | 878 | head = &hash->table[i]; |
898 | 879 | ||
899 | rcu_read_lock(); | 880 | rcu_read_lock(); |
900 | hlist_for_each_entry_rcu(tt_global_entry, node, | 881 | hlist_for_each_entry_rcu(tt_common_entry, node, |
901 | head, hash_entry) { | 882 | head, hash_entry) { |
883 | tt_global_entry = container_of(tt_common_entry, | ||
884 | struct tt_global_entry, | ||
885 | common); | ||
902 | if (compare_eth(tt_global_entry->orig_node, | 886 | if (compare_eth(tt_global_entry->orig_node, |
903 | orig_node)) { | 887 | orig_node)) { |
904 | /* Roaming clients are in the global table for | 888 | /* Roaming clients are in the global table for |
905 | * consistency only. They don't have to be | 889 | * consistency only. They don't have to be |
906 | * taken into account while computing the | 890 | * taken into account while computing the |
907 | * global crc */ | 891 | * global crc */ |
908 | if (tt_global_entry->flags & TT_CLIENT_ROAM) | 892 | if (tt_common_entry->flags & TT_CLIENT_ROAM) |
909 | continue; | 893 | continue; |
910 | total_one = 0; | 894 | total_one = 0; |
911 | for (j = 0; j < ETH_ALEN; j++) | 895 | for (j = 0; j < ETH_ALEN; j++) |
912 | total_one = crc16_byte(total_one, | 896 | total_one = crc16_byte(total_one, |
913 | tt_global_entry->addr[j]); | 897 | tt_common_entry->addr[j]); |
914 | total ^= total_one; | 898 | total ^= total_one; |
915 | } | 899 | } |
916 | } | 900 | } |
@@ -925,25 +909,26 @@ uint16_t tt_local_crc(struct bat_priv *bat_priv) | |||
925 | { | 909 | { |
926 | uint16_t total = 0, total_one; | 910 | uint16_t total = 0, total_one; |
927 | struct hashtable_t *hash = bat_priv->tt_local_hash; | 911 | struct hashtable_t *hash = bat_priv->tt_local_hash; |
928 | struct tt_local_entry *tt_local_entry; | 912 | struct tt_common_entry *tt_common_entry; |
929 | struct hlist_node *node; | 913 | struct hlist_node *node; |
930 | struct hlist_head *head; | 914 | struct hlist_head *head; |
931 | int i, j; | 915 | uint32_t i; |
916 | int j; | ||
932 | 917 | ||
933 | for (i = 0; i < hash->size; i++) { | 918 | for (i = 0; i < hash->size; i++) { |
934 | head = &hash->table[i]; | 919 | head = &hash->table[i]; |
935 | 920 | ||
936 | rcu_read_lock(); | 921 | rcu_read_lock(); |
937 | hlist_for_each_entry_rcu(tt_local_entry, node, | 922 | hlist_for_each_entry_rcu(tt_common_entry, node, |
938 | head, hash_entry) { | 923 | head, hash_entry) { |
939 | /* not yet committed clients have not to be taken into | 924 | /* not yet committed clients have not to be taken into |
940 | * account while computing the CRC */ | 925 | * account while computing the CRC */ |
941 | if (tt_local_entry->flags & TT_CLIENT_NEW) | 926 | if (tt_common_entry->flags & TT_CLIENT_NEW) |
942 | continue; | 927 | continue; |
943 | total_one = 0; | 928 | total_one = 0; |
944 | for (j = 0; j < ETH_ALEN; j++) | 929 | for (j = 0; j < ETH_ALEN; j++) |
945 | total_one = crc16_byte(total_one, | 930 | total_one = crc16_byte(total_one, |
946 | tt_local_entry->addr[j]); | 931 | tt_common_entry->addr[j]); |
947 | total ^= total_one; | 932 | total ^= total_one; |
948 | } | 933 | } |
949 | rcu_read_unlock(); | 934 | rcu_read_unlock(); |
@@ -1032,21 +1017,25 @@ unlock: | |||
1032 | /* data_ptr is useless here, but has to be kept to respect the prototype */ | 1017 | /* data_ptr is useless here, but has to be kept to respect the prototype */ |
1033 | static int tt_local_valid_entry(const void *entry_ptr, const void *data_ptr) | 1018 | static int tt_local_valid_entry(const void *entry_ptr, const void *data_ptr) |
1034 | { | 1019 | { |
1035 | const struct tt_local_entry *tt_local_entry = entry_ptr; | 1020 | const struct tt_common_entry *tt_common_entry = entry_ptr; |
1036 | 1021 | ||
1037 | if (tt_local_entry->flags & TT_CLIENT_NEW) | 1022 | if (tt_common_entry->flags & TT_CLIENT_NEW) |
1038 | return 0; | 1023 | return 0; |
1039 | return 1; | 1024 | return 1; |
1040 | } | 1025 | } |
1041 | 1026 | ||
1042 | static int tt_global_valid_entry(const void *entry_ptr, const void *data_ptr) | 1027 | static int tt_global_valid_entry(const void *entry_ptr, const void *data_ptr) |
1043 | { | 1028 | { |
1044 | const struct tt_global_entry *tt_global_entry = entry_ptr; | 1029 | const struct tt_common_entry *tt_common_entry = entry_ptr; |
1030 | const struct tt_global_entry *tt_global_entry; | ||
1045 | const struct orig_node *orig_node = data_ptr; | 1031 | const struct orig_node *orig_node = data_ptr; |
1046 | 1032 | ||
1047 | if (tt_global_entry->flags & TT_CLIENT_ROAM) | 1033 | if (tt_common_entry->flags & TT_CLIENT_ROAM) |
1048 | return 0; | 1034 | return 0; |
1049 | 1035 | ||
1036 | tt_global_entry = container_of(tt_common_entry, struct tt_global_entry, | ||
1037 | common); | ||
1038 | |||
1050 | return (tt_global_entry->orig_node == orig_node); | 1039 | return (tt_global_entry->orig_node == orig_node); |
1051 | } | 1040 | } |
1052 | 1041 | ||
@@ -1057,7 +1046,7 @@ static struct sk_buff *tt_response_fill_table(uint16_t tt_len, uint8_t ttvn, | |||
1057 | const void *), | 1046 | const void *), |
1058 | void *cb_data) | 1047 | void *cb_data) |
1059 | { | 1048 | { |
1060 | struct tt_local_entry *tt_local_entry; | 1049 | struct tt_common_entry *tt_common_entry; |
1061 | struct tt_query_packet *tt_response; | 1050 | struct tt_query_packet *tt_response; |
1062 | struct tt_change *tt_change; | 1051 | struct tt_change *tt_change; |
1063 | struct hlist_node *node; | 1052 | struct hlist_node *node; |
@@ -1065,7 +1054,7 @@ static struct sk_buff *tt_response_fill_table(uint16_t tt_len, uint8_t ttvn, | |||
1065 | struct sk_buff *skb = NULL; | 1054 | struct sk_buff *skb = NULL; |
1066 | uint16_t tt_tot, tt_count; | 1055 | uint16_t tt_tot, tt_count; |
1067 | ssize_t tt_query_size = sizeof(struct tt_query_packet); | 1056 | ssize_t tt_query_size = sizeof(struct tt_query_packet); |
1068 | int i; | 1057 | uint32_t i; |
1069 | 1058 | ||
1070 | if (tt_query_size + tt_len > primary_if->soft_iface->mtu) { | 1059 | if (tt_query_size + tt_len > primary_if->soft_iface->mtu) { |
1071 | tt_len = primary_if->soft_iface->mtu - tt_query_size; | 1060 | tt_len = primary_if->soft_iface->mtu - tt_query_size; |
@@ -1089,15 +1078,16 @@ static struct sk_buff *tt_response_fill_table(uint16_t tt_len, uint8_t ttvn, | |||
1089 | for (i = 0; i < hash->size; i++) { | 1078 | for (i = 0; i < hash->size; i++) { |
1090 | head = &hash->table[i]; | 1079 | head = &hash->table[i]; |
1091 | 1080 | ||
1092 | hlist_for_each_entry_rcu(tt_local_entry, node, | 1081 | hlist_for_each_entry_rcu(tt_common_entry, node, |
1093 | head, hash_entry) { | 1082 | head, hash_entry) { |
1094 | if (tt_count == tt_tot) | 1083 | if (tt_count == tt_tot) |
1095 | break; | 1084 | break; |
1096 | 1085 | ||
1097 | if ((valid_cb) && (!valid_cb(tt_local_entry, cb_data))) | 1086 | if ((valid_cb) && (!valid_cb(tt_common_entry, cb_data))) |
1098 | continue; | 1087 | continue; |
1099 | 1088 | ||
1100 | memcpy(tt_change->addr, tt_local_entry->addr, ETH_ALEN); | 1089 | memcpy(tt_change->addr, tt_common_entry->addr, |
1090 | ETH_ALEN); | ||
1101 | tt_change->flags = NO_FLAGS; | 1091 | tt_change->flags = NO_FLAGS; |
1102 | 1092 | ||
1103 | tt_count++; | 1093 | tt_count++; |
@@ -1204,11 +1194,11 @@ static bool send_other_tt_response(struct bat_priv *bat_priv, | |||
1204 | (tt_request->flags & TT_FULL_TABLE ? 'F' : '.')); | 1194 | (tt_request->flags & TT_FULL_TABLE ? 'F' : '.')); |
1205 | 1195 | ||
1206 | /* Let's get the orig node of the REAL destination */ | 1196 | /* Let's get the orig node of the REAL destination */ |
1207 | req_dst_orig_node = get_orig_node(bat_priv, tt_request->dst); | 1197 | req_dst_orig_node = orig_hash_find(bat_priv, tt_request->dst); |
1208 | if (!req_dst_orig_node) | 1198 | if (!req_dst_orig_node) |
1209 | goto out; | 1199 | goto out; |
1210 | 1200 | ||
1211 | res_dst_orig_node = get_orig_node(bat_priv, tt_request->src); | 1201 | res_dst_orig_node = orig_hash_find(bat_priv, tt_request->src); |
1212 | if (!res_dst_orig_node) | 1202 | if (!res_dst_orig_node) |
1213 | goto out; | 1203 | goto out; |
1214 | 1204 | ||
@@ -1334,7 +1324,7 @@ static bool send_my_tt_response(struct bat_priv *bat_priv, | |||
1334 | my_ttvn = (uint8_t)atomic_read(&bat_priv->ttvn); | 1324 | my_ttvn = (uint8_t)atomic_read(&bat_priv->ttvn); |
1335 | req_ttvn = tt_request->ttvn; | 1325 | req_ttvn = tt_request->ttvn; |
1336 | 1326 | ||
1337 | orig_node = get_orig_node(bat_priv, tt_request->src); | 1327 | orig_node = orig_hash_find(bat_priv, tt_request->src); |
1338 | if (!orig_node) | 1328 | if (!orig_node) |
1339 | goto out; | 1329 | goto out; |
1340 | 1330 | ||
@@ -1514,7 +1504,7 @@ bool is_my_client(struct bat_priv *bat_priv, const uint8_t *addr) | |||
1514 | goto out; | 1504 | goto out; |
1515 | /* Check if the client has been logically deleted (but is kept for | 1505 | /* Check if the client has been logically deleted (but is kept for |
1516 | * consistency purpose) */ | 1506 | * consistency purpose) */ |
1517 | if (tt_local_entry->flags & TT_CLIENT_PENDING) | 1507 | if (tt_local_entry->common.flags & TT_CLIENT_PENDING) |
1518 | goto out; | 1508 | goto out; |
1519 | ret = true; | 1509 | ret = true; |
1520 | out: | 1510 | out: |
@@ -1737,45 +1727,53 @@ void tt_free(struct bat_priv *bat_priv) | |||
1737 | kfree(bat_priv->tt_buff); | 1727 | kfree(bat_priv->tt_buff); |
1738 | } | 1728 | } |
1739 | 1729 | ||
1740 | /* This function will reset the specified flags from all the entries in | 1730 | /* This function will enable or disable the specified flags for all the entries |
1741 | * the given hash table and will increment num_local_tt for each involved | 1731 | * in the given hash table and returns the number of modified entries */ |
1742 | * entry */ | 1732 | static uint16_t tt_set_flags(struct hashtable_t *hash, uint16_t flags, |
1743 | static void tt_local_reset_flags(struct bat_priv *bat_priv, uint16_t flags) | 1733 | bool enable) |
1744 | { | 1734 | { |
1745 | int i; | 1735 | uint32_t i; |
1746 | struct hashtable_t *hash = bat_priv->tt_local_hash; | 1736 | uint16_t changed_num = 0; |
1747 | struct hlist_head *head; | 1737 | struct hlist_head *head; |
1748 | struct hlist_node *node; | 1738 | struct hlist_node *node; |
1749 | struct tt_local_entry *tt_local_entry; | 1739 | struct tt_common_entry *tt_common_entry; |
1750 | 1740 | ||
1751 | if (!hash) | 1741 | if (!hash) |
1752 | return; | 1742 | goto out; |
1753 | 1743 | ||
1754 | for (i = 0; i < hash->size; i++) { | 1744 | for (i = 0; i < hash->size; i++) { |
1755 | head = &hash->table[i]; | 1745 | head = &hash->table[i]; |
1756 | 1746 | ||
1757 | rcu_read_lock(); | 1747 | rcu_read_lock(); |
1758 | hlist_for_each_entry_rcu(tt_local_entry, node, | 1748 | hlist_for_each_entry_rcu(tt_common_entry, node, |
1759 | head, hash_entry) { | 1749 | head, hash_entry) { |
1760 | if (!(tt_local_entry->flags & flags)) | 1750 | if (enable) { |
1761 | continue; | 1751 | if ((tt_common_entry->flags & flags) == flags) |
1762 | tt_local_entry->flags &= ~flags; | 1752 | continue; |
1763 | atomic_inc(&bat_priv->num_local_tt); | 1753 | tt_common_entry->flags |= flags; |
1754 | } else { | ||
1755 | if (!(tt_common_entry->flags & flags)) | ||
1756 | continue; | ||
1757 | tt_common_entry->flags &= ~flags; | ||
1758 | } | ||
1759 | changed_num++; | ||
1764 | } | 1760 | } |
1765 | rcu_read_unlock(); | 1761 | rcu_read_unlock(); |
1766 | } | 1762 | } |
1767 | 1763 | out: | |
1764 | return changed_num; | ||
1768 | } | 1765 | } |
1769 | 1766 | ||
1770 | /* Purge out all the tt local entries marked with TT_CLIENT_PENDING */ | 1767 | /* Purge out all the tt local entries marked with TT_CLIENT_PENDING */ |
1771 | static void tt_local_purge_pending_clients(struct bat_priv *bat_priv) | 1768 | static void tt_local_purge_pending_clients(struct bat_priv *bat_priv) |
1772 | { | 1769 | { |
1773 | struct hashtable_t *hash = bat_priv->tt_local_hash; | 1770 | struct hashtable_t *hash = bat_priv->tt_local_hash; |
1771 | struct tt_common_entry *tt_common_entry; | ||
1774 | struct tt_local_entry *tt_local_entry; | 1772 | struct tt_local_entry *tt_local_entry; |
1775 | struct hlist_node *node, *node_tmp; | 1773 | struct hlist_node *node, *node_tmp; |
1776 | struct hlist_head *head; | 1774 | struct hlist_head *head; |
1777 | spinlock_t *list_lock; /* protects write access to the hash lists */ | 1775 | spinlock_t *list_lock; /* protects write access to the hash lists */ |
1778 | int i; | 1776 | uint32_t i; |
1779 | 1777 | ||
1780 | if (!hash) | 1778 | if (!hash) |
1781 | return; | 1779 | return; |
@@ -1785,16 +1783,19 @@ static void tt_local_purge_pending_clients(struct bat_priv *bat_priv) | |||
1785 | list_lock = &hash->list_locks[i]; | 1783 | list_lock = &hash->list_locks[i]; |
1786 | 1784 | ||
1787 | spin_lock_bh(list_lock); | 1785 | spin_lock_bh(list_lock); |
1788 | hlist_for_each_entry_safe(tt_local_entry, node, node_tmp, | 1786 | hlist_for_each_entry_safe(tt_common_entry, node, node_tmp, |
1789 | head, hash_entry) { | 1787 | head, hash_entry) { |
1790 | if (!(tt_local_entry->flags & TT_CLIENT_PENDING)) | 1788 | if (!(tt_common_entry->flags & TT_CLIENT_PENDING)) |
1791 | continue; | 1789 | continue; |
1792 | 1790 | ||
1793 | bat_dbg(DBG_TT, bat_priv, "Deleting local tt entry " | 1791 | bat_dbg(DBG_TT, bat_priv, "Deleting local tt entry " |
1794 | "(%pM): pending\n", tt_local_entry->addr); | 1792 | "(%pM): pending\n", tt_common_entry->addr); |
1795 | 1793 | ||
1796 | atomic_dec(&bat_priv->num_local_tt); | 1794 | atomic_dec(&bat_priv->num_local_tt); |
1797 | hlist_del_rcu(node); | 1795 | hlist_del_rcu(node); |
1796 | tt_local_entry = container_of(tt_common_entry, | ||
1797 | struct tt_local_entry, | ||
1798 | common); | ||
1798 | tt_local_entry_free_ref(tt_local_entry); | 1799 | tt_local_entry_free_ref(tt_local_entry); |
1799 | } | 1800 | } |
1800 | spin_unlock_bh(list_lock); | 1801 | spin_unlock_bh(list_lock); |
@@ -1804,7 +1805,11 @@ static void tt_local_purge_pending_clients(struct bat_priv *bat_priv) | |||
1804 | 1805 | ||
1805 | void tt_commit_changes(struct bat_priv *bat_priv) | 1806 | void tt_commit_changes(struct bat_priv *bat_priv) |
1806 | { | 1807 | { |
1807 | tt_local_reset_flags(bat_priv, TT_CLIENT_NEW); | 1808 | uint16_t changed_num = tt_set_flags(bat_priv->tt_local_hash, |
1809 | TT_CLIENT_NEW, false); | ||
1810 | /* all the reset entries have now to be effectively counted as local | ||
1811 | * entries */ | ||
1812 | atomic_add(changed_num, &bat_priv->num_local_tt); | ||
1808 | tt_local_purge_pending_clients(bat_priv); | 1813 | tt_local_purge_pending_clients(bat_priv); |
1809 | 1814 | ||
1810 | /* Increment the TTVN only once per OGM interval */ | 1815 | /* Increment the TTVN only once per OGM interval */ |
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index ab8d0fe6df5a..e9eb043719ac 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h | |||
@@ -222,24 +222,24 @@ struct socket_packet { | |||
222 | struct icmp_packet_rr icmp_packet; | 222 | struct icmp_packet_rr icmp_packet; |
223 | }; | 223 | }; |
224 | 224 | ||
225 | struct tt_local_entry { | 225 | struct tt_common_entry { |
226 | uint8_t addr[ETH_ALEN]; | 226 | uint8_t addr[ETH_ALEN]; |
227 | struct hlist_node hash_entry; | 227 | struct hlist_node hash_entry; |
228 | unsigned long last_seen; | ||
229 | uint16_t flags; | 228 | uint16_t flags; |
230 | atomic_t refcount; | 229 | atomic_t refcount; |
231 | struct rcu_head rcu; | 230 | struct rcu_head rcu; |
232 | }; | 231 | }; |
233 | 232 | ||
233 | struct tt_local_entry { | ||
234 | struct tt_common_entry common; | ||
235 | unsigned long last_seen; | ||
236 | }; | ||
237 | |||
234 | struct tt_global_entry { | 238 | struct tt_global_entry { |
235 | uint8_t addr[ETH_ALEN]; | 239 | struct tt_common_entry common; |
236 | struct hlist_node hash_entry; /* entry in the global table */ | ||
237 | struct orig_node *orig_node; | 240 | struct orig_node *orig_node; |
238 | uint8_t ttvn; | 241 | uint8_t ttvn; |
239 | uint16_t flags; /* only TT_GLOBAL_ROAM is used */ | ||
240 | unsigned long roam_at; /* time at which TT_GLOBAL_ROAM was set */ | 242 | unsigned long roam_at; /* time at which TT_GLOBAL_ROAM was set */ |
241 | atomic_t refcount; | ||
242 | struct rcu_head rcu; | ||
243 | }; | 243 | }; |
244 | 244 | ||
245 | struct tt_change_node { | 245 | struct tt_change_node { |
diff --git a/net/batman-adv/vis.c b/net/batman-adv/vis.c index f81a6b668b0c..cc3b9f2f3b5d 100644 --- a/net/batman-adv/vis.c +++ b/net/batman-adv/vis.c | |||
@@ -66,7 +66,7 @@ static int vis_info_cmp(const struct hlist_node *node, const void *data2) | |||
66 | 66 | ||
67 | /* 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 */ |
68 | /* hash algorithm from http://en.wikipedia.org/wiki/Hash_table */ | 68 | /* hash algorithm from http://en.wikipedia.org/wiki/Hash_table */ |
69 | static int vis_info_choose(const void *data, int size) | 69 | static uint32_t vis_info_choose(const void *data, uint32_t size) |
70 | { | 70 | { |
71 | const struct vis_info *vis_info = data; | 71 | const struct vis_info *vis_info = data; |
72 | const struct vis_packet *packet; | 72 | const struct vis_packet *packet; |
@@ -96,7 +96,7 @@ static struct vis_info *vis_hash_find(struct bat_priv *bat_priv, | |||
96 | struct hlist_head *head; | 96 | struct hlist_head *head; |
97 | struct hlist_node *node; | 97 | struct hlist_node *node; |
98 | struct vis_info *vis_info, *vis_info_tmp = NULL; | 98 | struct vis_info *vis_info, *vis_info_tmp = NULL; |
99 | int index; | 99 | uint32_t index; |
100 | 100 | ||
101 | if (!hash) | 101 | if (!hash) |
102 | return NULL; | 102 | return NULL; |
@@ -202,7 +202,8 @@ int vis_seq_print_text(struct seq_file *seq, void *offset) | |||
202 | HLIST_HEAD(vis_if_list); | 202 | HLIST_HEAD(vis_if_list); |
203 | struct if_list_entry *entry; | 203 | struct if_list_entry *entry; |
204 | struct hlist_node *pos, *n; | 204 | struct hlist_node *pos, *n; |
205 | int i, j, ret = 0; | 205 | uint32_t i; |
206 | int j, ret = 0; | ||
206 | int vis_server = atomic_read(&bat_priv->vis_mode); | 207 | int vis_server = atomic_read(&bat_priv->vis_mode); |
207 | size_t buff_pos, buf_size; | 208 | size_t buff_pos, buf_size; |
208 | char *buff; | 209 | char *buff; |
@@ -556,7 +557,8 @@ static int find_best_vis_server(struct bat_priv *bat_priv, | |||
556 | struct hlist_head *head; | 557 | struct hlist_head *head; |
557 | struct orig_node *orig_node; | 558 | struct orig_node *orig_node; |
558 | struct vis_packet *packet; | 559 | struct vis_packet *packet; |
559 | int best_tq = -1, i; | 560 | int best_tq = -1; |
561 | uint32_t i; | ||
560 | 562 | ||
561 | packet = (struct vis_packet *)info->skb_packet->data; | 563 | packet = (struct vis_packet *)info->skb_packet->data; |
562 | 564 | ||
@@ -607,8 +609,9 @@ static int generate_vis_packet(struct bat_priv *bat_priv) | |||
607 | struct vis_info *info = bat_priv->my_vis_info; | 609 | struct vis_info *info = bat_priv->my_vis_info; |
608 | struct vis_packet *packet = (struct vis_packet *)info->skb_packet->data; | 610 | struct vis_packet *packet = (struct vis_packet *)info->skb_packet->data; |
609 | struct vis_info_entry *entry; | 611 | struct vis_info_entry *entry; |
610 | struct tt_local_entry *tt_local_entry; | 612 | struct tt_common_entry *tt_common_entry; |
611 | int best_tq = -1, i; | 613 | int best_tq = -1; |
614 | uint32_t i; | ||
612 | 615 | ||
613 | info->first_seen = jiffies; | 616 | info->first_seen = jiffies; |
614 | packet->vis_type = atomic_read(&bat_priv->vis_mode); | 617 | packet->vis_type = atomic_read(&bat_priv->vis_mode); |
@@ -669,13 +672,13 @@ next: | |||
669 | head = &hash->table[i]; | 672 | head = &hash->table[i]; |
670 | 673 | ||
671 | rcu_read_lock(); | 674 | rcu_read_lock(); |
672 | hlist_for_each_entry_rcu(tt_local_entry, node, head, | 675 | hlist_for_each_entry_rcu(tt_common_entry, node, head, |
673 | hash_entry) { | 676 | hash_entry) { |
674 | entry = (struct vis_info_entry *) | 677 | entry = (struct vis_info_entry *) |
675 | skb_put(info->skb_packet, | 678 | skb_put(info->skb_packet, |
676 | sizeof(*entry)); | 679 | sizeof(*entry)); |
677 | memset(entry->src, 0, ETH_ALEN); | 680 | memset(entry->src, 0, ETH_ALEN); |
678 | memcpy(entry->dest, tt_local_entry->addr, ETH_ALEN); | 681 | memcpy(entry->dest, tt_common_entry->addr, ETH_ALEN); |
679 | entry->quality = 0; /* 0 means TT */ | 682 | entry->quality = 0; /* 0 means TT */ |
680 | packet->entries++; | 683 | packet->entries++; |
681 | 684 | ||
@@ -696,7 +699,7 @@ unlock: | |||
696 | * held */ | 699 | * held */ |
697 | static void purge_vis_packets(struct bat_priv *bat_priv) | 700 | static void purge_vis_packets(struct bat_priv *bat_priv) |
698 | { | 701 | { |
699 | int i; | 702 | uint32_t i; |
700 | struct hashtable_t *hash = bat_priv->vis_hash; | 703 | struct hashtable_t *hash = bat_priv->vis_hash; |
701 | struct hlist_node *node, *node_tmp; | 704 | struct hlist_node *node, *node_tmp; |
702 | struct hlist_head *head; | 705 | struct hlist_head *head; |
@@ -733,7 +736,7 @@ static void broadcast_vis_packet(struct bat_priv *bat_priv, | |||
733 | struct sk_buff *skb; | 736 | struct sk_buff *skb; |
734 | struct hard_iface *hard_iface; | 737 | struct hard_iface *hard_iface; |
735 | uint8_t dstaddr[ETH_ALEN]; | 738 | uint8_t dstaddr[ETH_ALEN]; |
736 | int i; | 739 | uint32_t i; |
737 | 740 | ||
738 | 741 | ||
739 | packet = (struct vis_packet *)info->skb_packet->data; | 742 | packet = (struct vis_packet *)info->skb_packet->data; |