aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2011-08-24 13:33:00 -0400
committerDavid S. Miller <davem@davemloft.net>2011-08-24 13:33:00 -0400
commit0e43182c0c9482a26a4108da9254f3e2869a8e18 (patch)
tree4631b42bebca8dd9bca61e167e543aabd3b981a7
parent131ea6675c761f655d43b808dd0fe83d15d5cdd3 (diff)
parenta943cac144e035c21d4f1b31b95f15b33c33a480 (diff)
Merge branch 'batman-adv/next' of git://git.open-mesh.org/linux-merge
-rw-r--r--Documentation/ABI/testing/sysfs-class-net-mesh8
-rw-r--r--net/batman-adv/aggregation.h3
-rw-r--r--net/batman-adv/bat_sysfs.c2
-rw-r--r--net/batman-adv/bitarray.c6
-rw-r--r--net/batman-adv/gateway_client.c10
-rw-r--r--net/batman-adv/hard-interface.c34
-rw-r--r--net/batman-adv/hard-interface.h1
-rw-r--r--net/batman-adv/hash.h25
-rw-r--r--net/batman-adv/main.c2
-rw-r--r--net/batman-adv/main.h6
-rw-r--r--net/batman-adv/originator.c2
-rw-r--r--net/batman-adv/packet.h1
-rw-r--r--net/batman-adv/routing.c77
-rw-r--r--net/batman-adv/send.c10
-rw-r--r--net/batman-adv/soft-interface.c13
-rw-r--r--net/batman-adv/translation-table.c199
-rw-r--r--net/batman-adv/translation-table.h21
-rw-r--r--net/batman-adv/types.h5
-rw-r--r--net/batman-adv/unicast.c6
-rw-r--r--net/batman-adv/unicast.h2
-rw-r--r--net/batman-adv/vis.c6
21 files changed, 291 insertions, 148 deletions
diff --git a/Documentation/ABI/testing/sysfs-class-net-mesh b/Documentation/ABI/testing/sysfs-class-net-mesh
index 748fe1701d25..b02001488eef 100644
--- a/Documentation/ABI/testing/sysfs-class-net-mesh
+++ b/Documentation/ABI/testing/sysfs-class-net-mesh
@@ -22,6 +22,14 @@ Description:
22 mesh will be fragmented or silently discarded if the 22 mesh will be fragmented or silently discarded if the
23 packet size exceeds the outgoing interface MTU. 23 packet size exceeds the outgoing interface MTU.
24 24
25What: /sys/class/net/<mesh_iface>/mesh/ap_isolation
26Date: May 2011
27Contact: Antonio Quartulli <ordex@autistici.org>
28Description:
29 Indicates whether the data traffic going from a
30 wireless client to another wireless client will be
31 silently dropped.
32
25What: /sys/class/net/<mesh_iface>/mesh/gw_bandwidth 33What: /sys/class/net/<mesh_iface>/mesh/gw_bandwidth
26Date: October 2010 34Date: October 2010
27Contact: Marek Lindner <lindner_marek@yahoo.de> 35Contact: Marek Lindner <lindner_marek@yahoo.de>
diff --git a/net/batman-adv/aggregation.h b/net/batman-adv/aggregation.h
index 216337bb841f..df4a5a943088 100644
--- a/net/batman-adv/aggregation.h
+++ b/net/batman-adv/aggregation.h
@@ -28,8 +28,7 @@
28static inline int aggregated_packet(int buff_pos, int packet_len, 28static inline int aggregated_packet(int buff_pos, int packet_len,
29 int tt_num_changes) 29 int tt_num_changes)
30{ 30{
31 int next_buff_pos = buff_pos + BAT_PACKET_LEN + (tt_num_changes * 31 int next_buff_pos = buff_pos + BAT_PACKET_LEN + tt_len(tt_num_changes);
32 sizeof(struct tt_change));
33 32
34 return (next_buff_pos <= packet_len) && 33 return (next_buff_pos <= packet_len) &&
35 (next_buff_pos <= MAX_AGGREGATION_BYTES); 34 (next_buff_pos <= MAX_AGGREGATION_BYTES);
diff --git a/net/batman-adv/bat_sysfs.c b/net/batman-adv/bat_sysfs.c
index cd15deba60a1..b8a7414c3571 100644
--- a/net/batman-adv/bat_sysfs.c
+++ b/net/batman-adv/bat_sysfs.c
@@ -380,6 +380,7 @@ static ssize_t store_gw_bwidth(struct kobject *kobj, struct attribute *attr,
380BAT_ATTR_BOOL(aggregated_ogms, S_IRUGO | S_IWUSR, NULL); 380BAT_ATTR_BOOL(aggregated_ogms, S_IRUGO | S_IWUSR, NULL);
381BAT_ATTR_BOOL(bonding, S_IRUGO | S_IWUSR, NULL); 381BAT_ATTR_BOOL(bonding, S_IRUGO | S_IWUSR, NULL);
382BAT_ATTR_BOOL(fragmentation, S_IRUGO | S_IWUSR, update_min_mtu); 382BAT_ATTR_BOOL(fragmentation, S_IRUGO | S_IWUSR, update_min_mtu);
383BAT_ATTR_BOOL(ap_isolation, S_IRUGO | S_IWUSR, NULL);
383static BAT_ATTR(vis_mode, S_IRUGO | S_IWUSR, show_vis_mode, store_vis_mode); 384static BAT_ATTR(vis_mode, S_IRUGO | S_IWUSR, show_vis_mode, store_vis_mode);
384static BAT_ATTR(gw_mode, S_IRUGO | S_IWUSR, show_gw_mode, store_gw_mode); 385static BAT_ATTR(gw_mode, S_IRUGO | S_IWUSR, show_gw_mode, store_gw_mode);
385BAT_ATTR_UINT(orig_interval, S_IRUGO | S_IWUSR, 2 * JITTER, INT_MAX, NULL); 386BAT_ATTR_UINT(orig_interval, S_IRUGO | S_IWUSR, 2 * JITTER, INT_MAX, NULL);
@@ -396,6 +397,7 @@ static struct bat_attribute *mesh_attrs[] = {
396 &bat_attr_aggregated_ogms, 397 &bat_attr_aggregated_ogms,
397 &bat_attr_bonding, 398 &bat_attr_bonding,
398 &bat_attr_fragmentation, 399 &bat_attr_fragmentation,
400 &bat_attr_ap_isolation,
399 &bat_attr_vis_mode, 401 &bat_attr_vis_mode,
400 &bat_attr_gw_mode, 402 &bat_attr_gw_mode,
401 &bat_attr_orig_interval, 403 &bat_attr_orig_interval,
diff --git a/net/batman-adv/bitarray.c b/net/batman-adv/bitarray.c
index c1f4bfc09cc3..0be9ff346fa0 100644
--- a/net/batman-adv/bitarray.c
+++ b/net/batman-adv/bitarray.c
@@ -97,12 +97,12 @@ static void bit_shift(unsigned long *seq_bits, int32_t n)
97 (seq_bits[i - word_num - 1] >> 97 (seq_bits[i - word_num - 1] >>
98 (WORD_BIT_SIZE-word_offset)); 98 (WORD_BIT_SIZE-word_offset));
99 /* and the upper part of the right half and shift it left to 99 /* and the upper part of the right half and shift it left to
100 * it's position */ 100 * its position */
101 /* for our example that would be: word[0] = 9800 + 0076 = 101 /* for our example that would be: word[0] = 9800 + 0076 =
102 * 9876 */ 102 * 9876 */
103 } 103 }
104 /* now for our last word, i==word_num, we only have the it's "left" 104 /* now for our last word, i==word_num, we only have its "left" half.
105 * half. that's the 1000 word in our example.*/ 105 * that's the 1000 word in our example.*/
106 106
107 seq_bits[i] = (seq_bits[i - word_num] << word_offset); 107 seq_bits[i] = (seq_bits[i - word_num] << word_offset);
108 108
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c
index 056180ef9e1a..619fb73b3b76 100644
--- a/net/batman-adv/gateway_client.c
+++ b/net/batman-adv/gateway_client.c
@@ -532,14 +532,14 @@ static bool is_type_dhcprequest(struct sk_buff *skb, int header_len)
532 pkt_len -= header_len + DHCP_OPTIONS_OFFSET + 1; 532 pkt_len -= header_len + DHCP_OPTIONS_OFFSET + 1;
533 533
534 /* Access the dhcp option lists. Each entry is made up by: 534 /* Access the dhcp option lists. Each entry is made up by:
535 * - octect 1: option type 535 * - octet 1: option type
536 * - octect 2: option data len (only if type != 255 and 0) 536 * - octet 2: option data len (only if type != 255 and 0)
537 * - octect 3: option data */ 537 * - octet 3: option data */
538 while (*p != 255 && !ret) { 538 while (*p != 255 && !ret) {
539 /* p now points to the first octect: option type */ 539 /* p now points to the first octet: option type */
540 if (*p == 53) { 540 if (*p == 53) {
541 /* type 53 is the message type option. 541 /* type 53 is the message type option.
542 * Jump the len octect and go to the data octect */ 542 * Jump the len octet and go to the data octet */
543 if (pkt_len < 2) 543 if (pkt_len < 2)
544 goto out; 544 goto out;
545 p += 2; 545 p += 2;
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index db7aacf1e095..bf91e4d8a47f 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -249,7 +249,7 @@ static void hardif_activate_interface(struct hard_iface *hard_iface)
249 249
250 /** 250 /**
251 * the first active interface becomes our primary interface or 251 * the first active interface becomes our primary interface or
252 * the next active interface after the old primay interface was removed 252 * the next active interface after the old primary interface was removed
253 */ 253 */
254 primary_if = primary_if_get_selected(bat_priv); 254 primary_if = primary_if_get_selected(bat_priv);
255 if (!primary_if) 255 if (!primary_if)
@@ -573,7 +573,7 @@ out:
573 return NOTIFY_DONE; 573 return NOTIFY_DONE;
574} 574}
575 575
576/* receive a packet with the batman ethertype coming on a hard 576/* incoming packets with the batman ethertype received on any active hard
577 * interface */ 577 * interface */
578static int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, 578static int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
579 struct packet_type *ptype, 579 struct packet_type *ptype,
@@ -681,6 +681,36 @@ err_out:
681 return NET_RX_DROP; 681 return NET_RX_DROP;
682} 682}
683 683
684/* This function returns true if the interface represented by ifindex is a
685 * 802.11 wireless device */
686bool is_wifi_iface(int ifindex)
687{
688 struct net_device *net_device = NULL;
689 bool ret = false;
690
691 if (ifindex == NULL_IFINDEX)
692 goto out;
693
694 net_device = dev_get_by_index(&init_net, ifindex);
695 if (!net_device)
696 goto out;
697
698#ifdef CONFIG_WIRELESS_EXT
699 /* pre-cfg80211 drivers have to implement WEXT, so it is possible to
700 * check for wireless_handlers != NULL */
701 if (net_device->wireless_handlers)
702 ret = true;
703 else
704#endif
705 /* cfg80211 drivers have to set ieee80211_ptr */
706 if (net_device->ieee80211_ptr)
707 ret = true;
708out:
709 if (net_device)
710 dev_put(net_device);
711 return ret;
712}
713
684struct notifier_block hard_if_notifier = { 714struct notifier_block hard_if_notifier = {
685 .notifier_call = hard_if_event, 715 .notifier_call = hard_if_event,
686}; 716};
diff --git a/net/batman-adv/hard-interface.h b/net/batman-adv/hard-interface.h
index 442eacbc9e3a..67f78d1a63b4 100644
--- a/net/batman-adv/hard-interface.h
+++ b/net/batman-adv/hard-interface.h
@@ -42,6 +42,7 @@ void hardif_remove_interfaces(void);
42int hardif_min_mtu(struct net_device *soft_iface); 42int hardif_min_mtu(struct net_device *soft_iface);
43void update_min_mtu(struct net_device *soft_iface); 43void update_min_mtu(struct net_device *soft_iface);
44void hardif_free_rcu(struct rcu_head *rcu); 44void hardif_free_rcu(struct rcu_head *rcu);
45bool is_wifi_iface(int ifindex);
45 46
46static inline void hardif_free_ref(struct hard_iface *hard_iface) 47static inline void hardif_free_ref(struct hard_iface *hard_iface)
47{ 48{
diff --git a/net/batman-adv/hash.h b/net/batman-adv/hash.h
index dd5c9fd7a905..d20aa71ba1e8 100644
--- a/net/batman-adv/hash.h
+++ b/net/batman-adv/hash.h
@@ -76,19 +76,30 @@ static inline void hash_delete(struct hashtable_t *hash,
76 hash_destroy(hash); 76 hash_destroy(hash);
77} 77}
78 78
79/* adds data to the hashtable. returns 0 on success, -1 on error */ 79/**
80 * hash_add - adds data to the hashtable
81 * @hash: storage hash table
82 * @compare: callback to determine if 2 hash elements are identical
83 * @choose: callback calculating the hash index
84 * @data: data passed to the aforementioned callbacks as argument
85 * @data_node: to be added element
86 *
87 * Returns 0 on success, 1 if the element already is in the hash
88 * and -1 on error.
89 */
90
80static inline int hash_add(struct hashtable_t *hash, 91static inline int hash_add(struct hashtable_t *hash,
81 hashdata_compare_cb compare, 92 hashdata_compare_cb compare,
82 hashdata_choose_cb choose, 93 hashdata_choose_cb choose,
83 const void *data, struct hlist_node *data_node) 94 const void *data, struct hlist_node *data_node)
84{ 95{
85 int index; 96 int index, ret = -1;
86 struct hlist_head *head; 97 struct hlist_head *head;
87 struct hlist_node *node; 98 struct hlist_node *node;
88 spinlock_t *list_lock; /* spinlock to protect write access */ 99 spinlock_t *list_lock; /* spinlock to protect write access */
89 100
90 if (!hash) 101 if (!hash)
91 goto err; 102 goto out;
92 103
93 index = choose(data, hash->size); 104 index = choose(data, hash->size);
94 head = &hash->table[index]; 105 head = &hash->table[index];
@@ -99,6 +110,7 @@ static inline int hash_add(struct hashtable_t *hash,
99 if (!compare(node, data)) 110 if (!compare(node, data))
100 continue; 111 continue;
101 112
113 ret = 1;
102 goto err_unlock; 114 goto err_unlock;
103 } 115 }
104 rcu_read_unlock(); 116 rcu_read_unlock();
@@ -108,12 +120,13 @@ static inline int hash_add(struct hashtable_t *hash,
108 hlist_add_head_rcu(data_node, head); 120 hlist_add_head_rcu(data_node, head);
109 spin_unlock_bh(list_lock); 121 spin_unlock_bh(list_lock);
110 122
111 return 0; 123 ret = 0;
124 goto out;
112 125
113err_unlock: 126err_unlock:
114 rcu_read_unlock(); 127 rcu_read_unlock();
115err: 128out:
116 return -1; 129 return ret;
117} 130}
118 131
119/* removes data from hash, if found. returns pointer do data on success, so you 132/* removes data from hash, if found. returns pointer do data on success, so you
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index b0f9068ade57..79b9ae522ce9 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -107,7 +107,7 @@ int mesh_init(struct net_device *soft_iface)
107 if (tt_init(bat_priv) < 1) 107 if (tt_init(bat_priv) < 1)
108 goto err; 108 goto err;
109 109
110 tt_local_add(soft_iface, soft_iface->dev_addr); 110 tt_local_add(soft_iface, soft_iface->dev_addr, NULL_IFINDEX);
111 111
112 if (vis_init(bat_priv) < 1) 112 if (vis_init(bat_priv) < 1)
113 goto err; 113 goto err;
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h
index a6df61a6933b..60b369635b4d 100644
--- a/net/batman-adv/main.h
+++ b/net/batman-adv/main.h
@@ -44,7 +44,7 @@
44#define PURGE_TIMEOUT 200 44#define PURGE_TIMEOUT 200
45#define TT_LOCAL_TIMEOUT 3600 /* in seconds */ 45#define TT_LOCAL_TIMEOUT 3600 /* in seconds */
46#define TT_CLIENT_ROAM_TIMEOUT 600 46#define TT_CLIENT_ROAM_TIMEOUT 600
47/* sliding packet range of received originator messages in squence numbers 47/* sliding packet range of received originator messages in sequence numbers
48 * (should be a multiple of our word size) */ 48 * (should be a multiple of our word size) */
49#define TQ_LOCAL_WINDOW_SIZE 64 49#define TQ_LOCAL_WINDOW_SIZE 64
50#define TT_REQUEST_TIMEOUT 3 /* seconds we have to keep pending tt_req */ 50#define TT_REQUEST_TIMEOUT 3 /* seconds we have to keep pending tt_req */
@@ -62,6 +62,8 @@
62 62
63#define NO_FLAGS 0 63#define NO_FLAGS 0
64 64
65#define NULL_IFINDEX 0 /* dummy ifindex used to avoid iface checks */
66
65#define NUM_WORDS (TQ_LOCAL_WINDOW_SIZE / WORD_BIT_SIZE) 67#define NUM_WORDS (TQ_LOCAL_WINDOW_SIZE / WORD_BIT_SIZE)
66 68
67#define LOG_BUF_LEN 8192 /* has to be a power of 2 */ 69#define LOG_BUF_LEN 8192 /* has to be a power of 2 */
@@ -133,7 +135,7 @@ enum dbg_level {
133#include <linux/mutex.h> /* mutex */ 135#include <linux/mutex.h> /* mutex */
134#include <linux/module.h> /* needed by all modules */ 136#include <linux/module.h> /* needed by all modules */
135#include <linux/netdevice.h> /* netdevice */ 137#include <linux/netdevice.h> /* netdevice */
136#include <linux/etherdevice.h> /* ethernet address classifaction */ 138#include <linux/etherdevice.h> /* ethernet address classification */
137#include <linux/if_ether.h> /* ethernet header */ 139#include <linux/if_ether.h> /* ethernet header */
138#include <linux/poll.h> /* poll_table */ 140#include <linux/poll.h> /* poll_table */
139#include <linux/kthread.h> /* kernel threads */ 141#include <linux/kthread.h> /* kernel threads */
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index f3c3f620d195..d448018e514f 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -252,7 +252,7 @@ struct orig_node *get_orig_node(struct bat_priv *bat_priv, const uint8_t *addr)
252 252
253 hash_added = hash_add(bat_priv->orig_hash, compare_orig, 253 hash_added = hash_add(bat_priv->orig_hash, compare_orig,
254 choose_orig, orig_node, &orig_node->hash_entry); 254 choose_orig, orig_node, &orig_node->hash_entry);
255 if (hash_added < 0) 255 if (hash_added != 0)
256 goto free_bcast_own_sum; 256 goto free_bcast_own_sum;
257 257
258 return orig_node; 258 return orig_node;
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h
index b76b4be10b92..8802eab2a46d 100644
--- a/net/batman-adv/packet.h
+++ b/net/batman-adv/packet.h
@@ -84,6 +84,7 @@ enum tt_query_flags {
84enum tt_client_flags { 84enum tt_client_flags {
85 TT_CLIENT_DEL = 1 << 0, 85 TT_CLIENT_DEL = 1 << 0,
86 TT_CLIENT_ROAM = 1 << 1, 86 TT_CLIENT_ROAM = 1 << 1,
87 TT_CLIENT_WIFI = 1 << 2,
87 TT_CLIENT_NOPURGE = 1 << 8, 88 TT_CLIENT_NOPURGE = 1 << 8,
88 TT_CLIENT_NEW = 1 << 9, 89 TT_CLIENT_NEW = 1 << 9,
89 TT_CLIENT_PENDING = 1 << 10 90 TT_CLIENT_PENDING = 1 << 10
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index 0f32c818874d..19499281b695 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -64,66 +64,6 @@ void slide_own_bcast_window(struct hard_iface *hard_iface)
64 } 64 }
65} 65}
66 66
67static void update_transtable(struct bat_priv *bat_priv,
68 struct orig_node *orig_node,
69 const unsigned char *tt_buff,
70 uint8_t tt_num_changes, uint8_t ttvn,
71 uint16_t tt_crc)
72{
73 uint8_t orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
74 bool full_table = true;
75
76 /* the ttvn increased by one -> we can apply the attached changes */
77 if (ttvn - orig_ttvn == 1) {
78 /* the OGM could not contain the changes because they were too
79 * many to fit in one frame or because they have already been
80 * sent TT_OGM_APPEND_MAX times. In this case send a tt
81 * request */
82 if (!tt_num_changes) {
83 full_table = false;
84 goto request_table;
85 }
86
87 tt_update_changes(bat_priv, orig_node, tt_num_changes, ttvn,
88 (struct tt_change *)tt_buff);
89
90 /* Even if we received the crc into the OGM, we prefer
91 * to recompute it to spot any possible inconsistency
92 * in the global table */
93 orig_node->tt_crc = tt_global_crc(bat_priv, orig_node);
94
95 /* The ttvn alone is not enough to guarantee consistency
96 * because a single value could repesent different states
97 * (due to the wrap around). Thus a node has to check whether
98 * the resulting table (after applying the changes) is still
99 * consistent or not. E.g. a node could disconnect while its
100 * ttvn is X and reconnect on ttvn = X + TTVN_MAX: in this case
101 * checking the CRC value is mandatory to detect the
102 * inconsistency */
103 if (orig_node->tt_crc != tt_crc)
104 goto request_table;
105
106 /* Roaming phase is over: tables are in sync again. I can
107 * unset the flag */
108 orig_node->tt_poss_change = false;
109 } else {
110 /* if we missed more than one change or our tables are not
111 * in sync anymore -> request fresh tt data */
112 if (ttvn != orig_ttvn || orig_node->tt_crc != tt_crc) {
113request_table:
114 bat_dbg(DBG_TT, bat_priv, "TT inconsistency for %pM. "
115 "Need to retrieve the correct information "
116 "(ttvn: %u last_ttvn: %u crc: %u last_crc: "
117 "%u num_changes: %u)\n", orig_node->orig, ttvn,
118 orig_ttvn, tt_crc, orig_node->tt_crc,
119 tt_num_changes);
120 send_tt_request(bat_priv, orig_node, ttvn, tt_crc,
121 full_table);
122 return;
123 }
124 }
125}
126
127static void update_route(struct bat_priv *bat_priv, 67static void update_route(struct bat_priv *bat_priv,
128 struct orig_node *orig_node, 68 struct orig_node *orig_node,
129 struct neigh_node *neigh_node) 69 struct neigh_node *neigh_node)
@@ -228,7 +168,7 @@ static int is_bidirectional_neigh(struct orig_node *orig_node,
228 if (!neigh_node) 168 if (!neigh_node)
229 goto out; 169 goto out;
230 170
231 /* if orig_node is direct neighbour update neigh_node last_valid */ 171 /* if orig_node is direct neighbor update neigh_node last_valid */
232 if (orig_node == orig_neigh_node) 172 if (orig_node == orig_neigh_node)
233 neigh_node->last_valid = jiffies; 173 neigh_node->last_valid = jiffies;
234 174
@@ -473,7 +413,7 @@ static void update_orig(struct bat_priv *bat_priv, struct orig_node *orig_node,
473 if (router && (router->tq_avg > neigh_node->tq_avg)) 413 if (router && (router->tq_avg > neigh_node->tq_avg))
474 goto update_tt; 414 goto update_tt;
475 415
476 /* if the TQ is the same and the link not more symetric we 416 /* if the TQ is the same and the link not more symmetric we
477 * won't consider it either */ 417 * won't consider it either */
478 if (router && (neigh_node->tq_avg == router->tq_avg)) { 418 if (router && (neigh_node->tq_avg == router->tq_avg)) {
479 orig_node_tmp = router->orig_node; 419 orig_node_tmp = router->orig_node;
@@ -500,10 +440,9 @@ update_tt:
500 if (((batman_packet->orig != ethhdr->h_source) && 440 if (((batman_packet->orig != ethhdr->h_source) &&
501 (batman_packet->ttl > 2)) || 441 (batman_packet->ttl > 2)) ||
502 (batman_packet->flags & PRIMARIES_FIRST_HOP)) 442 (batman_packet->flags & PRIMARIES_FIRST_HOP))
503 update_transtable(bat_priv, orig_node, tt_buff, 443 tt_update_orig(bat_priv, orig_node, tt_buff,
504 batman_packet->tt_num_changes, 444 batman_packet->tt_num_changes,
505 batman_packet->ttvn, 445 batman_packet->ttvn, batman_packet->tt_crc);
506 batman_packet->tt_crc);
507 446
508 if (orig_node->gw_flags != batman_packet->gw_flags) 447 if (orig_node->gw_flags != batman_packet->gw_flags)
509 gw_node_update(bat_priv, orig_node, batman_packet->gw_flags); 448 gw_node_update(bat_priv, orig_node, batman_packet->gw_flags);
@@ -1243,7 +1182,7 @@ int recv_tt_query(struct sk_buff *skb, struct hard_iface *recv_if)
1243 } 1182 }
1244 break; 1183 break;
1245 case TT_RESPONSE: 1184 case TT_RESPONSE:
1246 /* packet needs to be linearised to access the TT changes */ 1185 /* packet needs to be linearized to access the TT changes */
1247 if (skb_linearize(skb) < 0) 1186 if (skb_linearize(skb) < 0)
1248 goto out; 1187 goto out;
1249 1188
@@ -1300,7 +1239,7 @@ int recv_roam_adv(struct sk_buff *skb, struct hard_iface *recv_if)
1300 roam_adv_packet->client); 1239 roam_adv_packet->client);
1301 1240
1302 tt_global_add(bat_priv, orig_node, roam_adv_packet->client, 1241 tt_global_add(bat_priv, orig_node, roam_adv_packet->client,
1303 atomic_read(&orig_node->last_ttvn) + 1, true); 1242 atomic_read(&orig_node->last_ttvn) + 1, true, false);
1304 1243
1305 /* Roaming phase starts: I have new information but the ttvn has not 1244 /* Roaming phase starts: I have new information but the ttvn has not
1306 * been incremented yet. This flag will make me check all the incoming 1245 * been incremented yet. This flag will make me check all the incoming
@@ -1536,7 +1475,7 @@ static int check_unicast_ttvn(struct bat_priv *bat_priv,
1536 1475
1537 ethhdr = (struct ethhdr *)(skb->data + 1476 ethhdr = (struct ethhdr *)(skb->data +
1538 sizeof(struct unicast_packet)); 1477 sizeof(struct unicast_packet));
1539 orig_node = transtable_search(bat_priv, ethhdr->h_dest); 1478 orig_node = transtable_search(bat_priv, NULL, ethhdr->h_dest);
1540 1479
1541 if (!orig_node) { 1480 if (!orig_node) {
1542 if (!is_my_client(bat_priv, ethhdr->h_dest)) 1481 if (!is_my_client(bat_priv, ethhdr->h_dest))
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c
index 58d14472068c..57ae80936911 100644
--- a/net/batman-adv/send.c
+++ b/net/batman-adv/send.c
@@ -135,7 +135,7 @@ static void send_packet_to_if(struct forw_packet *forw_packet,
135 "Forwarding")); 135 "Forwarding"));
136 bat_dbg(DBG_BATMAN, bat_priv, 136 bat_dbg(DBG_BATMAN, bat_priv,
137 "%s %spacket (originator %pM, seqno %d, TQ %d, TTL %d," 137 "%s %spacket (originator %pM, seqno %d, TQ %d, TTL %d,"
138 " IDF %s, hvn %d) on interface %s [%pM]\n", 138 " IDF %s, ttvn %d) on interface %s [%pM]\n",
139 fwd_str, (packet_num > 0 ? "aggregated " : ""), 139 fwd_str, (packet_num > 0 ? "aggregated " : ""),
140 batman_packet->orig, ntohl(batman_packet->seqno), 140 batman_packet->orig, ntohl(batman_packet->seqno),
141 batman_packet->tq, batman_packet->ttl, 141 batman_packet->tq, batman_packet->ttl,
@@ -313,7 +313,7 @@ void schedule_own_packet(struct hard_iface *hard_iface)
313 prepare_packet_buffer(bat_priv, hard_iface); 313 prepare_packet_buffer(bat_priv, hard_iface);
314 } 314 }
315 315
316 /* if the changes have been sent enough times */ 316 /* if the changes have been sent often enough */
317 if (!atomic_dec_not_zero(&bat_priv->tt_ogm_append_cnt)) 317 if (!atomic_dec_not_zero(&bat_priv->tt_ogm_append_cnt))
318 reset_packet_buffer(bat_priv, hard_iface); 318 reset_packet_buffer(bat_priv, hard_iface);
319 } 319 }
@@ -454,7 +454,7 @@ static void _add_bcast_packet_to_list(struct bat_priv *bat_priv,
454} 454}
455 455
456/* add a broadcast packet to the queue and setup timers. broadcast packets 456/* add a broadcast packet to the queue and setup timers. broadcast packets
457 * are sent multiple times to increase probability for beeing received. 457 * are sent multiple times to increase probability for being received.
458 * 458 *
459 * This function returns NETDEV_TX_OK on success and NETDEV_TX_BUSY on 459 * This function returns NETDEV_TX_OK on success and NETDEV_TX_BUSY on
460 * errors. 460 * errors.
@@ -612,7 +612,7 @@ void purge_outstanding_packets(struct bat_priv *bat_priv,
612 &bat_priv->forw_bcast_list, list) { 612 &bat_priv->forw_bcast_list, list) {
613 613
614 /** 614 /**
615 * if purge_outstanding_packets() was called with an argmument 615 * if purge_outstanding_packets() was called with an argument
616 * we delete only packets belonging to the given interface 616 * we delete only packets belonging to the given interface
617 */ 617 */
618 if ((hard_iface) && 618 if ((hard_iface) &&
@@ -641,7 +641,7 @@ void purge_outstanding_packets(struct bat_priv *bat_priv,
641 &bat_priv->forw_bat_list, list) { 641 &bat_priv->forw_bat_list, list) {
642 642
643 /** 643 /**
644 * if purge_outstanding_packets() was called with an argmument 644 * if purge_outstanding_packets() was called with an argument
645 * we delete only packets belonging to the given interface 645 * we delete only packets belonging to the given interface
646 */ 646 */
647 if ((hard_iface) && 647 if ((hard_iface) &&
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index 3e2f91ffa4e2..402fd96239d8 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -532,11 +532,11 @@ static int interface_set_mac_addr(struct net_device *dev, void *p)
532 if (!is_valid_ether_addr(addr->sa_data)) 532 if (!is_valid_ether_addr(addr->sa_data))
533 return -EADDRNOTAVAIL; 533 return -EADDRNOTAVAIL;
534 534
535 /* only modify transtable if it has been initialised before */ 535 /* only modify transtable if it has been initialized before */
536 if (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE) { 536 if (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE) {
537 tt_local_remove(bat_priv, dev->dev_addr, 537 tt_local_remove(bat_priv, dev->dev_addr,
538 "mac address changed", false); 538 "mac address changed", false);
539 tt_local_add(dev, addr->sa_data); 539 tt_local_add(dev, addr->sa_data, NULL_IFINDEX);
540 } 540 }
541 541
542 memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); 542 memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
@@ -595,9 +595,10 @@ static int interface_tx(struct sk_buff *skb, struct net_device *soft_iface)
595 goto dropped; 595 goto dropped;
596 596
597 /* Register the client MAC in the transtable */ 597 /* Register the client MAC in the transtable */
598 tt_local_add(soft_iface, ethhdr->h_source); 598 tt_local_add(soft_iface, ethhdr->h_source, skb->skb_iif);
599 599
600 orig_node = transtable_search(bat_priv, ethhdr->h_dest); 600 orig_node = transtable_search(bat_priv, ethhdr->h_source,
601 ethhdr->h_dest);
601 if (is_multicast_ether_addr(ethhdr->h_dest) || 602 if (is_multicast_ether_addr(ethhdr->h_dest) ||
602 (orig_node && orig_node->gw_flags)) { 603 (orig_node && orig_node->gw_flags)) {
603 ret = gw_is_target(bat_priv, skb, orig_node); 604 ret = gw_is_target(bat_priv, skb, orig_node);
@@ -739,6 +740,9 @@ void interface_rx(struct net_device *soft_iface,
739 740
740 soft_iface->last_rx = jiffies; 741 soft_iface->last_rx = jiffies;
741 742
743 if (is_ap_isolated(bat_priv, ethhdr->h_source, ethhdr->h_dest))
744 goto dropped;
745
742 netif_rx(skb); 746 netif_rx(skb);
743 goto out; 747 goto out;
744 748
@@ -812,6 +816,7 @@ struct net_device *softif_create(const char *name)
812 816
813 atomic_set(&bat_priv->aggregated_ogms, 1); 817 atomic_set(&bat_priv->aggregated_ogms, 1);
814 atomic_set(&bat_priv->bonding, 0); 818 atomic_set(&bat_priv->bonding, 0);
819 atomic_set(&bat_priv->ap_isolation, 0);
815 atomic_set(&bat_priv->vis_mode, VIS_TYPE_CLIENT_UPDATE); 820 atomic_set(&bat_priv->vis_mode, VIS_TYPE_CLIENT_UPDATE);
816 atomic_set(&bat_priv->gw_mode, GW_MODE_OFF); 821 atomic_set(&bat_priv->gw_mode, GW_MODE_OFF);
817 atomic_set(&bat_priv->gw_sel_class, 20); 822 atomic_set(&bat_priv->gw_sel_class, 20);
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index fb6931d00cd7..cc53f78e448c 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -183,7 +183,8 @@ static int tt_local_init(struct bat_priv *bat_priv)
183 return 1; 183 return 1;
184} 184}
185 185
186void tt_local_add(struct net_device *soft_iface, const uint8_t *addr) 186void tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
187 int ifindex)
187{ 188{
188 struct bat_priv *bat_priv = netdev_priv(soft_iface); 189 struct bat_priv *bat_priv = netdev_priv(soft_iface);
189 struct tt_local_entry *tt_local_entry = NULL; 190 struct tt_local_entry *tt_local_entry = NULL;
@@ -207,6 +208,8 @@ void tt_local_add(struct net_device *soft_iface, const uint8_t *addr)
207 memcpy(tt_local_entry->addr, addr, ETH_ALEN); 208 memcpy(tt_local_entry->addr, addr, ETH_ALEN);
208 tt_local_entry->last_seen = jiffies; 209 tt_local_entry->last_seen = jiffies;
209 tt_local_entry->flags = NO_FLAGS; 210 tt_local_entry->flags = NO_FLAGS;
211 if (is_wifi_iface(ifindex))
212 tt_local_entry->flags |= TT_CLIENT_WIFI;
210 atomic_set(&tt_local_entry->refcount, 2); 213 atomic_set(&tt_local_entry->refcount, 2);
211 214
212 /* the batman interface mac address should never be purged */ 215 /* the batman interface mac address should never be purged */
@@ -329,7 +332,7 @@ int tt_local_seq_print_text(struct seq_file *seq, void *offset)
329 332
330 rcu_read_lock(); 333 rcu_read_lock();
331 __hlist_for_each_rcu(node, head) 334 __hlist_for_each_rcu(node, head)
332 buf_size += 21; 335 buf_size += 29;
333 rcu_read_unlock(); 336 rcu_read_unlock();
334 } 337 }
335 338
@@ -348,8 +351,19 @@ int tt_local_seq_print_text(struct seq_file *seq, void *offset)
348 rcu_read_lock(); 351 rcu_read_lock();
349 hlist_for_each_entry_rcu(tt_local_entry, node, 352 hlist_for_each_entry_rcu(tt_local_entry, node,
350 head, hash_entry) { 353 head, hash_entry) {
351 pos += snprintf(buff + pos, 22, " * %pM\n", 354 pos += snprintf(buff + pos, 30, " * %pM "
352 tt_local_entry->addr); 355 "[%c%c%c%c%c]\n",
356 tt_local_entry->addr,
357 (tt_local_entry->flags &
358 TT_CLIENT_ROAM ? 'R' : '.'),
359 (tt_local_entry->flags &
360 TT_CLIENT_NOPURGE ? 'P' : '.'),
361 (tt_local_entry->flags &
362 TT_CLIENT_NEW ? 'N' : '.'),
363 (tt_local_entry->flags &
364 TT_CLIENT_PENDING ? 'X' : '.'),
365 (tt_local_entry->flags &
366 TT_CLIENT_WIFI ? 'W' : '.'));
353 } 367 }
354 rcu_read_unlock(); 368 rcu_read_unlock();
355 } 369 }
@@ -369,8 +383,8 @@ static void tt_local_set_pending(struct bat_priv *bat_priv,
369 tt_local_event(bat_priv, tt_local_entry->addr, 383 tt_local_event(bat_priv, tt_local_entry->addr,
370 tt_local_entry->flags | flags); 384 tt_local_entry->flags | flags);
371 385
372 /* The local client has to be merked as "pending to be removed" but has 386 /* The local client has to be marked as "pending to be removed" but has
373 * to be kept in the table in order to send it in an full tables 387 * to be kept in the table in order to send it in a full table
374 * response issued before the net ttvn increment (consistency check) */ 388 * response issued before the net ttvn increment (consistency check) */
375 tt_local_entry->flags |= TT_CLIENT_PENDING; 389 tt_local_entry->flags |= TT_CLIENT_PENDING;
376} 390}
@@ -495,7 +509,8 @@ static void tt_changes_list_free(struct bat_priv *bat_priv)
495 509
496/* caller must hold orig_node refcount */ 510/* caller must hold orig_node refcount */
497int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node, 511int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node,
498 const unsigned char *tt_addr, uint8_t ttvn, bool roaming) 512 const unsigned char *tt_addr, uint8_t ttvn, bool roaming,
513 bool wifi)
499{ 514{
500 struct tt_global_entry *tt_global_entry; 515 struct tt_global_entry *tt_global_entry;
501 struct orig_node *orig_node_tmp; 516 struct orig_node *orig_node_tmp;
@@ -537,6 +552,9 @@ int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node,
537 tt_global_entry->roam_at = 0; 552 tt_global_entry->roam_at = 0;
538 } 553 }
539 554
555 if (wifi)
556 tt_global_entry->flags |= TT_CLIENT_WIFI;
557
540 bat_dbg(DBG_TT, bat_priv, 558 bat_dbg(DBG_TT, bat_priv,
541 "Creating new global tt entry: %pM (via %pM)\n", 559 "Creating new global tt entry: %pM (via %pM)\n",
542 tt_global_entry->addr, orig_node->orig); 560 tt_global_entry->addr, orig_node->orig);
@@ -582,8 +600,8 @@ int tt_global_seq_print_text(struct seq_file *seq, void *offset)
582 seq_printf(seq, 600 seq_printf(seq,
583 "Globally announced TT entries received via the mesh %s\n", 601 "Globally announced TT entries received via the mesh %s\n",
584 net_dev->name); 602 net_dev->name);
585 seq_printf(seq, " %-13s %s %-15s %s\n", 603 seq_printf(seq, " %-13s %s %-15s %s %s\n",
586 "Client", "(TTVN)", "Originator", "(Curr TTVN)"); 604 "Client", "(TTVN)", "Originator", "(Curr TTVN)", "Flags");
587 605
588 buf_size = 1; 606 buf_size = 1;
589 /* Estimate length for: " * xx:xx:xx:xx:xx:xx (ttvn) via 607 /* Estimate length for: " * xx:xx:xx:xx:xx:xx (ttvn) via
@@ -593,7 +611,7 @@ int tt_global_seq_print_text(struct seq_file *seq, void *offset)
593 611
594 rcu_read_lock(); 612 rcu_read_lock();
595 __hlist_for_each_rcu(node, head) 613 __hlist_for_each_rcu(node, head)
596 buf_size += 59; 614 buf_size += 67;
597 rcu_read_unlock(); 615 rcu_read_unlock();
598 } 616 }
599 617
@@ -612,14 +630,20 @@ int tt_global_seq_print_text(struct seq_file *seq, void *offset)
612 rcu_read_lock(); 630 rcu_read_lock();
613 hlist_for_each_entry_rcu(tt_global_entry, node, 631 hlist_for_each_entry_rcu(tt_global_entry, node,
614 head, hash_entry) { 632 head, hash_entry) {
615 pos += snprintf(buff + pos, 61, 633 pos += snprintf(buff + pos, 69,
616 " * %pM (%3u) via %pM (%3u)\n", 634 " * %pM (%3u) via %pM (%3u) "
617 tt_global_entry->addr, 635 "[%c%c%c]\n", tt_global_entry->addr,
618 tt_global_entry->ttvn, 636 tt_global_entry->ttvn,
619 tt_global_entry->orig_node->orig, 637 tt_global_entry->orig_node->orig,
620 (uint8_t) atomic_read( 638 (uint8_t) atomic_read(
621 &tt_global_entry->orig_node-> 639 &tt_global_entry->orig_node->
622 last_ttvn)); 640 last_ttvn),
641 (tt_global_entry->flags &
642 TT_CLIENT_ROAM ? 'R' : '.'),
643 (tt_global_entry->flags &
644 TT_CLIENT_PENDING ? 'X' : '.'),
645 (tt_global_entry->flags &
646 TT_CLIENT_WIFI ? 'W' : '.'));
623 } 647 }
624 rcu_read_unlock(); 648 rcu_read_unlock();
625 } 649 }
@@ -774,30 +798,56 @@ static void tt_global_table_free(struct bat_priv *bat_priv)
774 bat_priv->tt_global_hash = NULL; 798 bat_priv->tt_global_hash = NULL;
775} 799}
776 800
801static bool _is_ap_isolated(struct tt_local_entry *tt_local_entry,
802 struct tt_global_entry *tt_global_entry)
803{
804 bool ret = false;
805
806 if (tt_local_entry->flags & TT_CLIENT_WIFI &&
807 tt_global_entry->flags & TT_CLIENT_WIFI)
808 ret = true;
809
810 return ret;
811}
812
777struct orig_node *transtable_search(struct bat_priv *bat_priv, 813struct orig_node *transtable_search(struct bat_priv *bat_priv,
778 const uint8_t *addr) 814 const uint8_t *src, const uint8_t *addr)
779{ 815{
780 struct tt_global_entry *tt_global_entry; 816 struct tt_local_entry *tt_local_entry = NULL;
817 struct tt_global_entry *tt_global_entry = NULL;
781 struct orig_node *orig_node = NULL; 818 struct orig_node *orig_node = NULL;
782 819
783 tt_global_entry = tt_global_hash_find(bat_priv, addr); 820 if (src && atomic_read(&bat_priv->ap_isolation)) {
821 tt_local_entry = tt_local_hash_find(bat_priv, src);
822 if (!tt_local_entry)
823 goto out;
824 }
784 825
826 tt_global_entry = tt_global_hash_find(bat_priv, addr);
785 if (!tt_global_entry) 827 if (!tt_global_entry)
786 goto out; 828 goto out;
787 829
830 /* check whether the clients should not communicate due to AP
831 * isolation */
832 if (tt_local_entry && _is_ap_isolated(tt_local_entry, tt_global_entry))
833 goto out;
834
788 if (!atomic_inc_not_zero(&tt_global_entry->orig_node->refcount)) 835 if (!atomic_inc_not_zero(&tt_global_entry->orig_node->refcount))
789 goto free_tt; 836 goto out;
790 837
791 /* A global client marked as PENDING has already moved from that 838 /* A global client marked as PENDING has already moved from that
792 * originator */ 839 * originator */
793 if (tt_global_entry->flags & TT_CLIENT_PENDING) 840 if (tt_global_entry->flags & TT_CLIENT_PENDING)
794 goto free_tt; 841 goto out;
795 842
796 orig_node = tt_global_entry->orig_node; 843 orig_node = tt_global_entry->orig_node;
797 844
798free_tt:
799 tt_global_entry_free_ref(tt_global_entry);
800out: 845out:
846 if (tt_global_entry)
847 tt_global_entry_free_ref(tt_global_entry);
848 if (tt_local_entry)
849 tt_local_entry_free_ref(tt_local_entry);
850
801 return orig_node; 851 return orig_node;
802} 852}
803 853
@@ -1029,8 +1079,9 @@ out:
1029 return skb; 1079 return skb;
1030} 1080}
1031 1081
1032int send_tt_request(struct bat_priv *bat_priv, struct orig_node *dst_orig_node, 1082static int send_tt_request(struct bat_priv *bat_priv,
1033 uint8_t ttvn, uint16_t tt_crc, bool full_table) 1083 struct orig_node *dst_orig_node,
1084 uint8_t ttvn, uint16_t tt_crc, bool full_table)
1034{ 1085{
1035 struct sk_buff *skb = NULL; 1086 struct sk_buff *skb = NULL;
1036 struct tt_query_packet *tt_request; 1087 struct tt_query_packet *tt_request;
@@ -1137,12 +1188,12 @@ static bool send_other_tt_response(struct bat_priv *bat_priv,
1137 orig_ttvn = (uint8_t)atomic_read(&req_dst_orig_node->last_ttvn); 1188 orig_ttvn = (uint8_t)atomic_read(&req_dst_orig_node->last_ttvn);
1138 req_ttvn = tt_request->ttvn; 1189 req_ttvn = tt_request->ttvn;
1139 1190
1140 /* I have not the requested data */ 1191 /* I don't have the requested data */
1141 if (orig_ttvn != req_ttvn || 1192 if (orig_ttvn != req_ttvn ||
1142 tt_request->tt_data != req_dst_orig_node->tt_crc) 1193 tt_request->tt_data != req_dst_orig_node->tt_crc)
1143 goto out; 1194 goto out;
1144 1195
1145 /* If it has explicitly been requested the full table */ 1196 /* If the full table has been explicitly requested */
1146 if (tt_request->flags & TT_FULL_TABLE || 1197 if (tt_request->flags & TT_FULL_TABLE ||
1147 !req_dst_orig_node->tt_buff) 1198 !req_dst_orig_node->tt_buff)
1148 full_table = true; 1199 full_table = true;
@@ -1363,7 +1414,9 @@ static void _tt_update_changes(struct bat_priv *bat_priv,
1363 (tt_change + i)->flags & TT_CLIENT_ROAM); 1414 (tt_change + i)->flags & TT_CLIENT_ROAM);
1364 else 1415 else
1365 if (!tt_global_add(bat_priv, orig_node, 1416 if (!tt_global_add(bat_priv, orig_node,
1366 (tt_change + i)->addr, ttvn, false)) 1417 (tt_change + i)->addr, ttvn, false,
1418 (tt_change + i)->flags &
1419 TT_CLIENT_WIFI))
1367 /* In case of problem while storing a 1420 /* In case of problem while storing a
1368 * global_entry, we stop the updating 1421 * global_entry, we stop the updating
1369 * procedure without committing the 1422 * procedure without committing the
@@ -1403,9 +1456,10 @@ out:
1403 orig_node_free_ref(orig_node); 1456 orig_node_free_ref(orig_node);
1404} 1457}
1405 1458
1406void tt_update_changes(struct bat_priv *bat_priv, struct orig_node *orig_node, 1459static void tt_update_changes(struct bat_priv *bat_priv,
1407 uint16_t tt_num_changes, uint8_t ttvn, 1460 struct orig_node *orig_node,
1408 struct tt_change *tt_change) 1461 uint16_t tt_num_changes, uint8_t ttvn,
1462 struct tt_change *tt_change)
1409{ 1463{
1410 _tt_update_changes(bat_priv, orig_node, tt_change, tt_num_changes, 1464 _tt_update_changes(bat_priv, orig_node, tt_change, tt_num_changes,
1411 ttvn); 1465 ttvn);
@@ -1720,3 +1774,90 @@ void tt_commit_changes(struct bat_priv *bat_priv)
1720 atomic_inc(&bat_priv->ttvn); 1774 atomic_inc(&bat_priv->ttvn);
1721 bat_priv->tt_poss_change = false; 1775 bat_priv->tt_poss_change = false;
1722} 1776}
1777
1778bool is_ap_isolated(struct bat_priv *bat_priv, uint8_t *src, uint8_t *dst)
1779{
1780 struct tt_local_entry *tt_local_entry = NULL;
1781 struct tt_global_entry *tt_global_entry = NULL;
1782 bool ret = true;
1783
1784 if (!atomic_read(&bat_priv->ap_isolation))
1785 return false;
1786
1787 tt_local_entry = tt_local_hash_find(bat_priv, dst);
1788 if (!tt_local_entry)
1789 goto out;
1790
1791 tt_global_entry = tt_global_hash_find(bat_priv, src);
1792 if (!tt_global_entry)
1793 goto out;
1794
1795 if (_is_ap_isolated(tt_local_entry, tt_global_entry))
1796 goto out;
1797
1798 ret = false;
1799
1800out:
1801 if (tt_global_entry)
1802 tt_global_entry_free_ref(tt_global_entry);
1803 if (tt_local_entry)
1804 tt_local_entry_free_ref(tt_local_entry);
1805 return ret;
1806}
1807
1808void tt_update_orig(struct bat_priv *bat_priv, struct orig_node *orig_node,
1809 const unsigned char *tt_buff, uint8_t tt_num_changes,
1810 uint8_t ttvn, uint16_t tt_crc)
1811{
1812 uint8_t orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
1813 bool full_table = true;
1814
1815 /* the ttvn increased by one -> we can apply the attached changes */
1816 if (ttvn - orig_ttvn == 1) {
1817 /* the OGM could not contain the changes due to their size or
1818 * because they have already been sent TT_OGM_APPEND_MAX times.
1819 * In this case send a tt request */
1820 if (!tt_num_changes) {
1821 full_table = false;
1822 goto request_table;
1823 }
1824
1825 tt_update_changes(bat_priv, orig_node, tt_num_changes, ttvn,
1826 (struct tt_change *)tt_buff);
1827
1828 /* Even if we received the precomputed crc with the OGM, we
1829 * prefer to recompute it to spot any possible inconsistency
1830 * in the global table */
1831 orig_node->tt_crc = tt_global_crc(bat_priv, orig_node);
1832
1833 /* The ttvn alone is not enough to guarantee consistency
1834 * because a single value could represent different states
1835 * (due to the wrap around). Thus a node has to check whether
1836 * the resulting table (after applying the changes) is still
1837 * consistent or not. E.g. a node could disconnect while its
1838 * ttvn is X and reconnect on ttvn = X + TTVN_MAX: in this case
1839 * checking the CRC value is mandatory to detect the
1840 * inconsistency */
1841 if (orig_node->tt_crc != tt_crc)
1842 goto request_table;
1843
1844 /* Roaming phase is over: tables are in sync again. I can
1845 * unset the flag */
1846 orig_node->tt_poss_change = false;
1847 } else {
1848 /* if we missed more than one change or our tables are not
1849 * in sync anymore -> request fresh tt data */
1850 if (ttvn != orig_ttvn || orig_node->tt_crc != tt_crc) {
1851request_table:
1852 bat_dbg(DBG_TT, bat_priv, "TT inconsistency for %pM. "
1853 "Need to retrieve the correct information "
1854 "(ttvn: %u last_ttvn: %u crc: %u last_crc: "
1855 "%u num_changes: %u)\n", orig_node->orig, ttvn,
1856 orig_ttvn, tt_crc, orig_node->tt_crc,
1857 tt_num_changes);
1858 send_tt_request(bat_priv, orig_node, ttvn, tt_crc,
1859 full_table);
1860 return;
1861 }
1862 }
1863}
diff --git a/net/batman-adv/translation-table.h b/net/batman-adv/translation-table.h
index d4122cba53b8..30efd49881a3 100644
--- a/net/batman-adv/translation-table.h
+++ b/net/batman-adv/translation-table.h
@@ -26,15 +26,16 @@ int tt_len(int changes_num);
26int tt_changes_fill_buffer(struct bat_priv *bat_priv, 26int tt_changes_fill_buffer(struct bat_priv *bat_priv,
27 unsigned char *buff, int buff_len); 27 unsigned char *buff, int buff_len);
28int tt_init(struct bat_priv *bat_priv); 28int tt_init(struct bat_priv *bat_priv);
29void tt_local_add(struct net_device *soft_iface, const uint8_t *addr); 29void tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
30 int ifindex);
30void tt_local_remove(struct bat_priv *bat_priv, 31void tt_local_remove(struct bat_priv *bat_priv,
31 const uint8_t *addr, const char *message, bool roaming); 32 const uint8_t *addr, const char *message, bool roaming);
32int tt_local_seq_print_text(struct seq_file *seq, void *offset); 33int tt_local_seq_print_text(struct seq_file *seq, void *offset);
33void tt_global_add_orig(struct bat_priv *bat_priv, struct orig_node *orig_node, 34void tt_global_add_orig(struct bat_priv *bat_priv, struct orig_node *orig_node,
34 const unsigned char *tt_buff, int tt_buff_len); 35 const unsigned char *tt_buff, int tt_buff_len);
35int tt_global_add(struct bat_priv *bat_priv, 36int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node,
36 struct orig_node *orig_node, const unsigned char *addr, 37 const unsigned char *addr, uint8_t ttvn, bool roaming,
37 uint8_t ttvn, bool roaming); 38 bool wifi);
38int tt_global_seq_print_text(struct seq_file *seq, void *offset); 39int tt_global_seq_print_text(struct seq_file *seq, void *offset);
39void tt_global_del_orig(struct bat_priv *bat_priv, 40void tt_global_del_orig(struct bat_priv *bat_priv,
40 struct orig_node *orig_node, const char *message); 41 struct orig_node *orig_node, const char *message);
@@ -42,25 +43,23 @@ void tt_global_del(struct bat_priv *bat_priv,
42 struct orig_node *orig_node, const unsigned char *addr, 43 struct orig_node *orig_node, const unsigned char *addr,
43 const char *message, bool roaming); 44 const char *message, bool roaming);
44struct orig_node *transtable_search(struct bat_priv *bat_priv, 45struct orig_node *transtable_search(struct bat_priv *bat_priv,
45 const uint8_t *addr); 46 const uint8_t *src, const uint8_t *addr);
46void tt_save_orig_buffer(struct bat_priv *bat_priv, struct orig_node *orig_node, 47void tt_save_orig_buffer(struct bat_priv *bat_priv, struct orig_node *orig_node,
47 const unsigned char *tt_buff, uint8_t tt_num_changes); 48 const unsigned char *tt_buff, uint8_t tt_num_changes);
48uint16_t tt_local_crc(struct bat_priv *bat_priv); 49uint16_t tt_local_crc(struct bat_priv *bat_priv);
49uint16_t tt_global_crc(struct bat_priv *bat_priv, struct orig_node *orig_node); 50uint16_t tt_global_crc(struct bat_priv *bat_priv, struct orig_node *orig_node);
50void tt_free(struct bat_priv *bat_priv); 51void tt_free(struct bat_priv *bat_priv);
51int send_tt_request(struct bat_priv *bat_priv,
52 struct orig_node *dst_orig_node, uint8_t hvn,
53 uint16_t tt_crc, bool full_table);
54bool send_tt_response(struct bat_priv *bat_priv, 52bool send_tt_response(struct bat_priv *bat_priv,
55 struct tt_query_packet *tt_request); 53 struct tt_query_packet *tt_request);
56void tt_update_changes(struct bat_priv *bat_priv, struct orig_node *orig_node,
57 uint16_t tt_num_changes, uint8_t ttvn,
58 struct tt_change *tt_change);
59bool is_my_client(struct bat_priv *bat_priv, const uint8_t *addr); 54bool is_my_client(struct bat_priv *bat_priv, const uint8_t *addr);
60void handle_tt_response(struct bat_priv *bat_priv, 55void handle_tt_response(struct bat_priv *bat_priv,
61 struct tt_query_packet *tt_response); 56 struct tt_query_packet *tt_response);
62void send_roam_adv(struct bat_priv *bat_priv, uint8_t *client, 57void send_roam_adv(struct bat_priv *bat_priv, uint8_t *client,
63 struct orig_node *orig_node); 58 struct orig_node *orig_node);
64void tt_commit_changes(struct bat_priv *bat_priv); 59void tt_commit_changes(struct bat_priv *bat_priv);
60bool is_ap_isolated(struct bat_priv *bat_priv, uint8_t *src, uint8_t *dst);
61void tt_update_orig(struct bat_priv *bat_priv, struct orig_node *orig_node,
62 const unsigned char *tt_buff, uint8_t tt_num_changes,
63 uint8_t ttvn, uint16_t tt_crc);
65 64
66#endif /* _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ */ 65#endif /* _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ */
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 25bd1db35370..1ae355750511 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -57,7 +57,7 @@ struct hard_iface {
57 * @batman_seqno_reset: time when the batman seqno window was reset 57 * @batman_seqno_reset: time when the batman seqno window was reset
58 * @gw_flags: flags related to gateway class 58 * @gw_flags: flags related to gateway class
59 * @flags: for now only VIS_SERVER flag 59 * @flags: for now only VIS_SERVER flag
60 * @last_real_seqno: last and best known squence number 60 * @last_real_seqno: last and best known sequence number
61 * @last_ttl: ttl of last received packet 61 * @last_ttl: ttl of last received packet
62 * @last_bcast_seqno: last broadcast sequence number received by this host 62 * @last_bcast_seqno: last broadcast sequence number received by this host
63 * 63 *
@@ -146,6 +146,7 @@ struct bat_priv {
146 atomic_t aggregated_ogms; /* boolean */ 146 atomic_t aggregated_ogms; /* boolean */
147 atomic_t bonding; /* boolean */ 147 atomic_t bonding; /* boolean */
148 atomic_t fragmentation; /* boolean */ 148 atomic_t fragmentation; /* boolean */
149 atomic_t ap_isolation; /* boolean */
149 atomic_t vis_mode; /* VIS_TYPE_* */ 150 atomic_t vis_mode; /* VIS_TYPE_* */
150 atomic_t gw_mode; /* GW_MODE_* */ 151 atomic_t gw_mode; /* GW_MODE_* */
151 atomic_t gw_sel_class; /* uint */ 152 atomic_t gw_sel_class; /* uint */
@@ -156,7 +157,7 @@ struct bat_priv {
156 atomic_t bcast_seqno; 157 atomic_t bcast_seqno;
157 atomic_t bcast_queue_left; 158 atomic_t bcast_queue_left;
158 atomic_t batman_queue_left; 159 atomic_t batman_queue_left;
159 atomic_t ttvn; /* tranlation table version number */ 160 atomic_t ttvn; /* translation table version number */
160 atomic_t tt_ogm_append_cnt; 161 atomic_t tt_ogm_append_cnt;
161 atomic_t tt_local_changes; /* changes registered in a OGM interval */ 162 atomic_t tt_local_changes; /* changes registered in a OGM interval */
162 /* The tt_poss_change flag is used to detect an ongoing roaming phase. 163 /* The tt_poss_change flag is used to detect an ongoing roaming phase.
diff --git a/net/batman-adv/unicast.c b/net/batman-adv/unicast.c
index 32b125fb3d3b..07d1c1da89dd 100644
--- a/net/batman-adv/unicast.c
+++ b/net/batman-adv/unicast.c
@@ -299,8 +299,10 @@ int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv)
299 goto find_router; 299 goto find_router;
300 } 300 }
301 301
302 /* check for tt host - increases orig_node refcount */ 302 /* check for tt host - increases orig_node refcount.
303 orig_node = transtable_search(bat_priv, ethhdr->h_dest); 303 * returns NULL in case of AP isolation */
304 orig_node = transtable_search(bat_priv, ethhdr->h_source,
305 ethhdr->h_dest);
304 306
305find_router: 307find_router:
306 /** 308 /**
diff --git a/net/batman-adv/unicast.h b/net/batman-adv/unicast.h
index 62f54b954625..8fd5535544b9 100644
--- a/net/batman-adv/unicast.h
+++ b/net/batman-adv/unicast.h
@@ -24,7 +24,7 @@
24 24
25#include "packet.h" 25#include "packet.h"
26 26
27#define FRAG_TIMEOUT 10000 /* purge frag list entrys after time in ms */ 27#define FRAG_TIMEOUT 10000 /* purge frag list entries after time in ms */
28#define FRAG_BUFFER_SIZE 6 /* number of list elements in buffer */ 28#define FRAG_BUFFER_SIZE 6 /* number of list elements in buffer */
29 29
30int frag_reassemble_skb(struct sk_buff *skb, struct bat_priv *bat_priv, 30int frag_reassemble_skb(struct sk_buff *skb, struct bat_priv *bat_priv,
diff --git a/net/batman-adv/vis.c b/net/batman-adv/vis.c
index 8a1b98589d76..fb9b19fc638d 100644
--- a/net/batman-adv/vis.c
+++ b/net/batman-adv/vis.c
@@ -131,7 +131,7 @@ static void vis_data_insert_interface(const uint8_t *interface,
131 return; 131 return;
132 } 132 }
133 133
134 /* its a new address, add it to the list */ 134 /* it's a new address, add it to the list */
135 entry = kmalloc(sizeof(*entry), GFP_ATOMIC); 135 entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
136 if (!entry) 136 if (!entry)
137 return; 137 return;
@@ -465,7 +465,7 @@ static struct vis_info *add_packet(struct bat_priv *bat_priv,
465 /* try to add it */ 465 /* try to add it */
466 hash_added = hash_add(bat_priv->vis_hash, vis_info_cmp, vis_info_choose, 466 hash_added = hash_add(bat_priv->vis_hash, vis_info_cmp, vis_info_choose,
467 info, &info->hash_entry); 467 info, &info->hash_entry);
468 if (hash_added < 0) { 468 if (hash_added != 0) {
469 /* did not work (for some reason) */ 469 /* did not work (for some reason) */
470 kref_put(&info->refcount, free_info); 470 kref_put(&info->refcount, free_info);
471 info = NULL; 471 info = NULL;
@@ -920,7 +920,7 @@ int vis_init(struct bat_priv *bat_priv)
920 hash_added = hash_add(bat_priv->vis_hash, vis_info_cmp, vis_info_choose, 920 hash_added = hash_add(bat_priv->vis_hash, vis_info_cmp, vis_info_choose,
921 bat_priv->my_vis_info, 921 bat_priv->my_vis_info,
922 &bat_priv->my_vis_info->hash_entry); 922 &bat_priv->my_vis_info->hash_entry);
923 if (hash_added < 0) { 923 if (hash_added != 0) {
924 pr_err("Can't add own vis packet into hash\n"); 924 pr_err("Can't add own vis packet into hash\n");
925 /* not in hash, need to remove it manually. */ 925 /* not in hash, need to remove it manually. */
926 kref_put(&bat_priv->my_vis_info->refcount, free_info); 926 kref_put(&bat_priv->my_vis_info->refcount, free_info);