aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/testing/sysfs-class-net-batman-adv4
-rw-r--r--Documentation/ABI/testing/sysfs-class-net-mesh23
-rw-r--r--Documentation/networking/batman-adv.txt4
-rw-r--r--MAINTAINERS2
-rw-r--r--net/batman-adv/bridge_loop_avoidance.c58
-rw-r--r--net/batman-adv/bridge_loop_avoidance.h10
-rw-r--r--net/batman-adv/distributed-arp-table.c160
-rw-r--r--net/batman-adv/gateway_client.c25
-rw-r--r--net/batman-adv/hard-interface.c2
-rw-r--r--net/batman-adv/main.c33
-rw-r--r--net/batman-adv/main.h15
-rw-r--r--net/batman-adv/originator.c104
-rw-r--r--net/batman-adv/originator.h7
-rw-r--r--net/batman-adv/packet.h32
-rw-r--r--net/batman-adv/routing.c28
-rw-r--r--net/batman-adv/send.c98
-rw-r--r--net/batman-adv/send.h51
-rw-r--r--net/batman-adv/soft-interface.c227
-rw-r--r--net/batman-adv/soft-interface.h4
-rw-r--r--net/batman-adv/sysfs.c178
-rw-r--r--net/batman-adv/sysfs.h10
-rw-r--r--net/batman-adv/translation-table.c1157
-rw-r--r--net/batman-adv/translation-table.h23
-rw-r--r--net/batman-adv/types.h83
24 files changed, 1851 insertions, 487 deletions
diff --git a/Documentation/ABI/testing/sysfs-class-net-batman-adv b/Documentation/ABI/testing/sysfs-class-net-batman-adv
index bdc00707c751..7f34a95bb963 100644
--- a/Documentation/ABI/testing/sysfs-class-net-batman-adv
+++ b/Documentation/ABI/testing/sysfs-class-net-batman-adv
@@ -1,13 +1,13 @@
1 1
2What: /sys/class/net/<iface>/batman-adv/iface_status 2What: /sys/class/net/<iface>/batman-adv/iface_status
3Date: May 2010 3Date: May 2010
4Contact: Marek Lindner <lindner_marek@yahoo.de> 4Contact: Marek Lindner <mareklindner@neomailbox.ch>
5Description: 5Description:
6 Indicates the status of <iface> as it is seen by batman. 6 Indicates the status of <iface> as it is seen by batman.
7 7
8What: /sys/class/net/<iface>/batman-adv/mesh_iface 8What: /sys/class/net/<iface>/batman-adv/mesh_iface
9Date: May 2010 9Date: May 2010
10Contact: Marek Lindner <lindner_marek@yahoo.de> 10Contact: Marek Lindner <mareklindner@neomailbox.ch>
11Description: 11Description:
12 The /sys/class/net/<iface>/batman-adv/mesh_iface file 12 The /sys/class/net/<iface>/batman-adv/mesh_iface file
13 displays the batman mesh interface this <iface> 13 displays the batman mesh interface this <iface>
diff --git a/Documentation/ABI/testing/sysfs-class-net-mesh b/Documentation/ABI/testing/sysfs-class-net-mesh
index f00a69b68a25..0baa657b18c4 100644
--- a/Documentation/ABI/testing/sysfs-class-net-mesh
+++ b/Documentation/ABI/testing/sysfs-class-net-mesh
@@ -1,22 +1,23 @@
1 1
2What: /sys/class/net/<mesh_iface>/mesh/aggregated_ogms 2What: /sys/class/net/<mesh_iface>/mesh/aggregated_ogms
3Date: May 2010 3Date: May 2010
4Contact: Marek Lindner <lindner_marek@yahoo.de> 4Contact: Marek Lindner <mareklindner@neomailbox.ch>
5Description: 5Description:
6 Indicates whether the batman protocol messages of the 6 Indicates whether the batman protocol messages of the
7 mesh <mesh_iface> shall be aggregated or not. 7 mesh <mesh_iface> shall be aggregated or not.
8 8
9What: /sys/class/net/<mesh_iface>/mesh/ap_isolation 9What: /sys/class/net/<mesh_iface>/mesh/<vlan_subdir>/ap_isolation
10Date: May 2011 10Date: May 2011
11Contact: Antonio Quartulli <ordex@autistici.org> 11Contact: Antonio Quartulli <antonio@meshcoding.com>
12Description: 12Description:
13 Indicates whether the data traffic going from a 13 Indicates whether the data traffic going from a
14 wireless client to another wireless client will be 14 wireless client to another wireless client will be
15 silently dropped. 15 silently dropped. <vlan_subdir> is empty when referring
16 to the untagged lan.
16 17
17What: /sys/class/net/<mesh_iface>/mesh/bonding 18What: /sys/class/net/<mesh_iface>/mesh/bonding
18Date: June 2010 19Date: June 2010
19Contact: Simon Wunderlich <siwu@hrz.tu-chemnitz.de> 20Contact: Simon Wunderlich <sw@simonwunderlich.de>
20Description: 21Description:
21 Indicates whether the data traffic going through the 22 Indicates whether the data traffic going through the
22 mesh will be sent using multiple interfaces at the 23 mesh will be sent using multiple interfaces at the
@@ -24,7 +25,7 @@ Description:
24 25
25What: /sys/class/net/<mesh_iface>/mesh/bridge_loop_avoidance 26What: /sys/class/net/<mesh_iface>/mesh/bridge_loop_avoidance
26Date: November 2011 27Date: November 2011
27Contact: Simon Wunderlich <siwu@hrz.tu-chemnitz.de> 28Contact: Simon Wunderlich <sw@simonwunderlich.de>
28Description: 29Description:
29 Indicates whether the bridge loop avoidance feature 30 Indicates whether the bridge loop avoidance feature
30 is enabled. This feature detects and avoids loops 31 is enabled. This feature detects and avoids loops
@@ -41,21 +42,21 @@ Description:
41 42
42What: /sys/class/net/<mesh_iface>/mesh/gw_bandwidth 43What: /sys/class/net/<mesh_iface>/mesh/gw_bandwidth
43Date: October 2010 44Date: October 2010
44Contact: Marek Lindner <lindner_marek@yahoo.de> 45Contact: Marek Lindner <mareklindner@neomailbox.ch>
45Description: 46Description:
46 Defines the bandwidth which is propagated by this 47 Defines the bandwidth which is propagated by this
47 node if gw_mode was set to 'server'. 48 node if gw_mode was set to 'server'.
48 49
49What: /sys/class/net/<mesh_iface>/mesh/gw_mode 50What: /sys/class/net/<mesh_iface>/mesh/gw_mode
50Date: October 2010 51Date: October 2010
51Contact: Marek Lindner <lindner_marek@yahoo.de> 52Contact: Marek Lindner <mareklindner@neomailbox.ch>
52Description: 53Description:
53 Defines the state of the gateway features. Can be 54 Defines the state of the gateway features. Can be
54 either 'off', 'client' or 'server'. 55 either 'off', 'client' or 'server'.
55 56
56What: /sys/class/net/<mesh_iface>/mesh/gw_sel_class 57What: /sys/class/net/<mesh_iface>/mesh/gw_sel_class
57Date: October 2010 58Date: October 2010
58Contact: Marek Lindner <lindner_marek@yahoo.de> 59Contact: Marek Lindner <mareklindner@neomailbox.ch>
59Description: 60Description:
60 Defines the selection criteria this node will use 61 Defines the selection criteria this node will use
61 to choose a gateway if gw_mode was set to 'client'. 62 to choose a gateway if gw_mode was set to 'client'.
@@ -77,14 +78,14 @@ Description:
77 78
78What: /sys/class/net/<mesh_iface>/mesh/orig_interval 79What: /sys/class/net/<mesh_iface>/mesh/orig_interval
79Date: May 2010 80Date: May 2010
80Contact: Marek Lindner <lindner_marek@yahoo.de> 81Contact: Marek Lindner <mareklindner@neomailbox.ch>
81Description: 82Description:
82 Defines the interval in milliseconds in which batman 83 Defines the interval in milliseconds in which batman
83 sends its protocol messages. 84 sends its protocol messages.
84 85
85What: /sys/class/net/<mesh_iface>/mesh/routing_algo 86What: /sys/class/net/<mesh_iface>/mesh/routing_algo
86Date: Dec 2011 87Date: Dec 2011
87Contact: Marek Lindner <lindner_marek@yahoo.de> 88Contact: Marek Lindner <mareklindner@neomailbox.ch>
88Description: 89Description:
89 Defines the routing procotol this mesh instance 90 Defines the routing procotol this mesh instance
90 uses to find the optimal paths through the mesh. 91 uses to find the optimal paths through the mesh.
diff --git a/Documentation/networking/batman-adv.txt b/Documentation/networking/batman-adv.txt
index 897d1f4e1df1..89490beb3c0b 100644
--- a/Documentation/networking/batman-adv.txt
+++ b/Documentation/networking/batman-adv.txt
@@ -199,5 +199,5 @@ Mailing-list: b.a.t.m.a.n@open-mesh.org (optional subscription
199 199
200You can also contact the Authors: 200You can also contact the Authors:
201 201
202Marek Lindner <lindner_marek@yahoo.de> 202Marek Lindner <mareklindner@neomailbox.ch>
203Simon Wunderlich <siwu@hrz.tu-chemnitz.de> 203Simon Wunderlich <sw@simonwunderlich.de>
diff --git a/MAINTAINERS b/MAINTAINERS
index a46bcf816a6a..f169259ccdc6 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1653,7 +1653,7 @@ F: include/linux/backlight.h
1653 1653
1654BATMAN ADVANCED 1654BATMAN ADVANCED
1655M: Marek Lindner <mareklindner@neomailbox.ch> 1655M: Marek Lindner <mareklindner@neomailbox.ch>
1656M: Simon Wunderlich <siwu@hrz.tu-chemnitz.de> 1656M: Simon Wunderlich <sw@simonwunderlich.de>
1657M: Antonio Quartulli <antonio@meshcoding.com> 1657M: Antonio Quartulli <antonio@meshcoding.com>
1658L: b.a.t.m.a.n@lists.open-mesh.org 1658L: b.a.t.m.a.n@lists.open-mesh.org
1659W: http://www.open-mesh.org/ 1659W: http://www.open-mesh.org/
diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c
index 5bb58d7bdd56..28eb5e6d0a02 100644
--- a/net/batman-adv/bridge_loop_avoidance.c
+++ b/net/batman-adv/bridge_loop_avoidance.c
@@ -411,10 +411,10 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, uint8_t *orig,
411 return NULL; 411 return NULL;
412 } 412 }
413 413
414 /* this is a gateway now, remove any tt entries */ 414 /* this is a gateway now, remove any TT entry on this VLAN */
415 orig_node = batadv_orig_hash_find(bat_priv, orig); 415 orig_node = batadv_orig_hash_find(bat_priv, orig);
416 if (orig_node) { 416 if (orig_node) {
417 batadv_tt_global_del_orig(bat_priv, orig_node, 417 batadv_tt_global_del_orig(bat_priv, orig_node, vid,
418 "became a backbone gateway"); 418 "became a backbone gateway");
419 batadv_orig_node_free_ref(orig_node); 419 batadv_orig_node_free_ref(orig_node);
420 } 420 }
@@ -858,27 +858,25 @@ static int batadv_bla_process_claim(struct batadv_priv *bat_priv,
858 struct batadv_hard_iface *primary_if, 858 struct batadv_hard_iface *primary_if,
859 struct sk_buff *skb) 859 struct sk_buff *skb)
860{ 860{
861 struct ethhdr *ethhdr; 861 struct batadv_bla_claim_dst *bla_dst;
862 uint8_t *hw_src, *hw_dst;
862 struct vlan_ethhdr *vhdr; 863 struct vlan_ethhdr *vhdr;
864 struct ethhdr *ethhdr;
863 struct arphdr *arphdr; 865 struct arphdr *arphdr;
864 uint8_t *hw_src, *hw_dst; 866 unsigned short vid;
865 struct batadv_bla_claim_dst *bla_dst;
866 __be16 proto; 867 __be16 proto;
867 int headlen; 868 int headlen;
868 unsigned short vid = BATADV_NO_FLAGS;
869 int ret; 869 int ret;
870 870
871 vid = batadv_get_vid(skb, 0);
871 ethhdr = eth_hdr(skb); 872 ethhdr = eth_hdr(skb);
872 873
873 if (ethhdr->h_proto == htons(ETH_P_8021Q)) { 874 proto = ethhdr->h_proto;
875 headlen = ETH_HLEN;
876 if (vid & BATADV_VLAN_HAS_TAG) {
874 vhdr = (struct vlan_ethhdr *)ethhdr; 877 vhdr = (struct vlan_ethhdr *)ethhdr;
875 vid = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK;
876 vid |= BATADV_VLAN_HAS_TAG;
877 proto = vhdr->h_vlan_encapsulated_proto; 878 proto = vhdr->h_vlan_encapsulated_proto;
878 headlen = sizeof(*vhdr); 879 headlen += VLAN_HLEN;
879 } else {
880 proto = ethhdr->h_proto;
881 headlen = ETH_HLEN;
882 } 880 }
883 881
884 if (proto != htons(ETH_P_ARP)) 882 if (proto != htons(ETH_P_ARP))
@@ -1317,12 +1315,14 @@ out:
1317 1315
1318/* @bat_priv: the bat priv with all the soft interface information 1316/* @bat_priv: the bat priv with all the soft interface information
1319 * @orig: originator mac address 1317 * @orig: originator mac address
1318 * @vid: VLAN identifier
1320 * 1319 *
1321 * check if the originator is a gateway for any VLAN ID. 1320 * Check if the originator is a gateway for the VLAN identified by vid.
1322 * 1321 *
1323 * returns 1 if it is found, 0 otherwise 1322 * Returns true if orig is a backbone for this vid, false otherwise.
1324 */ 1323 */
1325int batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, uint8_t *orig) 1324bool batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, uint8_t *orig,
1325 unsigned short vid)
1326{ 1326{
1327 struct batadv_hashtable *hash = bat_priv->bla.backbone_hash; 1327 struct batadv_hashtable *hash = bat_priv->bla.backbone_hash;
1328 struct hlist_head *head; 1328 struct hlist_head *head;
@@ -1330,25 +1330,26 @@ int batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, uint8_t *orig)
1330 int i; 1330 int i;
1331 1331
1332 if (!atomic_read(&bat_priv->bridge_loop_avoidance)) 1332 if (!atomic_read(&bat_priv->bridge_loop_avoidance))
1333 return 0; 1333 return false;
1334 1334
1335 if (!hash) 1335 if (!hash)
1336 return 0; 1336 return false;
1337 1337
1338 for (i = 0; i < hash->size; i++) { 1338 for (i = 0; i < hash->size; i++) {
1339 head = &hash->table[i]; 1339 head = &hash->table[i];
1340 1340
1341 rcu_read_lock(); 1341 rcu_read_lock();
1342 hlist_for_each_entry_rcu(backbone_gw, head, hash_entry) { 1342 hlist_for_each_entry_rcu(backbone_gw, head, hash_entry) {
1343 if (batadv_compare_eth(backbone_gw->orig, orig)) { 1343 if (batadv_compare_eth(backbone_gw->orig, orig) &&
1344 backbone_gw->vid == vid) {
1344 rcu_read_unlock(); 1345 rcu_read_unlock();
1345 return 1; 1346 return true;
1346 } 1347 }
1347 } 1348 }
1348 rcu_read_unlock(); 1349 rcu_read_unlock();
1349 } 1350 }
1350 1351
1351 return 0; 1352 return false;
1352} 1353}
1353 1354
1354 1355
@@ -1365,10 +1366,8 @@ int batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, uint8_t *orig)
1365int batadv_bla_is_backbone_gw(struct sk_buff *skb, 1366int batadv_bla_is_backbone_gw(struct sk_buff *skb,
1366 struct batadv_orig_node *orig_node, int hdr_size) 1367 struct batadv_orig_node *orig_node, int hdr_size)
1367{ 1368{
1368 struct ethhdr *ethhdr;
1369 struct vlan_ethhdr *vhdr;
1370 struct batadv_bla_backbone_gw *backbone_gw; 1369 struct batadv_bla_backbone_gw *backbone_gw;
1371 unsigned short vid = BATADV_NO_FLAGS; 1370 unsigned short vid;
1372 1371
1373 if (!atomic_read(&orig_node->bat_priv->bridge_loop_avoidance)) 1372 if (!atomic_read(&orig_node->bat_priv->bridge_loop_avoidance))
1374 return 0; 1373 return 0;
@@ -1377,16 +1376,7 @@ int batadv_bla_is_backbone_gw(struct sk_buff *skb,
1377 if (!pskb_may_pull(skb, hdr_size + ETH_HLEN)) 1376 if (!pskb_may_pull(skb, hdr_size + ETH_HLEN))
1378 return 0; 1377 return 0;
1379 1378
1380 ethhdr = (struct ethhdr *)(((uint8_t *)skb->data) + hdr_size); 1379 vid = batadv_get_vid(skb, hdr_size);
1381
1382 if (ethhdr->h_proto == htons(ETH_P_8021Q)) {
1383 if (!pskb_may_pull(skb, hdr_size + VLAN_ETH_HLEN))
1384 return 0;
1385
1386 vhdr = (struct vlan_ethhdr *)(skb->data + hdr_size);
1387 vid = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK;
1388 vid |= BATADV_VLAN_HAS_TAG;
1389 }
1390 1380
1391 /* see if this originator is a backbone gw for this VLAN */ 1381 /* see if this originator is a backbone gw for this VLAN */
1392 backbone_gw = batadv_backbone_hash_find(orig_node->bat_priv, 1382 backbone_gw = batadv_backbone_hash_find(orig_node->bat_priv,
diff --git a/net/batman-adv/bridge_loop_avoidance.h b/net/batman-adv/bridge_loop_avoidance.h
index 4b102e71e5bd..da173e760e77 100644
--- a/net/batman-adv/bridge_loop_avoidance.h
+++ b/net/batman-adv/bridge_loop_avoidance.h
@@ -30,7 +30,8 @@ int batadv_bla_is_backbone_gw(struct sk_buff *skb,
30int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset); 30int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset);
31int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, 31int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq,
32 void *offset); 32 void *offset);
33int batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, uint8_t *orig); 33bool batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, uint8_t *orig,
34 unsigned short vid);
34int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv, 35int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
35 struct sk_buff *skb); 36 struct sk_buff *skb);
36void batadv_bla_update_orig_address(struct batadv_priv *bat_priv, 37void batadv_bla_update_orig_address(struct batadv_priv *bat_priv,
@@ -74,10 +75,11 @@ static inline int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq,
74 return 0; 75 return 0;
75} 76}
76 77
77static inline int batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, 78static inline bool batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv,
78 uint8_t *orig) 79 uint8_t *orig,
80 unsigned short vid)
79{ 81{
80 return 0; 82 return false;
81} 83}
82 84
83static inline int 85static inline int
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c
index 99da41290f82..6c8c3934bd7b 100644
--- a/net/batman-adv/distributed-arp-table.c
+++ b/net/batman-adv/distributed-arp-table.c
@@ -19,6 +19,7 @@
19 19
20#include <linux/if_ether.h> 20#include <linux/if_ether.h>
21#include <linux/if_arp.h> 21#include <linux/if_arp.h>
22#include <linux/if_vlan.h>
22#include <net/arp.h> 23#include <net/arp.h>
23 24
24#include "main.h" 25#include "main.h"
@@ -205,15 +206,11 @@ static __be32 batadv_arp_ip_dst(struct sk_buff *skb, int hdr_size)
205 */ 206 */
206static uint32_t batadv_hash_dat(const void *data, uint32_t size) 207static uint32_t batadv_hash_dat(const void *data, uint32_t size)
207{ 208{
208 const unsigned char *key = data;
209 uint32_t hash = 0; 209 uint32_t hash = 0;
210 size_t i; 210 const struct batadv_dat_entry *dat = data;
211 211
212 for (i = 0; i < 4; i++) { 212 hash = batadv_hash_bytes(hash, &dat->ip, sizeof(dat->ip));
213 hash += key[i]; 213 hash = batadv_hash_bytes(hash, &dat->vid, sizeof(dat->vid));
214 hash += (hash << 10);
215 hash ^= (hash >> 6);
216 }
217 214
218 hash += (hash << 3); 215 hash += (hash << 3);
219 hash ^= (hash >> 11); 216 hash ^= (hash >> 11);
@@ -227,21 +224,26 @@ static uint32_t batadv_hash_dat(const void *data, uint32_t size)
227 * table 224 * table
228 * @bat_priv: the bat priv with all the soft interface information 225 * @bat_priv: the bat priv with all the soft interface information
229 * @ip: search key 226 * @ip: search key
227 * @vid: VLAN identifier
230 * 228 *
231 * Returns the dat_entry if found, NULL otherwise. 229 * Returns the dat_entry if found, NULL otherwise.
232 */ 230 */
233static struct batadv_dat_entry * 231static struct batadv_dat_entry *
234batadv_dat_entry_hash_find(struct batadv_priv *bat_priv, __be32 ip) 232batadv_dat_entry_hash_find(struct batadv_priv *bat_priv, __be32 ip,
233 unsigned short vid)
235{ 234{
236 struct hlist_head *head; 235 struct hlist_head *head;
237 struct batadv_dat_entry *dat_entry, *dat_entry_tmp = NULL; 236 struct batadv_dat_entry to_find, *dat_entry, *dat_entry_tmp = NULL;
238 struct batadv_hashtable *hash = bat_priv->dat.hash; 237 struct batadv_hashtable *hash = bat_priv->dat.hash;
239 uint32_t index; 238 uint32_t index;
240 239
241 if (!hash) 240 if (!hash)
242 return NULL; 241 return NULL;
243 242
244 index = batadv_hash_dat(&ip, hash->size); 243 to_find.ip = ip;
244 to_find.vid = vid;
245
246 index = batadv_hash_dat(&to_find, hash->size);
245 head = &hash->table[index]; 247 head = &hash->table[index];
246 248
247 rcu_read_lock(); 249 rcu_read_lock();
@@ -265,22 +267,24 @@ batadv_dat_entry_hash_find(struct batadv_priv *bat_priv, __be32 ip)
265 * @bat_priv: the bat priv with all the soft interface information 267 * @bat_priv: the bat priv with all the soft interface information
266 * @ip: ipv4 to add/edit 268 * @ip: ipv4 to add/edit
267 * @mac_addr: mac address to assign to the given ipv4 269 * @mac_addr: mac address to assign to the given ipv4
270 * @vid: VLAN identifier
268 */ 271 */
269static void batadv_dat_entry_add(struct batadv_priv *bat_priv, __be32 ip, 272static void batadv_dat_entry_add(struct batadv_priv *bat_priv, __be32 ip,
270 uint8_t *mac_addr) 273 uint8_t *mac_addr, unsigned short vid)
271{ 274{
272 struct batadv_dat_entry *dat_entry; 275 struct batadv_dat_entry *dat_entry;
273 int hash_added; 276 int hash_added;
274 277
275 dat_entry = batadv_dat_entry_hash_find(bat_priv, ip); 278 dat_entry = batadv_dat_entry_hash_find(bat_priv, ip, vid);
276 /* if this entry is already known, just update it */ 279 /* if this entry is already known, just update it */
277 if (dat_entry) { 280 if (dat_entry) {
278 if (!batadv_compare_eth(dat_entry->mac_addr, mac_addr)) 281 if (!batadv_compare_eth(dat_entry->mac_addr, mac_addr))
279 memcpy(dat_entry->mac_addr, mac_addr, ETH_ALEN); 282 memcpy(dat_entry->mac_addr, mac_addr, ETH_ALEN);
280 dat_entry->last_update = jiffies; 283 dat_entry->last_update = jiffies;
281 batadv_dbg(BATADV_DBG_DAT, bat_priv, 284 batadv_dbg(BATADV_DBG_DAT, bat_priv,
282 "Entry updated: %pI4 %pM\n", &dat_entry->ip, 285 "Entry updated: %pI4 %pM (vid: %d)\n",
283 dat_entry->mac_addr); 286 &dat_entry->ip, dat_entry->mac_addr,
287 BATADV_PRINT_VID(vid));
284 goto out; 288 goto out;
285 } 289 }
286 290
@@ -289,12 +293,13 @@ static void batadv_dat_entry_add(struct batadv_priv *bat_priv, __be32 ip,
289 goto out; 293 goto out;
290 294
291 dat_entry->ip = ip; 295 dat_entry->ip = ip;
296 dat_entry->vid = vid;
292 memcpy(dat_entry->mac_addr, mac_addr, ETH_ALEN); 297 memcpy(dat_entry->mac_addr, mac_addr, ETH_ALEN);
293 dat_entry->last_update = jiffies; 298 dat_entry->last_update = jiffies;
294 atomic_set(&dat_entry->refcount, 2); 299 atomic_set(&dat_entry->refcount, 2);
295 300
296 hash_added = batadv_hash_add(bat_priv->dat.hash, batadv_compare_dat, 301 hash_added = batadv_hash_add(bat_priv->dat.hash, batadv_compare_dat,
297 batadv_hash_dat, &dat_entry->ip, 302 batadv_hash_dat, dat_entry,
298 &dat_entry->hash_entry); 303 &dat_entry->hash_entry);
299 304
300 if (unlikely(hash_added != 0)) { 305 if (unlikely(hash_added != 0)) {
@@ -303,8 +308,8 @@ static void batadv_dat_entry_add(struct batadv_priv *bat_priv, __be32 ip,
303 goto out; 308 goto out;
304 } 309 }
305 310
306 batadv_dbg(BATADV_DBG_DAT, bat_priv, "New entry added: %pI4 %pM\n", 311 batadv_dbg(BATADV_DBG_DAT, bat_priv, "New entry added: %pI4 %pM (vid: %d)\n",
307 &dat_entry->ip, dat_entry->mac_addr); 312 &dat_entry->ip, dat_entry->mac_addr, BATADV_PRINT_VID(vid));
308 313
309out: 314out:
310 if (dat_entry) 315 if (dat_entry)
@@ -756,8 +761,8 @@ int batadv_dat_cache_seq_print_text(struct seq_file *seq, void *offset)
756 goto out; 761 goto out;
757 762
758 seq_printf(seq, "Distributed ARP Table (%s):\n", net_dev->name); 763 seq_printf(seq, "Distributed ARP Table (%s):\n", net_dev->name);
759 seq_printf(seq, " %-7s %-13s %5s\n", "IPv4", "MAC", 764 seq_printf(seq, " %-7s %-9s %4s %11s\n", "IPv4",
760 "last-seen"); 765 "MAC", "VID", "last-seen");
761 766
762 for (i = 0; i < hash->size; i++) { 767 for (i = 0; i < hash->size; i++) {
763 head = &hash->table[i]; 768 head = &hash->table[i];
@@ -770,8 +775,9 @@ int batadv_dat_cache_seq_print_text(struct seq_file *seq, void *offset)
770 last_seen_msecs = last_seen_msecs % 60000; 775 last_seen_msecs = last_seen_msecs % 60000;
771 last_seen_secs = last_seen_msecs / 1000; 776 last_seen_secs = last_seen_msecs / 1000;
772 777
773 seq_printf(seq, " * %15pI4 %14pM %6i:%02i\n", 778 seq_printf(seq, " * %15pI4 %14pM %4i %6i:%02i\n",
774 &dat_entry->ip, dat_entry->mac_addr, 779 &dat_entry->ip, dat_entry->mac_addr,
780 BATADV_PRINT_VID(dat_entry->vid),
775 last_seen_mins, last_seen_secs); 781 last_seen_mins, last_seen_secs);
776 } 782 }
777 rcu_read_unlock(); 783 rcu_read_unlock();
@@ -858,6 +864,31 @@ out:
858} 864}
859 865
860/** 866/**
867 * batadv_dat_get_vid - extract the VLAN identifier from skb if any
868 * @skb: the buffer containing the packet to extract the VID from
869 * @hdr_size: the size of the batman-adv header encapsulating the packet
870 *
871 * If the packet embedded in the skb is vlan tagged this function returns the
872 * VID with the BATADV_VLAN_HAS_TAG flag. Otherwise BATADV_NO_FLAGS is returned.
873 */
874static unsigned short batadv_dat_get_vid(struct sk_buff *skb, int *hdr_size)
875{
876 unsigned short vid;
877
878 vid = batadv_get_vid(skb, *hdr_size);
879
880 /* ARP parsing functions jump forward of hdr_size + ETH_HLEN.
881 * If the header contained in the packet is a VLAN one (which is longer)
882 * hdr_size is updated so that the functions will still skip the
883 * correct amount of bytes.
884 */
885 if (vid & BATADV_VLAN_HAS_TAG)
886 *hdr_size += VLAN_HLEN;
887
888 return vid;
889}
890
891/**
861 * batadv_dat_snoop_outgoing_arp_request - snoop the ARP request and try to 892 * batadv_dat_snoop_outgoing_arp_request - snoop the ARP request and try to
862 * answer using DAT 893 * answer using DAT
863 * @bat_priv: the bat priv with all the soft interface information 894 * @bat_priv: the bat priv with all the soft interface information
@@ -876,26 +907,31 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
876 bool ret = false; 907 bool ret = false;
877 struct batadv_dat_entry *dat_entry = NULL; 908 struct batadv_dat_entry *dat_entry = NULL;
878 struct sk_buff *skb_new; 909 struct sk_buff *skb_new;
910 int hdr_size = 0;
911 unsigned short vid;
879 912
880 if (!atomic_read(&bat_priv->distributed_arp_table)) 913 if (!atomic_read(&bat_priv->distributed_arp_table))
881 goto out; 914 goto out;
882 915
883 type = batadv_arp_get_type(bat_priv, skb, 0); 916 vid = batadv_dat_get_vid(skb, &hdr_size);
917
918 type = batadv_arp_get_type(bat_priv, skb, hdr_size);
884 /* If the node gets an ARP_REQUEST it has to send a DHT_GET unicast 919 /* If the node gets an ARP_REQUEST it has to send a DHT_GET unicast
885 * message to the selected DHT candidates 920 * message to the selected DHT candidates
886 */ 921 */
887 if (type != ARPOP_REQUEST) 922 if (type != ARPOP_REQUEST)
888 goto out; 923 goto out;
889 924
890 batadv_dbg_arp(bat_priv, skb, type, 0, "Parsing outgoing ARP REQUEST"); 925 batadv_dbg_arp(bat_priv, skb, type, hdr_size,
926 "Parsing outgoing ARP REQUEST");
891 927
892 ip_src = batadv_arp_ip_src(skb, 0); 928 ip_src = batadv_arp_ip_src(skb, hdr_size);
893 hw_src = batadv_arp_hw_src(skb, 0); 929 hw_src = batadv_arp_hw_src(skb, hdr_size);
894 ip_dst = batadv_arp_ip_dst(skb, 0); 930 ip_dst = batadv_arp_ip_dst(skb, hdr_size);
895 931
896 batadv_dat_entry_add(bat_priv, ip_src, hw_src); 932 batadv_dat_entry_add(bat_priv, ip_src, hw_src, vid);
897 933
898 dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst); 934 dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst, vid);
899 if (dat_entry) { 935 if (dat_entry) {
900 /* If the ARP request is destined for a local client the local 936 /* If the ARP request is destined for a local client the local
901 * client will answer itself. DAT would only generate a 937 * client will answer itself. DAT would only generate a
@@ -905,7 +941,8 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
905 * additional DAT answer may trigger kernel warnings about 941 * additional DAT answer may trigger kernel warnings about
906 * a packet coming from the wrong port. 942 * a packet coming from the wrong port.
907 */ 943 */
908 if (batadv_is_my_client(bat_priv, dat_entry->mac_addr)) { 944 if (batadv_is_my_client(bat_priv, dat_entry->mac_addr,
945 BATADV_NO_FLAGS)) {
909 ret = true; 946 ret = true;
910 goto out; 947 goto out;
911 } 948 }
@@ -916,11 +953,15 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
916 if (!skb_new) 953 if (!skb_new)
917 goto out; 954 goto out;
918 955
956 if (vid & BATADV_VLAN_HAS_TAG)
957 skb_new = vlan_insert_tag(skb_new, htons(ETH_P_8021Q),
958 vid & VLAN_VID_MASK);
959
919 skb_reset_mac_header(skb_new); 960 skb_reset_mac_header(skb_new);
920 skb_new->protocol = eth_type_trans(skb_new, 961 skb_new->protocol = eth_type_trans(skb_new,
921 bat_priv->soft_iface); 962 bat_priv->soft_iface);
922 bat_priv->stats.rx_packets++; 963 bat_priv->stats.rx_packets++;
923 bat_priv->stats.rx_bytes += skb->len + ETH_HLEN; 964 bat_priv->stats.rx_bytes += skb->len + ETH_HLEN + hdr_size;
924 bat_priv->soft_iface->last_rx = jiffies; 965 bat_priv->soft_iface->last_rx = jiffies;
925 966
926 netif_rx(skb_new); 967 netif_rx(skb_new);
@@ -955,11 +996,14 @@ bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
955 struct sk_buff *skb_new; 996 struct sk_buff *skb_new;
956 struct batadv_dat_entry *dat_entry = NULL; 997 struct batadv_dat_entry *dat_entry = NULL;
957 bool ret = false; 998 bool ret = false;
999 unsigned short vid;
958 int err; 1000 int err;
959 1001
960 if (!atomic_read(&bat_priv->distributed_arp_table)) 1002 if (!atomic_read(&bat_priv->distributed_arp_table))
961 goto out; 1003 goto out;
962 1004
1005 vid = batadv_dat_get_vid(skb, &hdr_size);
1006
963 type = batadv_arp_get_type(bat_priv, skb, hdr_size); 1007 type = batadv_arp_get_type(bat_priv, skb, hdr_size);
964 if (type != ARPOP_REQUEST) 1008 if (type != ARPOP_REQUEST)
965 goto out; 1009 goto out;
@@ -971,9 +1015,9 @@ bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
971 batadv_dbg_arp(bat_priv, skb, type, hdr_size, 1015 batadv_dbg_arp(bat_priv, skb, type, hdr_size,
972 "Parsing incoming ARP REQUEST"); 1016 "Parsing incoming ARP REQUEST");
973 1017
974 batadv_dat_entry_add(bat_priv, ip_src, hw_src); 1018 batadv_dat_entry_add(bat_priv, ip_src, hw_src, vid);
975 1019
976 dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst); 1020 dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst, vid);
977 if (!dat_entry) 1021 if (!dat_entry)
978 goto out; 1022 goto out;
979 1023
@@ -984,17 +1028,22 @@ bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
984 if (!skb_new) 1028 if (!skb_new)
985 goto out; 1029 goto out;
986 1030
1031 if (vid & BATADV_VLAN_HAS_TAG)
1032 skb_new = vlan_insert_tag(skb_new, htons(ETH_P_8021Q),
1033 vid & VLAN_VID_MASK);
1034
987 /* To preserve backwards compatibility, the node has choose the outgoing 1035 /* To preserve backwards compatibility, the node has choose the outgoing
988 * format based on the incoming request packet type. The assumption is 1036 * format based on the incoming request packet type. The assumption is
989 * that a node not using the 4addr packet format doesn't support it. 1037 * that a node not using the 4addr packet format doesn't support it.
990 */ 1038 */
991 if (hdr_size == sizeof(struct batadv_unicast_4addr_packet)) 1039 if (hdr_size == sizeof(struct batadv_unicast_4addr_packet))
992 err = batadv_send_skb_unicast_4addr(bat_priv, skb_new, 1040 err = batadv_send_skb_via_tt_4addr(bat_priv, skb_new,
993 BATADV_P_DAT_CACHE_REPLY); 1041 BATADV_P_DAT_CACHE_REPLY,
1042 vid);
994 else 1043 else
995 err = batadv_send_skb_unicast(bat_priv, skb_new); 1044 err = batadv_send_skb_via_tt(bat_priv, skb_new, vid);
996 1045
997 if (!err) { 1046 if (err != NET_XMIT_DROP) {
998 batadv_inc_counter(bat_priv, BATADV_CNT_DAT_CACHED_REPLY_TX); 1047 batadv_inc_counter(bat_priv, BATADV_CNT_DAT_CACHED_REPLY_TX);
999 ret = true; 1048 ret = true;
1000 } 1049 }
@@ -1017,23 +1066,28 @@ void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv,
1017 uint16_t type; 1066 uint16_t type;
1018 __be32 ip_src, ip_dst; 1067 __be32 ip_src, ip_dst;
1019 uint8_t *hw_src, *hw_dst; 1068 uint8_t *hw_src, *hw_dst;
1069 int hdr_size = 0;
1070 unsigned short vid;
1020 1071
1021 if (!atomic_read(&bat_priv->distributed_arp_table)) 1072 if (!atomic_read(&bat_priv->distributed_arp_table))
1022 return; 1073 return;
1023 1074
1024 type = batadv_arp_get_type(bat_priv, skb, 0); 1075 vid = batadv_dat_get_vid(skb, &hdr_size);
1076
1077 type = batadv_arp_get_type(bat_priv, skb, hdr_size);
1025 if (type != ARPOP_REPLY) 1078 if (type != ARPOP_REPLY)
1026 return; 1079 return;
1027 1080
1028 batadv_dbg_arp(bat_priv, skb, type, 0, "Parsing outgoing ARP REPLY"); 1081 batadv_dbg_arp(bat_priv, skb, type, hdr_size,
1082 "Parsing outgoing ARP REPLY");
1029 1083
1030 hw_src = batadv_arp_hw_src(skb, 0); 1084 hw_src = batadv_arp_hw_src(skb, hdr_size);
1031 ip_src = batadv_arp_ip_src(skb, 0); 1085 ip_src = batadv_arp_ip_src(skb, hdr_size);
1032 hw_dst = batadv_arp_hw_dst(skb, 0); 1086 hw_dst = batadv_arp_hw_dst(skb, hdr_size);
1033 ip_dst = batadv_arp_ip_dst(skb, 0); 1087 ip_dst = batadv_arp_ip_dst(skb, hdr_size);
1034 1088
1035 batadv_dat_entry_add(bat_priv, ip_src, hw_src); 1089 batadv_dat_entry_add(bat_priv, ip_src, hw_src, vid);
1036 batadv_dat_entry_add(bat_priv, ip_dst, hw_dst); 1090 batadv_dat_entry_add(bat_priv, ip_dst, hw_dst, vid);
1037 1091
1038 /* Send the ARP reply to the candidates for both the IP addresses that 1092 /* Send the ARP reply to the candidates for both the IP addresses that
1039 * the node obtained from the ARP reply 1093 * the node obtained from the ARP reply
@@ -1055,10 +1109,13 @@ bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
1055 __be32 ip_src, ip_dst; 1109 __be32 ip_src, ip_dst;
1056 uint8_t *hw_src, *hw_dst; 1110 uint8_t *hw_src, *hw_dst;
1057 bool ret = false; 1111 bool ret = false;
1112 unsigned short vid;
1058 1113
1059 if (!atomic_read(&bat_priv->distributed_arp_table)) 1114 if (!atomic_read(&bat_priv->distributed_arp_table))
1060 goto out; 1115 goto out;
1061 1116
1117 vid = batadv_dat_get_vid(skb, &hdr_size);
1118
1062 type = batadv_arp_get_type(bat_priv, skb, hdr_size); 1119 type = batadv_arp_get_type(bat_priv, skb, hdr_size);
1063 if (type != ARPOP_REPLY) 1120 if (type != ARPOP_REPLY)
1064 goto out; 1121 goto out;
@@ -1074,13 +1131,13 @@ bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
1074 /* Update our internal cache with both the IP addresses the node got 1131 /* Update our internal cache with both the IP addresses the node got
1075 * within the ARP reply 1132 * within the ARP reply
1076 */ 1133 */
1077 batadv_dat_entry_add(bat_priv, ip_src, hw_src); 1134 batadv_dat_entry_add(bat_priv, ip_src, hw_src, vid);
1078 batadv_dat_entry_add(bat_priv, ip_dst, hw_dst); 1135 batadv_dat_entry_add(bat_priv, ip_dst, hw_dst, vid);
1079 1136
1080 /* if this REPLY is directed to a client of mine, let's deliver the 1137 /* if this REPLY is directed to a client of mine, let's deliver the
1081 * packet to the interface 1138 * packet to the interface
1082 */ 1139 */
1083 ret = !batadv_is_my_client(bat_priv, hw_dst); 1140 ret = !batadv_is_my_client(bat_priv, hw_dst, vid);
1084out: 1141out:
1085 if (ret) 1142 if (ret)
1086 kfree_skb(skb); 1143 kfree_skb(skb);
@@ -1103,7 +1160,8 @@ bool batadv_dat_drop_broadcast_packet(struct batadv_priv *bat_priv,
1103 __be32 ip_dst; 1160 __be32 ip_dst;
1104 struct batadv_dat_entry *dat_entry = NULL; 1161 struct batadv_dat_entry *dat_entry = NULL;
1105 bool ret = false; 1162 bool ret = false;
1106 const size_t bcast_len = sizeof(struct batadv_bcast_packet); 1163 int hdr_size = sizeof(struct batadv_bcast_packet);
1164 unsigned short vid;
1107 1165
1108 if (!atomic_read(&bat_priv->distributed_arp_table)) 1166 if (!atomic_read(&bat_priv->distributed_arp_table))
1109 goto out; 1167 goto out;
@@ -1114,12 +1172,14 @@ bool batadv_dat_drop_broadcast_packet(struct batadv_priv *bat_priv,
1114 if (forw_packet->num_packets) 1172 if (forw_packet->num_packets)
1115 goto out; 1173 goto out;
1116 1174
1117 type = batadv_arp_get_type(bat_priv, forw_packet->skb, bcast_len); 1175 vid = batadv_dat_get_vid(forw_packet->skb, &hdr_size);
1176
1177 type = batadv_arp_get_type(bat_priv, forw_packet->skb, hdr_size);
1118 if (type != ARPOP_REQUEST) 1178 if (type != ARPOP_REQUEST)
1119 goto out; 1179 goto out;
1120 1180
1121 ip_dst = batadv_arp_ip_dst(forw_packet->skb, bcast_len); 1181 ip_dst = batadv_arp_ip_dst(forw_packet->skb, hdr_size);
1122 dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst); 1182 dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst, vid);
1123 /* check if the node already got this entry */ 1183 /* check if the node already got this entry */
1124 if (!dat_entry) { 1184 if (!dat_entry) {
1125 batadv_dbg(BATADV_DBG_DAT, bat_priv, 1185 batadv_dbg(BATADV_DBG_DAT, bat_priv,
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c
index 053bb318c7a7..20fa053b7f57 100644
--- a/net/batman-adv/gateway_client.c
+++ b/net/batman-adv/gateway_client.c
@@ -221,11 +221,6 @@ void batadv_gw_election(struct batadv_priv *bat_priv)
221 struct batadv_neigh_node *router = NULL; 221 struct batadv_neigh_node *router = NULL;
222 char gw_addr[18] = { '\0' }; 222 char gw_addr[18] = { '\0' };
223 223
224 /* The batman daemon checks here if we already passed a full originator
225 * cycle in order to make sure we don't choose the first gateway we
226 * hear about. This check is based on the daemon's uptime which we
227 * don't have.
228 */
229 if (atomic_read(&bat_priv->gw_mode) != BATADV_GW_MODE_CLIENT) 224 if (atomic_read(&bat_priv->gw_mode) != BATADV_GW_MODE_CLIENT)
230 goto out; 225 goto out;
231 226
@@ -726,7 +721,20 @@ bool batadv_gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len)
726 return true; 721 return true;
727} 722}
728 723
729/* this call might reallocate skb data */ 724/**
725 * batadv_gw_out_of_range - check if the dhcp request destination is the best gw
726 * @bat_priv: the bat priv with all the soft interface information
727 * @skb: the outgoing packet
728 *
729 * Check if the skb is a DHCP request and if it is sent to the current best GW
730 * server. Due to topology changes it may be the case that the GW server
731 * previously selected is not the best one anymore.
732 *
733 * Returns true if the packet destination is unicast and it is not the best gw,
734 * false otherwise.
735 *
736 * This call might reallocate skb data.
737 */
730bool batadv_gw_out_of_range(struct batadv_priv *bat_priv, 738bool batadv_gw_out_of_range(struct batadv_priv *bat_priv,
731 struct sk_buff *skb) 739 struct sk_buff *skb)
732{ 740{
@@ -737,6 +745,9 @@ bool batadv_gw_out_of_range(struct batadv_priv *bat_priv,
737 bool ret, out_of_range = false; 745 bool ret, out_of_range = false;
738 unsigned int header_len = 0; 746 unsigned int header_len = 0;
739 uint8_t curr_tq_avg; 747 uint8_t curr_tq_avg;
748 unsigned short vid;
749
750 vid = batadv_get_vid(skb, 0);
740 751
741 ret = batadv_gw_is_dhcp_target(skb, &header_len); 752 ret = batadv_gw_is_dhcp_target(skb, &header_len);
742 if (!ret) 753 if (!ret)
@@ -744,7 +755,7 @@ bool batadv_gw_out_of_range(struct batadv_priv *bat_priv,
744 755
745 ethhdr = (struct ethhdr *)skb->data; 756 ethhdr = (struct ethhdr *)skb->data;
746 orig_dst_node = batadv_transtable_search(bat_priv, ethhdr->h_source, 757 orig_dst_node = batadv_transtable_search(bat_priv, ethhdr->h_source,
747 ethhdr->h_dest); 758 ethhdr->h_dest, vid);
748 if (!orig_dst_node) 759 if (!orig_dst_node)
749 goto out; 760 goto out;
750 761
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index d564af295db4..c5f871f218c6 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -643,6 +643,8 @@ static int batadv_hard_if_event(struct notifier_block *this,
643 643
644 if (batadv_softif_is_valid(net_dev) && event == NETDEV_REGISTER) { 644 if (batadv_softif_is_valid(net_dev) && event == NETDEV_REGISTER) {
645 batadv_sysfs_add_meshif(net_dev); 645 batadv_sysfs_add_meshif(net_dev);
646 bat_priv = netdev_priv(net_dev);
647 batadv_softif_create_vlan(bat_priv, BATADV_NO_FLAGS);
646 return NOTIFY_DONE; 648 return NOTIFY_DONE;
647 } 649 }
648 650
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index 7f3a5c426615..3159a148c1ac 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -110,9 +110,11 @@ int batadv_mesh_init(struct net_device *soft_iface)
110 spin_lock_init(&bat_priv->tt.req_list_lock); 110 spin_lock_init(&bat_priv->tt.req_list_lock);
111 spin_lock_init(&bat_priv->tt.roam_list_lock); 111 spin_lock_init(&bat_priv->tt.roam_list_lock);
112 spin_lock_init(&bat_priv->tt.last_changeset_lock); 112 spin_lock_init(&bat_priv->tt.last_changeset_lock);
113 spin_lock_init(&bat_priv->tt.commit_lock);
113 spin_lock_init(&bat_priv->gw.list_lock); 114 spin_lock_init(&bat_priv->gw.list_lock);
114 spin_lock_init(&bat_priv->tvlv.container_list_lock); 115 spin_lock_init(&bat_priv->tvlv.container_list_lock);
115 spin_lock_init(&bat_priv->tvlv.handler_list_lock); 116 spin_lock_init(&bat_priv->tvlv.handler_list_lock);
117 spin_lock_init(&bat_priv->softif_vlan_list_lock);
116 118
117 INIT_HLIST_HEAD(&bat_priv->forw_bat_list); 119 INIT_HLIST_HEAD(&bat_priv->forw_bat_list);
118 INIT_HLIST_HEAD(&bat_priv->forw_bcast_list); 120 INIT_HLIST_HEAD(&bat_priv->forw_bcast_list);
@@ -122,6 +124,7 @@ int batadv_mesh_init(struct net_device *soft_iface)
122 INIT_LIST_HEAD(&bat_priv->tt.roam_list); 124 INIT_LIST_HEAD(&bat_priv->tt.roam_list);
123 INIT_HLIST_HEAD(&bat_priv->tvlv.container_list); 125 INIT_HLIST_HEAD(&bat_priv->tvlv.container_list);
124 INIT_HLIST_HEAD(&bat_priv->tvlv.handler_list); 126 INIT_HLIST_HEAD(&bat_priv->tvlv.handler_list);
127 INIT_HLIST_HEAD(&bat_priv->softif_vlan_list);
125 128
126 ret = batadv_originator_init(bat_priv); 129 ret = batadv_originator_init(bat_priv);
127 if (ret < 0) 130 if (ret < 0)
@@ -131,9 +134,6 @@ int batadv_mesh_init(struct net_device *soft_iface)
131 if (ret < 0) 134 if (ret < 0)
132 goto err; 135 goto err;
133 136
134 batadv_tt_local_add(soft_iface, soft_iface->dev_addr,
135 BATADV_NULL_IFINDEX);
136
137 ret = batadv_bla_init(bat_priv); 137 ret = batadv_bla_init(bat_priv);
138 if (ret < 0) 138 if (ret < 0)
139 goto err; 139 goto err;
@@ -1144,6 +1144,33 @@ out:
1144 batadv_orig_node_free_ref(orig_node); 1144 batadv_orig_node_free_ref(orig_node);
1145} 1145}
1146 1146
1147/**
1148 * batadv_get_vid - extract the VLAN identifier from skb if any
1149 * @skb: the buffer containing the packet
1150 * @header_len: length of the batman header preceding the ethernet header
1151 *
1152 * If the packet embedded in the skb is vlan tagged this function returns the
1153 * VID with the BATADV_VLAN_HAS_TAG flag. Otherwise BATADV_NO_FLAGS is returned.
1154 */
1155unsigned short batadv_get_vid(struct sk_buff *skb, size_t header_len)
1156{
1157 struct ethhdr *ethhdr = (struct ethhdr *)(skb->data + header_len);
1158 struct vlan_ethhdr *vhdr;
1159 unsigned short vid;
1160
1161 if (ethhdr->h_proto != htons(ETH_P_8021Q))
1162 return BATADV_NO_FLAGS;
1163
1164 if (!pskb_may_pull(skb, header_len + VLAN_ETH_HLEN))
1165 return BATADV_NO_FLAGS;
1166
1167 vhdr = (struct vlan_ethhdr *)(skb->data + header_len);
1168 vid = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK;
1169 vid |= BATADV_VLAN_HAS_TAG;
1170
1171 return vid;
1172}
1173
1147static int batadv_param_set_ra(const char *val, const struct kernel_param *kp) 1174static int batadv_param_set_ra(const char *val, const struct kernel_param *kp)
1148{ 1175{
1149 struct batadv_algo_ops *bat_algo_ops; 1176 struct batadv_algo_ops *bat_algo_ops;
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h
index 54c13d51edbe..d7dfafe45f29 100644
--- a/net/batman-adv/main.h
+++ b/net/batman-adv/main.h
@@ -20,8 +20,8 @@
20#ifndef _NET_BATMAN_ADV_MAIN_H_ 20#ifndef _NET_BATMAN_ADV_MAIN_H_
21#define _NET_BATMAN_ADV_MAIN_H_ 21#define _NET_BATMAN_ADV_MAIN_H_
22 22
23#define BATADV_DRIVER_AUTHOR "Marek Lindner <lindner_marek@yahoo.de>, " \ 23#define BATADV_DRIVER_AUTHOR "Marek Lindner <mareklindner@neomailbox.ch>, " \
24 "Simon Wunderlich <siwu@hrz.tu-chemnitz.de>" 24 "Simon Wunderlich <sw@simonwunderlich.de>"
25#define BATADV_DRIVER_DESC "B.A.T.M.A.N. advanced" 25#define BATADV_DRIVER_DESC "B.A.T.M.A.N. advanced"
26#define BATADV_DRIVER_DEVICE "batman-adv" 26#define BATADV_DRIVER_DEVICE "batman-adv"
27 27
@@ -167,15 +167,9 @@ enum batadv_uev_type {
167#include <net/rtnetlink.h> 167#include <net/rtnetlink.h>
168#include <linux/jiffies.h> 168#include <linux/jiffies.h>
169#include <linux/seq_file.h> 169#include <linux/seq_file.h>
170#include "types.h" 170#include <linux/if_vlan.h>
171 171
172/** 172#include "types.h"
173 * batadv_vlan_flags - flags for the four MSB of any vlan ID field
174 * @BATADV_VLAN_HAS_TAG: whether the field contains a valid vlan tag or not
175 */
176enum batadv_vlan_flags {
177 BATADV_VLAN_HAS_TAG = BIT(15),
178};
179 173
180#define BATADV_PRINT_VID(vid) (vid & BATADV_VLAN_HAS_TAG ? \ 174#define BATADV_PRINT_VID(vid) (vid & BATADV_VLAN_HAS_TAG ? \
181 (int)(vid & VLAN_VID_MASK) : -1) 175 (int)(vid & VLAN_VID_MASK) : -1)
@@ -368,5 +362,6 @@ int batadv_tvlv_containers_process(struct batadv_priv *bat_priv,
368void batadv_tvlv_unicast_send(struct batadv_priv *bat_priv, uint8_t *src, 362void batadv_tvlv_unicast_send(struct batadv_priv *bat_priv, uint8_t *src,
369 uint8_t *dst, uint8_t type, uint8_t version, 363 uint8_t *dst, uint8_t type, uint8_t version,
370 void *tvlv_value, uint16_t tvlv_value_len); 364 void *tvlv_value, uint16_t tvlv_value_len);
365unsigned short batadv_get_vid(struct sk_buff *skb, size_t header_len);
371 366
372#endif /* _NET_BATMAN_ADV_MAIN_H_ */ 367#endif /* _NET_BATMAN_ADV_MAIN_H_ */
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index a591dc5c321e..ee1d84724205 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -44,6 +44,88 @@ static int batadv_compare_orig(const struct hlist_node *node, const void *data2)
44 return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0); 44 return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
45} 45}
46 46
47/**
48 * batadv_orig_node_vlan_get - get an orig_node_vlan object
49 * @orig_node: the originator serving the VLAN
50 * @vid: the VLAN identifier
51 *
52 * Returns the vlan object identified by vid and belonging to orig_node or NULL
53 * if it does not exist.
54 */
55struct batadv_orig_node_vlan *
56batadv_orig_node_vlan_get(struct batadv_orig_node *orig_node,
57 unsigned short vid)
58{
59 struct batadv_orig_node_vlan *vlan = NULL, *tmp;
60
61 rcu_read_lock();
62 list_for_each_entry_rcu(tmp, &orig_node->vlan_list, list) {
63 if (tmp->vid != vid)
64 continue;
65
66 if (!atomic_inc_not_zero(&tmp->refcount))
67 continue;
68
69 vlan = tmp;
70
71 break;
72 }
73 rcu_read_unlock();
74
75 return vlan;
76}
77
78/**
79 * batadv_orig_node_vlan_new - search and possibly create an orig_node_vlan
80 * object
81 * @orig_node: the originator serving the VLAN
82 * @vid: the VLAN identifier
83 *
84 * Returns NULL in case of failure or the vlan object identified by vid and
85 * belonging to orig_node otherwise. The object is created and added to the list
86 * if it does not exist.
87 *
88 * The object is returned with refcounter increased by 1.
89 */
90struct batadv_orig_node_vlan *
91batadv_orig_node_vlan_new(struct batadv_orig_node *orig_node,
92 unsigned short vid)
93{
94 struct batadv_orig_node_vlan *vlan;
95
96 spin_lock_bh(&orig_node->vlan_list_lock);
97
98 /* first look if an object for this vid already exists */
99 vlan = batadv_orig_node_vlan_get(orig_node, vid);
100 if (vlan)
101 goto out;
102
103 vlan = kzalloc(sizeof(*vlan), GFP_ATOMIC);
104 if (!vlan)
105 goto out;
106
107 atomic_set(&vlan->refcount, 2);
108 vlan->vid = vid;
109
110 list_add_rcu(&vlan->list, &orig_node->vlan_list);
111
112out:
113 spin_unlock_bh(&orig_node->vlan_list_lock);
114
115 return vlan;
116}
117
118/**
119 * batadv_orig_node_vlan_free_ref - decrement the refcounter and possibly free
120 * the originator-vlan object
121 * @orig_vlan: the originator-vlan object to release
122 */
123void batadv_orig_node_vlan_free_ref(struct batadv_orig_node_vlan *orig_vlan)
124{
125 if (atomic_dec_and_test(&orig_vlan->refcount))
126 kfree_rcu(orig_vlan, rcu);
127}
128
47int batadv_originator_init(struct batadv_priv *bat_priv) 129int batadv_originator_init(struct batadv_priv *bat_priv)
48{ 130{
49 if (bat_priv->orig_hash) 131 if (bat_priv->orig_hash)
@@ -148,7 +230,7 @@ static void batadv_orig_node_free_rcu(struct rcu_head *rcu)
148 230
149 batadv_frag_purge_orig(orig_node, NULL); 231 batadv_frag_purge_orig(orig_node, NULL);
150 232
151 batadv_tt_global_del_orig(orig_node->bat_priv, orig_node, 233 batadv_tt_global_del_orig(orig_node->bat_priv, orig_node, -1,
152 "originator timed out"); 234 "originator timed out");
153 235
154 kfree(orig_node->tt_buff); 236 kfree(orig_node->tt_buff);
@@ -218,6 +300,7 @@ struct batadv_orig_node *batadv_get_orig_node(struct batadv_priv *bat_priv,
218 const uint8_t *addr) 300 const uint8_t *addr)
219{ 301{
220 struct batadv_orig_node *orig_node; 302 struct batadv_orig_node *orig_node;
303 struct batadv_orig_node_vlan *vlan;
221 int size, i; 304 int size, i;
222 int hash_added; 305 int hash_added;
223 unsigned long reset_time; 306 unsigned long reset_time;
@@ -235,10 +318,13 @@ struct batadv_orig_node *batadv_get_orig_node(struct batadv_priv *bat_priv,
235 318
236 INIT_HLIST_HEAD(&orig_node->neigh_list); 319 INIT_HLIST_HEAD(&orig_node->neigh_list);
237 INIT_LIST_HEAD(&orig_node->bond_list); 320 INIT_LIST_HEAD(&orig_node->bond_list);
321 INIT_LIST_HEAD(&orig_node->vlan_list);
238 spin_lock_init(&orig_node->ogm_cnt_lock); 322 spin_lock_init(&orig_node->ogm_cnt_lock);
239 spin_lock_init(&orig_node->bcast_seqno_lock); 323 spin_lock_init(&orig_node->bcast_seqno_lock);
240 spin_lock_init(&orig_node->neigh_list_lock); 324 spin_lock_init(&orig_node->neigh_list_lock);
241 spin_lock_init(&orig_node->tt_buff_lock); 325 spin_lock_init(&orig_node->tt_buff_lock);
326 spin_lock_init(&orig_node->tt_lock);
327 spin_lock_init(&orig_node->vlan_list_lock);
242 328
243 batadv_nc_init_orig(orig_node); 329 batadv_nc_init_orig(orig_node);
244 330
@@ -250,22 +336,30 @@ struct batadv_orig_node *batadv_get_orig_node(struct batadv_priv *bat_priv,
250 memcpy(orig_node->orig, addr, ETH_ALEN); 336 memcpy(orig_node->orig, addr, ETH_ALEN);
251 batadv_dat_init_orig_node_addr(orig_node); 337 batadv_dat_init_orig_node_addr(orig_node);
252 orig_node->router = NULL; 338 orig_node->router = NULL;
253 orig_node->tt_crc = 0;
254 atomic_set(&orig_node->last_ttvn, 0); 339 atomic_set(&orig_node->last_ttvn, 0);
255 orig_node->tt_buff = NULL; 340 orig_node->tt_buff = NULL;
256 orig_node->tt_buff_len = 0; 341 orig_node->tt_buff_len = 0;
257 atomic_set(&orig_node->tt_size, 0);
258 reset_time = jiffies - 1 - msecs_to_jiffies(BATADV_RESET_PROTECTION_MS); 342 reset_time = jiffies - 1 - msecs_to_jiffies(BATADV_RESET_PROTECTION_MS);
259 orig_node->bcast_seqno_reset = reset_time; 343 orig_node->bcast_seqno_reset = reset_time;
260 orig_node->batman_seqno_reset = reset_time; 344 orig_node->batman_seqno_reset = reset_time;
261 345
262 atomic_set(&orig_node->bond_candidates, 0); 346 atomic_set(&orig_node->bond_candidates, 0);
263 347
348 /* create a vlan object for the "untagged" LAN */
349 vlan = batadv_orig_node_vlan_new(orig_node, BATADV_NO_FLAGS);
350 if (!vlan)
351 goto free_orig_node;
352 /* batadv_orig_node_vlan_new() increases the refcounter.
353 * Immediately release vlan since it is not needed anymore in this
354 * context
355 */
356 batadv_orig_node_vlan_free_ref(vlan);
357
264 size = bat_priv->num_ifaces * sizeof(unsigned long) * BATADV_NUM_WORDS; 358 size = bat_priv->num_ifaces * sizeof(unsigned long) * BATADV_NUM_WORDS;
265 359
266 orig_node->bcast_own = kzalloc(size, GFP_ATOMIC); 360 orig_node->bcast_own = kzalloc(size, GFP_ATOMIC);
267 if (!orig_node->bcast_own) 361 if (!orig_node->bcast_own)
268 goto free_orig_node; 362 goto free_vlan;
269 363
270 size = bat_priv->num_ifaces * sizeof(uint8_t); 364 size = bat_priv->num_ifaces * sizeof(uint8_t);
271 orig_node->bcast_own_sum = kzalloc(size, GFP_ATOMIC); 365 orig_node->bcast_own_sum = kzalloc(size, GFP_ATOMIC);
@@ -290,6 +384,8 @@ free_bcast_own_sum:
290 kfree(orig_node->bcast_own_sum); 384 kfree(orig_node->bcast_own_sum);
291free_bcast_own: 385free_bcast_own:
292 kfree(orig_node->bcast_own); 386 kfree(orig_node->bcast_own);
387free_vlan:
388 batadv_orig_node_vlan_free_ref(vlan);
293free_orig_node: 389free_orig_node:
294 kfree(orig_node); 390 kfree(orig_node);
295 return NULL; 391 return NULL;
diff --git a/net/batman-adv/originator.h b/net/batman-adv/originator.h
index 7887b84a9af4..cc6d686cfe6d 100644
--- a/net/batman-adv/originator.h
+++ b/net/batman-adv/originator.h
@@ -40,6 +40,13 @@ int batadv_orig_hash_add_if(struct batadv_hard_iface *hard_iface,
40 int max_if_num); 40 int max_if_num);
41int batadv_orig_hash_del_if(struct batadv_hard_iface *hard_iface, 41int batadv_orig_hash_del_if(struct batadv_hard_iface *hard_iface,
42 int max_if_num); 42 int max_if_num);
43struct batadv_orig_node_vlan *
44batadv_orig_node_vlan_new(struct batadv_orig_node *orig_node,
45 unsigned short vid);
46struct batadv_orig_node_vlan *
47batadv_orig_node_vlan_get(struct batadv_orig_node *orig_node,
48 unsigned short vid);
49void batadv_orig_node_vlan_free_ref(struct batadv_orig_node_vlan *orig_vlan);
43 50
44 51
45/* hashfunction to choose an entry in a hash table of given size 52/* hashfunction to choose an entry in a hash table of given size
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h
index 65e723ed030b..9fbcaacc345a 100644
--- a/net/batman-adv/packet.h
+++ b/net/batman-adv/packet.h
@@ -122,6 +122,14 @@ enum batadv_tt_client_flags {
122 BATADV_TT_CLIENT_TEMP = BIT(11), 122 BATADV_TT_CLIENT_TEMP = BIT(11),
123}; 123};
124 124
125/**
126 * batadv_vlan_flags - flags for the four MSB of any vlan ID field
127 * @BATADV_VLAN_HAS_TAG: whether the field contains a valid vlan tag or not
128 */
129enum batadv_vlan_flags {
130 BATADV_VLAN_HAS_TAG = BIT(15),
131};
132
125/* claim frame types for the bridge loop avoidance */ 133/* claim frame types for the bridge loop avoidance */
126enum batadv_bla_claimframe { 134enum batadv_bla_claimframe {
127 BATADV_CLAIM_TYPE_CLAIM = 0x00, 135 BATADV_CLAIM_TYPE_CLAIM = 0x00,
@@ -383,14 +391,26 @@ struct batadv_tvlv_gateway_data {
383 * struct batadv_tvlv_tt_data - tt data propagated through the tt tvlv container 391 * struct batadv_tvlv_tt_data - tt data propagated through the tt tvlv container
384 * @flags: translation table flags (see batadv_tt_data_flags) 392 * @flags: translation table flags (see batadv_tt_data_flags)
385 * @ttvn: translation table version number 393 * @ttvn: translation table version number
386 * @reserved: field reserved for future use 394 * @vlan_num: number of announced VLANs. In the TVLV this struct is followed by
387 * @crc: crc32 checksum of the local translation table 395 * one batadv_tvlv_tt_vlan_data object per announced vlan
388 */ 396 */
389struct batadv_tvlv_tt_data { 397struct batadv_tvlv_tt_data {
390 uint8_t flags; 398 uint8_t flags;
391 uint8_t ttvn; 399 uint8_t ttvn;
400 __be16 num_vlan;
401};
402
403/**
404 * struct batadv_tvlv_tt_vlan_data - vlan specific tt data propagated through
405 * the tt tvlv container
406 * @crc: crc32 checksum of the entries belonging to this vlan
407 * @vid: vlan identifier
408 * @reserved: unused, useful for alignment purposes
409 */
410struct batadv_tvlv_tt_vlan_data {
411 __be32 crc;
412 __be16 vid;
392 uint16_t reserved; 413 uint16_t reserved;
393 __be32 crc;
394}; 414};
395 415
396/** 416/**
@@ -399,21 +419,23 @@ struct batadv_tvlv_tt_data {
399 * batadv_tt_client_flags) 419 * batadv_tt_client_flags)
400 * @reserved: reserved field 420 * @reserved: reserved field
401 * @addr: mac address of non-mesh client that triggered this tt change 421 * @addr: mac address of non-mesh client that triggered this tt change
422 * @vid: VLAN identifier
402 */ 423 */
403struct batadv_tvlv_tt_change { 424struct batadv_tvlv_tt_change {
404 uint8_t flags; 425 uint8_t flags;
405 uint8_t reserved; 426 uint8_t reserved;
406 uint8_t addr[ETH_ALEN]; 427 uint8_t addr[ETH_ALEN];
428 __be16 vid;
407}; 429};
408 430
409/** 431/**
410 * struct batadv_tvlv_roam_adv - roaming advertisement 432 * struct batadv_tvlv_roam_adv - roaming advertisement
411 * @client: mac address of roaming client 433 * @client: mac address of roaming client
412 * @reserved: field reserved for future use 434 * @vid: VLAN identifier
413 */ 435 */
414struct batadv_tvlv_roam_adv { 436struct batadv_tvlv_roam_adv {
415 uint8_t client[ETH_ALEN]; 437 uint8_t client[ETH_ALEN];
416 uint16_t reserved; 438 __be16 vid;
417}; 439};
418 440
419#endif /* _NET_BATMAN_ADV_PACKET_H_ */ 441#endif /* _NET_BATMAN_ADV_PACKET_H_ */
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index 3281a504c20a..4bcf22129ffe 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -30,6 +30,8 @@
30#include "network-coding.h" 30#include "network-coding.h"
31#include "fragmentation.h" 31#include "fragmentation.h"
32 32
33#include <linux/if_vlan.h>
34
33static int batadv_route_unicast_packet(struct sk_buff *skb, 35static int batadv_route_unicast_packet(struct sk_buff *skb,
34 struct batadv_hard_iface *recv_if); 36 struct batadv_hard_iface *recv_if);
35 37
@@ -45,7 +47,7 @@ static void _batadv_update_route(struct batadv_priv *bat_priv,
45 if ((curr_router) && (!neigh_node)) { 47 if ((curr_router) && (!neigh_node)) {
46 batadv_dbg(BATADV_DBG_ROUTES, bat_priv, 48 batadv_dbg(BATADV_DBG_ROUTES, bat_priv,
47 "Deleting route towards: %pM\n", orig_node->orig); 49 "Deleting route towards: %pM\n", orig_node->orig);
48 batadv_tt_global_del_orig(bat_priv, orig_node, 50 batadv_tt_global_del_orig(bat_priv, orig_node, -1,
49 "Deleted route towards originator"); 51 "Deleted route towards originator");
50 52
51 /* route added */ 53 /* route added */
@@ -724,6 +726,7 @@ out:
724 * @bat_priv: the bat priv with all the soft interface information 726 * @bat_priv: the bat priv with all the soft interface information
725 * @unicast_packet: the unicast header to be updated 727 * @unicast_packet: the unicast header to be updated
726 * @dst_addr: the payload destination 728 * @dst_addr: the payload destination
729 * @vid: VLAN identifier
727 * 730 *
728 * Search the translation table for dst_addr and update the unicast header with 731 * Search the translation table for dst_addr and update the unicast header with
729 * the new corresponding information (originator address where the destination 732 * the new corresponding information (originator address where the destination
@@ -734,21 +737,22 @@ out:
734static bool 737static bool
735batadv_reroute_unicast_packet(struct batadv_priv *bat_priv, 738batadv_reroute_unicast_packet(struct batadv_priv *bat_priv,
736 struct batadv_unicast_packet *unicast_packet, 739 struct batadv_unicast_packet *unicast_packet,
737 uint8_t *dst_addr) 740 uint8_t *dst_addr, unsigned short vid)
738{ 741{
739 struct batadv_orig_node *orig_node = NULL; 742 struct batadv_orig_node *orig_node = NULL;
740 struct batadv_hard_iface *primary_if = NULL; 743 struct batadv_hard_iface *primary_if = NULL;
741 bool ret = false; 744 bool ret = false;
742 uint8_t *orig_addr, orig_ttvn; 745 uint8_t *orig_addr, orig_ttvn;
743 746
744 if (batadv_is_my_client(bat_priv, dst_addr)) { 747 if (batadv_is_my_client(bat_priv, dst_addr, vid)) {
745 primary_if = batadv_primary_if_get_selected(bat_priv); 748 primary_if = batadv_primary_if_get_selected(bat_priv);
746 if (!primary_if) 749 if (!primary_if)
747 goto out; 750 goto out;
748 orig_addr = primary_if->net_dev->dev_addr; 751 orig_addr = primary_if->net_dev->dev_addr;
749 orig_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn); 752 orig_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn);
750 } else { 753 } else {
751 orig_node = batadv_transtable_search(bat_priv, NULL, dst_addr); 754 orig_node = batadv_transtable_search(bat_priv, NULL, dst_addr,
755 vid);
752 if (!orig_node) 756 if (!orig_node)
753 goto out; 757 goto out;
754 758
@@ -775,11 +779,12 @@ out:
775 779
776static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv, 780static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
777 struct sk_buff *skb, int hdr_len) { 781 struct sk_buff *skb, int hdr_len) {
778 uint8_t curr_ttvn, old_ttvn; 782 struct batadv_unicast_packet *unicast_packet;
783 struct batadv_hard_iface *primary_if;
779 struct batadv_orig_node *orig_node; 784 struct batadv_orig_node *orig_node;
785 uint8_t curr_ttvn, old_ttvn;
780 struct ethhdr *ethhdr; 786 struct ethhdr *ethhdr;
781 struct batadv_hard_iface *primary_if; 787 unsigned short vid;
782 struct batadv_unicast_packet *unicast_packet;
783 int is_old_ttvn; 788 int is_old_ttvn;
784 789
785 /* check if there is enough data before accessing it */ 790 /* check if there is enough data before accessing it */
@@ -791,6 +796,7 @@ static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
791 return 0; 796 return 0;
792 797
793 unicast_packet = (struct batadv_unicast_packet *)skb->data; 798 unicast_packet = (struct batadv_unicast_packet *)skb->data;
799 vid = batadv_get_vid(skb, hdr_len);
794 ethhdr = (struct ethhdr *)(skb->data + hdr_len); 800 ethhdr = (struct ethhdr *)(skb->data + hdr_len);
795 801
796 /* check if the destination client was served by this node and it is now 802 /* check if the destination client was served by this node and it is now
@@ -798,9 +804,9 @@ static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
798 * message and that it knows the new destination in the mesh to re-route 804 * message and that it knows the new destination in the mesh to re-route
799 * the packet to 805 * the packet to
800 */ 806 */
801 if (batadv_tt_local_client_is_roaming(bat_priv, ethhdr->h_dest)) { 807 if (batadv_tt_local_client_is_roaming(bat_priv, ethhdr->h_dest, vid)) {
802 if (batadv_reroute_unicast_packet(bat_priv, unicast_packet, 808 if (batadv_reroute_unicast_packet(bat_priv, unicast_packet,
803 ethhdr->h_dest)) 809 ethhdr->h_dest, vid))
804 net_ratelimited_function(batadv_dbg, BATADV_DBG_TT, 810 net_ratelimited_function(batadv_dbg, BATADV_DBG_TT,
805 bat_priv, 811 bat_priv,
806 "Rerouting unicast packet to %pM (dst=%pM): Local Roaming\n", 812 "Rerouting unicast packet to %pM (dst=%pM): Local Roaming\n",
@@ -846,7 +852,7 @@ static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
846 * target host 852 * target host
847 */ 853 */
848 if (batadv_reroute_unicast_packet(bat_priv, unicast_packet, 854 if (batadv_reroute_unicast_packet(bat_priv, unicast_packet,
849 ethhdr->h_dest)) { 855 ethhdr->h_dest, vid)) {
850 net_ratelimited_function(batadv_dbg, BATADV_DBG_TT, bat_priv, 856 net_ratelimited_function(batadv_dbg, BATADV_DBG_TT, bat_priv,
851 "Rerouting unicast packet to %pM (dst=%pM): TTVN mismatch old_ttvn=%u new_ttvn=%u\n", 857 "Rerouting unicast packet to %pM (dst=%pM): TTVN mismatch old_ttvn=%u new_ttvn=%u\n",
852 unicast_packet->dest, ethhdr->h_dest, 858 unicast_packet->dest, ethhdr->h_dest,
@@ -858,7 +864,7 @@ static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
858 * currently served by this node or there is no destination at all and 864 * currently served by this node or there is no destination at all and
859 * it is possible to drop the packet 865 * it is possible to drop the packet
860 */ 866 */
861 if (!batadv_is_my_client(bat_priv, ethhdr->h_dest)) 867 if (!batadv_is_my_client(bat_priv, ethhdr->h_dest, vid))
862 return 0; 868 return 0;
863 869
864 /* update the header in order to let the packet be delivered to this 870 /* update the header in order to let the packet be delivered to this
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c
index 82588e425641..c83be5ebaa28 100644
--- a/net/batman-adv/send.c
+++ b/net/batman-adv/send.c
@@ -234,44 +234,45 @@ out:
234} 234}
235 235
236/** 236/**
237 * batadv_send_generic_unicast_skb - send an skb as unicast 237 * batadv_send_skb_unicast - encapsulate and send an skb via unicast
238 * @bat_priv: the bat priv with all the soft interface information 238 * @bat_priv: the bat priv with all the soft interface information
239 * @skb: payload to send 239 * @skb: payload to send
240 * @packet_type: the batman unicast packet type to use 240 * @packet_type: the batman unicast packet type to use
241 * @packet_subtype: the unicast 4addr packet subtype (only relevant for unicast 241 * @packet_subtype: the unicast 4addr packet subtype (only relevant for unicast
242 * 4addr packets) 242 * 4addr packets)
243 * @orig_node: the originator to send the packet to
244 * @vid: the vid to be used to search the translation table
243 * 245 *
244 * Returns 1 in case of error or 0 otherwise. 246 * Wrap the given skb into a batman-adv unicast or unicast-4addr header
247 * depending on whether BATADV_UNICAST or BATADV_UNICAST_4ADDR was supplied
248 * as packet_type. Then send this frame to the given orig_node and release a
249 * reference to this orig_node.
250 *
251 * Returns NET_XMIT_DROP in case of error or NET_XMIT_SUCCESS otherwise.
245 */ 252 */
246int batadv_send_skb_generic_unicast(struct batadv_priv *bat_priv, 253static int batadv_send_skb_unicast(struct batadv_priv *bat_priv,
247 struct sk_buff *skb, int packet_type, 254 struct sk_buff *skb, int packet_type,
248 int packet_subtype) 255 int packet_subtype,
256 struct batadv_orig_node *orig_node,
257 unsigned short vid)
249{ 258{
250 struct ethhdr *ethhdr = (struct ethhdr *)skb->data; 259 struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
251 struct batadv_unicast_packet *unicast_packet; 260 struct batadv_unicast_packet *unicast_packet;
252 struct batadv_orig_node *orig_node; 261 int ret = NET_XMIT_DROP;
253 int ret = NET_RX_DROP;
254
255 /* get routing information */
256 if (is_multicast_ether_addr(ethhdr->h_dest))
257 orig_node = batadv_gw_get_selected_orig(bat_priv);
258 else
259 /* check for tt host - increases orig_node refcount.
260 * returns NULL in case of AP isolation
261 */
262 orig_node = batadv_transtable_search(bat_priv, ethhdr->h_source,
263 ethhdr->h_dest);
264 262
265 if (!orig_node) 263 if (!orig_node)
266 goto out; 264 goto out;
267 265
268 switch (packet_type) { 266 switch (packet_type) {
269 case BATADV_UNICAST: 267 case BATADV_UNICAST:
270 batadv_send_skb_prepare_unicast(skb, orig_node); 268 if (!batadv_send_skb_prepare_unicast(skb, orig_node))
269 goto out;
271 break; 270 break;
272 case BATADV_UNICAST_4ADDR: 271 case BATADV_UNICAST_4ADDR:
273 batadv_send_skb_prepare_unicast_4addr(bat_priv, skb, orig_node, 272 if (!batadv_send_skb_prepare_unicast_4addr(bat_priv, skb,
274 packet_subtype); 273 orig_node,
274 packet_subtype))
275 goto out;
275 break; 276 break;
276 default: 277 default:
277 /* this function supports UNICAST and UNICAST_4ADDR only. It 278 /* this function supports UNICAST and UNICAST_4ADDR only. It
@@ -287,20 +288,71 @@ int batadv_send_skb_generic_unicast(struct batadv_priv *bat_priv,
287 * try to reroute it because the ttvn contained in the header is less 288 * try to reroute it because the ttvn contained in the header is less
288 * than the current one 289 * than the current one
289 */ 290 */
290 if (batadv_tt_global_client_is_roaming(bat_priv, ethhdr->h_dest)) 291 if (batadv_tt_global_client_is_roaming(bat_priv, ethhdr->h_dest, vid))
291 unicast_packet->ttvn = unicast_packet->ttvn - 1; 292 unicast_packet->ttvn = unicast_packet->ttvn - 1;
292 293
293 if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP) 294 if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP)
294 ret = 0; 295 ret = NET_XMIT_SUCCESS;
295 296
296out: 297out:
297 if (orig_node) 298 if (orig_node)
298 batadv_orig_node_free_ref(orig_node); 299 batadv_orig_node_free_ref(orig_node);
299 if (ret == NET_RX_DROP) 300 if (ret == NET_XMIT_DROP)
300 kfree_skb(skb); 301 kfree_skb(skb);
301 return ret; 302 return ret;
302} 303}
303 304
305/**
306 * batadv_send_skb_via_tt_generic - send an skb via TT lookup
307 * @bat_priv: the bat priv with all the soft interface information
308 * @skb: payload to send
309 * @packet_type: the batman unicast packet type to use
310 * @packet_subtype: the unicast 4addr packet subtype (only relevant for unicast
311 * 4addr packets)
312 * @vid: the vid to be used to search the translation table
313 *
314 * Look up the recipient node for the destination address in the ethernet
315 * header via the translation table. Wrap the given skb into a batman-adv
316 * unicast or unicast-4addr header depending on whether BATADV_UNICAST or
317 * BATADV_UNICAST_4ADDR was supplied as packet_type. Then send this frame
318 * to the according destination node.
319 *
320 * Returns NET_XMIT_DROP in case of error or NET_XMIT_SUCCESS otherwise.
321 */
322int batadv_send_skb_via_tt_generic(struct batadv_priv *bat_priv,
323 struct sk_buff *skb, int packet_type,
324 int packet_subtype, unsigned short vid)
325{
326 struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
327 struct batadv_orig_node *orig_node;
328
329 orig_node = batadv_transtable_search(bat_priv, ethhdr->h_source,
330 ethhdr->h_dest, vid);
331 return batadv_send_skb_unicast(bat_priv, skb, packet_type,
332 packet_subtype, orig_node, vid);
333}
334
335/**
336 * batadv_send_skb_via_gw - send an skb via gateway lookup
337 * @bat_priv: the bat priv with all the soft interface information
338 * @skb: payload to send
339 * @vid: the vid to be used to search the translation table
340 *
341 * Look up the currently selected gateway. Wrap the given skb into a batman-adv
342 * unicast header and send this frame to this gateway node.
343 *
344 * Returns NET_XMIT_DROP in case of error or NET_XMIT_SUCCESS otherwise.
345 */
346int batadv_send_skb_via_gw(struct batadv_priv *bat_priv, struct sk_buff *skb,
347 unsigned short vid)
348{
349 struct batadv_orig_node *orig_node;
350
351 orig_node = batadv_gw_get_selected_orig(bat_priv);
352 return batadv_send_skb_unicast(bat_priv, skb, BATADV_UNICAST, 0,
353 orig_node, vid);
354}
355
304void batadv_schedule_bat_ogm(struct batadv_hard_iface *hard_iface) 356void batadv_schedule_bat_ogm(struct batadv_hard_iface *hard_iface)
305{ 357{
306 struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface); 358 struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
diff --git a/net/batman-adv/send.h b/net/batman-adv/send.h
index ad63184a4dd9..aa2e2537a739 100644
--- a/net/batman-adv/send.h
+++ b/net/batman-adv/send.h
@@ -38,41 +38,54 @@ bool batadv_send_skb_prepare_unicast_4addr(struct batadv_priv *bat_priv,
38 struct sk_buff *skb, 38 struct sk_buff *skb,
39 struct batadv_orig_node *orig_node, 39 struct batadv_orig_node *orig_node,
40 int packet_subtype); 40 int packet_subtype);
41int batadv_send_skb_generic_unicast(struct batadv_priv *bat_priv, 41int batadv_send_skb_via_tt_generic(struct batadv_priv *bat_priv,
42 struct sk_buff *skb, int packet_type, 42 struct sk_buff *skb, int packet_type,
43 int packet_subtype); 43 int packet_subtype, unsigned short vid);
44 44int batadv_send_skb_via_gw(struct batadv_priv *bat_priv, struct sk_buff *skb,
45 unsigned short vid);
45 46
46/** 47/**
47 * batadv_send_unicast_skb - send the skb encapsulated in a unicast packet 48 * batadv_send_skb_via_tt - send an skb via TT lookup
48 * @bat_priv: the bat priv with all the soft interface information 49 * @bat_priv: the bat priv with all the soft interface information
49 * @skb: the payload to send 50 * @skb: the payload to send
51 * @vid: the vid to be used to search the translation table
52 *
53 * Look up the recipient node for the destination address in the ethernet
54 * header via the translation table. Wrap the given skb into a batman-adv
55 * unicast header. Then send this frame to the according destination node.
50 * 56 *
51 * Returns 1 in case of error or 0 otherwise. 57 * Returns NET_XMIT_DROP in case of error or NET_XMIT_SUCCESS otherwise.
52 */ 58 */
53static inline int batadv_send_skb_unicast(struct batadv_priv *bat_priv, 59static inline int batadv_send_skb_via_tt(struct batadv_priv *bat_priv,
54 struct sk_buff *skb) 60 struct sk_buff *skb,
61 unsigned short vid)
55{ 62{
56 return batadv_send_skb_generic_unicast(bat_priv, skb, BATADV_UNICAST, 63 return batadv_send_skb_via_tt_generic(bat_priv, skb, BATADV_UNICAST, 0,
57 0); 64 vid);
58} 65}
59 66
60/** 67/**
61 * batadv_send_4addr_unicast_skb - send the skb encapsulated in a unicast 4addr 68 * batadv_send_skb_via_tt_4addr - send an skb via TT lookup
62 * packet
63 * @bat_priv: the bat priv with all the soft interface information 69 * @bat_priv: the bat priv with all the soft interface information
64 * @skb: the payload to send 70 * @skb: the payload to send
65 * @packet_subtype: the unicast 4addr packet subtype to use 71 * @packet_subtype: the unicast 4addr packet subtype to use
72 * @vid: the vid to be used to search the translation table
73 *
74 * Look up the recipient node for the destination address in the ethernet
75 * header via the translation table. Wrap the given skb into a batman-adv
76 * unicast-4addr header. Then send this frame to the according destination
77 * node.
66 * 78 *
67 * Returns 1 in case of error or 0 otherwise. 79 * Returns NET_XMIT_DROP in case of error or NET_XMIT_SUCCESS otherwise.
68 */ 80 */
69static inline int batadv_send_skb_unicast_4addr(struct batadv_priv *bat_priv, 81static inline int batadv_send_skb_via_tt_4addr(struct batadv_priv *bat_priv,
70 struct sk_buff *skb, 82 struct sk_buff *skb,
71 int packet_subtype) 83 int packet_subtype,
84 unsigned short vid)
72{ 85{
73 return batadv_send_skb_generic_unicast(bat_priv, skb, 86 return batadv_send_skb_via_tt_generic(bat_priv, skb,
74 BATADV_UNICAST_4ADDR, 87 BATADV_UNICAST_4ADDR,
75 packet_subtype); 88 packet_subtype, vid);
76} 89}
77 90
78#endif /* _NET_BATMAN_ADV_SEND_H_ */ 91#endif /* _NET_BATMAN_ADV_SEND_H_ */
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index e8a2bd699d40..e70f530d8568 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -118,9 +118,10 @@ static int batadv_interface_set_mac_addr(struct net_device *dev, void *p)
118 118
119 /* only modify transtable if it has been initialized before */ 119 /* only modify transtable if it has been initialized before */
120 if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_ACTIVE) { 120 if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_ACTIVE) {
121 batadv_tt_local_remove(bat_priv, old_addr, 121 batadv_tt_local_remove(bat_priv, old_addr, BATADV_NO_FLAGS,
122 "mac address changed", false); 122 "mac address changed", false);
123 batadv_tt_local_add(dev, addr->sa_data, BATADV_NULL_IFINDEX); 123 batadv_tt_local_add(dev, addr->sa_data, BATADV_NO_FLAGS,
124 BATADV_NULL_IFINDEX);
124 } 125 }
125 126
126 return 0; 127 return 0;
@@ -152,33 +153,33 @@ static void batadv_interface_set_rx_mode(struct net_device *dev)
152static int batadv_interface_tx(struct sk_buff *skb, 153static int batadv_interface_tx(struct sk_buff *skb,
153 struct net_device *soft_iface) 154 struct net_device *soft_iface)
154{ 155{
155 struct ethhdr *ethhdr = (struct ethhdr *)skb->data; 156 struct ethhdr *ethhdr;
156 struct batadv_priv *bat_priv = netdev_priv(soft_iface); 157 struct batadv_priv *bat_priv = netdev_priv(soft_iface);
157 struct batadv_hard_iface *primary_if = NULL; 158 struct batadv_hard_iface *primary_if = NULL;
158 struct batadv_bcast_packet *bcast_packet; 159 struct batadv_bcast_packet *bcast_packet;
159 struct vlan_ethhdr *vhdr;
160 __be16 ethertype = htons(ETH_P_BATMAN); 160 __be16 ethertype = htons(ETH_P_BATMAN);
161 static const uint8_t stp_addr[ETH_ALEN] = {0x01, 0x80, 0xC2, 0x00, 161 static const uint8_t stp_addr[ETH_ALEN] = {0x01, 0x80, 0xC2, 0x00,
162 0x00, 0x00}; 162 0x00, 0x00};
163 static const uint8_t ectp_addr[ETH_ALEN] = {0xCF, 0x00, 0x00, 0x00, 163 static const uint8_t ectp_addr[ETH_ALEN] = {0xCF, 0x00, 0x00, 0x00,
164 0x00, 0x00}; 164 0x00, 0x00};
165 struct vlan_ethhdr *vhdr;
165 unsigned int header_len = 0; 166 unsigned int header_len = 0;
166 int data_len = skb->len, ret; 167 int data_len = skb->len, ret;
167 unsigned short vid __maybe_unused = BATADV_NO_FLAGS; 168 unsigned long brd_delay = 1;
168 bool do_bcast = false; 169 bool do_bcast = false;
170 unsigned short vid;
169 uint32_t seqno; 171 uint32_t seqno;
170 unsigned long brd_delay = 1;
171 172
172 if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) 173 if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
173 goto dropped; 174 goto dropped;
174 175
175 soft_iface->trans_start = jiffies; 176 soft_iface->trans_start = jiffies;
177 vid = batadv_get_vid(skb, 0);
178 ethhdr = (struct ethhdr *)skb->data;
176 179
177 switch (ntohs(ethhdr->h_proto)) { 180 switch (ntohs(ethhdr->h_proto)) {
178 case ETH_P_8021Q: 181 case ETH_P_8021Q:
179 vhdr = (struct vlan_ethhdr *)skb->data; 182 vhdr = (struct vlan_ethhdr *)skb->data;
180 vid = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK;
181 vid |= BATADV_VLAN_HAS_TAG;
182 183
183 if (vhdr->h_vlan_encapsulated_proto != ethertype) 184 if (vhdr->h_vlan_encapsulated_proto != ethertype)
184 break; 185 break;
@@ -196,7 +197,8 @@ static int batadv_interface_tx(struct sk_buff *skb,
196 197
197 /* Register the client MAC in the transtable */ 198 /* Register the client MAC in the transtable */
198 if (!is_multicast_ether_addr(ethhdr->h_source)) 199 if (!is_multicast_ether_addr(ethhdr->h_source))
199 batadv_tt_local_add(soft_iface, ethhdr->h_source, skb->skb_iif); 200 batadv_tt_local_add(soft_iface, ethhdr->h_source, vid,
201 skb->skb_iif);
200 202
201 /* don't accept stp packets. STP does not help in meshes. 203 /* don't accept stp packets. STP does not help in meshes.
202 * better use the bridge loop avoidance ... 204 * better use the bridge loop avoidance ...
@@ -296,8 +298,12 @@ static int batadv_interface_tx(struct sk_buff *skb,
296 298
297 batadv_dat_snoop_outgoing_arp_reply(bat_priv, skb); 299 batadv_dat_snoop_outgoing_arp_reply(bat_priv, skb);
298 300
299 ret = batadv_send_skb_unicast(bat_priv, skb); 301 if (is_multicast_ether_addr(ethhdr->h_dest))
300 if (ret != 0) 302 ret = batadv_send_skb_via_gw(bat_priv, skb, vid);
303 else
304 ret = batadv_send_skb_via_tt(bat_priv, skb, vid);
305
306 if (ret == NET_XMIT_DROP)
301 goto dropped_freed; 307 goto dropped_freed;
302 } 308 }
303 309
@@ -319,12 +325,12 @@ void batadv_interface_rx(struct net_device *soft_iface,
319 struct sk_buff *skb, struct batadv_hard_iface *recv_if, 325 struct sk_buff *skb, struct batadv_hard_iface *recv_if,
320 int hdr_size, struct batadv_orig_node *orig_node) 326 int hdr_size, struct batadv_orig_node *orig_node)
321{ 327{
322 struct batadv_priv *bat_priv = netdev_priv(soft_iface);
323 struct ethhdr *ethhdr;
324 struct vlan_ethhdr *vhdr;
325 struct batadv_header *batadv_header = (struct batadv_header *)skb->data; 328 struct batadv_header *batadv_header = (struct batadv_header *)skb->data;
326 unsigned short vid __maybe_unused = BATADV_NO_FLAGS; 329 struct batadv_priv *bat_priv = netdev_priv(soft_iface);
327 __be16 ethertype = htons(ETH_P_BATMAN); 330 __be16 ethertype = htons(ETH_P_BATMAN);
331 struct vlan_ethhdr *vhdr;
332 struct ethhdr *ethhdr;
333 unsigned short vid;
328 bool is_bcast; 334 bool is_bcast;
329 335
330 is_bcast = (batadv_header->packet_type == BATADV_BCAST); 336 is_bcast = (batadv_header->packet_type == BATADV_BCAST);
@@ -336,13 +342,12 @@ void batadv_interface_rx(struct net_device *soft_iface,
336 skb_pull_rcsum(skb, hdr_size); 342 skb_pull_rcsum(skb, hdr_size);
337 skb_reset_mac_header(skb); 343 skb_reset_mac_header(skb);
338 344
345 vid = batadv_get_vid(skb, hdr_size);
339 ethhdr = eth_hdr(skb); 346 ethhdr = eth_hdr(skb);
340 347
341 switch (ntohs(ethhdr->h_proto)) { 348 switch (ntohs(ethhdr->h_proto)) {
342 case ETH_P_8021Q: 349 case ETH_P_8021Q:
343 vhdr = (struct vlan_ethhdr *)skb->data; 350 vhdr = (struct vlan_ethhdr *)skb->data;
344 vid = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK;
345 vid |= BATADV_VLAN_HAS_TAG;
346 351
347 if (vhdr->h_vlan_encapsulated_proto != ethertype) 352 if (vhdr->h_vlan_encapsulated_proto != ethertype)
348 break; 353 break;
@@ -378,9 +383,10 @@ void batadv_interface_rx(struct net_device *soft_iface,
378 383
379 if (orig_node) 384 if (orig_node)
380 batadv_tt_add_temporary_global_entry(bat_priv, orig_node, 385 batadv_tt_add_temporary_global_entry(bat_priv, orig_node,
381 ethhdr->h_source); 386 ethhdr->h_source, vid);
382 387
383 if (batadv_is_ap_isolated(bat_priv, ethhdr->h_source, ethhdr->h_dest)) 388 if (batadv_is_ap_isolated(bat_priv, ethhdr->h_source, ethhdr->h_dest,
389 vid))
384 goto dropped; 390 goto dropped;
385 391
386 netif_rx(skb); 392 netif_rx(skb);
@@ -392,6 +398,177 @@ out:
392 return; 398 return;
393} 399}
394 400
401/**
402 * batadv_softif_vlan_free_ref - decrease the vlan object refcounter and
403 * possibly free it
404 * @softif_vlan: the vlan object to release
405 */
406void batadv_softif_vlan_free_ref(struct batadv_softif_vlan *softif_vlan)
407{
408 if (atomic_dec_and_test(&softif_vlan->refcount))
409 kfree_rcu(softif_vlan, rcu);
410}
411
412/**
413 * batadv_softif_vlan_get - get the vlan object for a specific vid
414 * @bat_priv: the bat priv with all the soft interface information
415 * @vid: the identifier of the vlan object to retrieve
416 *
417 * Returns the private data of the vlan matching the vid passed as argument or
418 * NULL otherwise. The refcounter of the returned object is incremented by 1.
419 */
420struct batadv_softif_vlan *batadv_softif_vlan_get(struct batadv_priv *bat_priv,
421 unsigned short vid)
422{
423 struct batadv_softif_vlan *vlan_tmp, *vlan = NULL;
424
425 rcu_read_lock();
426 hlist_for_each_entry_rcu(vlan_tmp, &bat_priv->softif_vlan_list, list) {
427 if (vlan_tmp->vid != vid)
428 continue;
429
430 if (!atomic_inc_not_zero(&vlan_tmp->refcount))
431 continue;
432
433 vlan = vlan_tmp;
434 break;
435 }
436 rcu_read_unlock();
437
438 return vlan;
439}
440
441/**
442 * batadv_create_vlan - allocate the needed resources for a new vlan
443 * @bat_priv: the bat priv with all the soft interface information
444 * @vid: the VLAN identifier
445 *
446 * Returns 0 on success, a negative error otherwise.
447 */
448int batadv_softif_create_vlan(struct batadv_priv *bat_priv, unsigned short vid)
449{
450 struct batadv_softif_vlan *vlan;
451 int err;
452
453 vlan = batadv_softif_vlan_get(bat_priv, vid);
454 if (vlan) {
455 batadv_softif_vlan_free_ref(vlan);
456 return -EEXIST;
457 }
458
459 vlan = kzalloc(sizeof(*vlan), GFP_ATOMIC);
460 if (!vlan)
461 return -ENOMEM;
462
463 vlan->vid = vid;
464 atomic_set(&vlan->refcount, 1);
465
466 atomic_set(&vlan->ap_isolation, 0);
467
468 err = batadv_sysfs_add_vlan(bat_priv->soft_iface, vlan);
469 if (err) {
470 kfree(vlan);
471 return err;
472 }
473
474 /* add a new TT local entry. This one will be marked with the NOPURGE
475 * flag
476 */
477 batadv_tt_local_add(bat_priv->soft_iface,
478 bat_priv->soft_iface->dev_addr, vid,
479 BATADV_NULL_IFINDEX);
480
481 spin_lock_bh(&bat_priv->softif_vlan_list_lock);
482 hlist_add_head_rcu(&vlan->list, &bat_priv->softif_vlan_list);
483 spin_unlock_bh(&bat_priv->softif_vlan_list_lock);
484
485 return 0;
486}
487
488/**
489 * batadv_softif_destroy_vlan - remove and destroy a softif_vlan object
490 * @bat_priv: the bat priv with all the soft interface information
491 * @vlan: the object to remove
492 */
493static void batadv_softif_destroy_vlan(struct batadv_priv *bat_priv,
494 struct batadv_softif_vlan *vlan)
495{
496 spin_lock_bh(&bat_priv->softif_vlan_list_lock);
497 hlist_del_rcu(&vlan->list);
498 spin_unlock_bh(&bat_priv->softif_vlan_list_lock);
499
500 batadv_sysfs_del_vlan(bat_priv, vlan);
501
502 /* explicitly remove the associated TT local entry because it is marked
503 * with the NOPURGE flag
504 */
505 batadv_tt_local_remove(bat_priv, bat_priv->soft_iface->dev_addr,
506 vlan->vid, "vlan interface destroyed", false);
507
508 batadv_softif_vlan_free_ref(vlan);
509}
510
511/**
512 * batadv_interface_add_vid - ndo_add_vid API implementation
513 * @dev: the netdev of the mesh interface
514 * @vid: identifier of the new vlan
515 *
516 * Set up all the internal structures for handling the new vlan on top of the
517 * mesh interface
518 *
519 * Returns 0 on success or a negative error code in case of failure.
520 */
521static int batadv_interface_add_vid(struct net_device *dev, __be16 proto,
522 unsigned short vid)
523{
524 struct batadv_priv *bat_priv = netdev_priv(dev);
525
526 /* only 802.1Q vlans are supported.
527 * batman-adv does not know how to handle other types
528 */
529 if (proto != htons(ETH_P_8021Q))
530 return -EINVAL;
531
532 vid |= BATADV_VLAN_HAS_TAG;
533
534 return batadv_softif_create_vlan(bat_priv, vid);
535}
536
537/**
538 * batadv_interface_kill_vid - ndo_kill_vid API implementation
539 * @dev: the netdev of the mesh interface
540 * @vid: identifier of the deleted vlan
541 *
542 * Destroy all the internal structures used to handle the vlan identified by vid
543 * on top of the mesh interface
544 *
545 * Returns 0 on success, -EINVAL if the specified prototype is not ETH_P_8021Q
546 * or -ENOENT if the specified vlan id wasn't registered.
547 */
548static int batadv_interface_kill_vid(struct net_device *dev, __be16 proto,
549 unsigned short vid)
550{
551 struct batadv_priv *bat_priv = netdev_priv(dev);
552 struct batadv_softif_vlan *vlan;
553
554 /* only 802.1Q vlans are supported. batman-adv does not know how to
555 * handle other types
556 */
557 if (proto != htons(ETH_P_8021Q))
558 return -EINVAL;
559
560 vlan = batadv_softif_vlan_get(bat_priv, vid | BATADV_VLAN_HAS_TAG);
561 if (!vlan)
562 return -ENOENT;
563
564 batadv_softif_destroy_vlan(bat_priv, vlan);
565
566 /* finally free the vlan object */
567 batadv_softif_vlan_free_ref(vlan);
568
569 return 0;
570}
571
395/* batman-adv network devices have devices nesting below it and are a special 572/* batman-adv network devices have devices nesting below it and are a special
396 * "super class" of normal network devices; split their locks off into a 573 * "super class" of normal network devices; split their locks off into a
397 * separate class since they always nest. 574 * separate class since they always nest.
@@ -431,6 +608,7 @@ static void batadv_set_lockdep_class(struct net_device *dev)
431 */ 608 */
432static void batadv_softif_destroy_finish(struct work_struct *work) 609static void batadv_softif_destroy_finish(struct work_struct *work)
433{ 610{
611 struct batadv_softif_vlan *vlan;
434 struct batadv_priv *bat_priv; 612 struct batadv_priv *bat_priv;
435 struct net_device *soft_iface; 613 struct net_device *soft_iface;
436 614
@@ -438,6 +616,13 @@ static void batadv_softif_destroy_finish(struct work_struct *work)
438 cleanup_work); 616 cleanup_work);
439 soft_iface = bat_priv->soft_iface; 617 soft_iface = bat_priv->soft_iface;
440 618
619 /* destroy the "untagged" VLAN */
620 vlan = batadv_softif_vlan_get(bat_priv, BATADV_NO_FLAGS);
621 if (vlan) {
622 batadv_softif_destroy_vlan(bat_priv, vlan);
623 batadv_softif_vlan_free_ref(vlan);
624 }
625
441 batadv_sysfs_del_meshif(soft_iface); 626 batadv_sysfs_del_meshif(soft_iface);
442 627
443 rtnl_lock(); 628 rtnl_lock();
@@ -479,7 +664,6 @@ static int batadv_softif_init_late(struct net_device *dev)
479#ifdef CONFIG_BATMAN_ADV_DAT 664#ifdef CONFIG_BATMAN_ADV_DAT
480 atomic_set(&bat_priv->distributed_arp_table, 1); 665 atomic_set(&bat_priv->distributed_arp_table, 1);
481#endif 666#endif
482 atomic_set(&bat_priv->ap_isolation, 0);
483 atomic_set(&bat_priv->gw_mode, BATADV_GW_MODE_OFF); 667 atomic_set(&bat_priv->gw_mode, BATADV_GW_MODE_OFF);
484 atomic_set(&bat_priv->gw_sel_class, 20); 668 atomic_set(&bat_priv->gw_sel_class, 20);
485 atomic_set(&bat_priv->gw.bandwidth_down, 100); 669 atomic_set(&bat_priv->gw.bandwidth_down, 100);
@@ -593,6 +777,8 @@ static const struct net_device_ops batadv_netdev_ops = {
593 .ndo_open = batadv_interface_open, 777 .ndo_open = batadv_interface_open,
594 .ndo_stop = batadv_interface_release, 778 .ndo_stop = batadv_interface_release,
595 .ndo_get_stats = batadv_interface_stats, 779 .ndo_get_stats = batadv_interface_stats,
780 .ndo_vlan_rx_add_vid = batadv_interface_add_vid,
781 .ndo_vlan_rx_kill_vid = batadv_interface_kill_vid,
596 .ndo_set_mac_address = batadv_interface_set_mac_addr, 782 .ndo_set_mac_address = batadv_interface_set_mac_addr,
597 .ndo_change_mtu = batadv_interface_change_mtu, 783 .ndo_change_mtu = batadv_interface_change_mtu,
598 .ndo_set_rx_mode = batadv_interface_set_rx_mode, 784 .ndo_set_rx_mode = batadv_interface_set_rx_mode,
@@ -632,6 +818,7 @@ static void batadv_softif_init_early(struct net_device *dev)
632 818
633 dev->netdev_ops = &batadv_netdev_ops; 819 dev->netdev_ops = &batadv_netdev_ops;
634 dev->destructor = batadv_softif_free; 820 dev->destructor = batadv_softif_free;
821 dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
635 dev->tx_queue_len = 0; 822 dev->tx_queue_len = 0;
636 823
637 /* can't call min_mtu, because the needed variables 824 /* can't call min_mtu, because the needed variables
diff --git a/net/batman-adv/soft-interface.h b/net/batman-adv/soft-interface.h
index 2f2472c2ea0d..06fc91ff5a02 100644
--- a/net/batman-adv/soft-interface.h
+++ b/net/batman-adv/soft-interface.h
@@ -28,5 +28,9 @@ struct net_device *batadv_softif_create(const char *name);
28void batadv_softif_destroy_sysfs(struct net_device *soft_iface); 28void batadv_softif_destroy_sysfs(struct net_device *soft_iface);
29int batadv_softif_is_valid(const struct net_device *net_dev); 29int batadv_softif_is_valid(const struct net_device *net_dev);
30extern struct rtnl_link_ops batadv_link_ops; 30extern struct rtnl_link_ops batadv_link_ops;
31int batadv_softif_create_vlan(struct batadv_priv *bat_priv, unsigned short vid);
32void batadv_softif_vlan_free_ref(struct batadv_softif_vlan *softif_vlan);
33struct batadv_softif_vlan *batadv_softif_vlan_get(struct batadv_priv *bat_priv,
34 unsigned short vid);
31 35
32#endif /* _NET_BATMAN_ADV_SOFT_INTERFACE_H_ */ 36#endif /* _NET_BATMAN_ADV_SOFT_INTERFACE_H_ */
diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c
index 869eb46329cb..6335433310af 100644
--- a/net/batman-adv/sysfs.c
+++ b/net/batman-adv/sysfs.c
@@ -24,6 +24,7 @@
24#include "network-coding.h" 24#include "network-coding.h"
25#include "originator.h" 25#include "originator.h"
26#include "hard-interface.h" 26#include "hard-interface.h"
27#include "soft-interface.h"
27#include "gateway_common.h" 28#include "gateway_common.h"
28#include "gateway_client.h" 29#include "gateway_client.h"
29 30
@@ -39,6 +40,53 @@ static struct batadv_priv *batadv_kobj_to_batpriv(struct kobject *obj)
39 return netdev_priv(net_dev); 40 return netdev_priv(net_dev);
40} 41}
41 42
43/**
44 * batadv_vlan_kobj_to_batpriv - convert a vlan kobj in the associated batpriv
45 * @obj: kobject to covert
46 *
47 * Returns the associated batadv_priv struct.
48 */
49static struct batadv_priv *batadv_vlan_kobj_to_batpriv(struct kobject *obj)
50{
51 /* VLAN specific attributes are located in the root sysfs folder if they
52 * refer to the untagged VLAN..
53 */
54 if (!strcmp(BATADV_SYSFS_IF_MESH_SUBDIR, obj->name))
55 return batadv_kobj_to_batpriv(obj);
56
57 /* ..while the attributes for the tagged vlans are located in
58 * the in the corresponding "vlan%VID" subfolder
59 */
60 return batadv_kobj_to_batpriv(obj->parent);
61}
62
63/**
64 * batadv_kobj_to_vlan - convert a kobj in the associated softif_vlan struct
65 * @obj: kobject to covert
66 *
67 * Returns the associated softif_vlan struct if found, NULL otherwise.
68 */
69static struct batadv_softif_vlan *
70batadv_kobj_to_vlan(struct batadv_priv *bat_priv, struct kobject *obj)
71{
72 struct batadv_softif_vlan *vlan_tmp, *vlan = NULL;
73
74 rcu_read_lock();
75 hlist_for_each_entry_rcu(vlan_tmp, &bat_priv->softif_vlan_list, list) {
76 if (vlan_tmp->kobj != obj)
77 continue;
78
79 if (!atomic_inc_not_zero(&vlan_tmp->refcount))
80 continue;
81
82 vlan = vlan_tmp;
83 break;
84 }
85 rcu_read_unlock();
86
87 return vlan;
88}
89
42#define BATADV_UEV_TYPE_VAR "BATTYPE=" 90#define BATADV_UEV_TYPE_VAR "BATTYPE="
43#define BATADV_UEV_ACTION_VAR "BATACTION=" 91#define BATADV_UEV_ACTION_VAR "BATACTION="
44#define BATADV_UEV_DATA_VAR "BATDATA=" 92#define BATADV_UEV_DATA_VAR "BATDATA="
@@ -53,6 +101,15 @@ static char *batadv_uev_type_str[] = {
53 "gw" 101 "gw"
54}; 102};
55 103
104/* Use this, if you have customized show and store functions for vlan attrs */
105#define BATADV_ATTR_VLAN(_name, _mode, _show, _store) \
106struct batadv_attribute batadv_attr_vlan_##_name = { \
107 .attr = {.name = __stringify(_name), \
108 .mode = _mode }, \
109 .show = _show, \
110 .store = _store, \
111};
112
56/* Use this, if you have customized show and store functions */ 113/* Use this, if you have customized show and store functions */
57#define BATADV_ATTR(_name, _mode, _show, _store) \ 114#define BATADV_ATTR(_name, _mode, _show, _store) \
58struct batadv_attribute batadv_attr_##_name = { \ 115struct batadv_attribute batadv_attr_##_name = { \
@@ -122,6 +179,41 @@ ssize_t batadv_show_##_name(struct kobject *kobj, \
122 static BATADV_ATTR(_name, _mode, batadv_show_##_name, \ 179 static BATADV_ATTR(_name, _mode, batadv_show_##_name, \
123 batadv_store_##_name) 180 batadv_store_##_name)
124 181
182#define BATADV_ATTR_VLAN_STORE_BOOL(_name, _post_func) \
183ssize_t batadv_store_vlan_##_name(struct kobject *kobj, \
184 struct attribute *attr, char *buff, \
185 size_t count) \
186{ \
187 struct batadv_priv *bat_priv = batadv_vlan_kobj_to_batpriv(kobj);\
188 struct batadv_softif_vlan *vlan = batadv_kobj_to_vlan(bat_priv, \
189 kobj); \
190 size_t res = __batadv_store_bool_attr(buff, count, _post_func, \
191 attr, &vlan->_name, \
192 bat_priv->soft_iface); \
193 batadv_softif_vlan_free_ref(vlan); \
194 return res; \
195}
196
197#define BATADV_ATTR_VLAN_SHOW_BOOL(_name) \
198ssize_t batadv_show_vlan_##_name(struct kobject *kobj, \
199 struct attribute *attr, char *buff) \
200{ \
201 struct batadv_priv *bat_priv = batadv_vlan_kobj_to_batpriv(kobj);\
202 struct batadv_softif_vlan *vlan = batadv_kobj_to_vlan(bat_priv, \
203 kobj); \
204 size_t res = sprintf(buff, "%s\n", \
205 atomic_read(&vlan->_name) == 0 ? \
206 "disabled" : "enabled"); \
207 batadv_softif_vlan_free_ref(vlan); \
208 return res; \
209}
210
211/* Use this, if you are going to turn a [name] in the vlan struct on or off */
212#define BATADV_ATTR_VLAN_BOOL(_name, _mode, _post_func) \
213 static BATADV_ATTR_VLAN_STORE_BOOL(_name, _post_func) \
214 static BATADV_ATTR_VLAN_SHOW_BOOL(_name) \
215 static BATADV_ATTR_VLAN(_name, _mode, batadv_show_vlan_##_name, \
216 batadv_store_vlan_##_name)
125 217
126static int batadv_store_bool_attr(char *buff, size_t count, 218static int batadv_store_bool_attr(char *buff, size_t count,
127 struct net_device *net_dev, 219 struct net_device *net_dev,
@@ -361,7 +453,6 @@ BATADV_ATTR_SIF_BOOL(distributed_arp_table, S_IRUGO | S_IWUSR,
361 batadv_dat_status_update); 453 batadv_dat_status_update);
362#endif 454#endif
363BATADV_ATTR_SIF_BOOL(fragmentation, S_IRUGO | S_IWUSR, batadv_update_min_mtu); 455BATADV_ATTR_SIF_BOOL(fragmentation, S_IRUGO | S_IWUSR, batadv_update_min_mtu);
364BATADV_ATTR_SIF_BOOL(ap_isolation, S_IRUGO | S_IWUSR, NULL);
365static BATADV_ATTR(routing_algo, S_IRUGO, batadv_show_bat_algo, NULL); 456static BATADV_ATTR(routing_algo, S_IRUGO, batadv_show_bat_algo, NULL);
366static BATADV_ATTR(gw_mode, S_IRUGO | S_IWUSR, batadv_show_gw_mode, 457static BATADV_ATTR(gw_mode, S_IRUGO | S_IWUSR, batadv_show_gw_mode,
367 batadv_store_gw_mode); 458 batadv_store_gw_mode);
@@ -391,7 +482,6 @@ static struct batadv_attribute *batadv_mesh_attrs[] = {
391 &batadv_attr_distributed_arp_table, 482 &batadv_attr_distributed_arp_table,
392#endif 483#endif
393 &batadv_attr_fragmentation, 484 &batadv_attr_fragmentation,
394 &batadv_attr_ap_isolation,
395 &batadv_attr_routing_algo, 485 &batadv_attr_routing_algo,
396 &batadv_attr_gw_mode, 486 &batadv_attr_gw_mode,
397 &batadv_attr_orig_interval, 487 &batadv_attr_orig_interval,
@@ -407,6 +497,16 @@ static struct batadv_attribute *batadv_mesh_attrs[] = {
407 NULL, 497 NULL,
408}; 498};
409 499
500BATADV_ATTR_VLAN_BOOL(ap_isolation, S_IRUGO | S_IWUSR, NULL);
501
502/**
503 * batadv_vlan_attrs - array of vlan specific sysfs attributes
504 */
505static struct batadv_attribute *batadv_vlan_attrs[] = {
506 &batadv_attr_vlan_ap_isolation,
507 NULL,
508};
509
410int batadv_sysfs_add_meshif(struct net_device *dev) 510int batadv_sysfs_add_meshif(struct net_device *dev)
411{ 511{
412 struct kobject *batif_kobject = &dev->dev.kobj; 512 struct kobject *batif_kobject = &dev->dev.kobj;
@@ -457,6 +557,80 @@ void batadv_sysfs_del_meshif(struct net_device *dev)
457 bat_priv->mesh_obj = NULL; 557 bat_priv->mesh_obj = NULL;
458} 558}
459 559
560/**
561 * batadv_sysfs_add_vlan - add all the needed sysfs objects for the new vlan
562 * @dev: netdev of the mesh interface
563 * @vlan: private data of the newly added VLAN interface
564 *
565 * Returns 0 on success and -ENOMEM if any of the structure allocations fails.
566 */
567int batadv_sysfs_add_vlan(struct net_device *dev,
568 struct batadv_softif_vlan *vlan)
569{
570 char vlan_subdir[sizeof(BATADV_SYSFS_VLAN_SUBDIR_PREFIX) + 5];
571 struct batadv_priv *bat_priv = netdev_priv(dev);
572 struct batadv_attribute **bat_attr;
573 int err;
574
575 if (vlan->vid & BATADV_VLAN_HAS_TAG) {
576 sprintf(vlan_subdir, BATADV_SYSFS_VLAN_SUBDIR_PREFIX "%hu",
577 vlan->vid & VLAN_VID_MASK);
578
579 vlan->kobj = kobject_create_and_add(vlan_subdir,
580 bat_priv->mesh_obj);
581 if (!vlan->kobj) {
582 batadv_err(dev, "Can't add sysfs directory: %s/%s\n",
583 dev->name, vlan_subdir);
584 goto out;
585 }
586 } else {
587 /* the untagged LAN uses the root folder to store its "VLAN
588 * specific attributes"
589 */
590 vlan->kobj = bat_priv->mesh_obj;
591 kobject_get(bat_priv->mesh_obj);
592 }
593
594 for (bat_attr = batadv_vlan_attrs; *bat_attr; ++bat_attr) {
595 err = sysfs_create_file(vlan->kobj,
596 &((*bat_attr)->attr));
597 if (err) {
598 batadv_err(dev, "Can't add sysfs file: %s/%s/%s\n",
599 dev->name, vlan_subdir,
600 ((*bat_attr)->attr).name);
601 goto rem_attr;
602 }
603 }
604
605 return 0;
606
607rem_attr:
608 for (bat_attr = batadv_vlan_attrs; *bat_attr; ++bat_attr)
609 sysfs_remove_file(vlan->kobj, &((*bat_attr)->attr));
610
611 kobject_put(vlan->kobj);
612 vlan->kobj = NULL;
613out:
614 return -ENOMEM;
615}
616
617/**
618 * batadv_sysfs_del_vlan - remove all the sysfs objects for a given VLAN
619 * @bat_priv: the bat priv with all the soft interface information
620 * @vlan: the private data of the VLAN to destroy
621 */
622void batadv_sysfs_del_vlan(struct batadv_priv *bat_priv,
623 struct batadv_softif_vlan *vlan)
624{
625 struct batadv_attribute **bat_attr;
626
627 for (bat_attr = batadv_vlan_attrs; *bat_attr; ++bat_attr)
628 sysfs_remove_file(vlan->kobj, &((*bat_attr)->attr));
629
630 kobject_put(vlan->kobj);
631 vlan->kobj = NULL;
632}
633
460static ssize_t batadv_show_mesh_iface(struct kobject *kobj, 634static ssize_t batadv_show_mesh_iface(struct kobject *kobj,
461 struct attribute *attr, char *buff) 635 struct attribute *attr, char *buff)
462{ 636{
diff --git a/net/batman-adv/sysfs.h b/net/batman-adv/sysfs.h
index 479acf4c16f4..c7d725de50ad 100644
--- a/net/batman-adv/sysfs.h
+++ b/net/batman-adv/sysfs.h
@@ -22,6 +22,12 @@
22 22
23#define BATADV_SYSFS_IF_MESH_SUBDIR "mesh" 23#define BATADV_SYSFS_IF_MESH_SUBDIR "mesh"
24#define BATADV_SYSFS_IF_BAT_SUBDIR "batman_adv" 24#define BATADV_SYSFS_IF_BAT_SUBDIR "batman_adv"
25/**
26 * BATADV_SYSFS_VLAN_SUBDIR_PREFIX - prefix of the subfolder that will be
27 * created in the sysfs hierarchy for each VLAN interface. The subfolder will
28 * be named "BATADV_SYSFS_VLAN_SUBDIR_PREFIX%vid".
29 */
30#define BATADV_SYSFS_VLAN_SUBDIR_PREFIX "vlan"
25 31
26struct batadv_attribute { 32struct batadv_attribute {
27 struct attribute attr; 33 struct attribute attr;
@@ -36,6 +42,10 @@ void batadv_sysfs_del_meshif(struct net_device *dev);
36int batadv_sysfs_add_hardif(struct kobject **hardif_obj, 42int batadv_sysfs_add_hardif(struct kobject **hardif_obj,
37 struct net_device *dev); 43 struct net_device *dev);
38void batadv_sysfs_del_hardif(struct kobject **hardif_obj); 44void batadv_sysfs_del_hardif(struct kobject **hardif_obj);
45int batadv_sysfs_add_vlan(struct net_device *dev,
46 struct batadv_softif_vlan *vlan);
47void batadv_sysfs_del_vlan(struct batadv_priv *bat_priv,
48 struct batadv_softif_vlan *vlan);
39int batadv_throw_uevent(struct batadv_priv *bat_priv, enum batadv_uev_type type, 49int batadv_throw_uevent(struct batadv_priv *bat_priv, enum batadv_uev_type type,
40 enum batadv_uev_action action, const char *data); 50 enum batadv_uev_action action, const char *data);
41 51
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index b521afb186d4..7731eaed737d 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -34,6 +34,7 @@ static struct lock_class_key batadv_tt_local_hash_lock_class_key;
34static struct lock_class_key batadv_tt_global_hash_lock_class_key; 34static struct lock_class_key batadv_tt_global_hash_lock_class_key;
35 35
36static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client, 36static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client,
37 unsigned short vid,
37 struct batadv_orig_node *orig_node); 38 struct batadv_orig_node *orig_node);
38static void batadv_tt_purge(struct work_struct *work); 39static void batadv_tt_purge(struct work_struct *work);
39static void 40static void
@@ -41,7 +42,8 @@ batadv_tt_global_del_orig_list(struct batadv_tt_global_entry *tt_global_entry);
41static void batadv_tt_global_del(struct batadv_priv *bat_priv, 42static void batadv_tt_global_del(struct batadv_priv *bat_priv,
42 struct batadv_orig_node *orig_node, 43 struct batadv_orig_node *orig_node,
43 const unsigned char *addr, 44 const unsigned char *addr,
44 const char *message, bool roaming); 45 unsigned short vid, const char *message,
46 bool roaming);
45 47
46/* returns 1 if they are the same mac addr */ 48/* returns 1 if they are the same mac addr */
47static int batadv_compare_tt(const struct hlist_node *node, const void *data2) 49static int batadv_compare_tt(const struct hlist_node *node, const void *data2)
@@ -52,43 +54,93 @@ static int batadv_compare_tt(const struct hlist_node *node, const void *data2)
52 return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0); 54 return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
53} 55}
54 56
57/**
58 * batadv_choose_tt - return the index of the tt entry in the hash table
59 * @data: pointer to the tt_common_entry object to map
60 * @size: the size of the hash table
61 *
62 * Returns the hash index where the object represented by 'data' should be
63 * stored at.
64 */
65static inline uint32_t batadv_choose_tt(const void *data, uint32_t size)
66{
67 struct batadv_tt_common_entry *tt;
68 uint32_t hash = 0;
69
70 tt = (struct batadv_tt_common_entry *)data;
71 hash = batadv_hash_bytes(hash, &tt->addr, ETH_ALEN);
72 hash = batadv_hash_bytes(hash, &tt->vid, sizeof(tt->vid));
73
74 hash += (hash << 3);
75 hash ^= (hash >> 11);
76 hash += (hash << 15);
77
78 return hash % size;
79}
80
81/**
82 * batadv_tt_hash_find - look for a client in the given hash table
83 * @hash: the hash table to search
84 * @addr: the mac address of the client to look for
85 * @vid: VLAN identifier
86 *
87 * Returns a pointer to the tt_common struct belonging to the searched client if
88 * found, NULL otherwise.
89 */
55static struct batadv_tt_common_entry * 90static struct batadv_tt_common_entry *
56batadv_tt_hash_find(struct batadv_hashtable *hash, const void *data) 91batadv_tt_hash_find(struct batadv_hashtable *hash, const uint8_t *addr,
92 unsigned short vid)
57{ 93{
58 struct hlist_head *head; 94 struct hlist_head *head;
59 struct batadv_tt_common_entry *tt_common_entry; 95 struct batadv_tt_common_entry to_search, *tt, *tt_tmp = NULL;
60 struct batadv_tt_common_entry *tt_common_entry_tmp = NULL;
61 uint32_t index; 96 uint32_t index;
62 97
63 if (!hash) 98 if (!hash)
64 return NULL; 99 return NULL;
65 100
66 index = batadv_choose_orig(data, hash->size); 101 memcpy(to_search.addr, addr, ETH_ALEN);
102 to_search.vid = vid;
103
104 index = batadv_choose_tt(&to_search, hash->size);
67 head = &hash->table[index]; 105 head = &hash->table[index];
68 106
69 rcu_read_lock(); 107 rcu_read_lock();
70 hlist_for_each_entry_rcu(tt_common_entry, head, hash_entry) { 108 hlist_for_each_entry_rcu(tt, head, hash_entry) {
71 if (!batadv_compare_eth(tt_common_entry, data)) 109 if (!batadv_compare_eth(tt, addr))
72 continue; 110 continue;
73 111
74 if (!atomic_inc_not_zero(&tt_common_entry->refcount)) 112 if (tt->vid != vid)
75 continue; 113 continue;
76 114
77 tt_common_entry_tmp = tt_common_entry; 115 if (!atomic_inc_not_zero(&tt->refcount))
116 continue;
117
118 tt_tmp = tt;
78 break; 119 break;
79 } 120 }
80 rcu_read_unlock(); 121 rcu_read_unlock();
81 122
82 return tt_common_entry_tmp; 123 return tt_tmp;
83} 124}
84 125
126/**
127 * batadv_tt_local_hash_find - search the local table for a given client
128 * @bat_priv: the bat priv with all the soft interface information
129 * @addr: the mac address of the client to look for
130 * @vid: VLAN identifier
131 *
132 * Returns a pointer to the corresponding tt_local_entry struct if the client is
133 * found, NULL otherwise.
134 */
85static struct batadv_tt_local_entry * 135static struct batadv_tt_local_entry *
86batadv_tt_local_hash_find(struct batadv_priv *bat_priv, const void *data) 136batadv_tt_local_hash_find(struct batadv_priv *bat_priv, const uint8_t *addr,
137 unsigned short vid)
87{ 138{
88 struct batadv_tt_common_entry *tt_common_entry; 139 struct batadv_tt_common_entry *tt_common_entry;
89 struct batadv_tt_local_entry *tt_local_entry = NULL; 140 struct batadv_tt_local_entry *tt_local_entry = NULL;
90 141
91 tt_common_entry = batadv_tt_hash_find(bat_priv->tt.local_hash, data); 142 tt_common_entry = batadv_tt_hash_find(bat_priv->tt.local_hash, addr,
143 vid);
92 if (tt_common_entry) 144 if (tt_common_entry)
93 tt_local_entry = container_of(tt_common_entry, 145 tt_local_entry = container_of(tt_common_entry,
94 struct batadv_tt_local_entry, 146 struct batadv_tt_local_entry,
@@ -96,13 +148,24 @@ batadv_tt_local_hash_find(struct batadv_priv *bat_priv, const void *data)
96 return tt_local_entry; 148 return tt_local_entry;
97} 149}
98 150
151/**
152 * batadv_tt_global_hash_find - search the global table for a given client
153 * @bat_priv: the bat priv with all the soft interface information
154 * @addr: the mac address of the client to look for
155 * @vid: VLAN identifier
156 *
157 * Returns a pointer to the corresponding tt_global_entry struct if the client
158 * is found, NULL otherwise.
159 */
99static struct batadv_tt_global_entry * 160static struct batadv_tt_global_entry *
100batadv_tt_global_hash_find(struct batadv_priv *bat_priv, const void *data) 161batadv_tt_global_hash_find(struct batadv_priv *bat_priv, const uint8_t *addr,
162 unsigned short vid)
101{ 163{
102 struct batadv_tt_common_entry *tt_common_entry; 164 struct batadv_tt_common_entry *tt_common_entry;
103 struct batadv_tt_global_entry *tt_global_entry = NULL; 165 struct batadv_tt_global_entry *tt_global_entry = NULL;
104 166
105 tt_common_entry = batadv_tt_hash_find(bat_priv->tt.global_hash, data); 167 tt_common_entry = batadv_tt_hash_find(bat_priv->tt.global_hash, addr,
168 vid);
106 if (tt_common_entry) 169 if (tt_common_entry)
107 tt_global_entry = container_of(tt_common_entry, 170 tt_global_entry = container_of(tt_common_entry,
108 struct batadv_tt_global_entry, 171 struct batadv_tt_global_entry,
@@ -145,13 +208,107 @@ static void batadv_tt_orig_list_entry_free_rcu(struct rcu_head *rcu)
145 kfree(orig_entry); 208 kfree(orig_entry);
146} 209}
147 210
211/**
212 * batadv_tt_local_size_mod - change the size by v of the local table identified
213 * by vid
214 * @bat_priv: the bat priv with all the soft interface information
215 * @vid: the VLAN identifier of the sub-table to change
216 * @v: the amount to sum to the local table size
217 */
218static void batadv_tt_local_size_mod(struct batadv_priv *bat_priv,
219 unsigned short vid, int v)
220{
221 struct batadv_softif_vlan *vlan;
222
223 vlan = batadv_softif_vlan_get(bat_priv, vid);
224 if (!vlan)
225 return;
226
227 atomic_add(v, &vlan->tt.num_entries);
228
229 batadv_softif_vlan_free_ref(vlan);
230}
231
232/**
233 * batadv_tt_local_size_inc - increase by one the local table size for the given
234 * vid
235 * @bat_priv: the bat priv with all the soft interface information
236 * @vid: the VLAN identifier
237 */
238static void batadv_tt_local_size_inc(struct batadv_priv *bat_priv,
239 unsigned short vid)
240{
241 batadv_tt_local_size_mod(bat_priv, vid, 1);
242}
243
244/**
245 * batadv_tt_local_size_dec - decrease by one the local table size for the given
246 * vid
247 * @bat_priv: the bat priv with all the soft interface information
248 * @vid: the VLAN identifier
249 */
250static void batadv_tt_local_size_dec(struct batadv_priv *bat_priv,
251 unsigned short vid)
252{
253 batadv_tt_local_size_mod(bat_priv, vid, -1);
254}
255
256/**
257 * batadv_tt_global_size_mod - change the size by v of the local table
258 * identified by vid
259 * @bat_priv: the bat priv with all the soft interface information
260 * @vid: the VLAN identifier
261 * @v: the amount to sum to the global table size
262 */
263static void batadv_tt_global_size_mod(struct batadv_orig_node *orig_node,
264 unsigned short vid, int v)
265{
266 struct batadv_orig_node_vlan *vlan;
267
268 vlan = batadv_orig_node_vlan_new(orig_node, vid);
269 if (!vlan)
270 return;
271
272 if (atomic_add_return(v, &vlan->tt.num_entries) == 0) {
273 spin_lock_bh(&orig_node->vlan_list_lock);
274 list_del_rcu(&vlan->list);
275 spin_unlock_bh(&orig_node->vlan_list_lock);
276 batadv_orig_node_vlan_free_ref(vlan);
277 }
278
279 batadv_orig_node_vlan_free_ref(vlan);
280}
281
282/**
283 * batadv_tt_global_size_inc - increase by one the global table size for the
284 * given vid
285 * @orig_node: the originator which global table size has to be decreased
286 * @vid: the vlan identifier
287 */
288static void batadv_tt_global_size_inc(struct batadv_orig_node *orig_node,
289 unsigned short vid)
290{
291 batadv_tt_global_size_mod(orig_node, vid, 1);
292}
293
294/**
295 * batadv_tt_global_size_dec - decrease by one the global table size for the
296 * given vid
297 * @orig_node: the originator which global table size has to be decreased
298 * @vid: the vlan identifier
299 */
300static void batadv_tt_global_size_dec(struct batadv_orig_node *orig_node,
301 unsigned short vid)
302{
303 batadv_tt_global_size_mod(orig_node, vid, -1);
304}
305
148static void 306static void
149batadv_tt_orig_list_entry_free_ref(struct batadv_tt_orig_list_entry *orig_entry) 307batadv_tt_orig_list_entry_free_ref(struct batadv_tt_orig_list_entry *orig_entry)
150{ 308{
151 if (!atomic_dec_and_test(&orig_entry->refcount)) 309 if (!atomic_dec_and_test(&orig_entry->refcount))
152 return; 310 return;
153 /* to avoid race conditions, immediately decrease the tt counter */ 311
154 atomic_dec(&orig_entry->orig_node->tt_size);
155 call_rcu(&orig_entry->rcu, batadv_tt_orig_list_entry_free_rcu); 312 call_rcu(&orig_entry->rcu, batadv_tt_orig_list_entry_free_rcu);
156} 313}
157 314
@@ -178,6 +335,7 @@ static void batadv_tt_local_event(struct batadv_priv *bat_priv,
178 tt_change_node->change.flags = flags; 335 tt_change_node->change.flags = flags;
179 tt_change_node->change.reserved = 0; 336 tt_change_node->change.reserved = 0;
180 memcpy(tt_change_node->change.addr, common->addr, ETH_ALEN); 337 memcpy(tt_change_node->change.addr, common->addr, ETH_ALEN);
338 tt_change_node->change.vid = htons(common->vid);
181 339
182 del_op_requested = flags & BATADV_TT_CLIENT_DEL; 340 del_op_requested = flags & BATADV_TT_CLIENT_DEL;
183 341
@@ -264,16 +422,26 @@ static void batadv_tt_global_free(struct batadv_priv *bat_priv,
264 const char *message) 422 const char *message)
265{ 423{
266 batadv_dbg(BATADV_DBG_TT, bat_priv, 424 batadv_dbg(BATADV_DBG_TT, bat_priv,
267 "Deleting global tt entry %pM: %s\n", 425 "Deleting global tt entry %pM (vid: %d): %s\n",
268 tt_global->common.addr, message); 426 tt_global->common.addr,
427 BATADV_PRINT_VID(tt_global->common.vid), message);
269 428
270 batadv_hash_remove(bat_priv->tt.global_hash, batadv_compare_tt, 429 batadv_hash_remove(bat_priv->tt.global_hash, batadv_compare_tt,
271 batadv_choose_orig, tt_global->common.addr); 430 batadv_choose_tt, &tt_global->common);
272 batadv_tt_global_entry_free_ref(tt_global); 431 batadv_tt_global_entry_free_ref(tt_global);
273} 432}
274 433
434/**
435 * batadv_tt_local_add - add a new client to the local table or update an
436 * existing client
437 * @soft_iface: netdev struct of the mesh interface
438 * @addr: the mac address of the client to add
439 * @vid: VLAN identifier
440 * @ifindex: index of the interface where the client is connected to (useful to
441 * identify wireless clients)
442 */
275void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr, 443void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
276 int ifindex) 444 unsigned short vid, int ifindex)
277{ 445{
278 struct batadv_priv *bat_priv = netdev_priv(soft_iface); 446 struct batadv_priv *bat_priv = netdev_priv(soft_iface);
279 struct batadv_tt_local_entry *tt_local; 447 struct batadv_tt_local_entry *tt_local;
@@ -283,14 +451,15 @@ void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
283 int hash_added; 451 int hash_added;
284 bool roamed_back = false; 452 bool roamed_back = false;
285 453
286 tt_local = batadv_tt_local_hash_find(bat_priv, addr); 454 tt_local = batadv_tt_local_hash_find(bat_priv, addr, vid);
287 tt_global = batadv_tt_global_hash_find(bat_priv, addr); 455 tt_global = batadv_tt_global_hash_find(bat_priv, addr, vid);
288 456
289 if (tt_local) { 457 if (tt_local) {
290 tt_local->last_seen = jiffies; 458 tt_local->last_seen = jiffies;
291 if (tt_local->common.flags & BATADV_TT_CLIENT_PENDING) { 459 if (tt_local->common.flags & BATADV_TT_CLIENT_PENDING) {
292 batadv_dbg(BATADV_DBG_TT, bat_priv, 460 batadv_dbg(BATADV_DBG_TT, bat_priv,
293 "Re-adding pending client %pM\n", addr); 461 "Re-adding pending client %pM (vid: %d)\n",
462 addr, BATADV_PRINT_VID(vid));
294 /* whatever the reason why the PENDING flag was set, 463 /* whatever the reason why the PENDING flag was set,
295 * this is a client which was enqueued to be removed in 464 * this is a client which was enqueued to be removed in
296 * this orig_interval. Since it popped up again, the 465 * this orig_interval. Since it popped up again, the
@@ -302,8 +471,8 @@ void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
302 471
303 if (tt_local->common.flags & BATADV_TT_CLIENT_ROAM) { 472 if (tt_local->common.flags & BATADV_TT_CLIENT_ROAM) {
304 batadv_dbg(BATADV_DBG_TT, bat_priv, 473 batadv_dbg(BATADV_DBG_TT, bat_priv,
305 "Roaming client %pM came back to its original location\n", 474 "Roaming client %pM (vid: %d) came back to its original location\n",
306 addr); 475 addr, BATADV_PRINT_VID(vid));
307 /* the ROAM flag is set because this client roamed away 476 /* the ROAM flag is set because this client roamed away
308 * and the node got a roaming_advertisement message. Now 477 * and the node got a roaming_advertisement message. Now
309 * that the client popped up again at its original 478 * that the client popped up again at its original
@@ -320,7 +489,8 @@ void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
320 goto out; 489 goto out;
321 490
322 batadv_dbg(BATADV_DBG_TT, bat_priv, 491 batadv_dbg(BATADV_DBG_TT, bat_priv,
323 "Creating new local tt entry: %pM (ttvn: %d)\n", addr, 492 "Creating new local tt entry: %pM (vid: %d, ttvn: %d)\n",
493 addr, BATADV_PRINT_VID(vid),
324 (uint8_t)atomic_read(&bat_priv->tt.vn)); 494 (uint8_t)atomic_read(&bat_priv->tt.vn));
325 495
326 memcpy(tt_local->common.addr, addr, ETH_ALEN); 496 memcpy(tt_local->common.addr, addr, ETH_ALEN);
@@ -329,6 +499,7 @@ void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
329 * (consistency check) 499 * (consistency check)
330 */ 500 */
331 tt_local->common.flags = BATADV_TT_CLIENT_NEW; 501 tt_local->common.flags = BATADV_TT_CLIENT_NEW;
502 tt_local->common.vid = vid;
332 if (batadv_is_wifi_iface(ifindex)) 503 if (batadv_is_wifi_iface(ifindex))
333 tt_local->common.flags |= BATADV_TT_CLIENT_WIFI; 504 tt_local->common.flags |= BATADV_TT_CLIENT_WIFI;
334 atomic_set(&tt_local->common.refcount, 2); 505 atomic_set(&tt_local->common.refcount, 2);
@@ -340,7 +511,7 @@ void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
340 tt_local->common.flags |= BATADV_TT_CLIENT_NOPURGE; 511 tt_local->common.flags |= BATADV_TT_CLIENT_NOPURGE;
341 512
342 hash_added = batadv_hash_add(bat_priv->tt.local_hash, batadv_compare_tt, 513 hash_added = batadv_hash_add(bat_priv->tt.local_hash, batadv_compare_tt,
343 batadv_choose_orig, &tt_local->common, 514 batadv_choose_tt, &tt_local->common,
344 &tt_local->common.hash_entry); 515 &tt_local->common.hash_entry);
345 516
346 if (unlikely(hash_added != 0)) { 517 if (unlikely(hash_added != 0)) {
@@ -362,6 +533,7 @@ check_roaming:
362 rcu_read_lock(); 533 rcu_read_lock();
363 hlist_for_each_entry_rcu(orig_entry, head, list) { 534 hlist_for_each_entry_rcu(orig_entry, head, list) {
364 batadv_send_roam_adv(bat_priv, tt_global->common.addr, 535 batadv_send_roam_adv(bat_priv, tt_global->common.addr,
536 tt_global->common.vid,
365 orig_entry->orig_node); 537 orig_entry->orig_node);
366 } 538 }
367 rcu_read_unlock(); 539 rcu_read_unlock();
@@ -386,6 +558,149 @@ out:
386} 558}
387 559
388/** 560/**
561 * batadv_tt_prepare_tvlv_global_data - prepare the TVLV TT header to send
562 * within a TT Response directed to another node
563 * @orig_node: originator for which the TT data has to be prepared
564 * @tt_data: uninitialised pointer to the address of the TVLV buffer
565 * @tt_change: uninitialised pointer to the address of the area where the TT
566 * changed can be stored
567 * @tt_len: pointer to the length to reserve to the tt_change. if -1 this
568 * function reserves the amount of space needed to send the entire global TT
569 * table. In case of success the value is updated with the real amount of
570 * reserved bytes
571
572 * Allocate the needed amount of memory for the entire TT TVLV and write its
573 * header made up by one tvlv_tt_data object and a series of tvlv_tt_vlan_data
574 * objects, one per active VLAN served by the originator node.
575 *
576 * Return the size of the allocated buffer or 0 in case of failure.
577 */
578static uint16_t
579batadv_tt_prepare_tvlv_global_data(struct batadv_orig_node *orig_node,
580 struct batadv_tvlv_tt_data **tt_data,
581 struct batadv_tvlv_tt_change **tt_change,
582 int32_t *tt_len)
583{
584 uint16_t num_vlan = 0, num_entries = 0, change_offset, tvlv_len;
585 struct batadv_tvlv_tt_vlan_data *tt_vlan;
586 struct batadv_orig_node_vlan *vlan;
587 uint8_t *tt_change_ptr;
588
589 rcu_read_lock();
590 list_for_each_entry_rcu(vlan, &orig_node->vlan_list, list) {
591 num_vlan++;
592 num_entries += atomic_read(&vlan->tt.num_entries);
593 }
594
595 change_offset = sizeof(**tt_data);
596 change_offset += num_vlan * sizeof(*tt_vlan);
597
598 /* if tt_len is negative, allocate the space needed by the full table */
599 if (*tt_len < 0)
600 *tt_len = batadv_tt_len(num_entries);
601
602 tvlv_len = *tt_len;
603 tvlv_len += change_offset;
604
605 *tt_data = kmalloc(tvlv_len, GFP_ATOMIC);
606 if (!*tt_data) {
607 *tt_len = 0;
608 goto out;
609 }
610
611 (*tt_data)->flags = BATADV_NO_FLAGS;
612 (*tt_data)->ttvn = atomic_read(&orig_node->last_ttvn);
613 (*tt_data)->num_vlan = htons(num_vlan);
614
615 tt_vlan = (struct batadv_tvlv_tt_vlan_data *)(*tt_data + 1);
616 list_for_each_entry_rcu(vlan, &orig_node->vlan_list, list) {
617 tt_vlan->vid = htons(vlan->vid);
618 tt_vlan->crc = htonl(vlan->tt.crc);
619
620 tt_vlan++;
621 }
622
623 tt_change_ptr = (uint8_t *)*tt_data + change_offset;
624 *tt_change = (struct batadv_tvlv_tt_change *)tt_change_ptr;
625
626out:
627 rcu_read_unlock();
628 return tvlv_len;
629}
630
631/**
632 * batadv_tt_prepare_tvlv_local_data - allocate and prepare the TT TVLV for this
633 * node
634 * @bat_priv: the bat priv with all the soft interface information
635 * @tt_data: uninitialised pointer to the address of the TVLV buffer
636 * @tt_change: uninitialised pointer to the address of the area where the TT
637 * changes can be stored
638 * @tt_len: pointer to the length to reserve to the tt_change. if -1 this
639 * function reserves the amount of space needed to send the entire local TT
640 * table. In case of success the value is updated with the real amount of
641 * reserved bytes
642 *
643 * Allocate the needed amount of memory for the entire TT TVLV and write its
644 * header made up by one tvlv_tt_data object and a series of tvlv_tt_vlan_data
645 * objects, one per active VLAN.
646 *
647 * Return the size of the allocated buffer or 0 in case of failure.
648 */
649static uint16_t
650batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv,
651 struct batadv_tvlv_tt_data **tt_data,
652 struct batadv_tvlv_tt_change **tt_change,
653 int32_t *tt_len)
654{
655 struct batadv_tvlv_tt_vlan_data *tt_vlan;
656 struct batadv_softif_vlan *vlan;
657 uint16_t num_vlan = 0, num_entries = 0, tvlv_len;
658 uint8_t *tt_change_ptr;
659 int change_offset;
660
661 rcu_read_lock();
662 hlist_for_each_entry_rcu(vlan, &bat_priv->softif_vlan_list, list) {
663 num_vlan++;
664 num_entries += atomic_read(&vlan->tt.num_entries);
665 }
666
667 change_offset = sizeof(**tt_data);
668 change_offset += num_vlan * sizeof(*tt_vlan);
669
670 /* if tt_len is negative, allocate the space needed by the full table */
671 if (*tt_len < 0)
672 *tt_len = batadv_tt_len(num_entries);
673
674 tvlv_len = *tt_len;
675 tvlv_len += change_offset;
676
677 *tt_data = kmalloc(tvlv_len, GFP_ATOMIC);
678 if (!*tt_data) {
679 tvlv_len = 0;
680 goto out;
681 }
682
683 (*tt_data)->flags = BATADV_NO_FLAGS;
684 (*tt_data)->ttvn = atomic_read(&bat_priv->tt.vn);
685 (*tt_data)->num_vlan = htons(num_vlan);
686
687 tt_vlan = (struct batadv_tvlv_tt_vlan_data *)(*tt_data + 1);
688 hlist_for_each_entry_rcu(vlan, &bat_priv->softif_vlan_list, list) {
689 tt_vlan->vid = htons(vlan->vid);
690 tt_vlan->crc = htonl(vlan->tt.crc);
691
692 tt_vlan++;
693 }
694
695 tt_change_ptr = (uint8_t *)*tt_data + change_offset;
696 *tt_change = (struct batadv_tvlv_tt_change *)tt_change_ptr;
697
698out:
699 rcu_read_unlock();
700 return tvlv_len;
701}
702
703/**
389 * batadv_tt_tvlv_container_update - update the translation table tvlv container 704 * batadv_tt_tvlv_container_update - update the translation table tvlv container
390 * after local tt changes have been committed 705 * after local tt changes have been committed
391 * @bat_priv: the bat priv with all the soft interface information 706 * @bat_priv: the bat priv with all the soft interface information
@@ -395,10 +710,12 @@ static void batadv_tt_tvlv_container_update(struct batadv_priv *bat_priv)
395 struct batadv_tt_change_node *entry, *safe; 710 struct batadv_tt_change_node *entry, *safe;
396 struct batadv_tvlv_tt_data *tt_data; 711 struct batadv_tvlv_tt_data *tt_data;
397 struct batadv_tvlv_tt_change *tt_change; 712 struct batadv_tvlv_tt_change *tt_change;
398 int tt_diff_len = 0, tt_change_len = 0; 713 int tt_diff_len, tt_change_len = 0;
399 int tt_diff_entries_num = 0, tt_diff_entries_count = 0; 714 int tt_diff_entries_num = 0, tt_diff_entries_count = 0;
715 uint16_t tvlv_len;
400 716
401 tt_diff_len += batadv_tt_len(atomic_read(&bat_priv->tt.local_changes)); 717 tt_diff_entries_num = atomic_read(&bat_priv->tt.local_changes);
718 tt_diff_len = batadv_tt_len(tt_diff_entries_num);
402 719
403 /* if we have too many changes for one packet don't send any 720 /* if we have too many changes for one packet don't send any
404 * and wait for the tt table request which will be fragmented 721 * and wait for the tt table request which will be fragmented
@@ -406,24 +723,19 @@ static void batadv_tt_tvlv_container_update(struct batadv_priv *bat_priv)
406 if (tt_diff_len > bat_priv->soft_iface->mtu) 723 if (tt_diff_len > bat_priv->soft_iface->mtu)
407 tt_diff_len = 0; 724 tt_diff_len = 0;
408 725
409 tt_data = kzalloc(sizeof(*tt_data) + tt_diff_len, GFP_ATOMIC); 726 tvlv_len = batadv_tt_prepare_tvlv_local_data(bat_priv, &tt_data,
410 if (!tt_data) 727 &tt_change, &tt_diff_len);
728 if (!tvlv_len)
411 return; 729 return;
412 730
413 tt_data->flags = BATADV_TT_OGM_DIFF; 731 tt_data->flags = BATADV_TT_OGM_DIFF;
414 tt_data->ttvn = atomic_read(&bat_priv->tt.vn);
415 tt_data->crc = htonl(bat_priv->tt.local_crc);
416 732
417 if (tt_diff_len == 0) 733 if (tt_diff_len == 0)
418 goto container_register; 734 goto container_register;
419 735
420 tt_diff_entries_num = batadv_tt_entries(tt_diff_len);
421
422 spin_lock_bh(&bat_priv->tt.changes_list_lock); 736 spin_lock_bh(&bat_priv->tt.changes_list_lock);
423 atomic_set(&bat_priv->tt.local_changes, 0); 737 atomic_set(&bat_priv->tt.local_changes, 0);
424 738
425 tt_change = (struct batadv_tvlv_tt_change *)(tt_data + 1);
426
427 list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list, 739 list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list,
428 list) { 740 list) {
429 if (tt_diff_entries_count < tt_diff_entries_num) { 741 if (tt_diff_entries_count < tt_diff_entries_num) {
@@ -459,7 +771,7 @@ static void batadv_tt_tvlv_container_update(struct batadv_priv *bat_priv)
459 771
460container_register: 772container_register:
461 batadv_tvlv_container_register(bat_priv, BATADV_TVLV_TT, 1, tt_data, 773 batadv_tvlv_container_register(bat_priv, BATADV_TVLV_TT, 1, tt_data,
462 sizeof(*tt_data) + tt_change_len); 774 tvlv_len);
463 kfree(tt_data); 775 kfree(tt_data);
464} 776}
465 777
@@ -471,7 +783,9 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
471 struct batadv_tt_common_entry *tt_common_entry; 783 struct batadv_tt_common_entry *tt_common_entry;
472 struct batadv_tt_local_entry *tt_local; 784 struct batadv_tt_local_entry *tt_local;
473 struct batadv_hard_iface *primary_if; 785 struct batadv_hard_iface *primary_if;
786 struct batadv_softif_vlan *vlan;
474 struct hlist_head *head; 787 struct hlist_head *head;
788 unsigned short vid;
475 uint32_t i; 789 uint32_t i;
476 int last_seen_secs; 790 int last_seen_secs;
477 int last_seen_msecs; 791 int last_seen_msecs;
@@ -484,11 +798,10 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
484 goto out; 798 goto out;
485 799
486 seq_printf(seq, 800 seq_printf(seq,
487 "Locally retrieved addresses (from %s) announced via TT (TTVN: %u CRC: %#.8x):\n", 801 "Locally retrieved addresses (from %s) announced via TT (TTVN: %u):\n",
488 net_dev->name, (uint8_t)atomic_read(&bat_priv->tt.vn), 802 net_dev->name, (uint8_t)atomic_read(&bat_priv->tt.vn));
489 bat_priv->tt.local_crc); 803 seq_printf(seq, " %-13s %s %-7s %-9s (%-10s)\n", "Client", "VID",
490 seq_printf(seq, " %-13s %-7s %-10s\n", "Client", "Flags", 804 "Flags", "Last seen", "CRC");
491 "Last seen");
492 805
493 for (i = 0; i < hash->size; i++) { 806 for (i = 0; i < hash->size; i++) {
494 head = &hash->table[i]; 807 head = &hash->table[i];
@@ -499,6 +812,7 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
499 tt_local = container_of(tt_common_entry, 812 tt_local = container_of(tt_common_entry,
500 struct batadv_tt_local_entry, 813 struct batadv_tt_local_entry,
501 common); 814 common);
815 vid = tt_common_entry->vid;
502 last_seen_jiffies = jiffies - tt_local->last_seen; 816 last_seen_jiffies = jiffies - tt_local->last_seen;
503 last_seen_msecs = jiffies_to_msecs(last_seen_jiffies); 817 last_seen_msecs = jiffies_to_msecs(last_seen_jiffies);
504 last_seen_secs = last_seen_msecs / 1000; 818 last_seen_secs = last_seen_msecs / 1000;
@@ -506,8 +820,17 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
506 820
507 no_purge = tt_common_entry->flags & np_flag; 821 no_purge = tt_common_entry->flags & np_flag;
508 822
509 seq_printf(seq, " * %pM [%c%c%c%c%c] %3u.%03u\n", 823 vlan = batadv_softif_vlan_get(bat_priv, vid);
824 if (!vlan) {
825 seq_printf(seq, "Cannot retrieve VLAN %d\n",
826 BATADV_PRINT_VID(vid));
827 continue;
828 }
829
830 seq_printf(seq,
831 " * %pM %4i [%c%c%c%c%c] %3u.%03u (%#.8x)\n",
510 tt_common_entry->addr, 832 tt_common_entry->addr,
833 BATADV_PRINT_VID(tt_common_entry->vid),
511 (tt_common_entry->flags & 834 (tt_common_entry->flags &
512 BATADV_TT_CLIENT_ROAM ? 'R' : '.'), 835 BATADV_TT_CLIENT_ROAM ? 'R' : '.'),
513 no_purge ? 'P' : '.', 836 no_purge ? 'P' : '.',
@@ -518,7 +841,10 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
518 (tt_common_entry->flags & 841 (tt_common_entry->flags &
519 BATADV_TT_CLIENT_WIFI ? 'W' : '.'), 842 BATADV_TT_CLIENT_WIFI ? 'W' : '.'),
520 no_purge ? 0 : last_seen_secs, 843 no_purge ? 0 : last_seen_secs,
521 no_purge ? 0 : last_seen_msecs); 844 no_purge ? 0 : last_seen_msecs,
845 vlan->tt.crc);
846
847 batadv_softif_vlan_free_ref(vlan);
522 } 848 }
523 rcu_read_unlock(); 849 rcu_read_unlock();
524 } 850 }
@@ -542,27 +868,29 @@ batadv_tt_local_set_pending(struct batadv_priv *bat_priv,
542 tt_local_entry->common.flags |= BATADV_TT_CLIENT_PENDING; 868 tt_local_entry->common.flags |= BATADV_TT_CLIENT_PENDING;
543 869
544 batadv_dbg(BATADV_DBG_TT, bat_priv, 870 batadv_dbg(BATADV_DBG_TT, bat_priv,
545 "Local tt entry (%pM) pending to be removed: %s\n", 871 "Local tt entry (%pM, vid: %d) pending to be removed: %s\n",
546 tt_local_entry->common.addr, message); 872 tt_local_entry->common.addr,
873 BATADV_PRINT_VID(tt_local_entry->common.vid), message);
547} 874}
548 875
549/** 876/**
550 * batadv_tt_local_remove - logically remove an entry from the local table 877 * batadv_tt_local_remove - logically remove an entry from the local table
551 * @bat_priv: the bat priv with all the soft interface information 878 * @bat_priv: the bat priv with all the soft interface information
552 * @addr: the MAC address of the client to remove 879 * @addr: the MAC address of the client to remove
880 * @vid: VLAN identifier
553 * @message: message to append to the log on deletion 881 * @message: message to append to the log on deletion
554 * @roaming: true if the deletion is due to a roaming event 882 * @roaming: true if the deletion is due to a roaming event
555 * 883 *
556 * Returns the flags assigned to the local entry before being deleted 884 * Returns the flags assigned to the local entry before being deleted
557 */ 885 */
558uint16_t batadv_tt_local_remove(struct batadv_priv *bat_priv, 886uint16_t batadv_tt_local_remove(struct batadv_priv *bat_priv,
559 const uint8_t *addr, const char *message, 887 const uint8_t *addr, unsigned short vid,
560 bool roaming) 888 const char *message, bool roaming)
561{ 889{
562 struct batadv_tt_local_entry *tt_local_entry; 890 struct batadv_tt_local_entry *tt_local_entry;
563 uint16_t flags, curr_flags = BATADV_NO_FLAGS; 891 uint16_t flags, curr_flags = BATADV_NO_FLAGS;
564 892
565 tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr); 893 tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr, vid);
566 if (!tt_local_entry) 894 if (!tt_local_entry)
567 goto out; 895 goto out;
568 896
@@ -779,7 +1107,7 @@ batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global,
779 1107
780 INIT_HLIST_NODE(&orig_entry->list); 1108 INIT_HLIST_NODE(&orig_entry->list);
781 atomic_inc(&orig_node->refcount); 1109 atomic_inc(&orig_node->refcount);
782 atomic_inc(&orig_node->tt_size); 1110 batadv_tt_global_size_inc(orig_node, tt_global->common.vid);
783 orig_entry->orig_node = orig_node; 1111 orig_entry->orig_node = orig_node;
784 orig_entry->ttvn = ttvn; 1112 orig_entry->ttvn = ttvn;
785 atomic_set(&orig_entry->refcount, 2); 1113 atomic_set(&orig_entry->refcount, 2);
@@ -798,6 +1126,7 @@ out:
798 * @bat_priv: the bat priv with all the soft interface information 1126 * @bat_priv: the bat priv with all the soft interface information
799 * @orig_node: the originator announcing the client 1127 * @orig_node: the originator announcing the client
800 * @tt_addr: the mac address of the non-mesh client 1128 * @tt_addr: the mac address of the non-mesh client
1129 * @vid: VLAN identifier
801 * @flags: TT flags that have to be set for this non-mesh client 1130 * @flags: TT flags that have to be set for this non-mesh client
802 * @ttvn: the tt version number ever announcing this non-mesh client 1131 * @ttvn: the tt version number ever announcing this non-mesh client
803 * 1132 *
@@ -813,7 +1142,8 @@ out:
813 */ 1142 */
814static bool batadv_tt_global_add(struct batadv_priv *bat_priv, 1143static bool batadv_tt_global_add(struct batadv_priv *bat_priv,
815 struct batadv_orig_node *orig_node, 1144 struct batadv_orig_node *orig_node,
816 const unsigned char *tt_addr, uint16_t flags, 1145 const unsigned char *tt_addr,
1146 unsigned short vid, uint16_t flags,
817 uint8_t ttvn) 1147 uint8_t ttvn)
818{ 1148{
819 struct batadv_tt_global_entry *tt_global_entry; 1149 struct batadv_tt_global_entry *tt_global_entry;
@@ -823,8 +1153,12 @@ static bool batadv_tt_global_add(struct batadv_priv *bat_priv,
823 struct batadv_tt_common_entry *common; 1153 struct batadv_tt_common_entry *common;
824 uint16_t local_flags; 1154 uint16_t local_flags;
825 1155
826 tt_global_entry = batadv_tt_global_hash_find(bat_priv, tt_addr); 1156 /* ignore global entries from backbone nodes */
827 tt_local_entry = batadv_tt_local_hash_find(bat_priv, tt_addr); 1157 if (batadv_bla_is_backbone_gw_orig(bat_priv, orig_node->orig, vid))
1158 return true;
1159
1160 tt_global_entry = batadv_tt_global_hash_find(bat_priv, tt_addr, vid);
1161 tt_local_entry = batadv_tt_local_hash_find(bat_priv, tt_addr, vid);
828 1162
829 /* if the node already has a local client for this entry, it has to wait 1163 /* if the node already has a local client for this entry, it has to wait
830 * for a roaming advertisement instead of manually messing up the global 1164 * for a roaming advertisement instead of manually messing up the global
@@ -841,6 +1175,7 @@ static bool batadv_tt_global_add(struct batadv_priv *bat_priv,
841 1175
842 common = &tt_global_entry->common; 1176 common = &tt_global_entry->common;
843 memcpy(common->addr, tt_addr, ETH_ALEN); 1177 memcpy(common->addr, tt_addr, ETH_ALEN);
1178 common->vid = vid;
844 1179
845 common->flags = flags; 1180 common->flags = flags;
846 tt_global_entry->roam_at = 0; 1181 tt_global_entry->roam_at = 0;
@@ -858,7 +1193,7 @@ static bool batadv_tt_global_add(struct batadv_priv *bat_priv,
858 1193
859 hash_added = batadv_hash_add(bat_priv->tt.global_hash, 1194 hash_added = batadv_hash_add(bat_priv->tt.global_hash,
860 batadv_compare_tt, 1195 batadv_compare_tt,
861 batadv_choose_orig, common, 1196 batadv_choose_tt, common,
862 &common->hash_entry); 1197 &common->hash_entry);
863 1198
864 if (unlikely(hash_added != 0)) { 1199 if (unlikely(hash_added != 0)) {
@@ -917,14 +1252,15 @@ add_orig_entry:
917 batadv_tt_global_orig_entry_add(tt_global_entry, orig_node, ttvn); 1252 batadv_tt_global_orig_entry_add(tt_global_entry, orig_node, ttvn);
918 1253
919 batadv_dbg(BATADV_DBG_TT, bat_priv, 1254 batadv_dbg(BATADV_DBG_TT, bat_priv,
920 "Creating new global tt entry: %pM (via %pM)\n", 1255 "Creating new global tt entry: %pM (vid: %d, via %pM)\n",
921 common->addr, orig_node->orig); 1256 common->addr, BATADV_PRINT_VID(common->vid),
1257 orig_node->orig);
922 ret = true; 1258 ret = true;
923 1259
924out_remove: 1260out_remove:
925 1261
926 /* remove address from local hash if present */ 1262 /* remove address from local hash if present */
927 local_flags = batadv_tt_local_remove(bat_priv, tt_addr, 1263 local_flags = batadv_tt_local_remove(bat_priv, tt_addr, vid,
928 "global tt received", 1264 "global tt received",
929 flags & BATADV_TT_CLIENT_ROAM); 1265 flags & BATADV_TT_CLIENT_ROAM);
930 tt_global_entry->common.flags |= local_flags & BATADV_TT_CLIENT_WIFI; 1266 tt_global_entry->common.flags |= local_flags & BATADV_TT_CLIENT_WIFI;
@@ -985,42 +1321,71 @@ static void
985batadv_tt_global_print_entry(struct batadv_tt_global_entry *tt_global_entry, 1321batadv_tt_global_print_entry(struct batadv_tt_global_entry *tt_global_entry,
986 struct seq_file *seq) 1322 struct seq_file *seq)
987{ 1323{
988 struct hlist_head *head;
989 struct batadv_tt_orig_list_entry *orig_entry, *best_entry; 1324 struct batadv_tt_orig_list_entry *orig_entry, *best_entry;
990 struct batadv_tt_common_entry *tt_common_entry; 1325 struct batadv_tt_common_entry *tt_common_entry;
991 uint16_t flags; 1326 struct batadv_orig_node_vlan *vlan;
1327 struct hlist_head *head;
992 uint8_t last_ttvn; 1328 uint8_t last_ttvn;
1329 uint16_t flags;
993 1330
994 tt_common_entry = &tt_global_entry->common; 1331 tt_common_entry = &tt_global_entry->common;
995 flags = tt_common_entry->flags; 1332 flags = tt_common_entry->flags;
996 1333
997 best_entry = batadv_transtable_best_orig(tt_global_entry); 1334 best_entry = batadv_transtable_best_orig(tt_global_entry);
998 if (best_entry) { 1335 if (best_entry) {
1336 vlan = batadv_orig_node_vlan_get(best_entry->orig_node,
1337 tt_common_entry->vid);
1338 if (!vlan) {
1339 seq_printf(seq,
1340 " * Cannot retrieve VLAN %d for originator %pM\n",
1341 BATADV_PRINT_VID(tt_common_entry->vid),
1342 best_entry->orig_node->orig);
1343 goto print_list;
1344 }
1345
999 last_ttvn = atomic_read(&best_entry->orig_node->last_ttvn); 1346 last_ttvn = atomic_read(&best_entry->orig_node->last_ttvn);
1000 seq_printf(seq, 1347 seq_printf(seq,
1001 " %c %pM (%3u) via %pM (%3u) (%#.8x) [%c%c%c]\n", 1348 " %c %pM %4i (%3u) via %pM (%3u) (%#.8x) [%c%c%c]\n",
1002 '*', tt_global_entry->common.addr, 1349 '*', tt_global_entry->common.addr,
1350 BATADV_PRINT_VID(tt_global_entry->common.vid),
1003 best_entry->ttvn, best_entry->orig_node->orig, 1351 best_entry->ttvn, best_entry->orig_node->orig,
1004 last_ttvn, best_entry->orig_node->tt_crc, 1352 last_ttvn, vlan->tt.crc,
1005 (flags & BATADV_TT_CLIENT_ROAM ? 'R' : '.'), 1353 (flags & BATADV_TT_CLIENT_ROAM ? 'R' : '.'),
1006 (flags & BATADV_TT_CLIENT_WIFI ? 'W' : '.'), 1354 (flags & BATADV_TT_CLIENT_WIFI ? 'W' : '.'),
1007 (flags & BATADV_TT_CLIENT_TEMP ? 'T' : '.')); 1355 (flags & BATADV_TT_CLIENT_TEMP ? 'T' : '.'));
1356
1357 batadv_orig_node_vlan_free_ref(vlan);
1008 } 1358 }
1009 1359
1360print_list:
1010 head = &tt_global_entry->orig_list; 1361 head = &tt_global_entry->orig_list;
1011 1362
1012 hlist_for_each_entry_rcu(orig_entry, head, list) { 1363 hlist_for_each_entry_rcu(orig_entry, head, list) {
1013 if (best_entry == orig_entry) 1364 if (best_entry == orig_entry)
1014 continue; 1365 continue;
1015 1366
1367 vlan = batadv_orig_node_vlan_get(orig_entry->orig_node,
1368 tt_common_entry->vid);
1369 if (!vlan) {
1370 seq_printf(seq,
1371 " + Cannot retrieve VLAN %d for originator %pM\n",
1372 BATADV_PRINT_VID(tt_common_entry->vid),
1373 orig_entry->orig_node->orig);
1374 continue;
1375 }
1376
1016 last_ttvn = atomic_read(&orig_entry->orig_node->last_ttvn); 1377 last_ttvn = atomic_read(&orig_entry->orig_node->last_ttvn);
1017 seq_printf(seq, " %c %pM (%3u) via %pM (%3u) [%c%c%c]\n", 1378 seq_printf(seq,
1379 " %c %pM %4d (%3u) via %pM (%3u) (%#.8x) [%c%c%c]\n",
1018 '+', tt_global_entry->common.addr, 1380 '+', tt_global_entry->common.addr,
1381 BATADV_PRINT_VID(tt_global_entry->common.vid),
1019 orig_entry->ttvn, orig_entry->orig_node->orig, 1382 orig_entry->ttvn, orig_entry->orig_node->orig,
1020 last_ttvn, 1383 last_ttvn, vlan->tt.crc,
1021 (flags & BATADV_TT_CLIENT_ROAM ? 'R' : '.'), 1384 (flags & BATADV_TT_CLIENT_ROAM ? 'R' : '.'),
1022 (flags & BATADV_TT_CLIENT_WIFI ? 'W' : '.'), 1385 (flags & BATADV_TT_CLIENT_WIFI ? 'W' : '.'),
1023 (flags & BATADV_TT_CLIENT_TEMP ? 'T' : '.')); 1386 (flags & BATADV_TT_CLIENT_TEMP ? 'T' : '.'));
1387
1388 batadv_orig_node_vlan_free_ref(vlan);
1024 } 1389 }
1025} 1390}
1026 1391
@@ -1042,9 +1407,9 @@ int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset)
1042 seq_printf(seq, 1407 seq_printf(seq,
1043 "Globally announced TT entries received via the mesh %s\n", 1408 "Globally announced TT entries received via the mesh %s\n",
1044 net_dev->name); 1409 net_dev->name);
1045 seq_printf(seq, " %-13s %s %-15s %s (%-10s) %s\n", 1410 seq_printf(seq, " %-13s %s %s %-15s %s (%-10s) %s\n",
1046 "Client", "(TTVN)", "Originator", "(Curr TTVN)", "CRC", 1411 "Client", "VID", "(TTVN)", "Originator", "(Curr TTVN)",
1047 "Flags"); 1412 "CRC", "Flags");
1048 1413
1049 for (i = 0; i < hash->size; i++) { 1414 for (i = 0; i < hash->size; i++) {
1050 head = &hash->table[i]; 1415 head = &hash->table[i];
@@ -1077,6 +1442,8 @@ batadv_tt_global_del_orig_list(struct batadv_tt_global_entry *tt_global_entry)
1077 head = &tt_global_entry->orig_list; 1442 head = &tt_global_entry->orig_list;
1078 hlist_for_each_entry_safe(orig_entry, safe, head, list) { 1443 hlist_for_each_entry_safe(orig_entry, safe, head, list) {
1079 hlist_del_rcu(&orig_entry->list); 1444 hlist_del_rcu(&orig_entry->list);
1445 batadv_tt_global_size_dec(orig_entry->orig_node,
1446 tt_global_entry->common.vid);
1080 batadv_tt_orig_list_entry_free_ref(orig_entry); 1447 batadv_tt_orig_list_entry_free_ref(orig_entry);
1081 } 1448 }
1082 spin_unlock_bh(&tt_global_entry->list_lock); 1449 spin_unlock_bh(&tt_global_entry->list_lock);
@@ -1091,16 +1458,21 @@ batadv_tt_global_del_orig_entry(struct batadv_priv *bat_priv,
1091 struct hlist_head *head; 1458 struct hlist_head *head;
1092 struct hlist_node *safe; 1459 struct hlist_node *safe;
1093 struct batadv_tt_orig_list_entry *orig_entry; 1460 struct batadv_tt_orig_list_entry *orig_entry;
1461 unsigned short vid;
1094 1462
1095 spin_lock_bh(&tt_global_entry->list_lock); 1463 spin_lock_bh(&tt_global_entry->list_lock);
1096 head = &tt_global_entry->orig_list; 1464 head = &tt_global_entry->orig_list;
1097 hlist_for_each_entry_safe(orig_entry, safe, head, list) { 1465 hlist_for_each_entry_safe(orig_entry, safe, head, list) {
1098 if (orig_entry->orig_node == orig_node) { 1466 if (orig_entry->orig_node == orig_node) {
1467 vid = tt_global_entry->common.vid;
1099 batadv_dbg(BATADV_DBG_TT, bat_priv, 1468 batadv_dbg(BATADV_DBG_TT, bat_priv,
1100 "Deleting %pM from global tt entry %pM: %s\n", 1469 "Deleting %pM from global tt entry %pM (vid: %d): %s\n",
1101 orig_node->orig, 1470 orig_node->orig,
1102 tt_global_entry->common.addr, message); 1471 tt_global_entry->common.addr,
1472 BATADV_PRINT_VID(vid), message);
1103 hlist_del_rcu(&orig_entry->list); 1473 hlist_del_rcu(&orig_entry->list);
1474 batadv_tt_global_size_dec(orig_node,
1475 tt_global_entry->common.vid);
1104 batadv_tt_orig_list_entry_free_ref(orig_entry); 1476 batadv_tt_orig_list_entry_free_ref(orig_entry);
1105 } 1477 }
1106 } 1478 }
@@ -1147,17 +1519,25 @@ batadv_tt_global_del_roaming(struct batadv_priv *bat_priv,
1147 orig_node, message); 1519 orig_node, message);
1148} 1520}
1149 1521
1150 1522/**
1151 1523 * batadv_tt_global_del - remove a client from the global table
1524 * @bat_priv: the bat priv with all the soft interface information
1525 * @orig_node: an originator serving this client
1526 * @addr: the mac address of the client
1527 * @vid: VLAN identifier
1528 * @message: a message explaining the reason for deleting the client to print
1529 * for debugging purpose
1530 * @roaming: true if the deletion has been triggered by a roaming event
1531 */
1152static void batadv_tt_global_del(struct batadv_priv *bat_priv, 1532static void batadv_tt_global_del(struct batadv_priv *bat_priv,
1153 struct batadv_orig_node *orig_node, 1533 struct batadv_orig_node *orig_node,
1154 const unsigned char *addr, 1534 const unsigned char *addr, unsigned short vid,
1155 const char *message, bool roaming) 1535 const char *message, bool roaming)
1156{ 1536{
1157 struct batadv_tt_global_entry *tt_global_entry; 1537 struct batadv_tt_global_entry *tt_global_entry;
1158 struct batadv_tt_local_entry *local_entry = NULL; 1538 struct batadv_tt_local_entry *local_entry = NULL;
1159 1539
1160 tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr); 1540 tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr, vid);
1161 if (!tt_global_entry) 1541 if (!tt_global_entry)
1162 goto out; 1542 goto out;
1163 1543
@@ -1186,7 +1566,8 @@ static void batadv_tt_global_del(struct batadv_priv *bat_priv,
1186 * the global entry, since it is useless now. 1566 * the global entry, since it is useless now.
1187 */ 1567 */
1188 local_entry = batadv_tt_local_hash_find(bat_priv, 1568 local_entry = batadv_tt_local_hash_find(bat_priv,
1189 tt_global_entry->common.addr); 1569 tt_global_entry->common.addr,
1570 vid);
1190 if (local_entry) { 1571 if (local_entry) {
1191 /* local entry exists, case 2: client roamed to us. */ 1572 /* local entry exists, case 2: client roamed to us. */
1192 batadv_tt_global_del_orig_list(tt_global_entry); 1573 batadv_tt_global_del_orig_list(tt_global_entry);
@@ -1204,8 +1585,18 @@ out:
1204 batadv_tt_local_entry_free_ref(local_entry); 1585 batadv_tt_local_entry_free_ref(local_entry);
1205} 1586}
1206 1587
1588/**
1589 * batadv_tt_global_del_orig - remove all the TT global entries belonging to the
1590 * given originator matching the provided vid
1591 * @bat_priv: the bat priv with all the soft interface information
1592 * @orig_node: the originator owning the entries to remove
1593 * @match_vid: the VLAN identifier to match. If negative all the entries will be
1594 * removed
1595 * @message: debug message to print as "reason"
1596 */
1207void batadv_tt_global_del_orig(struct batadv_priv *bat_priv, 1597void batadv_tt_global_del_orig(struct batadv_priv *bat_priv,
1208 struct batadv_orig_node *orig_node, 1598 struct batadv_orig_node *orig_node,
1599 int32_t match_vid,
1209 const char *message) 1600 const char *message)
1210{ 1601{
1211 struct batadv_tt_global_entry *tt_global; 1602 struct batadv_tt_global_entry *tt_global;
@@ -1215,6 +1606,7 @@ void batadv_tt_global_del_orig(struct batadv_priv *bat_priv,
1215 struct hlist_node *safe; 1606 struct hlist_node *safe;
1216 struct hlist_head *head; 1607 struct hlist_head *head;
1217 spinlock_t *list_lock; /* protects write access to the hash lists */ 1608 spinlock_t *list_lock; /* protects write access to the hash lists */
1609 unsigned short vid;
1218 1610
1219 if (!hash) 1611 if (!hash)
1220 return; 1612 return;
@@ -1226,6 +1618,10 @@ void batadv_tt_global_del_orig(struct batadv_priv *bat_priv,
1226 spin_lock_bh(list_lock); 1618 spin_lock_bh(list_lock);
1227 hlist_for_each_entry_safe(tt_common_entry, safe, 1619 hlist_for_each_entry_safe(tt_common_entry, safe,
1228 head, hash_entry) { 1620 head, hash_entry) {
1621 /* remove only matching entries */
1622 if (match_vid >= 0 && tt_common_entry->vid != match_vid)
1623 continue;
1624
1229 tt_global = container_of(tt_common_entry, 1625 tt_global = container_of(tt_common_entry,
1230 struct batadv_tt_global_entry, 1626 struct batadv_tt_global_entry,
1231 common); 1627 common);
@@ -1234,9 +1630,11 @@ void batadv_tt_global_del_orig(struct batadv_priv *bat_priv,
1234 orig_node, message); 1630 orig_node, message);
1235 1631
1236 if (hlist_empty(&tt_global->orig_list)) { 1632 if (hlist_empty(&tt_global->orig_list)) {
1633 vid = tt_global->common.vid;
1237 batadv_dbg(BATADV_DBG_TT, bat_priv, 1634 batadv_dbg(BATADV_DBG_TT, bat_priv,
1238 "Deleting global tt entry %pM: %s\n", 1635 "Deleting global tt entry %pM (vid: %d): %s\n",
1239 tt_global->common.addr, message); 1636 tt_global->common.addr,
1637 BATADV_PRINT_VID(vid), message);
1240 hlist_del_rcu(&tt_common_entry->hash_entry); 1638 hlist_del_rcu(&tt_common_entry->hash_entry);
1241 batadv_tt_global_entry_free_ref(tt_global); 1639 batadv_tt_global_entry_free_ref(tt_global);
1242 } 1640 }
@@ -1294,8 +1692,10 @@ static void batadv_tt_global_purge(struct batadv_priv *bat_priv)
1294 continue; 1692 continue;
1295 1693
1296 batadv_dbg(BATADV_DBG_TT, bat_priv, 1694 batadv_dbg(BATADV_DBG_TT, bat_priv,
1297 "Deleting global tt entry (%pM): %s\n", 1695 "Deleting global tt entry %pM (vid: %d): %s\n",
1298 tt_global->common.addr, msg); 1696 tt_global->common.addr,
1697 BATADV_PRINT_VID(tt_global->common.vid),
1698 msg);
1299 1699
1300 hlist_del_rcu(&tt_common->hash_entry); 1700 hlist_del_rcu(&tt_common->hash_entry);
1301 1701
@@ -1354,23 +1754,49 @@ _batadv_is_ap_isolated(struct batadv_tt_local_entry *tt_local_entry,
1354 return ret; 1754 return ret;
1355} 1755}
1356 1756
1757/**
1758 * batadv_transtable_search - get the mesh destination for a given client
1759 * @bat_priv: the bat priv with all the soft interface information
1760 * @src: mac address of the source client
1761 * @addr: mac address of the destination client
1762 * @vid: VLAN identifier
1763 *
1764 * Returns a pointer to the originator that was selected as destination in the
1765 * mesh for contacting the client 'addr', NULL otherwise.
1766 * In case of multiple originators serving the same client, the function returns
1767 * the best one (best in terms of metric towards the destination node).
1768 *
1769 * If the two clients are AP isolated the function returns NULL.
1770 */
1357struct batadv_orig_node *batadv_transtable_search(struct batadv_priv *bat_priv, 1771struct batadv_orig_node *batadv_transtable_search(struct batadv_priv *bat_priv,
1358 const uint8_t *src, 1772 const uint8_t *src,
1359 const uint8_t *addr) 1773 const uint8_t *addr,
1774 unsigned short vid)
1360{ 1775{
1361 struct batadv_tt_local_entry *tt_local_entry = NULL; 1776 struct batadv_tt_local_entry *tt_local_entry = NULL;
1362 struct batadv_tt_global_entry *tt_global_entry = NULL; 1777 struct batadv_tt_global_entry *tt_global_entry = NULL;
1363 struct batadv_orig_node *orig_node = NULL; 1778 struct batadv_orig_node *orig_node = NULL;
1364 struct batadv_tt_orig_list_entry *best_entry; 1779 struct batadv_tt_orig_list_entry *best_entry;
1780 bool ap_isolation_enabled = false;
1781 struct batadv_softif_vlan *vlan;
1782
1783 /* if the AP isolation is requested on a VLAN, then check for its
1784 * setting in the proper VLAN private data structure
1785 */
1786 vlan = batadv_softif_vlan_get(bat_priv, vid);
1787 if (vlan) {
1788 ap_isolation_enabled = atomic_read(&vlan->ap_isolation);
1789 batadv_softif_vlan_free_ref(vlan);
1790 }
1365 1791
1366 if (src && atomic_read(&bat_priv->ap_isolation)) { 1792 if (src && ap_isolation_enabled) {
1367 tt_local_entry = batadv_tt_local_hash_find(bat_priv, src); 1793 tt_local_entry = batadv_tt_local_hash_find(bat_priv, src, vid);
1368 if (!tt_local_entry || 1794 if (!tt_local_entry ||
1369 (tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING)) 1795 (tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING))
1370 goto out; 1796 goto out;
1371 } 1797 }
1372 1798
1373 tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr); 1799 tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr, vid);
1374 if (!tt_global_entry) 1800 if (!tt_global_entry)
1375 goto out; 1801 goto out;
1376 1802
@@ -1403,15 +1829,35 @@ out:
1403 * batadv_tt_global_crc - calculates the checksum of the local table belonging 1829 * batadv_tt_global_crc - calculates the checksum of the local table belonging
1404 * to the given orig_node 1830 * to the given orig_node
1405 * @bat_priv: the bat priv with all the soft interface information 1831 * @bat_priv: the bat priv with all the soft interface information
1832 * @orig_node: originator for which the CRC should be computed
1833 * @vid: VLAN identifier for which the CRC32 has to be computed
1834 *
1835 * This function computes the checksum for the global table corresponding to a
1836 * specific originator. In particular, the checksum is computed as follows: For
1837 * each client connected to the originator the CRC32C of the MAC address and the
1838 * VID is computed and then all the CRC32Cs of the various clients are xor'ed
1839 * together.
1840 *
1841 * The idea behind is that CRC32C should be used as much as possible in order to
1842 * produce a unique hash of the table, but since the order which is used to feed
1843 * the CRC32C function affects the result and since every node in the network
1844 * probably sorts the clients differently, the hash function cannot be directly
1845 * computed over the entire table. Hence the CRC32C is used only on
1846 * the single client entry, while all the results are then xor'ed together
1847 * because the XOR operation can combine them all while trying to reduce the
1848 * noise as much as possible.
1849 *
1850 * Returns the checksum of the global table of a given originator.
1406 */ 1851 */
1407static uint32_t batadv_tt_global_crc(struct batadv_priv *bat_priv, 1852static uint32_t batadv_tt_global_crc(struct batadv_priv *bat_priv,
1408 struct batadv_orig_node *orig_node) 1853 struct batadv_orig_node *orig_node,
1854 unsigned short vid)
1409{ 1855{
1410 struct batadv_hashtable *hash = bat_priv->tt.global_hash; 1856 struct batadv_hashtable *hash = bat_priv->tt.global_hash;
1411 struct batadv_tt_common_entry *tt_common; 1857 struct batadv_tt_common_entry *tt_common;
1412 struct batadv_tt_global_entry *tt_global; 1858 struct batadv_tt_global_entry *tt_global;
1413 struct hlist_head *head; 1859 struct hlist_head *head;
1414 uint32_t i, crc = 0; 1860 uint32_t i, crc_tmp, crc = 0;
1415 1861
1416 for (i = 0; i < hash->size; i++) { 1862 for (i = 0; i < hash->size; i++) {
1417 head = &hash->table[i]; 1863 head = &hash->table[i];
@@ -1421,6 +1867,12 @@ static uint32_t batadv_tt_global_crc(struct batadv_priv *bat_priv,
1421 tt_global = container_of(tt_common, 1867 tt_global = container_of(tt_common,
1422 struct batadv_tt_global_entry, 1868 struct batadv_tt_global_entry,
1423 common); 1869 common);
1870 /* compute the CRC only for entries belonging to the
1871 * VLAN identified by the vid passed as parameter
1872 */
1873 if (tt_common->vid != vid)
1874 continue;
1875
1424 /* Roaming clients are in the global table for 1876 /* Roaming clients are in the global table for
1425 * consistency only. They don't have to be 1877 * consistency only. They don't have to be
1426 * taken into account while computing the 1878 * taken into account while computing the
@@ -1442,7 +1894,9 @@ static uint32_t batadv_tt_global_crc(struct batadv_priv *bat_priv,
1442 orig_node)) 1894 orig_node))
1443 continue; 1895 continue;
1444 1896
1445 crc ^= crc32c(0, tt_common->addr, ETH_ALEN); 1897 crc_tmp = crc32c(0, &tt_common->vid,
1898 sizeof(tt_common->vid));
1899 crc ^= crc32c(crc_tmp, tt_common->addr, ETH_ALEN);
1446 } 1900 }
1447 rcu_read_unlock(); 1901 rcu_read_unlock();
1448 } 1902 }
@@ -1453,26 +1907,41 @@ static uint32_t batadv_tt_global_crc(struct batadv_priv *bat_priv,
1453/** 1907/**
1454 * batadv_tt_local_crc - calculates the checksum of the local table 1908 * batadv_tt_local_crc - calculates the checksum of the local table
1455 * @bat_priv: the bat priv with all the soft interface information 1909 * @bat_priv: the bat priv with all the soft interface information
1910 * @vid: VLAN identifier for which the CRC32 has to be computed
1911 *
1912 * For details about the computation, please refer to the documentation for
1913 * batadv_tt_global_crc().
1914 *
1915 * Returns the checksum of the local table
1456 */ 1916 */
1457static uint32_t batadv_tt_local_crc(struct batadv_priv *bat_priv) 1917static uint32_t batadv_tt_local_crc(struct batadv_priv *bat_priv,
1918 unsigned short vid)
1458{ 1919{
1459 struct batadv_hashtable *hash = bat_priv->tt.local_hash; 1920 struct batadv_hashtable *hash = bat_priv->tt.local_hash;
1460 struct batadv_tt_common_entry *tt_common; 1921 struct batadv_tt_common_entry *tt_common;
1461 struct hlist_head *head; 1922 struct hlist_head *head;
1462 uint32_t i, crc = 0; 1923 uint32_t i, crc_tmp, crc = 0;
1463 1924
1464 for (i = 0; i < hash->size; i++) { 1925 for (i = 0; i < hash->size; i++) {
1465 head = &hash->table[i]; 1926 head = &hash->table[i];
1466 1927
1467 rcu_read_lock(); 1928 rcu_read_lock();
1468 hlist_for_each_entry_rcu(tt_common, head, hash_entry) { 1929 hlist_for_each_entry_rcu(tt_common, head, hash_entry) {
1930 /* compute the CRC only for entries belonging to the
1931 * VLAN identified by vid
1932 */
1933 if (tt_common->vid != vid)
1934 continue;
1935
1469 /* not yet committed clients have not to be taken into 1936 /* not yet committed clients have not to be taken into
1470 * account while computing the CRC 1937 * account while computing the CRC
1471 */ 1938 */
1472 if (tt_common->flags & BATADV_TT_CLIENT_NEW) 1939 if (tt_common->flags & BATADV_TT_CLIENT_NEW)
1473 continue; 1940 continue;
1474 1941
1475 crc ^= crc32c(0, tt_common->addr, ETH_ALEN); 1942 crc_tmp = crc32c(0, &tt_common->vid,
1943 sizeof(tt_common->vid));
1944 crc ^= crc32c(crc_tmp, tt_common->addr, ETH_ALEN);
1476 } 1945 }
1477 rcu_read_unlock(); 1946 rcu_read_unlock();
1478 } 1947 }
@@ -1595,44 +2064,29 @@ static int batadv_tt_global_valid(const void *entry_ptr,
1595} 2064}
1596 2065
1597/** 2066/**
1598 * batadv_tt_tvlv_generate - creates tvlv tt data buffer to fill it with the 2067 * batadv_tt_tvlv_generate - fill the tvlv buff with the tt entries from the
1599 * tt entries from the specified tt hash 2068 * specified tt hash
1600 * @bat_priv: the bat priv with all the soft interface information 2069 * @bat_priv: the bat priv with all the soft interface information
1601 * @hash: hash table containing the tt entries 2070 * @hash: hash table containing the tt entries
1602 * @tt_len: expected tvlv tt data buffer length in number of bytes 2071 * @tt_len: expected tvlv tt data buffer length in number of bytes
2072 * @tvlv_buff: pointer to the buffer to fill with the TT data
1603 * @valid_cb: function to filter tt change entries 2073 * @valid_cb: function to filter tt change entries
1604 * @cb_data: data passed to the filter function as argument 2074 * @cb_data: data passed to the filter function as argument
1605 *
1606 * Returns pointer to allocated tvlv tt data buffer if operation was
1607 * successful or NULL otherwise.
1608 */ 2075 */
1609static struct batadv_tvlv_tt_data * 2076static void batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
1610batadv_tt_tvlv_generate(struct batadv_priv *bat_priv, 2077 struct batadv_hashtable *hash,
1611 struct batadv_hashtable *hash, uint16_t tt_len, 2078 void *tvlv_buff, uint16_t tt_len,
1612 int (*valid_cb)(const void *, const void *), 2079 int (*valid_cb)(const void *, const void *),
1613 void *cb_data) 2080 void *cb_data)
1614{ 2081{
1615 struct batadv_tt_common_entry *tt_common_entry; 2082 struct batadv_tt_common_entry *tt_common_entry;
1616 struct batadv_tvlv_tt_data *tvlv_tt_data = NULL;
1617 struct batadv_tvlv_tt_change *tt_change; 2083 struct batadv_tvlv_tt_change *tt_change;
1618 struct hlist_head *head; 2084 struct hlist_head *head;
1619 uint16_t tt_tot, tt_num_entries = 0; 2085 uint16_t tt_tot, tt_num_entries = 0;
1620 ssize_t tvlv_tt_size = sizeof(struct batadv_tvlv_tt_data);
1621 uint32_t i; 2086 uint32_t i;
1622 2087
1623 if (tvlv_tt_size + tt_len > bat_priv->soft_iface->mtu) {
1624 tt_len = bat_priv->soft_iface->mtu - tvlv_tt_size;
1625 tt_len -= tt_len % sizeof(struct batadv_tvlv_tt_change);
1626 }
1627
1628 tt_tot = batadv_tt_entries(tt_len); 2088 tt_tot = batadv_tt_entries(tt_len);
1629 2089 tt_change = (struct batadv_tvlv_tt_change *)tvlv_buff;
1630 tvlv_tt_data = kzalloc(sizeof(*tvlv_tt_data) + tt_len,
1631 GFP_ATOMIC);
1632 if (!tvlv_tt_data)
1633 goto out;
1634
1635 tt_change = (struct batadv_tvlv_tt_change *)(tvlv_tt_data + 1);
1636 2090
1637 rcu_read_lock(); 2091 rcu_read_lock();
1638 for (i = 0; i < hash->size; i++) { 2092 for (i = 0; i < hash->size; i++) {
@@ -1649,6 +2103,7 @@ batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
1649 memcpy(tt_change->addr, tt_common_entry->addr, 2103 memcpy(tt_change->addr, tt_common_entry->addr,
1650 ETH_ALEN); 2104 ETH_ALEN);
1651 tt_change->flags = tt_common_entry->flags; 2105 tt_change->flags = tt_common_entry->flags;
2106 tt_change->vid = htons(tt_common_entry->vid);
1652 tt_change->reserved = 0; 2107 tt_change->reserved = 0;
1653 2108
1654 tt_num_entries++; 2109 tt_num_entries++;
@@ -1656,9 +2111,91 @@ batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
1656 } 2111 }
1657 } 2112 }
1658 rcu_read_unlock(); 2113 rcu_read_unlock();
2114}
1659 2115
1660out: 2116/**
1661 return tvlv_tt_data; 2117 * batadv_tt_global_check_crc - check if all the CRCs are correct
2118 * @orig_node: originator for which the CRCs have to be checked
2119 * @tt_vlan: pointer to the first tvlv VLAN entry
2120 * @num_vlan: number of tvlv VLAN entries
2121 * @create: if true, create VLAN objects if not found
2122 *
2123 * Return true if all the received CRCs match the locally stored ones, false
2124 * otherwise
2125 */
2126static bool batadv_tt_global_check_crc(struct batadv_orig_node *orig_node,
2127 struct batadv_tvlv_tt_vlan_data *tt_vlan,
2128 uint16_t num_vlan)
2129{
2130 struct batadv_tvlv_tt_vlan_data *tt_vlan_tmp;
2131 struct batadv_orig_node_vlan *vlan;
2132 int i;
2133
2134 /* check if each received CRC matches the locally stored one */
2135 for (i = 0; i < num_vlan; i++) {
2136 tt_vlan_tmp = tt_vlan + i;
2137
2138 /* if orig_node is a backbone node for this VLAN, don't check
2139 * the CRC as we ignore all the global entries over it
2140 */
2141 if (batadv_bla_is_backbone_gw_orig(orig_node->bat_priv,
2142 orig_node->orig,
2143 ntohs(tt_vlan_tmp->vid)))
2144 continue;
2145
2146 vlan = batadv_orig_node_vlan_get(orig_node,
2147 ntohs(tt_vlan_tmp->vid));
2148 if (!vlan)
2149 return false;
2150
2151 if (vlan->tt.crc != ntohl(tt_vlan_tmp->crc))
2152 return false;
2153 }
2154
2155 return true;
2156}
2157
2158/**
2159 * batadv_tt_local_update_crc - update all the local CRCs
2160 * @bat_priv: the bat priv with all the soft interface information
2161 */
2162static void batadv_tt_local_update_crc(struct batadv_priv *bat_priv)
2163{
2164 struct batadv_softif_vlan *vlan;
2165
2166 /* recompute the global CRC for each VLAN */
2167 rcu_read_lock();
2168 hlist_for_each_entry_rcu(vlan, &bat_priv->softif_vlan_list, list) {
2169 vlan->tt.crc = batadv_tt_local_crc(bat_priv, vlan->vid);
2170 }
2171 rcu_read_unlock();
2172}
2173
2174/**
2175 * batadv_tt_global_update_crc - update all the global CRCs for this orig_node
2176 * @bat_priv: the bat priv with all the soft interface information
2177 * @orig_node: the orig_node for which the CRCs have to be updated
2178 */
2179static void batadv_tt_global_update_crc(struct batadv_priv *bat_priv,
2180 struct batadv_orig_node *orig_node)
2181{
2182 struct batadv_orig_node_vlan *vlan;
2183 uint32_t crc;
2184
2185 /* recompute the global CRC for each VLAN */
2186 rcu_read_lock();
2187 list_for_each_entry_rcu(vlan, &orig_node->vlan_list, list) {
2188 /* if orig_node is a backbone node for this VLAN, don't compute
2189 * the CRC as we ignore all the global entries over it
2190 */
2191 if (batadv_bla_is_backbone_gw_orig(bat_priv, orig_node->orig,
2192 vlan->vid))
2193 continue;
2194
2195 crc = batadv_tt_global_crc(bat_priv, orig_node, vlan->vid);
2196 vlan->tt.crc = crc;
2197 }
2198 rcu_read_unlock();
1662} 2199}
1663 2200
1664/** 2201/**
@@ -1666,19 +2203,23 @@ out:
1666 * @bat_priv: the bat priv with all the soft interface information 2203 * @bat_priv: the bat priv with all the soft interface information
1667 * @dst_orig_node: the destination of the message 2204 * @dst_orig_node: the destination of the message
1668 * @ttvn: the version number that the source of the message is looking for 2205 * @ttvn: the version number that the source of the message is looking for
1669 * @tt_crc: the CRC associated with the version number 2206 * @tt_vlan: pointer to the first tvlv VLAN object to request
2207 * @num_vlan: number of tvlv VLAN entries
1670 * @full_table: ask for the entire translation table if true, while only for the 2208 * @full_table: ask for the entire translation table if true, while only for the
1671 * last TT diff otherwise 2209 * last TT diff otherwise
1672 */ 2210 */
1673static int batadv_send_tt_request(struct batadv_priv *bat_priv, 2211static int batadv_send_tt_request(struct batadv_priv *bat_priv,
1674 struct batadv_orig_node *dst_orig_node, 2212 struct batadv_orig_node *dst_orig_node,
1675 uint8_t ttvn, uint32_t tt_crc, 2213 uint8_t ttvn,
1676 bool full_table) 2214 struct batadv_tvlv_tt_vlan_data *tt_vlan,
2215 uint16_t num_vlan, bool full_table)
1677{ 2216{
1678 struct batadv_tvlv_tt_data *tvlv_tt_data = NULL; 2217 struct batadv_tvlv_tt_data *tvlv_tt_data = NULL;
1679 struct batadv_hard_iface *primary_if;
1680 struct batadv_tt_req_node *tt_req_node = NULL; 2218 struct batadv_tt_req_node *tt_req_node = NULL;
2219 struct batadv_tvlv_tt_vlan_data *tt_vlan_req;
2220 struct batadv_hard_iface *primary_if;
1681 bool ret = false; 2221 bool ret = false;
2222 int i, size;
1682 2223
1683 primary_if = batadv_primary_if_get_selected(bat_priv); 2224 primary_if = batadv_primary_if_get_selected(bat_priv);
1684 if (!primary_if) 2225 if (!primary_if)
@@ -1691,13 +2232,26 @@ static int batadv_send_tt_request(struct batadv_priv *bat_priv,
1691 if (!tt_req_node) 2232 if (!tt_req_node)
1692 goto out; 2233 goto out;
1693 2234
1694 tvlv_tt_data = kzalloc(sizeof(*tvlv_tt_data), GFP_ATOMIC); 2235 size = sizeof(*tvlv_tt_data) + sizeof(*tt_vlan_req) * num_vlan;
2236 tvlv_tt_data = kzalloc(size, GFP_ATOMIC);
1695 if (!tvlv_tt_data) 2237 if (!tvlv_tt_data)
1696 goto out; 2238 goto out;
1697 2239
1698 tvlv_tt_data->flags = BATADV_TT_REQUEST; 2240 tvlv_tt_data->flags = BATADV_TT_REQUEST;
1699 tvlv_tt_data->ttvn = ttvn; 2241 tvlv_tt_data->ttvn = ttvn;
1700 tvlv_tt_data->crc = htonl(tt_crc); 2242 tvlv_tt_data->num_vlan = htons(num_vlan);
2243
2244 /* send all the CRCs within the request. This is needed by intermediate
2245 * nodes to ensure they have the correct table before replying
2246 */
2247 tt_vlan_req = (struct batadv_tvlv_tt_vlan_data *)(tvlv_tt_data + 1);
2248 for (i = 0; i < num_vlan; i++) {
2249 tt_vlan_req->vid = tt_vlan->vid;
2250 tt_vlan_req->crc = tt_vlan->crc;
2251
2252 tt_vlan_req++;
2253 tt_vlan++;
2254 }
1701 2255
1702 if (full_table) 2256 if (full_table)
1703 tvlv_tt_data->flags |= BATADV_TT_FULL_TABLE; 2257 tvlv_tt_data->flags |= BATADV_TT_FULL_TABLE;
@@ -1708,7 +2262,7 @@ static int batadv_send_tt_request(struct batadv_priv *bat_priv,
1708 batadv_inc_counter(bat_priv, BATADV_CNT_TT_REQUEST_TX); 2262 batadv_inc_counter(bat_priv, BATADV_CNT_TT_REQUEST_TX);
1709 batadv_tvlv_unicast_send(bat_priv, primary_if->net_dev->dev_addr, 2263 batadv_tvlv_unicast_send(bat_priv, primary_if->net_dev->dev_addr,
1710 dst_orig_node->orig, BATADV_TVLV_TT, 1, 2264 dst_orig_node->orig, BATADV_TVLV_TT, 1,
1711 tvlv_tt_data, sizeof(*tvlv_tt_data)); 2265 tvlv_tt_data, size);
1712 ret = true; 2266 ret = true;
1713 2267
1714out: 2268out:
@@ -1740,10 +2294,13 @@ static bool batadv_send_other_tt_response(struct batadv_priv *bat_priv,
1740{ 2294{
1741 struct batadv_orig_node *req_dst_orig_node; 2295 struct batadv_orig_node *req_dst_orig_node;
1742 struct batadv_orig_node *res_dst_orig_node = NULL; 2296 struct batadv_orig_node *res_dst_orig_node = NULL;
2297 struct batadv_tvlv_tt_change *tt_change;
1743 struct batadv_tvlv_tt_data *tvlv_tt_data = NULL; 2298 struct batadv_tvlv_tt_data *tvlv_tt_data = NULL;
1744 uint8_t orig_ttvn, req_ttvn; 2299 struct batadv_tvlv_tt_vlan_data *tt_vlan;
1745 uint16_t tt_len;
1746 bool ret = false, full_table; 2300 bool ret = false, full_table;
2301 uint8_t orig_ttvn, req_ttvn;
2302 uint16_t tvlv_len;
2303 int32_t tt_len;
1747 2304
1748 batadv_dbg(BATADV_DBG_TT, bat_priv, 2305 batadv_dbg(BATADV_DBG_TT, bat_priv,
1749 "Received TT_REQUEST from %pM for ttvn: %u (%pM) [%c]\n", 2306 "Received TT_REQUEST from %pM for ttvn: %u (%pM) [%c]\n",
@@ -1762,9 +2319,11 @@ static bool batadv_send_other_tt_response(struct batadv_priv *bat_priv,
1762 orig_ttvn = (uint8_t)atomic_read(&req_dst_orig_node->last_ttvn); 2319 orig_ttvn = (uint8_t)atomic_read(&req_dst_orig_node->last_ttvn);
1763 req_ttvn = tt_data->ttvn; 2320 req_ttvn = tt_data->ttvn;
1764 2321
2322 tt_vlan = (struct batadv_tvlv_tt_vlan_data *)(tt_data + 1);
1765 /* this node doesn't have the requested data */ 2323 /* this node doesn't have the requested data */
1766 if (orig_ttvn != req_ttvn || 2324 if (orig_ttvn != req_ttvn ||
1767 tt_data->crc != htonl(req_dst_orig_node->tt_crc)) 2325 !batadv_tt_global_check_crc(req_dst_orig_node, tt_vlan,
2326 ntohs(tt_data->num_vlan)))
1768 goto out; 2327 goto out;
1769 2328
1770 /* If the full table has been explicitly requested */ 2329 /* If the full table has been explicitly requested */
@@ -1781,26 +2340,34 @@ static bool batadv_send_other_tt_response(struct batadv_priv *bat_priv,
1781 spin_lock_bh(&req_dst_orig_node->tt_buff_lock); 2340 spin_lock_bh(&req_dst_orig_node->tt_buff_lock);
1782 tt_len = req_dst_orig_node->tt_buff_len; 2341 tt_len = req_dst_orig_node->tt_buff_len;
1783 2342
1784 tvlv_tt_data = kzalloc(sizeof(*tvlv_tt_data) + tt_len, 2343 tvlv_len = batadv_tt_prepare_tvlv_global_data(req_dst_orig_node,
1785 GFP_ATOMIC); 2344 &tvlv_tt_data,
1786 if (!tvlv_tt_data) 2345 &tt_change,
2346 &tt_len);
2347 if (!tt_len)
1787 goto unlock; 2348 goto unlock;
1788 2349
1789 /* Copy the last orig_node's OGM buffer */ 2350 /* Copy the last orig_node's OGM buffer */
1790 memcpy(tvlv_tt_data + 1, req_dst_orig_node->tt_buff, 2351 memcpy(tt_change, req_dst_orig_node->tt_buff,
1791 req_dst_orig_node->tt_buff_len); 2352 req_dst_orig_node->tt_buff_len);
1792 spin_unlock_bh(&req_dst_orig_node->tt_buff_lock); 2353 spin_unlock_bh(&req_dst_orig_node->tt_buff_lock);
1793 } else { 2354 } else {
1794 tt_len = (uint16_t)atomic_read(&req_dst_orig_node->tt_size); 2355 /* allocate the tvlv, put the tt_data and all the tt_vlan_data
1795 tt_len = batadv_tt_len(tt_len); 2356 * in the initial part
1796 2357 */
1797 tvlv_tt_data = batadv_tt_tvlv_generate(bat_priv, 2358 tt_len = -1;
1798 bat_priv->tt.global_hash, 2359 tvlv_len = batadv_tt_prepare_tvlv_global_data(req_dst_orig_node,
1799 tt_len, 2360 &tvlv_tt_data,
1800 batadv_tt_global_valid, 2361 &tt_change,
1801 req_dst_orig_node); 2362 &tt_len);
1802 if (!tvlv_tt_data) 2363 if (!tt_len)
1803 goto out; 2364 goto out;
2365
2366 /* fill the rest of the tvlv with the real TT entries */
2367 batadv_tt_tvlv_generate(bat_priv, bat_priv->tt.global_hash,
2368 tt_change, tt_len,
2369 batadv_tt_global_valid,
2370 req_dst_orig_node);
1804 } 2371 }
1805 2372
1806 tvlv_tt_data->flags = BATADV_TT_RESPONSE; 2373 tvlv_tt_data->flags = BATADV_TT_RESPONSE;
@@ -1817,8 +2384,8 @@ static bool batadv_send_other_tt_response(struct batadv_priv *bat_priv,
1817 batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX); 2384 batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX);
1818 2385
1819 batadv_tvlv_unicast_send(bat_priv, req_dst_orig_node->orig, 2386 batadv_tvlv_unicast_send(bat_priv, req_dst_orig_node->orig,
1820 req_src, BATADV_TVLV_TT, 1, 2387 req_src, BATADV_TVLV_TT, 1, tvlv_tt_data,
1821 tvlv_tt_data, sizeof(*tvlv_tt_data) + tt_len); 2388 tvlv_len);
1822 2389
1823 ret = true; 2390 ret = true;
1824 goto out; 2391 goto out;
@@ -1849,17 +2416,20 @@ static bool batadv_send_my_tt_response(struct batadv_priv *bat_priv,
1849 uint8_t *req_src) 2416 uint8_t *req_src)
1850{ 2417{
1851 struct batadv_tvlv_tt_data *tvlv_tt_data = NULL; 2418 struct batadv_tvlv_tt_data *tvlv_tt_data = NULL;
1852 struct batadv_orig_node *orig_node;
1853 struct batadv_hard_iface *primary_if = NULL; 2419 struct batadv_hard_iface *primary_if = NULL;
2420 struct batadv_tvlv_tt_change *tt_change;
2421 struct batadv_orig_node *orig_node;
1854 uint8_t my_ttvn, req_ttvn; 2422 uint8_t my_ttvn, req_ttvn;
2423 uint16_t tvlv_len;
1855 bool full_table; 2424 bool full_table;
1856 uint16_t tt_len; 2425 int32_t tt_len;
1857 2426
1858 batadv_dbg(BATADV_DBG_TT, bat_priv, 2427 batadv_dbg(BATADV_DBG_TT, bat_priv,
1859 "Received TT_REQUEST from %pM for ttvn: %u (me) [%c]\n", 2428 "Received TT_REQUEST from %pM for ttvn: %u (me) [%c]\n",
1860 req_src, tt_data->ttvn, 2429 req_src, tt_data->ttvn,
1861 (tt_data->flags & BATADV_TT_FULL_TABLE ? 'F' : '.')); 2430 (tt_data->flags & BATADV_TT_FULL_TABLE ? 'F' : '.'));
1862 2431
2432 spin_lock_bh(&bat_priv->tt.commit_lock);
1863 2433
1864 my_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn); 2434 my_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn);
1865 req_ttvn = tt_data->ttvn; 2435 req_ttvn = tt_data->ttvn;
@@ -1886,29 +2456,37 @@ static bool batadv_send_my_tt_response(struct batadv_priv *bat_priv,
1886 */ 2456 */
1887 if (!full_table) { 2457 if (!full_table) {
1888 spin_lock_bh(&bat_priv->tt.last_changeset_lock); 2458 spin_lock_bh(&bat_priv->tt.last_changeset_lock);
1889 tt_len = bat_priv->tt.last_changeset_len;
1890 2459
1891 tvlv_tt_data = kzalloc(sizeof(*tvlv_tt_data) + tt_len, 2460 tt_len = bat_priv->tt.last_changeset_len;
1892 GFP_ATOMIC); 2461 tvlv_len = batadv_tt_prepare_tvlv_local_data(bat_priv,
1893 if (!tvlv_tt_data) 2462 &tvlv_tt_data,
2463 &tt_change,
2464 &tt_len);
2465 if (!tt_len)
1894 goto unlock; 2466 goto unlock;
1895 2467
1896 /* Copy the last orig_node's OGM buffer */ 2468 /* Copy the last orig_node's OGM buffer */
1897 memcpy(tvlv_tt_data + 1, bat_priv->tt.last_changeset, 2469 memcpy(tt_change, bat_priv->tt.last_changeset,
1898 bat_priv->tt.last_changeset_len); 2470 bat_priv->tt.last_changeset_len);
1899 spin_unlock_bh(&bat_priv->tt.last_changeset_lock); 2471 spin_unlock_bh(&bat_priv->tt.last_changeset_lock);
1900 } else { 2472 } else {
1901 tt_len = (uint16_t)atomic_read(&bat_priv->tt.local_entry_num);
1902 tt_len = batadv_tt_len(tt_len);
1903 req_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn); 2473 req_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn);
1904 2474
1905 tvlv_tt_data = batadv_tt_tvlv_generate(bat_priv, 2475 /* allocate the tvlv, put the tt_data and all the tt_vlan_data
1906 bat_priv->tt.local_hash, 2476 * in the initial part
1907 tt_len, 2477 */
1908 batadv_tt_local_valid, 2478 tt_len = -1;
1909 NULL); 2479 tvlv_len = batadv_tt_prepare_tvlv_local_data(bat_priv,
1910 if (!tvlv_tt_data) 2480 &tvlv_tt_data,
2481 &tt_change,
2482 &tt_len);
2483 if (!tt_len)
1911 goto out; 2484 goto out;
2485
2486 /* fill the rest of the tvlv with the real TT entries */
2487 batadv_tt_tvlv_generate(bat_priv, bat_priv->tt.local_hash,
2488 tt_change, tt_len,
2489 batadv_tt_local_valid, NULL);
1912 } 2490 }
1913 2491
1914 tvlv_tt_data->flags = BATADV_TT_RESPONSE; 2492 tvlv_tt_data->flags = BATADV_TT_RESPONSE;
@@ -1924,14 +2502,15 @@ static bool batadv_send_my_tt_response(struct batadv_priv *bat_priv,
1924 batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX); 2502 batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX);
1925 2503
1926 batadv_tvlv_unicast_send(bat_priv, primary_if->net_dev->dev_addr, 2504 batadv_tvlv_unicast_send(bat_priv, primary_if->net_dev->dev_addr,
1927 req_src, BATADV_TVLV_TT, 1, 2505 req_src, BATADV_TVLV_TT, 1, tvlv_tt_data,
1928 tvlv_tt_data, sizeof(*tvlv_tt_data) + tt_len); 2506 tvlv_len);
1929 2507
1930 goto out; 2508 goto out;
1931 2509
1932unlock: 2510unlock:
1933 spin_unlock_bh(&bat_priv->tt.last_changeset_lock); 2511 spin_unlock_bh(&bat_priv->tt.last_changeset_lock);
1934out: 2512out:
2513 spin_unlock_bh(&bat_priv->tt.commit_lock);
1935 if (orig_node) 2514 if (orig_node)
1936 batadv_orig_node_free_ref(orig_node); 2515 batadv_orig_node_free_ref(orig_node);
1937 if (primary_if) 2516 if (primary_if)
@@ -1954,16 +2533,11 @@ static bool batadv_send_tt_response(struct batadv_priv *bat_priv,
1954 struct batadv_tvlv_tt_data *tt_data, 2533 struct batadv_tvlv_tt_data *tt_data,
1955 uint8_t *req_src, uint8_t *req_dst) 2534 uint8_t *req_src, uint8_t *req_dst)
1956{ 2535{
1957 if (batadv_is_my_mac(bat_priv, req_dst)) { 2536 if (batadv_is_my_mac(bat_priv, req_dst))
1958 /* don't answer backbone gws! */
1959 if (batadv_bla_is_backbone_gw_orig(bat_priv, req_src))
1960 return true;
1961
1962 return batadv_send_my_tt_response(bat_priv, tt_data, req_src); 2537 return batadv_send_my_tt_response(bat_priv, tt_data, req_src);
1963 } else { 2538 else
1964 return batadv_send_other_tt_response(bat_priv, tt_data, 2539 return batadv_send_other_tt_response(bat_priv, tt_data,
1965 req_src, req_dst); 2540 req_src, req_dst);
1966 }
1967} 2541}
1968 2542
1969static void _batadv_tt_update_changes(struct batadv_priv *bat_priv, 2543static void _batadv_tt_update_changes(struct batadv_priv *bat_priv,
@@ -1979,11 +2553,13 @@ static void _batadv_tt_update_changes(struct batadv_priv *bat_priv,
1979 roams = (tt_change + i)->flags & BATADV_TT_CLIENT_ROAM; 2553 roams = (tt_change + i)->flags & BATADV_TT_CLIENT_ROAM;
1980 batadv_tt_global_del(bat_priv, orig_node, 2554 batadv_tt_global_del(bat_priv, orig_node,
1981 (tt_change + i)->addr, 2555 (tt_change + i)->addr,
2556 ntohs((tt_change + i)->vid),
1982 "tt removed by changes", 2557 "tt removed by changes",
1983 roams); 2558 roams);
1984 } else { 2559 } else {
1985 if (!batadv_tt_global_add(bat_priv, orig_node, 2560 if (!batadv_tt_global_add(bat_priv, orig_node,
1986 (tt_change + i)->addr, 2561 (tt_change + i)->addr,
2562 ntohs((tt_change + i)->vid),
1987 (tt_change + i)->flags, ttvn)) 2563 (tt_change + i)->flags, ttvn))
1988 /* In case of problem while storing a 2564 /* In case of problem while storing a
1989 * global_entry, we stop the updating 2565 * global_entry, we stop the updating
@@ -1998,8 +2574,9 @@ static void _batadv_tt_update_changes(struct batadv_priv *bat_priv,
1998} 2574}
1999 2575
2000static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv, 2576static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv,
2001 struct batadv_tvlv_tt_data *tt_data, 2577 struct batadv_tvlv_tt_change *tt_change,
2002 uint8_t *resp_src, uint16_t num_entries) 2578 uint8_t ttvn, uint8_t *resp_src,
2579 uint16_t num_entries)
2003{ 2580{
2004 struct batadv_orig_node *orig_node; 2581 struct batadv_orig_node *orig_node;
2005 2582
@@ -2008,11 +2585,11 @@ static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv,
2008 goto out; 2585 goto out;
2009 2586
2010 /* Purge the old table first.. */ 2587 /* Purge the old table first.. */
2011 batadv_tt_global_del_orig(bat_priv, orig_node, "Received full table"); 2588 batadv_tt_global_del_orig(bat_priv, orig_node, -1,
2589 "Received full table");
2012 2590
2013 _batadv_tt_update_changes(bat_priv, orig_node, 2591 _batadv_tt_update_changes(bat_priv, orig_node, tt_change, num_entries,
2014 (struct batadv_tvlv_tt_change *)(tt_data + 1), 2592 ttvn);
2015 num_entries, tt_data->ttvn);
2016 2593
2017 spin_lock_bh(&orig_node->tt_buff_lock); 2594 spin_lock_bh(&orig_node->tt_buff_lock);
2018 kfree(orig_node->tt_buff); 2595 kfree(orig_node->tt_buff);
@@ -2020,7 +2597,7 @@ static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv,
2020 orig_node->tt_buff = NULL; 2597 orig_node->tt_buff = NULL;
2021 spin_unlock_bh(&orig_node->tt_buff_lock); 2598 spin_unlock_bh(&orig_node->tt_buff_lock);
2022 2599
2023 atomic_set(&orig_node->last_ttvn, tt_data->ttvn); 2600 atomic_set(&orig_node->last_ttvn, ttvn);
2024 2601
2025out: 2602out:
2026 if (orig_node) 2603 if (orig_node)
@@ -2040,12 +2617,21 @@ static void batadv_tt_update_changes(struct batadv_priv *bat_priv,
2040 atomic_set(&orig_node->last_ttvn, ttvn); 2617 atomic_set(&orig_node->last_ttvn, ttvn);
2041} 2618}
2042 2619
2043bool batadv_is_my_client(struct batadv_priv *bat_priv, const uint8_t *addr) 2620/**
2621 * batadv_is_my_client - check if a client is served by the local node
2622 * @bat_priv: the bat priv with all the soft interface information
2623 * @addr: the mac adress of the client to check
2624 * @vid: VLAN identifier
2625 *
2626 * Returns true if the client is served by this node, false otherwise.
2627 */
2628bool batadv_is_my_client(struct batadv_priv *bat_priv, const uint8_t *addr,
2629 unsigned short vid)
2044{ 2630{
2045 struct batadv_tt_local_entry *tt_local_entry; 2631 struct batadv_tt_local_entry *tt_local_entry;
2046 bool ret = false; 2632 bool ret = false;
2047 2633
2048 tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr); 2634 tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr, vid);
2049 if (!tt_local_entry) 2635 if (!tt_local_entry)
2050 goto out; 2636 goto out;
2051 /* Check if the client has been logically deleted (but is kept for 2637 /* Check if the client has been logically deleted (but is kept for
@@ -2075,28 +2661,39 @@ static void batadv_handle_tt_response(struct batadv_priv *bat_priv,
2075 struct batadv_tt_req_node *node, *safe; 2661 struct batadv_tt_req_node *node, *safe;
2076 struct batadv_orig_node *orig_node = NULL; 2662 struct batadv_orig_node *orig_node = NULL;
2077 struct batadv_tvlv_tt_change *tt_change; 2663 struct batadv_tvlv_tt_change *tt_change;
2664 uint8_t *tvlv_ptr = (uint8_t *)tt_data;
2665 uint16_t change_offset;
2078 2666
2079 batadv_dbg(BATADV_DBG_TT, bat_priv, 2667 batadv_dbg(BATADV_DBG_TT, bat_priv,
2080 "Received TT_RESPONSE from %pM for ttvn %d t_size: %d [%c]\n", 2668 "Received TT_RESPONSE from %pM for ttvn %d t_size: %d [%c]\n",
2081 resp_src, tt_data->ttvn, num_entries, 2669 resp_src, tt_data->ttvn, num_entries,
2082 (tt_data->flags & BATADV_TT_FULL_TABLE ? 'F' : '.')); 2670 (tt_data->flags & BATADV_TT_FULL_TABLE ? 'F' : '.'));
2083 2671
2084 /* we should have never asked a backbone gw */
2085 if (batadv_bla_is_backbone_gw_orig(bat_priv, resp_src))
2086 goto out;
2087
2088 orig_node = batadv_orig_hash_find(bat_priv, resp_src); 2672 orig_node = batadv_orig_hash_find(bat_priv, resp_src);
2089 if (!orig_node) 2673 if (!orig_node)
2090 goto out; 2674 goto out;
2091 2675
2676 spin_lock_bh(&orig_node->tt_lock);
2677
2678 change_offset = sizeof(struct batadv_tvlv_tt_vlan_data);
2679 change_offset *= ntohs(tt_data->num_vlan);
2680 change_offset += sizeof(*tt_data);
2681 tvlv_ptr += change_offset;
2682
2683 tt_change = (struct batadv_tvlv_tt_change *)tvlv_ptr;
2092 if (tt_data->flags & BATADV_TT_FULL_TABLE) { 2684 if (tt_data->flags & BATADV_TT_FULL_TABLE) {
2093 batadv_tt_fill_gtable(bat_priv, tt_data, resp_src, num_entries); 2685 batadv_tt_fill_gtable(bat_priv, tt_change, tt_data->ttvn,
2686 resp_src, num_entries);
2094 } else { 2687 } else {
2095 tt_change = (struct batadv_tvlv_tt_change *)(tt_data + 1);
2096 batadv_tt_update_changes(bat_priv, orig_node, num_entries, 2688 batadv_tt_update_changes(bat_priv, orig_node, num_entries,
2097 tt_data->ttvn, tt_change); 2689 tt_data->ttvn, tt_change);
2098 } 2690 }
2099 2691
2692 /* Recalculate the CRC for this orig_node and store it */
2693 batadv_tt_global_update_crc(bat_priv, orig_node);
2694
2695 spin_unlock_bh(&orig_node->tt_lock);
2696
2100 /* Delete the tt_req_node from pending tt_requests list */ 2697 /* Delete the tt_req_node from pending tt_requests list */
2101 spin_lock_bh(&bat_priv->tt.req_list_lock); 2698 spin_lock_bh(&bat_priv->tt.req_list_lock);
2102 list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) { 2699 list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) {
@@ -2105,10 +2702,8 @@ static void batadv_handle_tt_response(struct batadv_priv *bat_priv,
2105 list_del(&node->list); 2702 list_del(&node->list);
2106 kfree(node); 2703 kfree(node);
2107 } 2704 }
2108 spin_unlock_bh(&bat_priv->tt.req_list_lock);
2109 2705
2110 /* Recalculate the CRC for this orig_node and store it */ 2706 spin_unlock_bh(&bat_priv->tt.req_list_lock);
2111 orig_node->tt_crc = batadv_tt_global_crc(bat_priv, orig_node);
2112out: 2707out:
2113 if (orig_node) 2708 if (orig_node)
2114 batadv_orig_node_free_ref(orig_node); 2709 batadv_orig_node_free_ref(orig_node);
@@ -2194,7 +2789,20 @@ unlock:
2194 return ret; 2789 return ret;
2195} 2790}
2196 2791
2792/**
2793 * batadv_send_roam_adv - send a roaming advertisement message
2794 * @bat_priv: the bat priv with all the soft interface information
2795 * @client: mac address of the roaming client
2796 * @vid: VLAN identifier
2797 * @orig_node: message destination
2798 *
2799 * Send a ROAMING_ADV message to the node which was previously serving this
2800 * client. This is done to inform the node that from now on all traffic destined
2801 * for this particular roamed client has to be forwarded to the sender of the
2802 * roaming message.
2803 */
2197static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client, 2804static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client,
2805 unsigned short vid,
2198 struct batadv_orig_node *orig_node) 2806 struct batadv_orig_node *orig_node)
2199{ 2807{
2200 struct batadv_hard_iface *primary_if; 2808 struct batadv_hard_iface *primary_if;
@@ -2211,13 +2819,13 @@ static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client,
2211 goto out; 2819 goto out;
2212 2820
2213 batadv_dbg(BATADV_DBG_TT, bat_priv, 2821 batadv_dbg(BATADV_DBG_TT, bat_priv,
2214 "Sending ROAMING_ADV to %pM (client %pM)\n", 2822 "Sending ROAMING_ADV to %pM (client %pM, vid: %d)\n",
2215 orig_node->orig, client); 2823 orig_node->orig, client, BATADV_PRINT_VID(vid));
2216 2824
2217 batadv_inc_counter(bat_priv, BATADV_CNT_TT_ROAM_ADV_TX); 2825 batadv_inc_counter(bat_priv, BATADV_CNT_TT_ROAM_ADV_TX);
2218 2826
2219 memcpy(tvlv_roam.client, client, sizeof(tvlv_roam.client)); 2827 memcpy(tvlv_roam.client, client, sizeof(tvlv_roam.client));
2220 tvlv_roam.reserved = 0; 2828 tvlv_roam.vid = htons(vid);
2221 2829
2222 batadv_tvlv_unicast_send(bat_priv, primary_if->net_dev->dev_addr, 2830 batadv_tvlv_unicast_send(bat_priv, primary_if->net_dev->dev_addr,
2223 orig_node->orig, BATADV_TVLV_ROAM, 1, 2831 orig_node->orig, BATADV_TVLV_ROAM, 1,
@@ -2263,19 +2871,25 @@ void batadv_tt_free(struct batadv_priv *bat_priv)
2263 kfree(bat_priv->tt.last_changeset); 2871 kfree(bat_priv->tt.last_changeset);
2264} 2872}
2265 2873
2266/* This function will enable or disable the specified flags for all the entries 2874/**
2267 * in the given hash table and returns the number of modified entries 2875 * batadv_tt_local_set_flags - set or unset the specified flags on the local
2876 * table and possibly count them in the TT size
2877 * @bat_priv: the bat priv with all the soft interface information
2878 * @flags: the flag to switch
2879 * @enable: whether to set or unset the flag
2880 * @count: whether to increase the TT size by the number of changed entries
2268 */ 2881 */
2269static uint16_t batadv_tt_set_flags(struct batadv_hashtable *hash, 2882static void batadv_tt_local_set_flags(struct batadv_priv *bat_priv,
2270 uint16_t flags, bool enable) 2883 uint16_t flags, bool enable, bool count)
2271{ 2884{
2272 uint32_t i; 2885 struct batadv_hashtable *hash = bat_priv->tt.local_hash;
2886 struct batadv_tt_common_entry *tt_common_entry;
2273 uint16_t changed_num = 0; 2887 uint16_t changed_num = 0;
2274 struct hlist_head *head; 2888 struct hlist_head *head;
2275 struct batadv_tt_common_entry *tt_common_entry; 2889 uint32_t i;
2276 2890
2277 if (!hash) 2891 if (!hash)
2278 goto out; 2892 return;
2279 2893
2280 for (i = 0; i < hash->size; i++) { 2894 for (i = 0; i < hash->size; i++) {
2281 head = &hash->table[i]; 2895 head = &hash->table[i];
@@ -2293,11 +2907,15 @@ static uint16_t batadv_tt_set_flags(struct batadv_hashtable *hash,
2293 tt_common_entry->flags &= ~flags; 2907 tt_common_entry->flags &= ~flags;
2294 } 2908 }
2295 changed_num++; 2909 changed_num++;
2910
2911 if (!count)
2912 continue;
2913
2914 batadv_tt_local_size_inc(bat_priv,
2915 tt_common_entry->vid);
2296 } 2916 }
2297 rcu_read_unlock(); 2917 rcu_read_unlock();
2298 } 2918 }
2299out:
2300 return changed_num;
2301} 2919}
2302 2920
2303/* Purge out all the tt local entries marked with BATADV_TT_CLIENT_PENDING */ 2921/* Purge out all the tt local entries marked with BATADV_TT_CLIENT_PENDING */
@@ -2325,10 +2943,11 @@ static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv)
2325 continue; 2943 continue;
2326 2944
2327 batadv_dbg(BATADV_DBG_TT, bat_priv, 2945 batadv_dbg(BATADV_DBG_TT, bat_priv,
2328 "Deleting local tt entry (%pM): pending\n", 2946 "Deleting local tt entry (%pM, vid: %d): pending\n",
2329 tt_common->addr); 2947 tt_common->addr,
2948 BATADV_PRINT_VID(tt_common->vid));
2330 2949
2331 atomic_dec(&bat_priv->tt.local_entry_num); 2950 batadv_tt_local_size_dec(bat_priv, tt_common->vid);
2332 hlist_del_rcu(&tt_common->hash_entry); 2951 hlist_del_rcu(&tt_common->hash_entry);
2333 tt_local = container_of(tt_common, 2952 tt_local = container_of(tt_common,
2334 struct batadv_tt_local_entry, 2953 struct batadv_tt_local_entry,
@@ -2346,21 +2965,18 @@ static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv)
2346 */ 2965 */
2347void batadv_tt_local_commit_changes(struct batadv_priv *bat_priv) 2966void batadv_tt_local_commit_changes(struct batadv_priv *bat_priv)
2348{ 2967{
2349 uint16_t changed_num = 0; 2968 spin_lock_bh(&bat_priv->tt.commit_lock);
2350 2969
2351 if (atomic_read(&bat_priv->tt.local_changes) < 1) { 2970 if (atomic_read(&bat_priv->tt.local_changes) < 1) {
2352 if (!batadv_atomic_dec_not_zero(&bat_priv->tt.ogm_append_cnt)) 2971 if (!batadv_atomic_dec_not_zero(&bat_priv->tt.ogm_append_cnt))
2353 batadv_tt_tvlv_container_update(bat_priv); 2972 batadv_tt_tvlv_container_update(bat_priv);
2354 return; 2973 goto out;
2355 } 2974 }
2356 2975
2357 changed_num = batadv_tt_set_flags(bat_priv->tt.local_hash, 2976 batadv_tt_local_set_flags(bat_priv, BATADV_TT_CLIENT_NEW, false, true);
2358 BATADV_TT_CLIENT_NEW, false);
2359 2977
2360 /* all reset entries have to be counted as local entries */
2361 atomic_add(changed_num, &bat_priv->tt.local_entry_num);
2362 batadv_tt_local_purge_pending_clients(bat_priv); 2978 batadv_tt_local_purge_pending_clients(bat_priv);
2363 bat_priv->tt.local_crc = batadv_tt_local_crc(bat_priv); 2979 batadv_tt_local_update_crc(bat_priv);
2364 2980
2365 /* Increment the TTVN only once per OGM interval */ 2981 /* Increment the TTVN only once per OGM interval */
2366 atomic_inc(&bat_priv->tt.vn); 2982 atomic_inc(&bat_priv->tt.vn);
@@ -2371,23 +2987,28 @@ void batadv_tt_local_commit_changes(struct batadv_priv *bat_priv)
2371 /* reset the sending counter */ 2987 /* reset the sending counter */
2372 atomic_set(&bat_priv->tt.ogm_append_cnt, BATADV_TT_OGM_APPEND_MAX); 2988 atomic_set(&bat_priv->tt.ogm_append_cnt, BATADV_TT_OGM_APPEND_MAX);
2373 batadv_tt_tvlv_container_update(bat_priv); 2989 batadv_tt_tvlv_container_update(bat_priv);
2990
2991out:
2992 spin_unlock_bh(&bat_priv->tt.commit_lock);
2374} 2993}
2375 2994
2376bool batadv_is_ap_isolated(struct batadv_priv *bat_priv, uint8_t *src, 2995bool batadv_is_ap_isolated(struct batadv_priv *bat_priv, uint8_t *src,
2377 uint8_t *dst) 2996 uint8_t *dst, unsigned short vid)
2378{ 2997{
2379 struct batadv_tt_local_entry *tt_local_entry = NULL; 2998 struct batadv_tt_local_entry *tt_local_entry = NULL;
2380 struct batadv_tt_global_entry *tt_global_entry = NULL; 2999 struct batadv_tt_global_entry *tt_global_entry = NULL;
3000 struct batadv_softif_vlan *vlan;
2381 bool ret = false; 3001 bool ret = false;
2382 3002
2383 if (!atomic_read(&bat_priv->ap_isolation)) 3003 vlan = batadv_softif_vlan_get(bat_priv, vid);
3004 if (!vlan || !atomic_read(&vlan->ap_isolation))
2384 goto out; 3005 goto out;
2385 3006
2386 tt_local_entry = batadv_tt_local_hash_find(bat_priv, dst); 3007 tt_local_entry = batadv_tt_local_hash_find(bat_priv, dst, vid);
2387 if (!tt_local_entry) 3008 if (!tt_local_entry)
2388 goto out; 3009 goto out;
2389 3010
2390 tt_global_entry = batadv_tt_global_hash_find(bat_priv, src); 3011 tt_global_entry = batadv_tt_global_hash_find(bat_priv, src, vid);
2391 if (!tt_global_entry) 3012 if (!tt_global_entry)
2392 goto out; 3013 goto out;
2393 3014
@@ -2397,6 +3018,8 @@ bool batadv_is_ap_isolated(struct batadv_priv *bat_priv, uint8_t *src,
2397 ret = true; 3018 ret = true;
2398 3019
2399out: 3020out:
3021 if (vlan)
3022 batadv_softif_vlan_free_ref(vlan);
2400 if (tt_global_entry) 3023 if (tt_global_entry)
2401 batadv_tt_global_entry_free_ref(tt_global_entry); 3024 batadv_tt_global_entry_free_ref(tt_global_entry);
2402 if (tt_local_entry) 3025 if (tt_local_entry)
@@ -2409,25 +3032,24 @@ out:
2409 * information received via ogms 3032 * information received via ogms
2410 * @bat_priv: the bat priv with all the soft interface information 3033 * @bat_priv: the bat priv with all the soft interface information
2411 * @orig: the orig_node of the ogm 3034 * @orig: the orig_node of the ogm
2412 * @tt_buff: buffer holding the tt information 3035 * @tt_vlan: pointer to the first tvlv VLAN entry
3036 * @tt_num_vlan: number of tvlv VLAN entries
3037 * @tt_change: pointer to the first entry in the TT buffer
2413 * @tt_num_changes: number of tt changes inside the tt buffer 3038 * @tt_num_changes: number of tt changes inside the tt buffer
2414 * @ttvn: translation table version number of this changeset 3039 * @ttvn: translation table version number of this changeset
2415 * @tt_crc: crc32 checksum of orig node's translation table 3040 * @tt_crc: crc32 checksum of orig node's translation table
2416 */ 3041 */
2417static void batadv_tt_update_orig(struct batadv_priv *bat_priv, 3042static void batadv_tt_update_orig(struct batadv_priv *bat_priv,
2418 struct batadv_orig_node *orig_node, 3043 struct batadv_orig_node *orig_node,
2419 const unsigned char *tt_buff, 3044 const void *tt_buff, uint16_t tt_num_vlan,
2420 uint16_t tt_num_changes, uint8_t ttvn, 3045 struct batadv_tvlv_tt_change *tt_change,
2421 uint32_t tt_crc) 3046 uint16_t tt_num_changes, uint8_t ttvn)
2422{ 3047{
2423 uint8_t orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn); 3048 uint8_t orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
3049 struct batadv_tvlv_tt_vlan_data *tt_vlan;
2424 bool full_table = true; 3050 bool full_table = true;
2425 struct batadv_tvlv_tt_change *tt_change;
2426
2427 /* don't care about a backbone gateways updates. */
2428 if (batadv_bla_is_backbone_gw_orig(bat_priv, orig_node->orig))
2429 return;
2430 3051
3052 tt_vlan = (struct batadv_tvlv_tt_vlan_data *)tt_buff;
2431 /* orig table not initialised AND first diff is in the OGM OR the ttvn 3053 /* orig table not initialised AND first diff is in the OGM OR the ttvn
2432 * increased by one -> we can apply the attached changes 3054 * increased by one -> we can apply the attached changes
2433 */ 3055 */
@@ -2443,6 +3065,8 @@ static void batadv_tt_update_orig(struct batadv_priv *bat_priv,
2443 goto request_table; 3065 goto request_table;
2444 } 3066 }
2445 3067
3068 spin_lock_bh(&orig_node->tt_lock);
3069
2446 tt_change = (struct batadv_tvlv_tt_change *)tt_buff; 3070 tt_change = (struct batadv_tvlv_tt_change *)tt_buff;
2447 batadv_tt_update_changes(bat_priv, orig_node, tt_num_changes, 3071 batadv_tt_update_changes(bat_priv, orig_node, tt_num_changes,
2448 ttvn, tt_change); 3072 ttvn, tt_change);
@@ -2451,7 +3075,9 @@ static void batadv_tt_update_orig(struct batadv_priv *bat_priv,
2451 * prefer to recompute it to spot any possible inconsistency 3075 * prefer to recompute it to spot any possible inconsistency
2452 * in the global table 3076 * in the global table
2453 */ 3077 */
2454 orig_node->tt_crc = batadv_tt_global_crc(bat_priv, orig_node); 3078 batadv_tt_global_update_crc(bat_priv, orig_node);
3079
3080 spin_unlock_bh(&orig_node->tt_lock);
2455 3081
2456 /* The ttvn alone is not enough to guarantee consistency 3082 /* The ttvn alone is not enough to guarantee consistency
2457 * because a single value could represent different states 3083 * because a single value could represent different states
@@ -2462,37 +3088,46 @@ static void batadv_tt_update_orig(struct batadv_priv *bat_priv,
2462 * checking the CRC value is mandatory to detect the 3088 * checking the CRC value is mandatory to detect the
2463 * inconsistency 3089 * inconsistency
2464 */ 3090 */
2465 if (orig_node->tt_crc != tt_crc) 3091 if (!batadv_tt_global_check_crc(orig_node, tt_vlan,
3092 tt_num_vlan))
2466 goto request_table; 3093 goto request_table;
2467 } else { 3094 } else {
2468 /* if we missed more than one change or our tables are not 3095 /* if we missed more than one change or our tables are not
2469 * in sync anymore -> request fresh tt data 3096 * in sync anymore -> request fresh tt data
2470 */ 3097 */
2471 if (!orig_node->tt_initialised || ttvn != orig_ttvn || 3098 if (!orig_node->tt_initialised || ttvn != orig_ttvn ||
2472 orig_node->tt_crc != tt_crc) { 3099 !batadv_tt_global_check_crc(orig_node, tt_vlan,
3100 tt_num_vlan)) {
2473request_table: 3101request_table:
2474 batadv_dbg(BATADV_DBG_TT, bat_priv, 3102 batadv_dbg(BATADV_DBG_TT, bat_priv,
2475 "TT inconsistency for %pM. Need to retrieve the correct information (ttvn: %u last_ttvn: %u crc: %#.8x last_crc: %#.8x num_changes: %u)\n", 3103 "TT inconsistency for %pM. Need to retrieve the correct information (ttvn: %u last_ttvn: %u num_changes: %u)\n",
2476 orig_node->orig, ttvn, orig_ttvn, tt_crc, 3104 orig_node->orig, ttvn, orig_ttvn,
2477 orig_node->tt_crc, tt_num_changes); 3105 tt_num_changes);
2478 batadv_send_tt_request(bat_priv, orig_node, ttvn, 3106 batadv_send_tt_request(bat_priv, orig_node, ttvn,
2479 tt_crc, full_table); 3107 tt_vlan, tt_num_vlan,
3108 full_table);
2480 return; 3109 return;
2481 } 3110 }
2482 } 3111 }
2483} 3112}
2484 3113
2485/* returns true whether we know that the client has moved from its old 3114/**
2486 * originator to another one. This entry is kept is still kept for consistency 3115 * batadv_tt_global_client_is_roaming - check if a client is marked as roaming
2487 * purposes 3116 * @bat_priv: the bat priv with all the soft interface information
3117 * @addr: the mac address of the client to check
3118 * @vid: VLAN identifier
3119 *
3120 * Returns true if we know that the client has moved from its old originator
3121 * to another one. This entry is still kept for consistency purposes and will be
3122 * deleted later by a DEL or because of timeout
2488 */ 3123 */
2489bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv, 3124bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv,
2490 uint8_t *addr) 3125 uint8_t *addr, unsigned short vid)
2491{ 3126{
2492 struct batadv_tt_global_entry *tt_global_entry; 3127 struct batadv_tt_global_entry *tt_global_entry;
2493 bool ret = false; 3128 bool ret = false;
2494 3129
2495 tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr); 3130 tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr, vid);
2496 if (!tt_global_entry) 3131 if (!tt_global_entry)
2497 goto out; 3132 goto out;
2498 3133
@@ -2505,19 +3140,20 @@ out:
2505/** 3140/**
2506 * batadv_tt_local_client_is_roaming - tells whether the client is roaming 3141 * batadv_tt_local_client_is_roaming - tells whether the client is roaming
2507 * @bat_priv: the bat priv with all the soft interface information 3142 * @bat_priv: the bat priv with all the soft interface information
2508 * @addr: the MAC address of the local client to query 3143 * @addr: the mac address of the local client to query
3144 * @vid: VLAN identifier
2509 * 3145 *
2510 * Returns true if the local client is known to be roaming (it is not served by 3146 * Returns true if the local client is known to be roaming (it is not served by
2511 * this node anymore) or not. If yes, the client is still present in the table 3147 * this node anymore) or not. If yes, the client is still present in the table
2512 * to keep the latter consistent with the node TTVN 3148 * to keep the latter consistent with the node TTVN
2513 */ 3149 */
2514bool batadv_tt_local_client_is_roaming(struct batadv_priv *bat_priv, 3150bool batadv_tt_local_client_is_roaming(struct batadv_priv *bat_priv,
2515 uint8_t *addr) 3151 uint8_t *addr, unsigned short vid)
2516{ 3152{
2517 struct batadv_tt_local_entry *tt_local_entry; 3153 struct batadv_tt_local_entry *tt_local_entry;
2518 bool ret = false; 3154 bool ret = false;
2519 3155
2520 tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr); 3156 tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr, vid);
2521 if (!tt_local_entry) 3157 if (!tt_local_entry)
2522 goto out; 3158 goto out;
2523 3159
@@ -2529,25 +3165,19 @@ out:
2529 3165
2530bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv, 3166bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv,
2531 struct batadv_orig_node *orig_node, 3167 struct batadv_orig_node *orig_node,
2532 const unsigned char *addr) 3168 const unsigned char *addr,
3169 unsigned short vid)
2533{ 3170{
2534 bool ret = false; 3171 bool ret = false;
2535 3172
2536 /* if the originator is a backbone node (meaning it belongs to the same 3173 if (!batadv_tt_global_add(bat_priv, orig_node, addr, vid,
2537 * LAN of this node) the temporary client must not be added because to
2538 * reach such destination the node must use the LAN instead of the mesh
2539 */
2540 if (batadv_bla_is_backbone_gw_orig(bat_priv, orig_node->orig))
2541 goto out;
2542
2543 if (!batadv_tt_global_add(bat_priv, orig_node, addr,
2544 BATADV_TT_CLIENT_TEMP, 3174 BATADV_TT_CLIENT_TEMP,
2545 atomic_read(&orig_node->last_ttvn))) 3175 atomic_read(&orig_node->last_ttvn)))
2546 goto out; 3176 goto out;
2547 3177
2548 batadv_dbg(BATADV_DBG_TT, bat_priv, 3178 batadv_dbg(BATADV_DBG_TT, bat_priv,
2549 "Added temporary global client (addr: %pM orig: %pM)\n", 3179 "Added temporary global client (addr: %pM, vid: %d, orig: %pM)\n",
2550 addr, orig_node->orig); 3180 addr, BATADV_PRINT_VID(vid), orig_node->orig);
2551 ret = true; 3181 ret = true;
2552out: 3182out:
2553 return ret; 3183 return ret;
@@ -2563,12 +3193,13 @@ out:
2563 */ 3193 */
2564static void batadv_tt_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv, 3194static void batadv_tt_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv,
2565 struct batadv_orig_node *orig, 3195 struct batadv_orig_node *orig,
2566 uint8_t flags, 3196 uint8_t flags, void *tvlv_value,
2567 void *tvlv_value,
2568 uint16_t tvlv_value_len) 3197 uint16_t tvlv_value_len)
2569{ 3198{
3199 struct batadv_tvlv_tt_vlan_data *tt_vlan;
3200 struct batadv_tvlv_tt_change *tt_change;
2570 struct batadv_tvlv_tt_data *tt_data; 3201 struct batadv_tvlv_tt_data *tt_data;
2571 uint16_t num_entries; 3202 uint16_t num_entries, num_vlan;
2572 3203
2573 if (tvlv_value_len < sizeof(*tt_data)) 3204 if (tvlv_value_len < sizeof(*tt_data))
2574 return; 3205 return;
@@ -2576,11 +3207,19 @@ static void batadv_tt_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv,
2576 tt_data = (struct batadv_tvlv_tt_data *)tvlv_value; 3207 tt_data = (struct batadv_tvlv_tt_data *)tvlv_value;
2577 tvlv_value_len -= sizeof(*tt_data); 3208 tvlv_value_len -= sizeof(*tt_data);
2578 3209
3210 num_vlan = ntohs(tt_data->num_vlan);
3211
3212 if (tvlv_value_len < sizeof(*tt_vlan) * num_vlan)
3213 return;
3214
3215 tt_vlan = (struct batadv_tvlv_tt_vlan_data *)(tt_data + 1);
3216 tt_change = (struct batadv_tvlv_tt_change *)(tt_vlan + num_vlan);
3217 tvlv_value_len -= sizeof(*tt_vlan) * num_vlan;
3218
2579 num_entries = batadv_tt_entries(tvlv_value_len); 3219 num_entries = batadv_tt_entries(tvlv_value_len);
2580 3220
2581 batadv_tt_update_orig(bat_priv, orig, 3221 batadv_tt_update_orig(bat_priv, orig, tt_vlan, num_vlan, tt_change,
2582 (unsigned char *)(tt_data + 1), 3222 num_entries, tt_data->ttvn);
2583 num_entries, tt_data->ttvn, ntohl(tt_data->crc));
2584} 3223}
2585 3224
2586/** 3225/**
@@ -2601,7 +3240,7 @@ static int batadv_tt_tvlv_unicast_handler_v1(struct batadv_priv *bat_priv,
2601 uint16_t tvlv_value_len) 3240 uint16_t tvlv_value_len)
2602{ 3241{
2603 struct batadv_tvlv_tt_data *tt_data; 3242 struct batadv_tvlv_tt_data *tt_data;
2604 uint16_t num_entries; 3243 uint16_t tt_vlan_len, tt_num_entries;
2605 char tt_flag; 3244 char tt_flag;
2606 bool ret; 3245 bool ret;
2607 3246
@@ -2611,7 +3250,14 @@ static int batadv_tt_tvlv_unicast_handler_v1(struct batadv_priv *bat_priv,
2611 tt_data = (struct batadv_tvlv_tt_data *)tvlv_value; 3250 tt_data = (struct batadv_tvlv_tt_data *)tvlv_value;
2612 tvlv_value_len -= sizeof(*tt_data); 3251 tvlv_value_len -= sizeof(*tt_data);
2613 3252
2614 num_entries = batadv_tt_entries(tvlv_value_len); 3253 tt_vlan_len = sizeof(struct batadv_tvlv_tt_vlan_data);
3254 tt_vlan_len *= ntohs(tt_data->num_vlan);
3255
3256 if (tvlv_value_len < tt_vlan_len)
3257 return NET_RX_SUCCESS;
3258
3259 tvlv_value_len -= tt_vlan_len;
3260 tt_num_entries = batadv_tt_entries(tvlv_value_len);
2615 3261
2616 switch (tt_data->flags & BATADV_TT_DATA_TYPE_MASK) { 3262 switch (tt_data->flags & BATADV_TT_DATA_TYPE_MASK) {
2617 case BATADV_TT_REQUEST: 3263 case BATADV_TT_REQUEST:
@@ -2639,7 +3285,7 @@ static int batadv_tt_tvlv_unicast_handler_v1(struct batadv_priv *bat_priv,
2639 3285
2640 if (batadv_is_my_mac(bat_priv, dst)) { 3286 if (batadv_is_my_mac(bat_priv, dst)) {
2641 batadv_handle_tt_response(bat_priv, tt_data, 3287 batadv_handle_tt_response(bat_priv, tt_data,
2642 src, num_entries); 3288 src, tt_num_entries);
2643 return NET_RX_SUCCESS; 3289 return NET_RX_SUCCESS;
2644 } 3290 }
2645 3291
@@ -2684,13 +3330,6 @@ static int batadv_roam_tvlv_unicast_handler_v1(struct batadv_priv *bat_priv,
2684 if (!batadv_is_my_mac(bat_priv, dst)) 3330 if (!batadv_is_my_mac(bat_priv, dst))
2685 return NET_RX_DROP; 3331 return NET_RX_DROP;
2686 3332
2687 /* check if it is a backbone gateway. we don't accept
2688 * roaming advertisement from it, as it has the same
2689 * entries as we have.
2690 */
2691 if (batadv_bla_is_backbone_gw_orig(bat_priv, src))
2692 goto out;
2693
2694 if (tvlv_value_len < sizeof(*roaming_adv)) 3333 if (tvlv_value_len < sizeof(*roaming_adv))
2695 goto out; 3334 goto out;
2696 3335
@@ -2706,7 +3345,7 @@ static int batadv_roam_tvlv_unicast_handler_v1(struct batadv_priv *bat_priv,
2706 src, roaming_adv->client); 3345 src, roaming_adv->client);
2707 3346
2708 batadv_tt_global_add(bat_priv, orig_node, roaming_adv->client, 3347 batadv_tt_global_add(bat_priv, orig_node, roaming_adv->client,
2709 BATADV_TT_CLIENT_ROAM, 3348 ntohs(roaming_adv->vid), BATADV_TT_CLIENT_ROAM,
2710 atomic_read(&orig_node->last_ttvn) + 1); 3349 atomic_read(&orig_node->last_ttvn) + 1);
2711 3350
2712out: 3351out:
diff --git a/net/batman-adv/translation-table.h b/net/batman-adv/translation-table.h
index 015d8b9e63b9..dc6db4e00a43 100644
--- a/net/batman-adv/translation-table.h
+++ b/net/batman-adv/translation-table.h
@@ -22,29 +22,32 @@
22 22
23int batadv_tt_init(struct batadv_priv *bat_priv); 23int batadv_tt_init(struct batadv_priv *bat_priv);
24void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr, 24void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
25 int ifindex); 25 unsigned short vid, int ifindex);
26uint16_t batadv_tt_local_remove(struct batadv_priv *bat_priv, 26uint16_t batadv_tt_local_remove(struct batadv_priv *bat_priv,
27 const uint8_t *addr, const char *message, 27 const uint8_t *addr, unsigned short vid,
28 bool roaming); 28 const char *message, bool roaming);
29int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset); 29int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset);
30int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset); 30int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset);
31void batadv_tt_global_del_orig(struct batadv_priv *bat_priv, 31void batadv_tt_global_del_orig(struct batadv_priv *bat_priv,
32 struct batadv_orig_node *orig_node, 32 struct batadv_orig_node *orig_node,
33 const char *message); 33 int32_t match_vid, const char *message);
34struct batadv_orig_node *batadv_transtable_search(struct batadv_priv *bat_priv, 34struct batadv_orig_node *batadv_transtable_search(struct batadv_priv *bat_priv,
35 const uint8_t *src, 35 const uint8_t *src,
36 const uint8_t *addr); 36 const uint8_t *addr,
37 unsigned short vid);
37void batadv_tt_free(struct batadv_priv *bat_priv); 38void batadv_tt_free(struct batadv_priv *bat_priv);
38bool batadv_is_my_client(struct batadv_priv *bat_priv, const uint8_t *addr); 39bool batadv_is_my_client(struct batadv_priv *bat_priv, const uint8_t *addr,
40 unsigned short vid);
39bool batadv_is_ap_isolated(struct batadv_priv *bat_priv, uint8_t *src, 41bool batadv_is_ap_isolated(struct batadv_priv *bat_priv, uint8_t *src,
40 uint8_t *dst); 42 uint8_t *dst, unsigned short vid);
41void batadv_tt_local_commit_changes(struct batadv_priv *bat_priv); 43void batadv_tt_local_commit_changes(struct batadv_priv *bat_priv);
42bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv, 44bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv,
43 uint8_t *addr); 45 uint8_t *addr, unsigned short vid);
44bool batadv_tt_local_client_is_roaming(struct batadv_priv *bat_priv, 46bool batadv_tt_local_client_is_roaming(struct batadv_priv *bat_priv,
45 uint8_t *addr); 47 uint8_t *addr, unsigned short vid);
46bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv, 48bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv,
47 struct batadv_orig_node *orig_node, 49 struct batadv_orig_node *orig_node,
48 const unsigned char *addr); 50 const unsigned char *addr,
51 unsigned short vid);
49 52
50#endif /* _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ */ 53#endif /* _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ */
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 5cbb0d09a9b5..ff53933b5a59 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -107,6 +107,32 @@ struct batadv_frag_list_entry {
107}; 107};
108 108
109/** 109/**
110 * struct batadv_vlan_tt - VLAN specific TT attributes
111 * @crc: CRC32 checksum of the entries belonging to this vlan
112 * @num_entries: number of TT entries for this VLAN
113 */
114struct batadv_vlan_tt {
115 uint32_t crc;
116 atomic_t num_entries;
117};
118
119/**
120 * batadv_orig_node_vlan - VLAN specific data per orig_node
121 * @vid: the VLAN identifier
122 * @tt: VLAN specific TT attributes
123 * @list: list node for orig_node::vlan_list
124 * @refcount: number of context where this object is currently in use
125 * @rcu: struct used for freeing in a RCU-safe manner
126 */
127struct batadv_orig_node_vlan {
128 unsigned short vid;
129 struct batadv_vlan_tt tt;
130 struct list_head list;
131 atomic_t refcount;
132 struct rcu_head rcu;
133};
134
135/**
110 * struct batadv_orig_node - structure for orig_list maintaining nodes of mesh 136 * struct batadv_orig_node - structure for orig_list maintaining nodes of mesh
111 * @orig: originator ethernet address 137 * @orig: originator ethernet address
112 * @primary_addr: hosts primary interface address 138 * @primary_addr: hosts primary interface address
@@ -120,14 +146,16 @@ struct batadv_frag_list_entry {
120 * @batman_seqno_reset: time when the batman seqno window was reset 146 * @batman_seqno_reset: time when the batman seqno window was reset
121 * @capabilities: announced capabilities of this originator 147 * @capabilities: announced capabilities of this originator
122 * @last_ttvn: last seen translation table version number 148 * @last_ttvn: last seen translation table version number
123 * @tt_crc: CRC of the translation table
124 * @tt_buff: last tt changeset this node received from the orig node 149 * @tt_buff: last tt changeset this node received from the orig node
125 * @tt_buff_len: length of the last tt changeset this node received from the 150 * @tt_buff_len: length of the last tt changeset this node received from the
126 * orig node 151 * orig node
127 * @tt_buff_lock: lock that protects tt_buff and tt_buff_len 152 * @tt_buff_lock: lock that protects tt_buff and tt_buff_len
128 * @tt_size: number of global TT entries announced by the orig node
129 * @tt_initialised: bool keeping track of whether or not this node have received 153 * @tt_initialised: bool keeping track of whether or not this node have received
130 * any translation table information from the orig node yet 154 * any translation table information from the orig node yet
155 * @tt_lock: prevents from updating the table while reading it. Table update is
156 * made up by two operations (data structure update and metdata -CRC/TTVN-
157 * recalculation) and they have to be executed atomically in order to avoid
158 * another thread to read the table/metadata between those.
131 * @last_real_seqno: last and best known sequence number 159 * @last_real_seqno: last and best known sequence number
132 * @last_ttl: ttl of last received packet 160 * @last_ttl: ttl of last received packet
133 * @bcast_bits: bitfield containing the info which payload broadcast originated 161 * @bcast_bits: bitfield containing the info which payload broadcast originated
@@ -150,6 +178,9 @@ struct batadv_frag_list_entry {
150 * @in_coding_list_lock: protects in_coding_list 178 * @in_coding_list_lock: protects in_coding_list
151 * @out_coding_list_lock: protects out_coding_list 179 * @out_coding_list_lock: protects out_coding_list
152 * @fragments: array with heads for fragment chains 180 * @fragments: array with heads for fragment chains
181 * @vlan_list: a list of orig_node_vlan structs, one per VLAN served by the
182 * originator represented by this object
183 * @vlan_list_lock: lock protecting vlan_list
153 */ 184 */
154struct batadv_orig_node { 185struct batadv_orig_node {
155 uint8_t orig[ETH_ALEN]; 186 uint8_t orig[ETH_ALEN];
@@ -165,12 +196,12 @@ struct batadv_orig_node {
165 unsigned long batman_seqno_reset; 196 unsigned long batman_seqno_reset;
166 uint8_t capabilities; 197 uint8_t capabilities;
167 atomic_t last_ttvn; 198 atomic_t last_ttvn;
168 uint32_t tt_crc;
169 unsigned char *tt_buff; 199 unsigned char *tt_buff;
170 int16_t tt_buff_len; 200 int16_t tt_buff_len;
171 spinlock_t tt_buff_lock; /* protects tt_buff & tt_buff_len */ 201 spinlock_t tt_buff_lock; /* protects tt_buff & tt_buff_len */
172 atomic_t tt_size;
173 bool tt_initialised; 202 bool tt_initialised;
203 /* prevents from changing the table while reading it */
204 spinlock_t tt_lock;
174 uint32_t last_real_seqno; 205 uint32_t last_real_seqno;
175 uint8_t last_ttl; 206 uint8_t last_ttl;
176 DECLARE_BITMAP(bcast_bits, BATADV_TQ_LOCAL_WINDOW_SIZE); 207 DECLARE_BITMAP(bcast_bits, BATADV_TQ_LOCAL_WINDOW_SIZE);
@@ -197,6 +228,8 @@ struct batadv_orig_node {
197 spinlock_t out_coding_list_lock; /* Protects out_coding_list */ 228 spinlock_t out_coding_list_lock; /* Protects out_coding_list */
198#endif 229#endif
199 struct batadv_frag_table_entry fragments[BATADV_FRAG_BUFFER_COUNT]; 230 struct batadv_frag_table_entry fragments[BATADV_FRAG_BUFFER_COUNT];
231 struct list_head vlan_list;
232 spinlock_t vlan_list_lock; /* protects vlan_list */
200}; 233};
201 234
202/** 235/**
@@ -383,11 +416,14 @@ enum batadv_counters {
383 * @changes_list_lock: lock protecting changes_list 416 * @changes_list_lock: lock protecting changes_list
384 * @req_list_lock: lock protecting req_list 417 * @req_list_lock: lock protecting req_list
385 * @roam_list_lock: lock protecting roam_list 418 * @roam_list_lock: lock protecting roam_list
386 * @local_entry_num: number of entries in the local hash table
387 * @local_crc: Checksum of the local table, recomputed before sending a new OGM
388 * @last_changeset: last tt changeset this host has generated 419 * @last_changeset: last tt changeset this host has generated
389 * @last_changeset_len: length of last tt changeset this host has generated 420 * @last_changeset_len: length of last tt changeset this host has generated
390 * @last_changeset_lock: lock protecting last_changeset & last_changeset_len 421 * @last_changeset_lock: lock protecting last_changeset & last_changeset_len
422 * @commit_lock: prevents from executing a local TT commit while reading the
423 * local table. The local TT commit is made up by two operations (data
424 * structure update and metdata -CRC/TTVN- recalculation) and they have to be
425 * executed atomically in order to avoid another thread to read the
426 * table/metadata between those.
391 * @work: work queue callback item for translation table purging 427 * @work: work queue callback item for translation table purging
392 */ 428 */
393struct batadv_priv_tt { 429struct batadv_priv_tt {
@@ -402,12 +438,12 @@ struct batadv_priv_tt {
402 spinlock_t changes_list_lock; /* protects changes */ 438 spinlock_t changes_list_lock; /* protects changes */
403 spinlock_t req_list_lock; /* protects req_list */ 439 spinlock_t req_list_lock; /* protects req_list */
404 spinlock_t roam_list_lock; /* protects roam_list */ 440 spinlock_t roam_list_lock; /* protects roam_list */
405 atomic_t local_entry_num;
406 uint32_t local_crc;
407 unsigned char *last_changeset; 441 unsigned char *last_changeset;
408 int16_t last_changeset_len; 442 int16_t last_changeset_len;
409 /* protects last_changeset & last_changeset_len */ 443 /* protects last_changeset & last_changeset_len */
410 spinlock_t last_changeset_lock; 444 spinlock_t last_changeset_lock;
445 /* prevents from executing a commit while reading the table */
446 spinlock_t commit_lock;
411 struct delayed_work work; 447 struct delayed_work work;
412}; 448};
413 449
@@ -531,6 +567,26 @@ struct batadv_priv_nc {
531}; 567};
532 568
533/** 569/**
570 * struct batadv_softif_vlan - per VLAN attributes set
571 * @vid: VLAN identifier
572 * @kobj: kobject for sysfs vlan subdirectory
573 * @ap_isolation: AP isolation state
574 * @tt: TT private attributes (VLAN specific)
575 * @list: list node for bat_priv::softif_vlan_list
576 * @refcount: number of context where this object is currently in use
577 * @rcu: struct used for freeing in a RCU-safe manner
578 */
579struct batadv_softif_vlan {
580 unsigned short vid;
581 struct kobject *kobj;
582 atomic_t ap_isolation; /* boolean */
583 struct batadv_vlan_tt tt;
584 struct hlist_node list;
585 atomic_t refcount;
586 struct rcu_head rcu;
587};
588
589/**
534 * struct batadv_priv - per mesh interface data 590 * struct batadv_priv - per mesh interface data
535 * @mesh_state: current status of the mesh (inactive/active/deactivating) 591 * @mesh_state: current status of the mesh (inactive/active/deactivating)
536 * @soft_iface: net device which holds this struct as private data 592 * @soft_iface: net device which holds this struct as private data
@@ -540,7 +596,6 @@ struct batadv_priv_nc {
540 * @bonding: bool indicating whether traffic bonding is enabled 596 * @bonding: bool indicating whether traffic bonding is enabled
541 * @fragmentation: bool indicating whether traffic fragmentation is enabled 597 * @fragmentation: bool indicating whether traffic fragmentation is enabled
542 * @frag_seqno: incremental counter to identify chains of egress fragments 598 * @frag_seqno: incremental counter to identify chains of egress fragments
543 * @ap_isolation: bool indicating whether ap isolation is enabled
544 * @bridge_loop_avoidance: bool indicating whether bridge loop avoidance is 599 * @bridge_loop_avoidance: bool indicating whether bridge loop avoidance is
545 * enabled 600 * enabled
546 * @distributed_arp_table: bool indicating whether distributed ARP table is 601 * @distributed_arp_table: bool indicating whether distributed ARP table is
@@ -566,6 +621,9 @@ struct batadv_priv_nc {
566 * @primary_if: one of the hard interfaces assigned to this mesh interface 621 * @primary_if: one of the hard interfaces assigned to this mesh interface
567 * becomes the primary interface 622 * becomes the primary interface
568 * @bat_algo_ops: routing algorithm used by this mesh interface 623 * @bat_algo_ops: routing algorithm used by this mesh interface
624 * @softif_vlan_list: a list of softif_vlan structs, one per VLAN created on top
625 * of the mesh interface represented by this object
626 * @softif_vlan_list_lock: lock protecting softif_vlan_list
569 * @bla: bridge loope avoidance data 627 * @bla: bridge loope avoidance data
570 * @debug_log: holding debug logging relevant data 628 * @debug_log: holding debug logging relevant data
571 * @gw: gateway data 629 * @gw: gateway data
@@ -584,7 +642,6 @@ struct batadv_priv {
584 atomic_t bonding; 642 atomic_t bonding;
585 atomic_t fragmentation; 643 atomic_t fragmentation;
586 atomic_t frag_seqno; 644 atomic_t frag_seqno;
587 atomic_t ap_isolation;
588#ifdef CONFIG_BATMAN_ADV_BLA 645#ifdef CONFIG_BATMAN_ADV_BLA
589 atomic_t bridge_loop_avoidance; 646 atomic_t bridge_loop_avoidance;
590#endif 647#endif
@@ -613,6 +670,8 @@ struct batadv_priv {
613 struct work_struct cleanup_work; 670 struct work_struct cleanup_work;
614 struct batadv_hard_iface __rcu *primary_if; /* rcu protected pointer */ 671 struct batadv_hard_iface __rcu *primary_if; /* rcu protected pointer */
615 struct batadv_algo_ops *bat_algo_ops; 672 struct batadv_algo_ops *bat_algo_ops;
673 struct hlist_head softif_vlan_list;
674 spinlock_t softif_vlan_list_lock; /* protects softif_vlan_list */
616#ifdef CONFIG_BATMAN_ADV_BLA 675#ifdef CONFIG_BATMAN_ADV_BLA
617 struct batadv_priv_bla bla; 676 struct batadv_priv_bla bla;
618#endif 677#endif
@@ -715,6 +774,7 @@ struct batadv_bla_claim {
715/** 774/**
716 * struct batadv_tt_common_entry - tt local & tt global common data 775 * struct batadv_tt_common_entry - tt local & tt global common data
717 * @addr: mac address of non-mesh client 776 * @addr: mac address of non-mesh client
777 * @vid: VLAN identifier
718 * @hash_entry: hlist node for batadv_priv_tt::local_hash or for 778 * @hash_entry: hlist node for batadv_priv_tt::local_hash or for
719 * batadv_priv_tt::global_hash 779 * batadv_priv_tt::global_hash
720 * @flags: various state handling flags (see batadv_tt_client_flags) 780 * @flags: various state handling flags (see batadv_tt_client_flags)
@@ -724,6 +784,7 @@ struct batadv_bla_claim {
724 */ 784 */
725struct batadv_tt_common_entry { 785struct batadv_tt_common_entry {
726 uint8_t addr[ETH_ALEN]; 786 uint8_t addr[ETH_ALEN];
787 unsigned short vid;
727 struct hlist_node hash_entry; 788 struct hlist_node hash_entry;
728 uint16_t flags; 789 uint16_t flags;
729 unsigned long added_at; 790 unsigned long added_at;
@@ -931,6 +992,7 @@ struct batadv_algo_ops {
931 * is used to stored ARP entries needed for the global DAT cache 992 * is used to stored ARP entries needed for the global DAT cache
932 * @ip: the IPv4 corresponding to this DAT/ARP entry 993 * @ip: the IPv4 corresponding to this DAT/ARP entry
933 * @mac_addr: the MAC address associated to the stored IPv4 994 * @mac_addr: the MAC address associated to the stored IPv4
995 * @vid: the vlan ID associated to this entry
934 * @last_update: time in jiffies when this entry was refreshed last time 996 * @last_update: time in jiffies when this entry was refreshed last time
935 * @hash_entry: hlist node for batadv_priv_dat::hash 997 * @hash_entry: hlist node for batadv_priv_dat::hash
936 * @refcount: number of contexts the object is used 998 * @refcount: number of contexts the object is used
@@ -939,6 +1001,7 @@ struct batadv_algo_ops {
939struct batadv_dat_entry { 1001struct batadv_dat_entry {
940 __be32 ip; 1002 __be32 ip;
941 uint8_t mac_addr[ETH_ALEN]; 1003 uint8_t mac_addr[ETH_ALEN];
1004 unsigned short vid;
942 unsigned long last_update; 1005 unsigned long last_update;
943 struct hlist_node hash_entry; 1006 struct hlist_node hash_entry;
944 atomic_t refcount; 1007 atomic_t refcount;