aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv
diff options
context:
space:
mode:
Diffstat (limited to 'net/batman-adv')
-rw-r--r--net/batman-adv/bat_sysfs.c4
-rw-r--r--net/batman-adv/bitarray.c2
-rw-r--r--net/batman-adv/gateway_client.c153
-rw-r--r--net/batman-adv/gateway_client.h5
-rw-r--r--net/batman-adv/gateway_common.c4
-rw-r--r--net/batman-adv/hash.c4
-rw-r--r--net/batman-adv/hash.h13
-rw-r--r--net/batman-adv/icmp_socket.c14
-rw-r--r--net/batman-adv/main.h2
-rw-r--r--net/batman-adv/originator.c13
-rw-r--r--net/batman-adv/originator.h2
-rw-r--r--net/batman-adv/routing.c21
-rw-r--r--net/batman-adv/soft-interface.c45
-rw-r--r--net/batman-adv/translation-table.c437
-rw-r--r--net/batman-adv/types.h14
-rw-r--r--net/batman-adv/vis.c23
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
575int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb, 576bool 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); 642bool 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 }
671free_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
704out:
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,
31void gw_node_delete(struct bat_priv *bat_priv, struct orig_node *orig_node); 31void gw_node_delete(struct bat_priv *bat_priv, struct orig_node *orig_node);
32void gw_node_purge(struct bat_priv *bat_priv); 32void gw_node_purge(struct bat_priv *bat_priv);
33int gw_client_seq_print_text(struct seq_file *seq, void *offset); 33int gw_client_seq_print_text(struct seq_file *seq, void *offset);
34int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb, 34bool gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len);
35 struct orig_node *old_gw); 35bool 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 */
26static void hash_init(struct hashtable_t *hash) 26static 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 */
45struct hashtable_t *hash_new(int size) 45struct 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 */
36typedef int (*hashdata_choose_cb)(const void *, int); 36typedef uint32_t (*hashdata_choose_cb)(const void *, uint32_t);
37typedef void (*hashdata_free_cb)(struct hlist_node *, void *); 37typedef void (*hashdata_free_cb)(struct hlist_node *, void *);
38 38
39struct hashtable_t { 39struct 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 */
46struct hashtable_t *hash_new(int size); 46struct 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. */
49void hash_destroy(struct hashtable_t *hash); 49void 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 */
45static inline int choose_orig(const void *data, int32_t size) 45static 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:
859unreg_sysfs: 874unreg_sysfs:
860 sysfs_del_meshif(soft_iface); 875 sysfs_del_meshif(soft_iface);
861unreg_soft_iface: 876unreg_soft_iface:
862 unregister_netdev(soft_iface); 877 unregister_netdevice(soft_iface);
863 return NULL; 878 return NULL;
864 879
865free_soft_iface: 880free_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,
36static void tt_purge(struct work_struct *work); 36static 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 */
39static int compare_ltt(const struct hlist_node *node, const void *data2) 39static 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 */
48static 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
63static struct tt_local_entry *tt_local_hash_find(struct bat_priv *bat_priv, 54static 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
94static struct tt_global_entry *tt_global_hash_find(struct bat_priv *bat_priv, 84static 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)) 97static 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
126static bool is_out_of_time(unsigned long starting_time, unsigned long timeout) 111static 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
134static void tt_local_entry_free_ref(struct tt_local_entry *tt_local_entry) 119static 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
140static void tt_global_entry_free_rcu(struct rcu_head *rcu) 125static 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
152static void tt_global_entry_free_ref(struct tt_global_entry *tt_global_entry) 140static 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
158static void tt_local_event(struct bat_priv *bat_priv, const uint8_t *addr, 147static 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 }
256out: 252out:
@@ -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);
387out: 358out:
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
406void tt_local_remove(struct bat_priv *bat_priv, const uint8_t *addr, 377void 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);
420out: 391out:
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
562out_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;
580out: 567out:
@@ -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);
667out: 633out:
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);
689out: 655out:
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,
767static void tt_global_roam_purge(struct bat_priv *bat_priv) 738static 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 */
1033static int tt_local_valid_entry(const void *entry_ptr, const void *data_ptr) 1018static 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
1042static int tt_global_valid_entry(const void *entry_ptr, const void *data_ptr) 1027static 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;
1520out: 1510out:
@@ -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 */ 1732static uint16_t tt_set_flags(struct hashtable_t *hash, uint16_t flags,
1743static 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 1763out:
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 */
1771static void tt_local_purge_pending_clients(struct bat_priv *bat_priv) 1768static 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
1805void tt_commit_changes(struct bat_priv *bat_priv) 1806void 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
225struct tt_local_entry { 225struct 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
233struct tt_local_entry {
234 struct tt_common_entry common;
235 unsigned long last_seen;
236};
237
234struct tt_global_entry { 238struct 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
245struct tt_change_node { 245struct 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 */
69static int vis_info_choose(const void *data, int size) 69static 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 */
697static void purge_vis_packets(struct bat_priv *bat_priv) 700static 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;