Blame view

net/batman-adv/translation-table.c 110 KB
e19f9759e   Simon Wunderlich   batman-adv: updat...
1
  /* Copyright (C) 2007-2014 B.A.T.M.A.N. contributors:
c6c8fea29   Sven Eckelmann   net: Add batman-a...
2
   *
35c133a00   Antonio Quartulli   batman-adv: add c...
3
   * Marek Lindner, Simon Wunderlich, Antonio Quartulli
c6c8fea29   Sven Eckelmann   net: Add batman-a...
4
5
6
7
8
9
10
11
12
13
14
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of version 2 of the GNU General Public
   * License as published by the Free Software Foundation.
   *
   * This program is distributed in the hope that it will be useful, but
   * WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   * General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
ebf38fb7a   Antonio Quartulli   batman-adv: remov...
15
   * along with this program; if not, see <http://www.gnu.org/licenses/>.
c6c8fea29   Sven Eckelmann   net: Add batman-a...
16
17
18
19
20
   */
  
  #include "main.h"
  #include "translation-table.h"
  #include "soft-interface.h"
32ae9b221   Marek Lindner   batman-adv: Make ...
21
  #include "hard-interface.h"
a73105b8d   Antonio Quartulli   batman-adv: impro...
22
  #include "send.h"
c6c8fea29   Sven Eckelmann   net: Add batman-a...
23
24
  #include "hash.h"
  #include "originator.h"
a73105b8d   Antonio Quartulli   batman-adv: impro...
25
  #include "routing.h"
20ff9d593   Simon Wunderlich   batman-adv: don't...
26
  #include "bridge_loop_avoidance.h"
c5caf4ef3   Linus Lüssing   batman-adv: Multi...
27
  #include "multicast.h"
c6c8fea29   Sven Eckelmann   net: Add batman-a...
28

ced72933a   Antonio Quartulli   batman-adv: use C...
29
  #include <linux/crc32c.h>
a73105b8d   Antonio Quartulli   batman-adv: impro...
30

dec05074b   Antonio Quartulli   batman-adv: Initi...
31
32
33
  /* hash class keys */
  static struct lock_class_key batadv_tt_local_hash_lock_class_key;
  static struct lock_class_key batadv_tt_global_hash_lock_class_key;
56303d34a   Sven Eckelmann   batman-adv: Prefi...
34
  static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client,
c018ad3de   Antonio Quartulli   batman-adv: add t...
35
  				 unsigned short vid,
56303d34a   Sven Eckelmann   batman-adv: Prefi...
36
  				 struct batadv_orig_node *orig_node);
a513088d0   Sven Eckelmann   batman-adv: Prefi...
37
38
  static void batadv_tt_purge(struct work_struct *work);
  static void
56303d34a   Sven Eckelmann   batman-adv: Prefi...
39
  batadv_tt_global_del_orig_list(struct batadv_tt_global_entry *tt_global_entry);
30cfd02b6   Antonio Quartulli   batman-adv: detec...
40
41
42
  static void batadv_tt_global_del(struct batadv_priv *bat_priv,
  				 struct batadv_orig_node *orig_node,
  				 const unsigned char *addr,
c018ad3de   Antonio Quartulli   batman-adv: add t...
43
44
  				 unsigned short vid, const char *message,
  				 bool roaming);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
45

7aadf889e   Marek Lindner   batman-adv: remov...
46
  /* returns 1 if they are the same mac addr */
a513088d0   Sven Eckelmann   batman-adv: Prefi...
47
  static int batadv_compare_tt(const struct hlist_node *node, const void *data2)
7aadf889e   Marek Lindner   batman-adv: remov...
48
  {
56303d34a   Sven Eckelmann   batman-adv: Prefi...
49
  	const void *data1 = container_of(node, struct batadv_tt_common_entry,
747e4221a   Sven Eckelmann   batman-adv: Add c...
50
  					 hash_entry);
7aadf889e   Marek Lindner   batman-adv: remov...
51

323813ed2   dingtianhong   batman-adv: use b...
52
  	return batadv_compare_eth(data1, data2);
7aadf889e   Marek Lindner   batman-adv: remov...
53
  }
c018ad3de   Antonio Quartulli   batman-adv: add t...
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
  /**
   * batadv_choose_tt - return the index of the tt entry in the hash table
   * @data: pointer to the tt_common_entry object to map
   * @size: the size of the hash table
   *
   * Returns the hash index where the object represented by 'data' should be
   * stored at.
   */
  static inline uint32_t batadv_choose_tt(const void *data, uint32_t size)
  {
  	struct batadv_tt_common_entry *tt;
  	uint32_t hash = 0;
  
  	tt = (struct batadv_tt_common_entry *)data;
  	hash = batadv_hash_bytes(hash, &tt->addr, ETH_ALEN);
  	hash = batadv_hash_bytes(hash, &tt->vid, sizeof(tt->vid));
  
  	hash += (hash << 3);
  	hash ^= (hash >> 11);
  	hash += (hash << 15);
  
  	return hash % size;
  }
  
  /**
   * batadv_tt_hash_find - look for a client in the given hash table
   * @hash: the hash table to search
   * @addr: the mac address of the client to look for
   * @vid: VLAN identifier
   *
   * Returns a pointer to the tt_common struct belonging to the searched client if
   * found, NULL otherwise.
   */
56303d34a   Sven Eckelmann   batman-adv: Prefi...
87
  static struct batadv_tt_common_entry *
c018ad3de   Antonio Quartulli   batman-adv: add t...
88
89
  batadv_tt_hash_find(struct batadv_hashtable *hash, const uint8_t *addr,
  		    unsigned short vid)
7aadf889e   Marek Lindner   batman-adv: remov...
90
  {
7aadf889e   Marek Lindner   batman-adv: remov...
91
  	struct hlist_head *head;
c018ad3de   Antonio Quartulli   batman-adv: add t...
92
  	struct batadv_tt_common_entry to_search, *tt, *tt_tmp = NULL;
c90681b85   Antonio Quartulli   batman-adv: fixed...
93
  	uint32_t index;
7aadf889e   Marek Lindner   batman-adv: remov...
94
95
96
  
  	if (!hash)
  		return NULL;
8fdd01530   Antonio Quartulli   batman-adv: prefe...
97
  	ether_addr_copy(to_search.addr, addr);
c018ad3de   Antonio Quartulli   batman-adv: add t...
98
99
100
  	to_search.vid = vid;
  
  	index = batadv_choose_tt(&to_search, hash->size);
7aadf889e   Marek Lindner   batman-adv: remov...
101
102
103
  	head = &hash->table[index];
  
  	rcu_read_lock();
c018ad3de   Antonio Quartulli   batman-adv: add t...
104
105
106
107
108
  	hlist_for_each_entry_rcu(tt, head, hash_entry) {
  		if (!batadv_compare_eth(tt, addr))
  			continue;
  
  		if (tt->vid != vid)
7aadf889e   Marek Lindner   batman-adv: remov...
109
  			continue;
c018ad3de   Antonio Quartulli   batman-adv: add t...
110
  		if (!atomic_inc_not_zero(&tt->refcount))
7683fdc1e   Antonio Quartulli   batman-adv: prote...
111
  			continue;
c018ad3de   Antonio Quartulli   batman-adv: add t...
112
  		tt_tmp = tt;
7aadf889e   Marek Lindner   batman-adv: remov...
113
114
115
  		break;
  	}
  	rcu_read_unlock();
c018ad3de   Antonio Quartulli   batman-adv: add t...
116
  	return tt_tmp;
7aadf889e   Marek Lindner   batman-adv: remov...
117
  }
c018ad3de   Antonio Quartulli   batman-adv: add t...
118
119
120
121
122
123
124
125
126
  /**
   * batadv_tt_local_hash_find - search the local table for a given client
   * @bat_priv: the bat priv with all the soft interface information
   * @addr: the mac address of the client to look for
   * @vid: VLAN identifier
   *
   * Returns a pointer to the corresponding tt_local_entry struct if the client is
   * found, NULL otherwise.
   */
56303d34a   Sven Eckelmann   batman-adv: Prefi...
127
  static struct batadv_tt_local_entry *
c018ad3de   Antonio Quartulli   batman-adv: add t...
128
129
  batadv_tt_local_hash_find(struct batadv_priv *bat_priv, const uint8_t *addr,
  			  unsigned short vid)
7aadf889e   Marek Lindner   batman-adv: remov...
130
  {
56303d34a   Sven Eckelmann   batman-adv: Prefi...
131
132
  	struct batadv_tt_common_entry *tt_common_entry;
  	struct batadv_tt_local_entry *tt_local_entry = NULL;
7aadf889e   Marek Lindner   batman-adv: remov...
133

c018ad3de   Antonio Quartulli   batman-adv: add t...
134
135
  	tt_common_entry = batadv_tt_hash_find(bat_priv->tt.local_hash, addr,
  					      vid);
48100bac8   Antonio Quartulli   batman-adv: creat...
136
137
  	if (tt_common_entry)
  		tt_local_entry = container_of(tt_common_entry,
56303d34a   Sven Eckelmann   batman-adv: Prefi...
138
139
  					      struct batadv_tt_local_entry,
  					      common);
48100bac8   Antonio Quartulli   batman-adv: creat...
140
141
  	return tt_local_entry;
  }
7aadf889e   Marek Lindner   batman-adv: remov...
142

c018ad3de   Antonio Quartulli   batman-adv: add t...
143
144
145
146
147
148
149
150
151
  /**
   * batadv_tt_global_hash_find - search the global table for a given client
   * @bat_priv: the bat priv with all the soft interface information
   * @addr: the mac address of the client to look for
   * @vid: VLAN identifier
   *
   * Returns a pointer to the corresponding tt_global_entry struct if the client
   * is found, NULL otherwise.
   */
56303d34a   Sven Eckelmann   batman-adv: Prefi...
152
  static struct batadv_tt_global_entry *
c018ad3de   Antonio Quartulli   batman-adv: add t...
153
154
  batadv_tt_global_hash_find(struct batadv_priv *bat_priv, const uint8_t *addr,
  			   unsigned short vid)
48100bac8   Antonio Quartulli   batman-adv: creat...
155
  {
56303d34a   Sven Eckelmann   batman-adv: Prefi...
156
157
  	struct batadv_tt_common_entry *tt_common_entry;
  	struct batadv_tt_global_entry *tt_global_entry = NULL;
7683fdc1e   Antonio Quartulli   batman-adv: prote...
158

c018ad3de   Antonio Quartulli   batman-adv: add t...
159
160
  	tt_common_entry = batadv_tt_hash_find(bat_priv->tt.global_hash, addr,
  					      vid);
48100bac8   Antonio Quartulli   batman-adv: creat...
161
162
  	if (tt_common_entry)
  		tt_global_entry = container_of(tt_common_entry,
56303d34a   Sven Eckelmann   batman-adv: Prefi...
163
164
  					       struct batadv_tt_global_entry,
  					       common);
48100bac8   Antonio Quartulli   batman-adv: creat...
165
  	return tt_global_entry;
7aadf889e   Marek Lindner   batman-adv: remov...
166
  }
a513088d0   Sven Eckelmann   batman-adv: Prefi...
167
  static void
56303d34a   Sven Eckelmann   batman-adv: Prefi...
168
  batadv_tt_local_entry_free_ref(struct batadv_tt_local_entry *tt_local_entry)
7683fdc1e   Antonio Quartulli   batman-adv: prote...
169
  {
48100bac8   Antonio Quartulli   batman-adv: creat...
170
171
  	if (atomic_dec_and_test(&tt_local_entry->common.refcount))
  		kfree_rcu(tt_local_entry, common.rcu);
7683fdc1e   Antonio Quartulli   batman-adv: prote...
172
  }
210260594   Antonio Quartulli   batman-adv: don't...
173
174
175
176
177
  /**
   * batadv_tt_global_entry_free_ref - decrement the refcounter for a
   *  tt_global_entry and possibly free it
   * @tt_global_entry: the object to free
   */
a513088d0   Sven Eckelmann   batman-adv: Prefi...
178
  static void
56303d34a   Sven Eckelmann   batman-adv: Prefi...
179
  batadv_tt_global_entry_free_ref(struct batadv_tt_global_entry *tt_global_entry)
7683fdc1e   Antonio Quartulli   batman-adv: prote...
180
  {
db08e6e55   Simon Wunderlich   batman-adv: allow...
181
  	if (atomic_dec_and_test(&tt_global_entry->common.refcount)) {
a513088d0   Sven Eckelmann   batman-adv: Prefi...
182
  		batadv_tt_global_del_orig_list(tt_global_entry);
210260594   Antonio Quartulli   batman-adv: don't...
183
  		kfree_rcu(tt_global_entry, common.rcu);
db08e6e55   Simon Wunderlich   batman-adv: allow...
184
185
  	}
  }
1d8ab8d3c   Linus Lüssing   batman-adv: Modif...
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
  /**
   * batadv_tt_global_hash_count - count the number of orig entries
   * @hash: hash table containing the tt entries
   * @addr: the mac address of the client to count entries for
   * @vid: VLAN identifier
   *
   * Return the number of originators advertising the given address/data
   * (excluding ourself).
   */
  int batadv_tt_global_hash_count(struct batadv_priv *bat_priv,
  				const uint8_t *addr, unsigned short vid)
  {
  	struct batadv_tt_global_entry *tt_global_entry;
  	int count;
  
  	tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr, vid);
  	if (!tt_global_entry)
  		return 0;
  
  	count = atomic_read(&tt_global_entry->orig_list_count);
  	batadv_tt_global_entry_free_ref(tt_global_entry);
  
  	return count;
  }
a513088d0   Sven Eckelmann   batman-adv: Prefi...
210
  static void batadv_tt_orig_list_entry_free_rcu(struct rcu_head *rcu)
db08e6e55   Simon Wunderlich   batman-adv: allow...
211
  {
56303d34a   Sven Eckelmann   batman-adv: Prefi...
212
  	struct batadv_tt_orig_list_entry *orig_entry;
db08e6e55   Simon Wunderlich   batman-adv: allow...
213

56303d34a   Sven Eckelmann   batman-adv: Prefi...
214
  	orig_entry = container_of(rcu, struct batadv_tt_orig_list_entry, rcu);
72822225b   Linus Lüssing   batman-adv: Fix r...
215
216
217
218
219
220
  
  	/* We are in an rcu callback here, therefore we cannot use
  	 * batadv_orig_node_free_ref() and its call_rcu():
  	 * An rcu_barrier() wouldn't wait for that to finish
  	 */
  	batadv_orig_node_free_ref_now(orig_entry->orig_node);
db08e6e55   Simon Wunderlich   batman-adv: allow...
221
222
  	kfree(orig_entry);
  }
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
  /**
   * batadv_tt_local_size_mod - change the size by v of the local table identified
   *  by vid
   * @bat_priv: the bat priv with all the soft interface information
   * @vid: the VLAN identifier of the sub-table to change
   * @v: the amount to sum to the local table size
   */
  static void batadv_tt_local_size_mod(struct batadv_priv *bat_priv,
  				     unsigned short vid, int v)
  {
  	struct batadv_softif_vlan *vlan;
  
  	vlan = batadv_softif_vlan_get(bat_priv, vid);
  	if (!vlan)
  		return;
  
  	atomic_add(v, &vlan->tt.num_entries);
  
  	batadv_softif_vlan_free_ref(vlan);
  }
  
  /**
   * batadv_tt_local_size_inc - increase by one the local table size for the given
   *  vid
   * @bat_priv: the bat priv with all the soft interface information
   * @vid: the VLAN identifier
   */
  static void batadv_tt_local_size_inc(struct batadv_priv *bat_priv,
  				     unsigned short vid)
  {
  	batadv_tt_local_size_mod(bat_priv, vid, 1);
  }
  
  /**
   * batadv_tt_local_size_dec - decrease by one the local table size for the given
   *  vid
   * @bat_priv: the bat priv with all the soft interface information
   * @vid: the VLAN identifier
   */
  static void batadv_tt_local_size_dec(struct batadv_priv *bat_priv,
  				     unsigned short vid)
  {
  	batadv_tt_local_size_mod(bat_priv, vid, -1);
  }
  
  /**
   * batadv_tt_global_size_mod - change the size by v of the local table
   *  identified by vid
   * @bat_priv: the bat priv with all the soft interface information
   * @vid: the VLAN identifier
   * @v: the amount to sum to the global table size
   */
  static void batadv_tt_global_size_mod(struct batadv_orig_node *orig_node,
  				      unsigned short vid, int v)
  {
  	struct batadv_orig_node_vlan *vlan;
  
  	vlan = batadv_orig_node_vlan_new(orig_node, vid);
  	if (!vlan)
  		return;
  
  	if (atomic_add_return(v, &vlan->tt.num_entries) == 0) {
  		spin_lock_bh(&orig_node->vlan_list_lock);
  		list_del_rcu(&vlan->list);
  		spin_unlock_bh(&orig_node->vlan_list_lock);
  		batadv_orig_node_vlan_free_ref(vlan);
  	}
  
  	batadv_orig_node_vlan_free_ref(vlan);
  }
  
  /**
   * batadv_tt_global_size_inc - increase by one the global table size for the
   *  given vid
   * @orig_node: the originator which global table size has to be decreased
   * @vid: the vlan identifier
   */
  static void batadv_tt_global_size_inc(struct batadv_orig_node *orig_node,
  				      unsigned short vid)
  {
  	batadv_tt_global_size_mod(orig_node, vid, 1);
  }
  
  /**
   * batadv_tt_global_size_dec - decrease by one the global table size for the
   *  given vid
   * @orig_node: the originator which global table size has to be decreased
   * @vid: the vlan identifier
   */
  static void batadv_tt_global_size_dec(struct batadv_orig_node *orig_node,
  				      unsigned short vid)
  {
  	batadv_tt_global_size_mod(orig_node, vid, -1);
  }
a513088d0   Sven Eckelmann   batman-adv: Prefi...
317
  static void
56303d34a   Sven Eckelmann   batman-adv: Prefi...
318
  batadv_tt_orig_list_entry_free_ref(struct batadv_tt_orig_list_entry *orig_entry)
db08e6e55   Simon Wunderlich   batman-adv: allow...
319
  {
d657e621a   Antonio Quartulli   batman-adv: add r...
320
321
  	if (!atomic_dec_and_test(&orig_entry->refcount))
  		return;
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
322

a513088d0   Sven Eckelmann   batman-adv: Prefi...
323
  	call_rcu(&orig_entry->rcu, batadv_tt_orig_list_entry_free_rcu);
7683fdc1e   Antonio Quartulli   batman-adv: prote...
324
  }
3abe4adbf   Antonio Quartulli   batman-adv: refac...
325
326
327
328
329
330
  /**
   * batadv_tt_local_event - store a local TT event (ADD/DEL)
   * @bat_priv: the bat priv with all the soft interface information
   * @tt_local_entry: the TT entry involved in the event
   * @event_flags: flags to store in the event structure
   */
56303d34a   Sven Eckelmann   batman-adv: Prefi...
331
  static void batadv_tt_local_event(struct batadv_priv *bat_priv,
3abe4adbf   Antonio Quartulli   batman-adv: refac...
332
333
  				  struct batadv_tt_local_entry *tt_local_entry,
  				  uint8_t event_flags)
a73105b8d   Antonio Quartulli   batman-adv: impro...
334
  {
56303d34a   Sven Eckelmann   batman-adv: Prefi...
335
  	struct batadv_tt_change_node *tt_change_node, *entry, *safe;
3abe4adbf   Antonio Quartulli   batman-adv: refac...
336
337
  	struct batadv_tt_common_entry *common = &tt_local_entry->common;
  	uint8_t flags = common->flags | event_flags;
3b643de54   Antonio Quartulli   batman-adv: clear...
338
339
  	bool event_removed = false;
  	bool del_op_requested, del_op_entry;
a73105b8d   Antonio Quartulli   batman-adv: impro...
340
341
  
  	tt_change_node = kmalloc(sizeof(*tt_change_node), GFP_ATOMIC);
a73105b8d   Antonio Quartulli   batman-adv: impro...
342
343
  	if (!tt_change_node)
  		return;
ff66c975d   Antonio Quartulli   batman-adv: pass ...
344
  	tt_change_node->change.flags = flags;
ca6630464   Antonio Quartulli   batman-adv: fix a...
345
346
  	memset(tt_change_node->change.reserved, 0,
  	       sizeof(tt_change_node->change.reserved));
8fdd01530   Antonio Quartulli   batman-adv: prefe...
347
  	ether_addr_copy(tt_change_node->change.addr, common->addr);
c018ad3de   Antonio Quartulli   batman-adv: add t...
348
  	tt_change_node->change.vid = htons(common->vid);
a73105b8d   Antonio Quartulli   batman-adv: impro...
349

acd34afa8   Sven Eckelmann   batman-adv: Prefi...
350
  	del_op_requested = flags & BATADV_TT_CLIENT_DEL;
3b643de54   Antonio Quartulli   batman-adv: clear...
351
352
  
  	/* check for ADD+DEL or DEL+ADD events */
807736f6e   Sven Eckelmann   batman-adv: Split...
353
354
  	spin_lock_bh(&bat_priv->tt.changes_list_lock);
  	list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list,
3b643de54   Antonio Quartulli   batman-adv: clear...
355
  				 list) {
3abe4adbf   Antonio Quartulli   batman-adv: refac...
356
  		if (!batadv_compare_eth(entry->change.addr, common->addr))
3b643de54   Antonio Quartulli   batman-adv: clear...
357
358
359
360
361
362
363
364
365
  			continue;
  
  		/* DEL+ADD in the same orig interval have no effect and can be
  		 * removed to avoid silly behaviour on the receiver side. The
  		 * other way around (ADD+DEL) can happen in case of roaming of
  		 * a client still in the NEW state. Roaming of NEW clients is
  		 * now possible due to automatically recognition of "temporary"
  		 * clients
  		 */
acd34afa8   Sven Eckelmann   batman-adv: Prefi...
366
  		del_op_entry = entry->change.flags & BATADV_TT_CLIENT_DEL;
3b643de54   Antonio Quartulli   batman-adv: clear...
367
368
369
370
  		if (!del_op_requested && del_op_entry)
  			goto del;
  		if (del_op_requested && !del_op_entry)
  			goto del;
3c4f7ab60   Antonio Quartulli   batman-adv: impro...
371
372
373
374
375
376
  
  		/* this is a second add in the same originator interval. It
  		 * means that flags have been changed: update them!
  		 */
  		if (!del_op_requested && !del_op_entry)
  			entry->change.flags = flags;
3b643de54   Antonio Quartulli   batman-adv: clear...
377
378
379
380
  		continue;
  del:
  		list_del(&entry->list);
  		kfree(entry);
155e4e12b   Jesper Juhl   batman-adv: Fix m...
381
  		kfree(tt_change_node);
3b643de54   Antonio Quartulli   batman-adv: clear...
382
383
384
  		event_removed = true;
  		goto unlock;
  	}
a73105b8d   Antonio Quartulli   batman-adv: impro...
385
  	/* track the change in the OGMinterval list */
807736f6e   Sven Eckelmann   batman-adv: Split...
386
  	list_add_tail(&tt_change_node->list, &bat_priv->tt.changes_list);
3b643de54   Antonio Quartulli   batman-adv: clear...
387
388
  
  unlock:
807736f6e   Sven Eckelmann   batman-adv: Split...
389
  	spin_unlock_bh(&bat_priv->tt.changes_list_lock);
a73105b8d   Antonio Quartulli   batman-adv: impro...
390

3b643de54   Antonio Quartulli   batman-adv: clear...
391
  	if (event_removed)
807736f6e   Sven Eckelmann   batman-adv: Split...
392
  		atomic_dec(&bat_priv->tt.local_changes);
3b643de54   Antonio Quartulli   batman-adv: clear...
393
  	else
807736f6e   Sven Eckelmann   batman-adv: Split...
394
  		atomic_inc(&bat_priv->tt.local_changes);
a73105b8d   Antonio Quartulli   batman-adv: impro...
395
  }
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
396
397
398
399
400
401
402
  /**
   * batadv_tt_len - compute length in bytes of given number of tt changes
   * @changes_num: number of tt changes
   *
   * Returns computed length in bytes.
   */
  static int batadv_tt_len(int changes_num)
a73105b8d   Antonio Quartulli   batman-adv: impro...
403
  {
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
404
  	return changes_num * sizeof(struct batadv_tvlv_tt_change);
a73105b8d   Antonio Quartulli   batman-adv: impro...
405
  }
298e6e685   Antonio Quartulli   batman-adv: imple...
406
407
408
409
410
411
412
413
414
415
  /**
   * batadv_tt_entries - compute the number of entries fitting in tt_len bytes
   * @tt_len: available space
   *
   * Returns the number of entries.
   */
  static uint16_t batadv_tt_entries(uint16_t tt_len)
  {
  	return tt_len / batadv_tt_len(1);
  }
a19d3d85e   Marek Lindner   batman-adv: limit...
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
  /**
   * batadv_tt_local_table_transmit_size - calculates the local translation table
   *  size when transmitted over the air
   * @bat_priv: the bat priv with all the soft interface information
   *
   * Returns local translation table size in bytes.
   */
  static int batadv_tt_local_table_transmit_size(struct batadv_priv *bat_priv)
  {
  	uint16_t num_vlan = 0, tt_local_entries = 0;
  	struct batadv_softif_vlan *vlan;
  	int hdr_size;
  
  	rcu_read_lock();
  	hlist_for_each_entry_rcu(vlan, &bat_priv->softif_vlan_list, list) {
  		num_vlan++;
  		tt_local_entries += atomic_read(&vlan->tt.num_entries);
  	}
  	rcu_read_unlock();
  
  	/* header size of tvlv encapsulated tt response payload */
  	hdr_size = sizeof(struct batadv_unicast_tvlv_packet);
  	hdr_size += sizeof(struct batadv_tvlv_hdr);
  	hdr_size += sizeof(struct batadv_tvlv_tt_data);
  	hdr_size += num_vlan * sizeof(struct batadv_tvlv_tt_vlan_data);
  
  	return hdr_size + batadv_tt_len(tt_local_entries);
  }
56303d34a   Sven Eckelmann   batman-adv: Prefi...
444
  static int batadv_tt_local_init(struct batadv_priv *bat_priv)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
445
  {
807736f6e   Sven Eckelmann   batman-adv: Split...
446
  	if (bat_priv->tt.local_hash)
5346c35eb   Sven Eckelmann   batman-adv: Retur...
447
  		return 0;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
448

807736f6e   Sven Eckelmann   batman-adv: Split...
449
  	bat_priv->tt.local_hash = batadv_hash_new(1024);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
450

807736f6e   Sven Eckelmann   batman-adv: Split...
451
  	if (!bat_priv->tt.local_hash)
5346c35eb   Sven Eckelmann   batman-adv: Retur...
452
  		return -ENOMEM;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
453

dec05074b   Antonio Quartulli   batman-adv: Initi...
454
455
  	batadv_hash_set_lock_class(bat_priv->tt.local_hash,
  				   &batadv_tt_local_hash_lock_class_key);
5346c35eb   Sven Eckelmann   batman-adv: Retur...
456
  	return 0;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
457
  }
068ee6e20   Antonio Quartulli   batman-adv: roami...
458
459
460
461
462
  static void batadv_tt_global_free(struct batadv_priv *bat_priv,
  				  struct batadv_tt_global_entry *tt_global,
  				  const char *message)
  {
  	batadv_dbg(BATADV_DBG_TT, bat_priv,
160527890   Antonio Quartulli   batman-adv: print...
463
464
465
466
  		   "Deleting global tt entry %pM (vid: %d): %s
  ",
  		   tt_global->common.addr,
  		   BATADV_PRINT_VID(tt_global->common.vid), message);
068ee6e20   Antonio Quartulli   batman-adv: roami...
467
468
  
  	batadv_hash_remove(bat_priv->tt.global_hash, batadv_compare_tt,
c018ad3de   Antonio Quartulli   batman-adv: add t...
469
  			   batadv_choose_tt, &tt_global->common);
068ee6e20   Antonio Quartulli   batman-adv: roami...
470
  	batadv_tt_global_entry_free_ref(tt_global);
068ee6e20   Antonio Quartulli   batman-adv: roami...
471
  }
c018ad3de   Antonio Quartulli   batman-adv: add t...
472
473
474
475
476
477
478
479
  /**
   * batadv_tt_local_add - add a new client to the local table or update an
   *  existing client
   * @soft_iface: netdev struct of the mesh interface
   * @addr: the mac address of the client to add
   * @vid: VLAN identifier
   * @ifindex: index of the interface where the client is connected to (useful to
   *  identify wireless clients)
9464d0718   Antonio Quartulli   batman-adv: mark ...
480
481
   * @mark: the value contained in the skb->mark field of the received packet (if
   *  any)
a19d3d85e   Marek Lindner   batman-adv: limit...
482
483
   *
   * Returns true if the client was successfully added, false otherwise.
c018ad3de   Antonio Quartulli   batman-adv: add t...
484
   */
a19d3d85e   Marek Lindner   batman-adv: limit...
485
  bool batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
9464d0718   Antonio Quartulli   batman-adv: mark ...
486
  			 unsigned short vid, int ifindex, uint32_t mark)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
487
  {
56303d34a   Sven Eckelmann   batman-adv: Prefi...
488
  	struct batadv_priv *bat_priv = netdev_priv(soft_iface);
170173bf3   Sven Eckelmann   batman-adv: Remov...
489
  	struct batadv_tt_local_entry *tt_local;
c5caf4ef3   Linus Lüssing   batman-adv: Multi...
490
  	struct batadv_tt_global_entry *tt_global = NULL;
0c69aecc5   Antonio Quartulli   batman-adv: invok...
491
  	struct net_device *in_dev = NULL;
db08e6e55   Simon Wunderlich   batman-adv: allow...
492
  	struct hlist_head *head;
56303d34a   Sven Eckelmann   batman-adv: Prefi...
493
  	struct batadv_tt_orig_list_entry *orig_entry;
a19d3d85e   Marek Lindner   batman-adv: limit...
494
495
  	int hash_added, table_size, packet_size_max;
  	bool ret = false, roamed_back = false;
3c4f7ab60   Antonio Quartulli   batman-adv: impro...
496
  	uint8_t remote_flags;
9464d0718   Antonio Quartulli   batman-adv: mark ...
497
  	uint32_t match_mark;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
498

0c69aecc5   Antonio Quartulli   batman-adv: invok...
499
500
  	if (ifindex != BATADV_NULL_IFINDEX)
  		in_dev = dev_get_by_index(&init_net, ifindex);
c018ad3de   Antonio Quartulli   batman-adv: add t...
501
  	tt_local = batadv_tt_local_hash_find(bat_priv, addr, vid);
c5caf4ef3   Linus Lüssing   batman-adv: Multi...
502
503
504
  
  	if (!is_multicast_ether_addr(addr))
  		tt_global = batadv_tt_global_hash_find(bat_priv, addr, vid);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
505

47c94655c   Antonio Quartulli   batman-adv: refac...
506
507
  	if (tt_local) {
  		tt_local->last_seen = jiffies;
068ee6e20   Antonio Quartulli   batman-adv: roami...
508
509
  		if (tt_local->common.flags & BATADV_TT_CLIENT_PENDING) {
  			batadv_dbg(BATADV_DBG_TT, bat_priv,
160527890   Antonio Quartulli   batman-adv: print...
510
511
512
  				   "Re-adding pending client %pM (vid: %d)
  ",
  				   addr, BATADV_PRINT_VID(vid));
068ee6e20   Antonio Quartulli   batman-adv: roami...
513
514
515
516
517
518
519
520
521
522
523
  			/* whatever the reason why the PENDING flag was set,
  			 * this is a client which was enqueued to be removed in
  			 * this orig_interval. Since it popped up again, the
  			 * flag can be reset like it was never enqueued
  			 */
  			tt_local->common.flags &= ~BATADV_TT_CLIENT_PENDING;
  			goto add_event;
  		}
  
  		if (tt_local->common.flags & BATADV_TT_CLIENT_ROAM) {
  			batadv_dbg(BATADV_DBG_TT, bat_priv,
160527890   Antonio Quartulli   batman-adv: print...
524
525
526
  				   "Roaming client %pM (vid: %d) came back to its original location
  ",
  				   addr, BATADV_PRINT_VID(vid));
068ee6e20   Antonio Quartulli   batman-adv: roami...
527
528
529
530
531
532
533
534
535
  			/* the ROAM flag is set because this client roamed away
  			 * and the node got a roaming_advertisement message. Now
  			 * that the client popped up again at its original
  			 * location such flag can be unset
  			 */
  			tt_local->common.flags &= ~BATADV_TT_CLIENT_ROAM;
  			roamed_back = true;
  		}
  		goto check_roaming;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
536
  	}
a19d3d85e   Marek Lindner   batman-adv: limit...
537
538
539
540
541
542
543
544
545
546
547
  	/* Ignore the client if we cannot send it in a full table response. */
  	table_size = batadv_tt_local_table_transmit_size(bat_priv);
  	table_size += batadv_tt_len(1);
  	packet_size_max = atomic_read(&bat_priv->packet_size_max);
  	if (table_size > packet_size_max) {
  		net_ratelimited_function(batadv_info, soft_iface,
  					 "Local translation table size (%i) exceeds maximum packet size (%i); Ignoring new local tt entry: %pM
  ",
  					 table_size, packet_size_max, addr);
  		goto out;
  	}
47c94655c   Antonio Quartulli   batman-adv: refac...
548
549
  	tt_local = kmalloc(sizeof(*tt_local), GFP_ATOMIC);
  	if (!tt_local)
7683fdc1e   Antonio Quartulli   batman-adv: prote...
550
  		goto out;
a73105b8d   Antonio Quartulli   batman-adv: impro...
551

39c75a51e   Sven Eckelmann   batman-adv: Prefi...
552
  	batadv_dbg(BATADV_DBG_TT, bat_priv,
160527890   Antonio Quartulli   batman-adv: print...
553
554
555
  		   "Creating new local tt entry: %pM (vid: %d, ttvn: %d)
  ",
  		   addr, BATADV_PRINT_VID(vid),
807736f6e   Sven Eckelmann   batman-adv: Split...
556
  		   (uint8_t)atomic_read(&bat_priv->tt.vn));
c6c8fea29   Sven Eckelmann   net: Add batman-a...
557

8fdd01530   Antonio Quartulli   batman-adv: prefe...
558
  	ether_addr_copy(tt_local->common.addr, addr);
8425ec6ae   Antonio Quartulli   batman-adv: remov...
559
560
561
562
563
  	/* The local entry has to be marked as NEW to avoid to send it in
  	 * a full table response going out before the next ttvn increment
  	 * (consistency check)
  	 */
  	tt_local->common.flags = BATADV_TT_CLIENT_NEW;
c018ad3de   Antonio Quartulli   batman-adv: add t...
564
  	tt_local->common.vid = vid;
0c69aecc5   Antonio Quartulli   batman-adv: invok...
565
  	if (batadv_is_wifi_netdev(in_dev))
47c94655c   Antonio Quartulli   batman-adv: refac...
566
567
568
569
  		tt_local->common.flags |= BATADV_TT_CLIENT_WIFI;
  	atomic_set(&tt_local->common.refcount, 2);
  	tt_local->last_seen = jiffies;
  	tt_local->common.added_at = tt_local->last_seen;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
570

c5caf4ef3   Linus Lüssing   batman-adv: Multi...
571
572
573
574
575
  	/* the batman interface mac and multicast addresses should never be
  	 * purged
  	 */
  	if (batadv_compare_eth(addr, soft_iface->dev_addr) ||
  	    is_multicast_ether_addr(addr))
47c94655c   Antonio Quartulli   batman-adv: refac...
576
  		tt_local->common.flags |= BATADV_TT_CLIENT_NOPURGE;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
577

807736f6e   Sven Eckelmann   batman-adv: Split...
578
  	hash_added = batadv_hash_add(bat_priv->tt.local_hash, batadv_compare_tt,
c018ad3de   Antonio Quartulli   batman-adv: add t...
579
  				     batadv_choose_tt, &tt_local->common,
47c94655c   Antonio Quartulli   batman-adv: refac...
580
  				     &tt_local->common.hash_entry);
80b3f58cf   Simon Wunderlich   batman-adv: check...
581
582
583
  
  	if (unlikely(hash_added != 0)) {
  		/* remove the reference for the hash */
47c94655c   Antonio Quartulli   batman-adv: refac...
584
  		batadv_tt_local_entry_free_ref(tt_local);
80b3f58cf   Simon Wunderlich   batman-adv: check...
585
586
  		goto out;
  	}
068ee6e20   Antonio Quartulli   batman-adv: roami...
587
  add_event:
3abe4adbf   Antonio Quartulli   batman-adv: refac...
588
  	batadv_tt_local_event(bat_priv, tt_local, BATADV_NO_FLAGS);
ff66c975d   Antonio Quartulli   batman-adv: pass ...
589

068ee6e20   Antonio Quartulli   batman-adv: roami...
590
591
592
593
594
  check_roaming:
  	/* Check whether it is a roaming, but don't do anything if the roaming
  	 * process has already been handled
  	 */
  	if (tt_global && !(tt_global->common.flags & BATADV_TT_CLIENT_ROAM)) {
db08e6e55   Simon Wunderlich   batman-adv: allow...
595
  		/* These node are probably going to update their tt table */
47c94655c   Antonio Quartulli   batman-adv: refac...
596
  		head = &tt_global->orig_list;
db08e6e55   Simon Wunderlich   batman-adv: allow...
597
  		rcu_read_lock();
b67bfe0d4   Sasha Levin   hlist: drop the n...
598
  		hlist_for_each_entry_rcu(orig_entry, head, list) {
47c94655c   Antonio Quartulli   batman-adv: refac...
599
  			batadv_send_roam_adv(bat_priv, tt_global->common.addr,
c018ad3de   Antonio Quartulli   batman-adv: add t...
600
  					     tt_global->common.vid,
a513088d0   Sven Eckelmann   batman-adv: Prefi...
601
  					     orig_entry->orig_node);
db08e6e55   Simon Wunderlich   batman-adv: allow...
602
603
  		}
  		rcu_read_unlock();
068ee6e20   Antonio Quartulli   batman-adv: roami...
604
605
606
607
608
609
610
611
612
613
614
  		if (roamed_back) {
  			batadv_tt_global_free(bat_priv, tt_global,
  					      "Roaming canceled");
  			tt_global = NULL;
  		} else {
  			/* The global entry has to be marked as ROAMING and
  			 * has to be kept for consistency purpose
  			 */
  			tt_global->common.flags |= BATADV_TT_CLIENT_ROAM;
  			tt_global->roam_at = jiffies;
  		}
7683fdc1e   Antonio Quartulli   batman-adv: prote...
615
  	}
068ee6e20   Antonio Quartulli   batman-adv: roami...
616

3c4f7ab60   Antonio Quartulli   batman-adv: impro...
617
618
619
620
621
622
623
624
625
  	/* store the current remote flags before altering them. This helps
  	 * understanding is flags are changing or not
  	 */
  	remote_flags = tt_local->common.flags & BATADV_TT_REMOTE_MASK;
  
  	if (batadv_is_wifi_netdev(in_dev))
  		tt_local->common.flags |= BATADV_TT_CLIENT_WIFI;
  	else
  		tt_local->common.flags &= ~BATADV_TT_CLIENT_WIFI;
a19d3d85e   Marek Lindner   batman-adv: limit...
626

9464d0718   Antonio Quartulli   batman-adv: mark ...
627
628
629
630
631
632
633
634
635
636
  	/* check the mark in the skb: if it's equal to the configured
  	 * isolation_mark, it means the packet is coming from an isolated
  	 * non-mesh client
  	 */
  	match_mark = (mark & bat_priv->isolation_mark_mask);
  	if (bat_priv->isolation_mark_mask &&
  	    match_mark == bat_priv->isolation_mark)
  		tt_local->common.flags |= BATADV_TT_CLIENT_ISOLA;
  	else
  		tt_local->common.flags &= ~BATADV_TT_CLIENT_ISOLA;
3c4f7ab60   Antonio Quartulli   batman-adv: impro...
637
638
639
640
641
642
643
  	/* if any "dynamic" flag has been modified, resend an ADD event for this
  	 * entry so that all the nodes can get the new flags
  	 */
  	if (remote_flags ^ (tt_local->common.flags & BATADV_TT_REMOTE_MASK))
  		batadv_tt_local_event(bat_priv, tt_local, BATADV_NO_FLAGS);
  
  	ret = true;
7683fdc1e   Antonio Quartulli   batman-adv: prote...
644
  out:
0c69aecc5   Antonio Quartulli   batman-adv: invok...
645
646
  	if (in_dev)
  		dev_put(in_dev);
47c94655c   Antonio Quartulli   batman-adv: refac...
647
648
649
650
  	if (tt_local)
  		batadv_tt_local_entry_free_ref(tt_local);
  	if (tt_global)
  		batadv_tt_global_entry_free_ref(tt_global);
a19d3d85e   Marek Lindner   batman-adv: limit...
651
  	return ret;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
652
  }
e1bf0c140   Marek Lindner   batman-adv: tvlv ...
653
  /**
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
   * batadv_tt_prepare_tvlv_global_data - prepare the TVLV TT header to send
   *  within a TT Response directed to another node
   * @orig_node: originator for which the TT data has to be prepared
   * @tt_data: uninitialised pointer to the address of the TVLV buffer
   * @tt_change: uninitialised pointer to the address of the area where the TT
   *  changed can be stored
   * @tt_len: pointer to the length to reserve to the tt_change. if -1 this
   *  function reserves the amount of space needed to send the entire global TT
   *  table. In case of success the value is updated with the real amount of
   *  reserved bytes
  
   * Allocate the needed amount of memory for the entire TT TVLV and write its
   * header made up by one tvlv_tt_data object and a series of tvlv_tt_vlan_data
   * objects, one per active VLAN served by the originator node.
   *
   * Return the size of the allocated buffer or 0 in case of failure.
   */
  static uint16_t
  batadv_tt_prepare_tvlv_global_data(struct batadv_orig_node *orig_node,
  				   struct batadv_tvlv_tt_data **tt_data,
  				   struct batadv_tvlv_tt_change **tt_change,
  				   int32_t *tt_len)
  {
  	uint16_t num_vlan = 0, num_entries = 0, change_offset, tvlv_len;
  	struct batadv_tvlv_tt_vlan_data *tt_vlan;
  	struct batadv_orig_node_vlan *vlan;
  	uint8_t *tt_change_ptr;
  
  	rcu_read_lock();
  	list_for_each_entry_rcu(vlan, &orig_node->vlan_list, list) {
  		num_vlan++;
  		num_entries += atomic_read(&vlan->tt.num_entries);
  	}
  
  	change_offset = sizeof(**tt_data);
  	change_offset += num_vlan * sizeof(*tt_vlan);
  
  	/* if tt_len is negative, allocate the space needed by the full table */
  	if (*tt_len < 0)
  		*tt_len = batadv_tt_len(num_entries);
  
  	tvlv_len = *tt_len;
  	tvlv_len += change_offset;
  
  	*tt_data = kmalloc(tvlv_len, GFP_ATOMIC);
  	if (!*tt_data) {
  		*tt_len = 0;
  		goto out;
  	}
  
  	(*tt_data)->flags = BATADV_NO_FLAGS;
  	(*tt_data)->ttvn = atomic_read(&orig_node->last_ttvn);
  	(*tt_data)->num_vlan = htons(num_vlan);
  
  	tt_vlan = (struct batadv_tvlv_tt_vlan_data *)(*tt_data + 1);
  	list_for_each_entry_rcu(vlan, &orig_node->vlan_list, list) {
  		tt_vlan->vid = htons(vlan->vid);
  		tt_vlan->crc = htonl(vlan->tt.crc);
  
  		tt_vlan++;
  	}
  
  	tt_change_ptr = (uint8_t *)*tt_data + change_offset;
  	*tt_change = (struct batadv_tvlv_tt_change *)tt_change_ptr;
  
  out:
  	rcu_read_unlock();
  	return tvlv_len;
  }
  
  /**
   * batadv_tt_prepare_tvlv_local_data - allocate and prepare the TT TVLV for this
   *  node
   * @bat_priv: the bat priv with all the soft interface information
   * @tt_data: uninitialised pointer to the address of the TVLV buffer
   * @tt_change: uninitialised pointer to the address of the area where the TT
   *  changes can be stored
   * @tt_len: pointer to the length to reserve to the tt_change. if -1 this
   *  function reserves the amount of space needed to send the entire local TT
   *  table. In case of success the value is updated with the real amount of
   *  reserved bytes
   *
   * Allocate the needed amount of memory for the entire TT TVLV and write its
   * header made up by one tvlv_tt_data object and a series of tvlv_tt_vlan_data
   * objects, one per active VLAN.
   *
   * Return the size of the allocated buffer or 0 in case of failure.
   */
  static uint16_t
  batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv,
  				  struct batadv_tvlv_tt_data **tt_data,
  				  struct batadv_tvlv_tt_change **tt_change,
  				  int32_t *tt_len)
  {
  	struct batadv_tvlv_tt_vlan_data *tt_vlan;
  	struct batadv_softif_vlan *vlan;
  	uint16_t num_vlan = 0, num_entries = 0, tvlv_len;
  	uint8_t *tt_change_ptr;
  	int change_offset;
  
  	rcu_read_lock();
  	hlist_for_each_entry_rcu(vlan, &bat_priv->softif_vlan_list, list) {
  		num_vlan++;
  		num_entries += atomic_read(&vlan->tt.num_entries);
  	}
  
  	change_offset = sizeof(**tt_data);
  	change_offset += num_vlan * sizeof(*tt_vlan);
  
  	/* if tt_len is negative, allocate the space needed by the full table */
  	if (*tt_len < 0)
  		*tt_len = batadv_tt_len(num_entries);
  
  	tvlv_len = *tt_len;
  	tvlv_len += change_offset;
  
  	*tt_data = kmalloc(tvlv_len, GFP_ATOMIC);
  	if (!*tt_data) {
  		tvlv_len = 0;
  		goto out;
  	}
  
  	(*tt_data)->flags = BATADV_NO_FLAGS;
  	(*tt_data)->ttvn = atomic_read(&bat_priv->tt.vn);
  	(*tt_data)->num_vlan = htons(num_vlan);
  
  	tt_vlan = (struct batadv_tvlv_tt_vlan_data *)(*tt_data + 1);
  	hlist_for_each_entry_rcu(vlan, &bat_priv->softif_vlan_list, list) {
  		tt_vlan->vid = htons(vlan->vid);
  		tt_vlan->crc = htonl(vlan->tt.crc);
  
  		tt_vlan++;
  	}
  
  	tt_change_ptr = (uint8_t *)*tt_data + change_offset;
  	*tt_change = (struct batadv_tvlv_tt_change *)tt_change_ptr;
  
  out:
  	rcu_read_unlock();
  	return tvlv_len;
  }
  
  /**
e1bf0c140   Marek Lindner   batman-adv: tvlv ...
797
798
799
800
801
   * batadv_tt_tvlv_container_update - update the translation table tvlv container
   *  after local tt changes have been committed
   * @bat_priv: the bat priv with all the soft interface information
   */
  static void batadv_tt_tvlv_container_update(struct batadv_priv *bat_priv)
be9aa4c1e   Marek Lindner   batman-adv: turn ...
802
  {
e1bf0c140   Marek Lindner   batman-adv: tvlv ...
803
804
805
  	struct batadv_tt_change_node *entry, *safe;
  	struct batadv_tvlv_tt_data *tt_data;
  	struct batadv_tvlv_tt_change *tt_change;
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
806
  	int tt_diff_len, tt_change_len = 0;
e1bf0c140   Marek Lindner   batman-adv: tvlv ...
807
  	int tt_diff_entries_num = 0, tt_diff_entries_count = 0;
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
808
  	uint16_t tvlv_len;
be9aa4c1e   Marek Lindner   batman-adv: turn ...
809

7ea7b4a14   Antonio Quartulli   batman-adv: make ...
810
811
  	tt_diff_entries_num = atomic_read(&bat_priv->tt.local_changes);
  	tt_diff_len = batadv_tt_len(tt_diff_entries_num);
be9aa4c1e   Marek Lindner   batman-adv: turn ...
812
813
814
815
  
  	/* if we have too many changes for one packet don't send any
  	 * and wait for the tt table request which will be fragmented
  	 */
e1bf0c140   Marek Lindner   batman-adv: tvlv ...
816
817
  	if (tt_diff_len > bat_priv->soft_iface->mtu)
  		tt_diff_len = 0;
be9aa4c1e   Marek Lindner   batman-adv: turn ...
818

7ea7b4a14   Antonio Quartulli   batman-adv: make ...
819
820
821
  	tvlv_len = batadv_tt_prepare_tvlv_local_data(bat_priv, &tt_data,
  						     &tt_change, &tt_diff_len);
  	if (!tvlv_len)
e1bf0c140   Marek Lindner   batman-adv: tvlv ...
822
  		return;
be9aa4c1e   Marek Lindner   batman-adv: turn ...
823

e1bf0c140   Marek Lindner   batman-adv: tvlv ...
824
  	tt_data->flags = BATADV_TT_OGM_DIFF;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
825

e1bf0c140   Marek Lindner   batman-adv: tvlv ...
826
827
  	if (tt_diff_len == 0)
  		goto container_register;
be9aa4c1e   Marek Lindner   batman-adv: turn ...
828

807736f6e   Sven Eckelmann   batman-adv: Split...
829
830
  	spin_lock_bh(&bat_priv->tt.changes_list_lock);
  	atomic_set(&bat_priv->tt.local_changes, 0);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
831

807736f6e   Sven Eckelmann   batman-adv: Split...
832
  	list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list,
7c64fd98c   Sven Eckelmann   batman-adv: Fix i...
833
  				 list) {
e1bf0c140   Marek Lindner   batman-adv: tvlv ...
834
835
836
837
838
  		if (tt_diff_entries_count < tt_diff_entries_num) {
  			memcpy(tt_change + tt_diff_entries_count,
  			       &entry->change,
  			       sizeof(struct batadv_tvlv_tt_change));
  			tt_diff_entries_count++;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
839
  		}
a73105b8d   Antonio Quartulli   batman-adv: impro...
840
841
  		list_del(&entry->list);
  		kfree(entry);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
842
  	}
807736f6e   Sven Eckelmann   batman-adv: Split...
843
  	spin_unlock_bh(&bat_priv->tt.changes_list_lock);
a73105b8d   Antonio Quartulli   batman-adv: impro...
844
845
  
  	/* Keep the buffer for possible tt_request */
807736f6e   Sven Eckelmann   batman-adv: Split...
846
847
848
849
  	spin_lock_bh(&bat_priv->tt.last_changeset_lock);
  	kfree(bat_priv->tt.last_changeset);
  	bat_priv->tt.last_changeset_len = 0;
  	bat_priv->tt.last_changeset = NULL;
e1bf0c140   Marek Lindner   batman-adv: tvlv ...
850
  	tt_change_len = batadv_tt_len(tt_diff_entries_count);
be9aa4c1e   Marek Lindner   batman-adv: turn ...
851
  	/* check whether this new OGM has no changes due to size problems */
e1bf0c140   Marek Lindner   batman-adv: tvlv ...
852
  	if (tt_diff_entries_count > 0) {
be9aa4c1e   Marek Lindner   batman-adv: turn ...
853
  		/* if kmalloc() fails we will reply with the full table
a73105b8d   Antonio Quartulli   batman-adv: impro...
854
855
  		 * instead of providing the diff
  		 */
e1bf0c140   Marek Lindner   batman-adv: tvlv ...
856
  		bat_priv->tt.last_changeset = kzalloc(tt_diff_len, GFP_ATOMIC);
807736f6e   Sven Eckelmann   batman-adv: Split...
857
  		if (bat_priv->tt.last_changeset) {
e1bf0c140   Marek Lindner   batman-adv: tvlv ...
858
859
860
  			memcpy(bat_priv->tt.last_changeset,
  			       tt_change, tt_change_len);
  			bat_priv->tt.last_changeset_len = tt_diff_len;
a73105b8d   Antonio Quartulli   batman-adv: impro...
861
862
  		}
  	}
807736f6e   Sven Eckelmann   batman-adv: Split...
863
  	spin_unlock_bh(&bat_priv->tt.last_changeset_lock);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
864

e1bf0c140   Marek Lindner   batman-adv: tvlv ...
865
866
  container_register:
  	batadv_tvlv_container_register(bat_priv, BATADV_TVLV_TT, 1, tt_data,
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
867
  				       tvlv_len);
e1bf0c140   Marek Lindner   batman-adv: tvlv ...
868
  	kfree(tt_data);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
869
  }
08c36d3e8   Sven Eckelmann   batman-adv: Prefi...
870
  int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
871
872
  {
  	struct net_device *net_dev = (struct net_device *)seq->private;
56303d34a   Sven Eckelmann   batman-adv: Prefi...
873
  	struct batadv_priv *bat_priv = netdev_priv(net_dev);
807736f6e   Sven Eckelmann   batman-adv: Split...
874
  	struct batadv_hashtable *hash = bat_priv->tt.local_hash;
56303d34a   Sven Eckelmann   batman-adv: Prefi...
875
  	struct batadv_tt_common_entry *tt_common_entry;
85766a820   Antonio Quartulli   batman-adv: impro...
876
  	struct batadv_tt_local_entry *tt_local;
56303d34a   Sven Eckelmann   batman-adv: Prefi...
877
  	struct batadv_hard_iface *primary_if;
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
878
  	struct batadv_softif_vlan *vlan;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
879
  	struct hlist_head *head;
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
880
  	unsigned short vid;
c90681b85   Antonio Quartulli   batman-adv: fixed...
881
  	uint32_t i;
85766a820   Antonio Quartulli   batman-adv: impro...
882
883
884
885
886
  	int last_seen_secs;
  	int last_seen_msecs;
  	unsigned long last_seen_jiffies;
  	bool no_purge;
  	uint16_t np_flag = BATADV_TT_CLIENT_NOPURGE;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
887

30da63a6a   Marek Lindner   batman-adv: conso...
888
889
  	primary_if = batadv_seq_print_text_primary_if_get(seq);
  	if (!primary_if)
32ae9b221   Marek Lindner   batman-adv: Make ...
890
  		goto out;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
891

86ceb3605   Sven Eckelmann   batman-adv: Ignor...
892
  	seq_printf(seq,
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
893
894
895
  		   "Locally retrieved addresses (from %s) announced via TT (TTVN: %u):
  ",
  		   net_dev->name, (uint8_t)atomic_read(&bat_priv->tt.vn));
dd24ddb26   Antonio Quartulli   batman-adv: print...
896
897
  	seq_printf(seq, "       %-13s  %s %-8s %-9s (%-10s)
  ", "Client", "VID",
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
898
  		   "Flags", "Last seen", "CRC");
c6c8fea29   Sven Eckelmann   net: Add batman-a...
899

c6c8fea29   Sven Eckelmann   net: Add batman-a...
900
901
  	for (i = 0; i < hash->size; i++) {
  		head = &hash->table[i];
7aadf889e   Marek Lindner   batman-adv: remov...
902
  		rcu_read_lock();
b67bfe0d4   Sasha Levin   hlist: drop the n...
903
  		hlist_for_each_entry_rcu(tt_common_entry,
7aadf889e   Marek Lindner   batman-adv: remov...
904
  					 head, hash_entry) {
85766a820   Antonio Quartulli   batman-adv: impro...
905
906
907
  			tt_local = container_of(tt_common_entry,
  						struct batadv_tt_local_entry,
  						common);
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
908
  			vid = tt_common_entry->vid;
85766a820   Antonio Quartulli   batman-adv: impro...
909
910
911
912
913
914
  			last_seen_jiffies = jiffies - tt_local->last_seen;
  			last_seen_msecs = jiffies_to_msecs(last_seen_jiffies);
  			last_seen_secs = last_seen_msecs / 1000;
  			last_seen_msecs = last_seen_msecs % 1000;
  
  			no_purge = tt_common_entry->flags & np_flag;
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
915
916
917
918
919
920
921
922
923
  			vlan = batadv_softif_vlan_get(bat_priv, vid);
  			if (!vlan) {
  				seq_printf(seq, "Cannot retrieve VLAN %d
  ",
  					   BATADV_PRINT_VID(vid));
  				continue;
  			}
  
  			seq_printf(seq,
dd24ddb26   Antonio Quartulli   batman-adv: print...
924
925
  				   " * %pM %4i [%c%c%c%c%c%c] %3u.%03u   (%#.8x)
  ",
7c64fd98c   Sven Eckelmann   batman-adv: Fix i...
926
  				   tt_common_entry->addr,
160527890   Antonio Quartulli   batman-adv: print...
927
  				   BATADV_PRINT_VID(tt_common_entry->vid),
7c64fd98c   Sven Eckelmann   batman-adv: Fix i...
928
  				   (tt_common_entry->flags &
acd34afa8   Sven Eckelmann   batman-adv: Prefi...
929
  				    BATADV_TT_CLIENT_ROAM ? 'R' : '.'),
85766a820   Antonio Quartulli   batman-adv: impro...
930
  				   no_purge ? 'P' : '.',
7c64fd98c   Sven Eckelmann   batman-adv: Fix i...
931
  				   (tt_common_entry->flags &
acd34afa8   Sven Eckelmann   batman-adv: Prefi...
932
  				    BATADV_TT_CLIENT_NEW ? 'N' : '.'),
7c64fd98c   Sven Eckelmann   batman-adv: Fix i...
933
  				   (tt_common_entry->flags &
acd34afa8   Sven Eckelmann   batman-adv: Prefi...
934
  				    BATADV_TT_CLIENT_PENDING ? 'X' : '.'),
7c64fd98c   Sven Eckelmann   batman-adv: Fix i...
935
  				   (tt_common_entry->flags &
85766a820   Antonio Quartulli   batman-adv: impro...
936
  				    BATADV_TT_CLIENT_WIFI ? 'W' : '.'),
dd24ddb26   Antonio Quartulli   batman-adv: print...
937
938
  				   (tt_common_entry->flags &
  				    BATADV_TT_CLIENT_ISOLA ? 'I' : '.'),
a7966d908   Antonio Quartulli   batman-adv: fix l...
939
  				   no_purge ? 0 : last_seen_secs,
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
940
941
942
943
  				   no_purge ? 0 : last_seen_msecs,
  				   vlan->tt.crc);
  
  			batadv_softif_vlan_free_ref(vlan);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
944
  		}
7aadf889e   Marek Lindner   batman-adv: remov...
945
  		rcu_read_unlock();
c6c8fea29   Sven Eckelmann   net: Add batman-a...
946
  	}
32ae9b221   Marek Lindner   batman-adv: Make ...
947
948
  out:
  	if (primary_if)
e5d89254b   Sven Eckelmann   batman-adv: Prefi...
949
  		batadv_hardif_free_ref(primary_if);
30da63a6a   Marek Lindner   batman-adv: conso...
950
  	return 0;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
951
  }
56303d34a   Sven Eckelmann   batman-adv: Prefi...
952
953
954
955
  static void
  batadv_tt_local_set_pending(struct batadv_priv *bat_priv,
  			    struct batadv_tt_local_entry *tt_local_entry,
  			    uint16_t flags, const char *message)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
956
  {
3abe4adbf   Antonio Quartulli   batman-adv: refac...
957
  	batadv_tt_local_event(bat_priv, tt_local_entry, flags);
a73105b8d   Antonio Quartulli   batman-adv: impro...
958

015758d00   Antonio Quartulli   batman-adv: corre...
959
960
  	/* The local client has to be marked as "pending to be removed" but has
  	 * to be kept in the table in order to send it in a full table
9cfc7bd60   Sven Eckelmann   batman-adv: Refor...
961
962
  	 * response issued before the net ttvn increment (consistency check)
  	 */
acd34afa8   Sven Eckelmann   batman-adv: Prefi...
963
  	tt_local_entry->common.flags |= BATADV_TT_CLIENT_PENDING;
c566dbbef   Antonio Quartulli   batman-adv: code ...
964

39c75a51e   Sven Eckelmann   batman-adv: Prefi...
965
  	batadv_dbg(BATADV_DBG_TT, bat_priv,
160527890   Antonio Quartulli   batman-adv: print...
966
967
968
969
  		   "Local tt entry (%pM, vid: %d) pending to be removed: %s
  ",
  		   tt_local_entry->common.addr,
  		   BATADV_PRINT_VID(tt_local_entry->common.vid), message);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
970
  }
7f91d06c9   Antonio Quartulli   batman-adv: pass ...
971
972
973
974
  /**
   * batadv_tt_local_remove - logically remove an entry from the local table
   * @bat_priv: the bat priv with all the soft interface information
   * @addr: the MAC address of the client to remove
c018ad3de   Antonio Quartulli   batman-adv: add t...
975
   * @vid: VLAN identifier
7f91d06c9   Antonio Quartulli   batman-adv: pass ...
976
977
978
979
980
981
   * @message: message to append to the log on deletion
   * @roaming: true if the deletion is due to a roaming event
   *
   * Returns the flags assigned to the local entry before being deleted
   */
  uint16_t batadv_tt_local_remove(struct batadv_priv *bat_priv,
c018ad3de   Antonio Quartulli   batman-adv: add t...
982
983
  				const uint8_t *addr, unsigned short vid,
  				const char *message, bool roaming)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
984
  {
170173bf3   Sven Eckelmann   batman-adv: Remov...
985
  	struct batadv_tt_local_entry *tt_local_entry;
7f91d06c9   Antonio Quartulli   batman-adv: pass ...
986
  	uint16_t flags, curr_flags = BATADV_NO_FLAGS;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
987

c018ad3de   Antonio Quartulli   batman-adv: add t...
988
  	tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr, vid);
7683fdc1e   Antonio Quartulli   batman-adv: prote...
989
990
  	if (!tt_local_entry)
  		goto out;
7f91d06c9   Antonio Quartulli   batman-adv: pass ...
991
  	curr_flags = tt_local_entry->common.flags;
acd34afa8   Sven Eckelmann   batman-adv: Prefi...
992
  	flags = BATADV_TT_CLIENT_DEL;
068ee6e20   Antonio Quartulli   batman-adv: roami...
993
994
995
996
  	/* if this global entry addition is due to a roaming, the node has to
  	 * mark the local entry as "roamed" in order to correctly reroute
  	 * packets later
  	 */
7c1fd91da   Antonio Quartulli   batman-adv: subst...
997
  	if (roaming) {
acd34afa8   Sven Eckelmann   batman-adv: Prefi...
998
  		flags |= BATADV_TT_CLIENT_ROAM;
7c1fd91da   Antonio Quartulli   batman-adv: subst...
999
1000
1001
  		/* mark the local client as ROAMed */
  		tt_local_entry->common.flags |= BATADV_TT_CLIENT_ROAM;
  	}
42d0b044b   Sven Eckelmann   batman-adv: Prefi...
1002

068ee6e20   Antonio Quartulli   batman-adv: roami...
1003
1004
1005
1006
1007
1008
1009
1010
  	if (!(tt_local_entry->common.flags & BATADV_TT_CLIENT_NEW)) {
  		batadv_tt_local_set_pending(bat_priv, tt_local_entry, flags,
  					    message);
  		goto out;
  	}
  	/* if this client has been added right now, it is possible to
  	 * immediately purge it
  	 */
3abe4adbf   Antonio Quartulli   batman-adv: refac...
1011
  	batadv_tt_local_event(bat_priv, tt_local_entry, BATADV_TT_CLIENT_DEL);
068ee6e20   Antonio Quartulli   batman-adv: roami...
1012
1013
  	hlist_del_rcu(&tt_local_entry->common.hash_entry);
  	batadv_tt_local_entry_free_ref(tt_local_entry);
7f91d06c9   Antonio Quartulli   batman-adv: pass ...
1014

7683fdc1e   Antonio Quartulli   batman-adv: prote...
1015
1016
  out:
  	if (tt_local_entry)
a513088d0   Sven Eckelmann   batman-adv: Prefi...
1017
  		batadv_tt_local_entry_free_ref(tt_local_entry);
7f91d06c9   Antonio Quartulli   batman-adv: pass ...
1018
1019
  
  	return curr_flags;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1020
  }
a19d3d85e   Marek Lindner   batman-adv: limit...
1021
1022
1023
1024
1025
1026
1027
  /**
   * batadv_tt_local_purge_list - purge inactive tt local entries
   * @bat_priv: the bat priv with all the soft interface information
   * @head: pointer to the list containing the local tt entries
   * @timeout: parameter deciding whether a given tt local entry is considered
   *  inactive or not
   */
56303d34a   Sven Eckelmann   batman-adv: Prefi...
1028
  static void batadv_tt_local_purge_list(struct batadv_priv *bat_priv,
a19d3d85e   Marek Lindner   batman-adv: limit...
1029
1030
  				       struct hlist_head *head,
  				       int timeout)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1031
  {
56303d34a   Sven Eckelmann   batman-adv: Prefi...
1032
1033
  	struct batadv_tt_local_entry *tt_local_entry;
  	struct batadv_tt_common_entry *tt_common_entry;
b67bfe0d4   Sasha Levin   hlist: drop the n...
1034
  	struct hlist_node *node_tmp;
acd34afa8   Sven Eckelmann   batman-adv: Prefi...
1035

b67bfe0d4   Sasha Levin   hlist: drop the n...
1036
  	hlist_for_each_entry_safe(tt_common_entry, node_tmp, head,
acd34afa8   Sven Eckelmann   batman-adv: Prefi...
1037
1038
  				  hash_entry) {
  		tt_local_entry = container_of(tt_common_entry,
56303d34a   Sven Eckelmann   batman-adv: Prefi...
1039
1040
  					      struct batadv_tt_local_entry,
  					      common);
acd34afa8   Sven Eckelmann   batman-adv: Prefi...
1041
1042
1043
1044
1045
1046
  		if (tt_local_entry->common.flags & BATADV_TT_CLIENT_NOPURGE)
  			continue;
  
  		/* entry already marked for deletion */
  		if (tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING)
  			continue;
a19d3d85e   Marek Lindner   batman-adv: limit...
1047
  		if (!batadv_has_timed_out(tt_local_entry->last_seen, timeout))
acd34afa8   Sven Eckelmann   batman-adv: Prefi...
1048
1049
1050
1051
1052
1053
  			continue;
  
  		batadv_tt_local_set_pending(bat_priv, tt_local_entry,
  					    BATADV_TT_CLIENT_DEL, "timed out");
  	}
  }
a19d3d85e   Marek Lindner   batman-adv: limit...
1054
1055
1056
1057
1058
1059
1060
1061
  /**
   * batadv_tt_local_purge - purge inactive tt local entries
   * @bat_priv: the bat priv with all the soft interface information
   * @timeout: parameter deciding whether a given tt local entry is considered
   *  inactive or not
   */
  static void batadv_tt_local_purge(struct batadv_priv *bat_priv,
  				  int timeout)
acd34afa8   Sven Eckelmann   batman-adv: Prefi...
1062
  {
807736f6e   Sven Eckelmann   batman-adv: Split...
1063
  	struct batadv_hashtable *hash = bat_priv->tt.local_hash;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1064
  	struct hlist_head *head;
7683fdc1e   Antonio Quartulli   batman-adv: prote...
1065
  	spinlock_t *list_lock; /* protects write access to the hash lists */
c90681b85   Antonio Quartulli   batman-adv: fixed...
1066
  	uint32_t i;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1067

c6c8fea29   Sven Eckelmann   net: Add batman-a...
1068
1069
  	for (i = 0; i < hash->size; i++) {
  		head = &hash->table[i];
7683fdc1e   Antonio Quartulli   batman-adv: prote...
1070
  		list_lock = &hash->list_locks[i];
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1071

7683fdc1e   Antonio Quartulli   batman-adv: prote...
1072
  		spin_lock_bh(list_lock);
a19d3d85e   Marek Lindner   batman-adv: limit...
1073
  		batadv_tt_local_purge_list(bat_priv, head, timeout);
7683fdc1e   Antonio Quartulli   batman-adv: prote...
1074
  		spin_unlock_bh(list_lock);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1075
  	}
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1076
  }
56303d34a   Sven Eckelmann   batman-adv: Prefi...
1077
  static void batadv_tt_local_table_free(struct batadv_priv *bat_priv)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1078
  {
5bf74e9ca   Sven Eckelmann   batman-adv: Prefi...
1079
  	struct batadv_hashtable *hash;
a73105b8d   Antonio Quartulli   batman-adv: impro...
1080
  	spinlock_t *list_lock; /* protects write access to the hash lists */
56303d34a   Sven Eckelmann   batman-adv: Prefi...
1081
1082
  	struct batadv_tt_common_entry *tt_common_entry;
  	struct batadv_tt_local_entry *tt_local;
b67bfe0d4   Sasha Levin   hlist: drop the n...
1083
  	struct hlist_node *node_tmp;
7683fdc1e   Antonio Quartulli   batman-adv: prote...
1084
  	struct hlist_head *head;
c90681b85   Antonio Quartulli   batman-adv: fixed...
1085
  	uint32_t i;
a73105b8d   Antonio Quartulli   batman-adv: impro...
1086

807736f6e   Sven Eckelmann   batman-adv: Split...
1087
  	if (!bat_priv->tt.local_hash)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1088
  		return;
807736f6e   Sven Eckelmann   batman-adv: Split...
1089
  	hash = bat_priv->tt.local_hash;
a73105b8d   Antonio Quartulli   batman-adv: impro...
1090
1091
1092
1093
1094
1095
  
  	for (i = 0; i < hash->size; i++) {
  		head = &hash->table[i];
  		list_lock = &hash->list_locks[i];
  
  		spin_lock_bh(list_lock);
b67bfe0d4   Sasha Levin   hlist: drop the n...
1096
  		hlist_for_each_entry_safe(tt_common_entry, node_tmp,
a73105b8d   Antonio Quartulli   batman-adv: impro...
1097
  					  head, hash_entry) {
b67bfe0d4   Sasha Levin   hlist: drop the n...
1098
  			hlist_del_rcu(&tt_common_entry->hash_entry);
56303d34a   Sven Eckelmann   batman-adv: Prefi...
1099
1100
1101
1102
  			tt_local = container_of(tt_common_entry,
  						struct batadv_tt_local_entry,
  						common);
  			batadv_tt_local_entry_free_ref(tt_local);
a73105b8d   Antonio Quartulli   batman-adv: impro...
1103
1104
1105
  		}
  		spin_unlock_bh(list_lock);
  	}
1a8eaf073   Sven Eckelmann   batman-adv: Prefi...
1106
  	batadv_hash_destroy(hash);
a73105b8d   Antonio Quartulli   batman-adv: impro...
1107

807736f6e   Sven Eckelmann   batman-adv: Split...
1108
  	bat_priv->tt.local_hash = NULL;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1109
  }
56303d34a   Sven Eckelmann   batman-adv: Prefi...
1110
  static int batadv_tt_global_init(struct batadv_priv *bat_priv)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1111
  {
807736f6e   Sven Eckelmann   batman-adv: Split...
1112
  	if (bat_priv->tt.global_hash)
5346c35eb   Sven Eckelmann   batman-adv: Retur...
1113
  		return 0;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1114

807736f6e   Sven Eckelmann   batman-adv: Split...
1115
  	bat_priv->tt.global_hash = batadv_hash_new(1024);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1116

807736f6e   Sven Eckelmann   batman-adv: Split...
1117
  	if (!bat_priv->tt.global_hash)
5346c35eb   Sven Eckelmann   batman-adv: Retur...
1118
  		return -ENOMEM;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1119

dec05074b   Antonio Quartulli   batman-adv: Initi...
1120
1121
  	batadv_hash_set_lock_class(bat_priv->tt.global_hash,
  				   &batadv_tt_global_hash_lock_class_key);
5346c35eb   Sven Eckelmann   batman-adv: Retur...
1122
  	return 0;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1123
  }
56303d34a   Sven Eckelmann   batman-adv: Prefi...
1124
  static void batadv_tt_changes_list_free(struct batadv_priv *bat_priv)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1125
  {
56303d34a   Sven Eckelmann   batman-adv: Prefi...
1126
  	struct batadv_tt_change_node *entry, *safe;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1127

807736f6e   Sven Eckelmann   batman-adv: Split...
1128
  	spin_lock_bh(&bat_priv->tt.changes_list_lock);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1129

807736f6e   Sven Eckelmann   batman-adv: Split...
1130
  	list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list,
a73105b8d   Antonio Quartulli   batman-adv: impro...
1131
1132
1133
1134
  				 list) {
  		list_del(&entry->list);
  		kfree(entry);
  	}
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1135

807736f6e   Sven Eckelmann   batman-adv: Split...
1136
1137
  	atomic_set(&bat_priv->tt.local_changes, 0);
  	spin_unlock_bh(&bat_priv->tt.changes_list_lock);
a73105b8d   Antonio Quartulli   batman-adv: impro...
1138
  }
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1139

d657e621a   Antonio Quartulli   batman-adv: add r...
1140
1141
1142
1143
  /* retrieves the orig_tt_list_entry belonging to orig_node from the
   * batadv_tt_global_entry list
   *
   * returns it with an increased refcounter, NULL if not found
db08e6e55   Simon Wunderlich   batman-adv: allow...
1144
   */
d657e621a   Antonio Quartulli   batman-adv: add r...
1145
1146
1147
  static struct batadv_tt_orig_list_entry *
  batadv_tt_global_orig_entry_find(const struct batadv_tt_global_entry *entry,
  				 const struct batadv_orig_node *orig_node)
db08e6e55   Simon Wunderlich   batman-adv: allow...
1148
  {
d657e621a   Antonio Quartulli   batman-adv: add r...
1149
  	struct batadv_tt_orig_list_entry *tmp_orig_entry, *orig_entry = NULL;
db08e6e55   Simon Wunderlich   batman-adv: allow...
1150
  	const struct hlist_head *head;
db08e6e55   Simon Wunderlich   batman-adv: allow...
1151
1152
1153
  
  	rcu_read_lock();
  	head = &entry->orig_list;
b67bfe0d4   Sasha Levin   hlist: drop the n...
1154
  	hlist_for_each_entry_rcu(tmp_orig_entry, head, list) {
d657e621a   Antonio Quartulli   batman-adv: add r...
1155
1156
1157
1158
1159
1160
1161
  		if (tmp_orig_entry->orig_node != orig_node)
  			continue;
  		if (!atomic_inc_not_zero(&tmp_orig_entry->refcount))
  			continue;
  
  		orig_entry = tmp_orig_entry;
  		break;
db08e6e55   Simon Wunderlich   batman-adv: allow...
1162
1163
  	}
  	rcu_read_unlock();
d657e621a   Antonio Quartulli   batman-adv: add r...
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
  
  	return orig_entry;
  }
  
  /* find out if an orig_node is already in the list of a tt_global_entry.
   * returns true if found, false otherwise
   */
  static bool
  batadv_tt_global_entry_has_orig(const struct batadv_tt_global_entry *entry,
  				const struct batadv_orig_node *orig_node)
  {
  	struct batadv_tt_orig_list_entry *orig_entry;
  	bool found = false;
  
  	orig_entry = batadv_tt_global_orig_entry_find(entry, orig_node);
  	if (orig_entry) {
  		found = true;
  		batadv_tt_orig_list_entry_free_ref(orig_entry);
  	}
db08e6e55   Simon Wunderlich   batman-adv: allow...
1183
1184
  	return found;
  }
a513088d0   Sven Eckelmann   batman-adv: Prefi...
1185
  static void
d657e621a   Antonio Quartulli   batman-adv: add r...
1186
  batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global,
56303d34a   Sven Eckelmann   batman-adv: Prefi...
1187
  				struct batadv_orig_node *orig_node, int ttvn)
db08e6e55   Simon Wunderlich   batman-adv: allow...
1188
  {
56303d34a   Sven Eckelmann   batman-adv: Prefi...
1189
  	struct batadv_tt_orig_list_entry *orig_entry;
db08e6e55   Simon Wunderlich   batman-adv: allow...
1190

d657e621a   Antonio Quartulli   batman-adv: add r...
1191
  	orig_entry = batadv_tt_global_orig_entry_find(tt_global, orig_node);
30cfd02b6   Antonio Quartulli   batman-adv: detec...
1192
1193
1194
1195
1196
  	if (orig_entry) {
  		/* refresh the ttvn: the current value could be a bogus one that
  		 * was added during a "temporary client detection"
  		 */
  		orig_entry->ttvn = ttvn;
d657e621a   Antonio Quartulli   batman-adv: add r...
1197
  		goto out;
30cfd02b6   Antonio Quartulli   batman-adv: detec...
1198
  	}
d657e621a   Antonio Quartulli   batman-adv: add r...
1199

db08e6e55   Simon Wunderlich   batman-adv: allow...
1200
1201
  	orig_entry = kzalloc(sizeof(*orig_entry), GFP_ATOMIC);
  	if (!orig_entry)
d657e621a   Antonio Quartulli   batman-adv: add r...
1202
  		goto out;
db08e6e55   Simon Wunderlich   batman-adv: allow...
1203
1204
1205
  
  	INIT_HLIST_NODE(&orig_entry->list);
  	atomic_inc(&orig_node->refcount);
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
1206
  	batadv_tt_global_size_inc(orig_node, tt_global->common.vid);
db08e6e55   Simon Wunderlich   batman-adv: allow...
1207
1208
  	orig_entry->orig_node = orig_node;
  	orig_entry->ttvn = ttvn;
d657e621a   Antonio Quartulli   batman-adv: add r...
1209
  	atomic_set(&orig_entry->refcount, 2);
db08e6e55   Simon Wunderlich   batman-adv: allow...
1210

d657e621a   Antonio Quartulli   batman-adv: add r...
1211
  	spin_lock_bh(&tt_global->list_lock);
db08e6e55   Simon Wunderlich   batman-adv: allow...
1212
  	hlist_add_head_rcu(&orig_entry->list,
d657e621a   Antonio Quartulli   batman-adv: add r...
1213
1214
  			   &tt_global->orig_list);
  	spin_unlock_bh(&tt_global->list_lock);
1d8ab8d3c   Linus Lüssing   batman-adv: Modif...
1215
  	atomic_inc(&tt_global->orig_list_count);
d657e621a   Antonio Quartulli   batman-adv: add r...
1216
1217
1218
  out:
  	if (orig_entry)
  		batadv_tt_orig_list_entry_free_ref(orig_entry);
db08e6e55   Simon Wunderlich   batman-adv: allow...
1219
  }
d4ff40f68   Antonio Quartulli   batman-adv: pass ...
1220
1221
1222
1223
1224
  /**
   * batadv_tt_global_add - add a new TT global entry or update an existing one
   * @bat_priv: the bat priv with all the soft interface information
   * @orig_node: the originator announcing the client
   * @tt_addr: the mac address of the non-mesh client
c018ad3de   Antonio Quartulli   batman-adv: add t...
1225
   * @vid: VLAN identifier
d4ff40f68   Antonio Quartulli   batman-adv: pass ...
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
   * @flags: TT flags that have to be set for this non-mesh client
   * @ttvn: the tt version number ever announcing this non-mesh client
   *
   * Add a new TT global entry for the given originator. If the entry already
   * exists add a new reference to the given originator (a global entry can have
   * references to multiple originators) and adjust the flags attribute to reflect
   * the function argument.
   * If a TT local entry exists for this non-mesh client remove it.
   *
   * The caller must hold orig_node refcount.
1e5d49fce   Antonio Quartulli   batman-adv: make ...
1236
1237
   *
   * Return true if the new entry has been added, false otherwise
d4ff40f68   Antonio Quartulli   batman-adv: pass ...
1238
   */
1e5d49fce   Antonio Quartulli   batman-adv: make ...
1239
1240
  static bool batadv_tt_global_add(struct batadv_priv *bat_priv,
  				 struct batadv_orig_node *orig_node,
c018ad3de   Antonio Quartulli   batman-adv: add t...
1241
1242
  				 const unsigned char *tt_addr,
  				 unsigned short vid, uint16_t flags,
1e5d49fce   Antonio Quartulli   batman-adv: make ...
1243
  				 uint8_t ttvn)
a73105b8d   Antonio Quartulli   batman-adv: impro...
1244
  {
170173bf3   Sven Eckelmann   batman-adv: Remov...
1245
1246
  	struct batadv_tt_global_entry *tt_global_entry;
  	struct batadv_tt_local_entry *tt_local_entry;
1e5d49fce   Antonio Quartulli   batman-adv: make ...
1247
  	bool ret = false;
80b3f58cf   Simon Wunderlich   batman-adv: check...
1248
  	int hash_added;
56303d34a   Sven Eckelmann   batman-adv: Prefi...
1249
  	struct batadv_tt_common_entry *common;
7f91d06c9   Antonio Quartulli   batman-adv: pass ...
1250
  	uint16_t local_flags;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1251

cfd4f7570   Antonio Quartulli   batman-adv: make ...
1252
1253
1254
  	/* ignore global entries from backbone nodes */
  	if (batadv_bla_is_backbone_gw_orig(bat_priv, orig_node->orig, vid))
  		return true;
c018ad3de   Antonio Quartulli   batman-adv: add t...
1255
1256
  	tt_global_entry = batadv_tt_global_hash_find(bat_priv, tt_addr, vid);
  	tt_local_entry = batadv_tt_local_hash_find(bat_priv, tt_addr, vid);
068ee6e20   Antonio Quartulli   batman-adv: roami...
1257
1258
1259
1260
1261
1262
1263
1264
  
  	/* if the node already has a local client for this entry, it has to wait
  	 * for a roaming advertisement instead of manually messing up the global
  	 * table
  	 */
  	if ((flags & BATADV_TT_CLIENT_TEMP) && tt_local_entry &&
  	    !(tt_local_entry->common.flags & BATADV_TT_CLIENT_NEW))
  		goto out;
a73105b8d   Antonio Quartulli   batman-adv: impro...
1265
1266
  
  	if (!tt_global_entry) {
d4f446925   Antonio Quartulli   batman-adv: beaut...
1267
  		tt_global_entry = kzalloc(sizeof(*tt_global_entry), GFP_ATOMIC);
a73105b8d   Antonio Quartulli   batman-adv: impro...
1268
  		if (!tt_global_entry)
7683fdc1e   Antonio Quartulli   batman-adv: prote...
1269
  			goto out;
c0a559295   Sven Eckelmann   batman-adv: Prefi...
1270
  		common = &tt_global_entry->common;
8fdd01530   Antonio Quartulli   batman-adv: prefe...
1271
  		ether_addr_copy(common->addr, tt_addr);
c018ad3de   Antonio Quartulli   batman-adv: add t...
1272
  		common->vid = vid;
db08e6e55   Simon Wunderlich   batman-adv: allow...
1273

d4f446925   Antonio Quartulli   batman-adv: beaut...
1274
  		common->flags = flags;
cc47f66e6   Antonio Quartulli   batman-adv: impro...
1275
  		tt_global_entry->roam_at = 0;
fdf793205   Antonio Quartulli   batman-adv: prope...
1276
1277
1278
1279
1280
1281
  		/* node must store current time in case of roaming. This is
  		 * needed to purge this entry out on timeout (if nobody claims
  		 * it)
  		 */
  		if (flags & BATADV_TT_CLIENT_ROAM)
  			tt_global_entry->roam_at = jiffies;
c0a559295   Sven Eckelmann   batman-adv: Prefi...
1282
  		atomic_set(&common->refcount, 2);
30cfd02b6   Antonio Quartulli   batman-adv: detec...
1283
  		common->added_at = jiffies;
db08e6e55   Simon Wunderlich   batman-adv: allow...
1284
1285
  
  		INIT_HLIST_HEAD(&tt_global_entry->orig_list);
1d8ab8d3c   Linus Lüssing   batman-adv: Modif...
1286
  		atomic_set(&tt_global_entry->orig_list_count, 0);
db08e6e55   Simon Wunderlich   batman-adv: allow...
1287
  		spin_lock_init(&tt_global_entry->list_lock);
7683fdc1e   Antonio Quartulli   batman-adv: prote...
1288

807736f6e   Sven Eckelmann   batman-adv: Split...
1289
  		hash_added = batadv_hash_add(bat_priv->tt.global_hash,
a513088d0   Sven Eckelmann   batman-adv: Prefi...
1290
  					     batadv_compare_tt,
c018ad3de   Antonio Quartulli   batman-adv: add t...
1291
  					     batadv_choose_tt, common,
a513088d0   Sven Eckelmann   batman-adv: Prefi...
1292
  					     &common->hash_entry);
80b3f58cf   Simon Wunderlich   batman-adv: check...
1293
1294
1295
  
  		if (unlikely(hash_added != 0)) {
  			/* remove the reference for the hash */
a513088d0   Sven Eckelmann   batman-adv: Prefi...
1296
  			batadv_tt_global_entry_free_ref(tt_global_entry);
80b3f58cf   Simon Wunderlich   batman-adv: check...
1297
1298
  			goto out_remove;
  		}
a73105b8d   Antonio Quartulli   batman-adv: impro...
1299
  	} else {
068ee6e20   Antonio Quartulli   batman-adv: roami...
1300
  		common = &tt_global_entry->common;
30cfd02b6   Antonio Quartulli   batman-adv: detec...
1301
1302
  		/* If there is already a global entry, we can use this one for
  		 * our processing.
068ee6e20   Antonio Quartulli   batman-adv: roami...
1303
1304
1305
1306
1307
1308
1309
  		 * But if we are trying to add a temporary client then here are
  		 * two options at this point:
  		 * 1) the global client is not a temporary client: the global
  		 *    client has to be left as it is, temporary information
  		 *    should never override any already known client state
  		 * 2) the global client is a temporary client: purge the
  		 *    originator list and add the new one orig_entry
30cfd02b6   Antonio Quartulli   batman-adv: detec...
1310
  		 */
068ee6e20   Antonio Quartulli   batman-adv: roami...
1311
1312
1313
1314
1315
1316
1317
1318
1319
  		if (flags & BATADV_TT_CLIENT_TEMP) {
  			if (!(common->flags & BATADV_TT_CLIENT_TEMP))
  				goto out;
  			if (batadv_tt_global_entry_has_orig(tt_global_entry,
  							    orig_node))
  				goto out_remove;
  			batadv_tt_global_del_orig_list(tt_global_entry);
  			goto add_orig_entry;
  		}
30cfd02b6   Antonio Quartulli   batman-adv: detec...
1320
1321
1322
1323
  
  		/* if the client was temporary added before receiving the first
  		 * OGM announcing it, we have to clear the TEMP flag
  		 */
068ee6e20   Antonio Quartulli   batman-adv: roami...
1324
  		common->flags &= ~BATADV_TT_CLIENT_TEMP;
db08e6e55   Simon Wunderlich   batman-adv: allow...
1325

e9c00136a   Antonio Quartulli   batman-adv: fix t...
1326
1327
1328
1329
1330
  		/* the change can carry possible "attribute" flags like the
  		 * TT_CLIENT_WIFI, therefore they have to be copied in the
  		 * client entry
  		 */
  		tt_global_entry->common.flags |= flags;
acd34afa8   Sven Eckelmann   batman-adv: Prefi...
1331
1332
  		/* If there is the BATADV_TT_CLIENT_ROAM flag set, there is only
  		 * one originator left in the list and we previously received a
db08e6e55   Simon Wunderlich   batman-adv: allow...
1333
1334
1335
1336
1337
  		 * delete + roaming change for this originator.
  		 *
  		 * We should first delete the old originator before adding the
  		 * new one.
  		 */
068ee6e20   Antonio Quartulli   batman-adv: roami...
1338
  		if (common->flags & BATADV_TT_CLIENT_ROAM) {
a513088d0   Sven Eckelmann   batman-adv: Prefi...
1339
  			batadv_tt_global_del_orig_list(tt_global_entry);
068ee6e20   Antonio Quartulli   batman-adv: roami...
1340
  			common->flags &= ~BATADV_TT_CLIENT_ROAM;
db08e6e55   Simon Wunderlich   batman-adv: allow...
1341
  			tt_global_entry->roam_at = 0;
a73105b8d   Antonio Quartulli   batman-adv: impro...
1342
1343
  		}
  	}
068ee6e20   Antonio Quartulli   batman-adv: roami...
1344
  add_orig_entry:
30cfd02b6   Antonio Quartulli   batman-adv: detec...
1345
  	/* add the new orig_entry (if needed) or update it */
d657e621a   Antonio Quartulli   batman-adv: add r...
1346
  	batadv_tt_global_orig_entry_add(tt_global_entry, orig_node, ttvn);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1347

39c75a51e   Sven Eckelmann   batman-adv: Prefi...
1348
  	batadv_dbg(BATADV_DBG_TT, bat_priv,
160527890   Antonio Quartulli   batman-adv: print...
1349
1350
1351
1352
  		   "Creating new global tt entry: %pM (vid: %d, via %pM)
  ",
  		   common->addr, BATADV_PRINT_VID(common->vid),
  		   orig_node->orig);
1e5d49fce   Antonio Quartulli   batman-adv: make ...
1353
  	ret = true;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1354

80b3f58cf   Simon Wunderlich   batman-adv: check...
1355
  out_remove:
c5caf4ef3   Linus Lüssing   batman-adv: Multi...
1356
1357
1358
1359
1360
  	/* Do not remove multicast addresses from the local hash on
  	 * global additions
  	 */
  	if (is_multicast_ether_addr(tt_addr))
  		goto out;
7f91d06c9   Antonio Quartulli   batman-adv: pass ...
1361

a73105b8d   Antonio Quartulli   batman-adv: impro...
1362
  	/* remove address from local hash if present */
c018ad3de   Antonio Quartulli   batman-adv: add t...
1363
  	local_flags = batadv_tt_local_remove(bat_priv, tt_addr, vid,
7f91d06c9   Antonio Quartulli   batman-adv: pass ...
1364
  					     "global tt received",
c1d07431b   Antonio Quartulli   batman-adv: don't...
1365
  					     flags & BATADV_TT_CLIENT_ROAM);
7f91d06c9   Antonio Quartulli   batman-adv: pass ...
1366
  	tt_global_entry->common.flags |= local_flags & BATADV_TT_CLIENT_WIFI;
068ee6e20   Antonio Quartulli   batman-adv: roami...
1367
1368
1369
1370
1371
  	if (!(flags & BATADV_TT_CLIENT_ROAM))
  		/* this is a normal global add. Therefore the client is not in a
  		 * roaming state anymore.
  		 */
  		tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_ROAM;
7683fdc1e   Antonio Quartulli   batman-adv: prote...
1372
1373
  out:
  	if (tt_global_entry)
a513088d0   Sven Eckelmann   batman-adv: Prefi...
1374
  		batadv_tt_global_entry_free_ref(tt_global_entry);
068ee6e20   Antonio Quartulli   batman-adv: roami...
1375
1376
  	if (tt_local_entry)
  		batadv_tt_local_entry_free_ref(tt_local_entry);
7683fdc1e   Antonio Quartulli   batman-adv: prote...
1377
  	return ret;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1378
  }
1b371d130   Simon Wunderlich   batman-adv: use c...
1379
1380
  /**
   * batadv_transtable_best_orig - Get best originator list entry from tt entry
4627456a7   Antonio Quartulli   batman-adv: adapt...
1381
   * @bat_priv: the bat priv with all the soft interface information
981d89002   Sven Eckelmann   batman-adv: Mark ...
1382
1383
1384
1385
1386
1387
   * @tt_global_entry: global translation table entry to be analyzed
   *
   * This functon assumes the caller holds rcu_read_lock().
   * Returns best originator list entry or NULL on errors.
   */
  static struct batadv_tt_orig_list_entry *
4627456a7   Antonio Quartulli   batman-adv: adapt...
1388
1389
  batadv_transtable_best_orig(struct batadv_priv *bat_priv,
  			    struct batadv_tt_global_entry *tt_global_entry)
981d89002   Sven Eckelmann   batman-adv: Mark ...
1390
  {
4627456a7   Antonio Quartulli   batman-adv: adapt...
1391
1392
  	struct batadv_neigh_node *router, *best_router = NULL;
  	struct batadv_algo_ops *bao = bat_priv->bat_algo_ops;
981d89002   Sven Eckelmann   batman-adv: Mark ...
1393
  	struct hlist_head *head;
981d89002   Sven Eckelmann   batman-adv: Mark ...
1394
  	struct batadv_tt_orig_list_entry *orig_entry, *best_entry = NULL;
981d89002   Sven Eckelmann   batman-adv: Mark ...
1395
1396
  
  	head = &tt_global_entry->orig_list;
b67bfe0d4   Sasha Levin   hlist: drop the n...
1397
  	hlist_for_each_entry_rcu(orig_entry, head, list) {
7351a4822   Simon Wunderlich   batman-adv: split...
1398
1399
  		router = batadv_orig_router_get(orig_entry->orig_node,
  						BATADV_IF_DEFAULT);
981d89002   Sven Eckelmann   batman-adv: Mark ...
1400
1401
  		if (!router)
  			continue;
4627456a7   Antonio Quartulli   batman-adv: adapt...
1402
  		if (best_router &&
89652331c   Simon Wunderlich   batman-adv: split...
1403
1404
  		    bao->bat_neigh_cmp(router, BATADV_IF_DEFAULT,
  				       best_router, BATADV_IF_DEFAULT) <= 0) {
4627456a7   Antonio Quartulli   batman-adv: adapt...
1405
1406
  			batadv_neigh_node_free_ref(router);
  			continue;
981d89002   Sven Eckelmann   batman-adv: Mark ...
1407
  		}
4627456a7   Antonio Quartulli   batman-adv: adapt...
1408
1409
1410
1411
1412
1413
  		/* release the refcount for the "old" best */
  		if (best_router)
  			batadv_neigh_node_free_ref(best_router);
  
  		best_entry = orig_entry;
  		best_router = router;
981d89002   Sven Eckelmann   batman-adv: Mark ...
1414
  	}
4627456a7   Antonio Quartulli   batman-adv: adapt...
1415
1416
  	if (best_router)
  		batadv_neigh_node_free_ref(best_router);
981d89002   Sven Eckelmann   batman-adv: Mark ...
1417
1418
  	return best_entry;
  }
1b371d130   Simon Wunderlich   batman-adv: use c...
1419
1420
1421
  /**
   * batadv_tt_global_print_entry - print all orig nodes who announce the address
   *  for this global entry
4627456a7   Antonio Quartulli   batman-adv: adapt...
1422
   * @bat_priv: the bat priv with all the soft interface information
981d89002   Sven Eckelmann   batman-adv: Mark ...
1423
1424
1425
1426
   * @tt_global_entry: global translation table entry to be printed
   * @seq: debugfs table seq_file struct
   *
   * This functon assumes the caller holds rcu_read_lock().
db08e6e55   Simon Wunderlich   batman-adv: allow...
1427
   */
a513088d0   Sven Eckelmann   batman-adv: Prefi...
1428
  static void
4627456a7   Antonio Quartulli   batman-adv: adapt...
1429
1430
  batadv_tt_global_print_entry(struct batadv_priv *bat_priv,
  			     struct batadv_tt_global_entry *tt_global_entry,
a513088d0   Sven Eckelmann   batman-adv: Prefi...
1431
  			     struct seq_file *seq)
db08e6e55   Simon Wunderlich   batman-adv: allow...
1432
  {
981d89002   Sven Eckelmann   batman-adv: Mark ...
1433
  	struct batadv_tt_orig_list_entry *orig_entry, *best_entry;
56303d34a   Sven Eckelmann   batman-adv: Prefi...
1434
  	struct batadv_tt_common_entry *tt_common_entry;
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
1435
1436
  	struct batadv_orig_node_vlan *vlan;
  	struct hlist_head *head;
db08e6e55   Simon Wunderlich   batman-adv: allow...
1437
  	uint8_t last_ttvn;
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
1438
  	uint16_t flags;
db08e6e55   Simon Wunderlich   batman-adv: allow...
1439
1440
  
  	tt_common_entry = &tt_global_entry->common;
981d89002   Sven Eckelmann   batman-adv: Mark ...
1441
  	flags = tt_common_entry->flags;
4627456a7   Antonio Quartulli   batman-adv: adapt...
1442
  	best_entry = batadv_transtable_best_orig(bat_priv, tt_global_entry);
981d89002   Sven Eckelmann   batman-adv: Mark ...
1443
  	if (best_entry) {
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
  		vlan = batadv_orig_node_vlan_get(best_entry->orig_node,
  						 tt_common_entry->vid);
  		if (!vlan) {
  			seq_printf(seq,
  				   " * Cannot retrieve VLAN %d for originator %pM
  ",
  				   BATADV_PRINT_VID(tt_common_entry->vid),
  				   best_entry->orig_node->orig);
  			goto print_list;
  		}
981d89002   Sven Eckelmann   batman-adv: Mark ...
1454
  		last_ttvn = atomic_read(&best_entry->orig_node->last_ttvn);
f9d8a5378   Antonio Quartulli   batman-adv: print...
1455
  		seq_printf(seq,
dd24ddb26   Antonio Quartulli   batman-adv: print...
1456
1457
  			   " %c %pM %4i   (%3u) via %pM     (%3u)   (%#.8x) [%c%c%c%c]
  ",
981d89002   Sven Eckelmann   batman-adv: Mark ...
1458
  			   '*', tt_global_entry->common.addr,
160527890   Antonio Quartulli   batman-adv: print...
1459
  			   BATADV_PRINT_VID(tt_global_entry->common.vid),
981d89002   Sven Eckelmann   batman-adv: Mark ...
1460
  			   best_entry->ttvn, best_entry->orig_node->orig,
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
1461
  			   last_ttvn, vlan->tt.crc,
981d89002   Sven Eckelmann   batman-adv: Mark ...
1462
1463
  			   (flags & BATADV_TT_CLIENT_ROAM ? 'R' : '.'),
  			   (flags & BATADV_TT_CLIENT_WIFI ? 'W' : '.'),
dd24ddb26   Antonio Quartulli   batman-adv: print...
1464
  			   (flags & BATADV_TT_CLIENT_ISOLA ? 'I' : '.'),
981d89002   Sven Eckelmann   batman-adv: Mark ...
1465
  			   (flags & BATADV_TT_CLIENT_TEMP ? 'T' : '.'));
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
1466
1467
  
  		batadv_orig_node_vlan_free_ref(vlan);
981d89002   Sven Eckelmann   batman-adv: Mark ...
1468
  	}
db08e6e55   Simon Wunderlich   batman-adv: allow...
1469

7ea7b4a14   Antonio Quartulli   batman-adv: make ...
1470
  print_list:
db08e6e55   Simon Wunderlich   batman-adv: allow...
1471
  	head = &tt_global_entry->orig_list;
b67bfe0d4   Sasha Levin   hlist: drop the n...
1472
  	hlist_for_each_entry_rcu(orig_entry, head, list) {
981d89002   Sven Eckelmann   batman-adv: Mark ...
1473
1474
  		if (best_entry == orig_entry)
  			continue;
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
  		vlan = batadv_orig_node_vlan_get(orig_entry->orig_node,
  						 tt_common_entry->vid);
  		if (!vlan) {
  			seq_printf(seq,
  				   " + Cannot retrieve VLAN %d for originator %pM
  ",
  				   BATADV_PRINT_VID(tt_common_entry->vid),
  				   orig_entry->orig_node->orig);
  			continue;
  		}
db08e6e55   Simon Wunderlich   batman-adv: allow...
1485
  		last_ttvn = atomic_read(&orig_entry->orig_node->last_ttvn);
160527890   Antonio Quartulli   batman-adv: print...
1486
  		seq_printf(seq,
dd24ddb26   Antonio Quartulli   batman-adv: print...
1487
1488
  			   " %c %pM %4d   (%3u) via %pM     (%3u)   (%#.8x) [%c%c%c%c]
  ",
981d89002   Sven Eckelmann   batman-adv: Mark ...
1489
  			   '+', tt_global_entry->common.addr,
160527890   Antonio Quartulli   batman-adv: print...
1490
  			   BATADV_PRINT_VID(tt_global_entry->common.vid),
981d89002   Sven Eckelmann   batman-adv: Mark ...
1491
  			   orig_entry->ttvn, orig_entry->orig_node->orig,
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
1492
  			   last_ttvn, vlan->tt.crc,
acd34afa8   Sven Eckelmann   batman-adv: Prefi...
1493
  			   (flags & BATADV_TT_CLIENT_ROAM ? 'R' : '.'),
30cfd02b6   Antonio Quartulli   batman-adv: detec...
1494
  			   (flags & BATADV_TT_CLIENT_WIFI ? 'W' : '.'),
dd24ddb26   Antonio Quartulli   batman-adv: print...
1495
  			   (flags & BATADV_TT_CLIENT_ISOLA ? 'I' : '.'),
30cfd02b6   Antonio Quartulli   batman-adv: detec...
1496
  			   (flags & BATADV_TT_CLIENT_TEMP ? 'T' : '.'));
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
1497
1498
  
  		batadv_orig_node_vlan_free_ref(vlan);
db08e6e55   Simon Wunderlich   batman-adv: allow...
1499
1500
  	}
  }
08c36d3e8   Sven Eckelmann   batman-adv: Prefi...
1501
  int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1502
1503
  {
  	struct net_device *net_dev = (struct net_device *)seq->private;
56303d34a   Sven Eckelmann   batman-adv: Prefi...
1504
  	struct batadv_priv *bat_priv = netdev_priv(net_dev);
807736f6e   Sven Eckelmann   batman-adv: Split...
1505
  	struct batadv_hashtable *hash = bat_priv->tt.global_hash;
56303d34a   Sven Eckelmann   batman-adv: Prefi...
1506
1507
1508
  	struct batadv_tt_common_entry *tt_common_entry;
  	struct batadv_tt_global_entry *tt_global;
  	struct batadv_hard_iface *primary_if;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1509
  	struct hlist_head *head;
c90681b85   Antonio Quartulli   batman-adv: fixed...
1510
  	uint32_t i;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1511

30da63a6a   Marek Lindner   batman-adv: conso...
1512
1513
  	primary_if = batadv_seq_print_text_primary_if_get(seq);
  	if (!primary_if)
32ae9b221   Marek Lindner   batman-adv: Make ...
1514
  		goto out;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1515

2dafb49d8   Antonio Quartulli   batman-adv: renam...
1516
1517
1518
  	seq_printf(seq,
  		   "Globally announced TT entries received via the mesh %s
  ",
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1519
  		   net_dev->name);
160527890   Antonio Quartulli   batman-adv: print...
1520
1521
1522
1523
  	seq_printf(seq, "       %-13s  %s  %s       %-15s %s (%-10s) %s
  ",
  		   "Client", "VID", "(TTVN)", "Originator", "(Curr TTVN)",
  		   "CRC", "Flags");
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1524

c6c8fea29   Sven Eckelmann   net: Add batman-a...
1525
1526
  	for (i = 0; i < hash->size; i++) {
  		head = &hash->table[i];
7aadf889e   Marek Lindner   batman-adv: remov...
1527
  		rcu_read_lock();
b67bfe0d4   Sasha Levin   hlist: drop the n...
1528
  		hlist_for_each_entry_rcu(tt_common_entry,
7aadf889e   Marek Lindner   batman-adv: remov...
1529
  					 head, hash_entry) {
56303d34a   Sven Eckelmann   batman-adv: Prefi...
1530
1531
1532
  			tt_global = container_of(tt_common_entry,
  						 struct batadv_tt_global_entry,
  						 common);
4627456a7   Antonio Quartulli   batman-adv: adapt...
1533
  			batadv_tt_global_print_entry(bat_priv, tt_global, seq);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1534
  		}
7aadf889e   Marek Lindner   batman-adv: remov...
1535
  		rcu_read_unlock();
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1536
  	}
32ae9b221   Marek Lindner   batman-adv: Make ...
1537
1538
  out:
  	if (primary_if)
e5d89254b   Sven Eckelmann   batman-adv: Prefi...
1539
  		batadv_hardif_free_ref(primary_if);
30da63a6a   Marek Lindner   batman-adv: conso...
1540
  	return 0;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1541
  }
1d8ab8d3c   Linus Lüssing   batman-adv: Modif...
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
  /**
   * batadv_tt_global_del_orig_entry - remove and free an orig_entry
   * @tt_global_entry: the global entry to remove the orig_entry from
   * @orig_entry: the orig entry to remove and free
   *
   * Remove an orig_entry from its list in the given tt_global_entry and
   * free this orig_entry afterwards.
   */
  static void
  batadv_tt_global_del_orig_entry(struct batadv_tt_global_entry *tt_global_entry,
  				struct batadv_tt_orig_list_entry *orig_entry)
  {
  	batadv_tt_global_size_dec(orig_entry->orig_node,
  				  tt_global_entry->common.vid);
  	atomic_dec(&tt_global_entry->orig_list_count);
  	hlist_del_rcu(&orig_entry->list);
  	batadv_tt_orig_list_entry_free_ref(orig_entry);
  }
db08e6e55   Simon Wunderlich   batman-adv: allow...
1560
  /* deletes the orig list of a tt_global_entry */
a513088d0   Sven Eckelmann   batman-adv: Prefi...
1561
  static void
56303d34a   Sven Eckelmann   batman-adv: Prefi...
1562
  batadv_tt_global_del_orig_list(struct batadv_tt_global_entry *tt_global_entry)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1563
  {
db08e6e55   Simon Wunderlich   batman-adv: allow...
1564
  	struct hlist_head *head;
b67bfe0d4   Sasha Levin   hlist: drop the n...
1565
  	struct hlist_node *safe;
56303d34a   Sven Eckelmann   batman-adv: Prefi...
1566
  	struct batadv_tt_orig_list_entry *orig_entry;
a73105b8d   Antonio Quartulli   batman-adv: impro...
1567

db08e6e55   Simon Wunderlich   batman-adv: allow...
1568
1569
  	spin_lock_bh(&tt_global_entry->list_lock);
  	head = &tt_global_entry->orig_list;
1d8ab8d3c   Linus Lüssing   batman-adv: Modif...
1570
1571
  	hlist_for_each_entry_safe(orig_entry, safe, head, list)
  		batadv_tt_global_del_orig_entry(tt_global_entry, orig_entry);
db08e6e55   Simon Wunderlich   batman-adv: allow...
1572
  	spin_unlock_bh(&tt_global_entry->list_lock);
db08e6e55   Simon Wunderlich   batman-adv: allow...
1573
  }
1d8ab8d3c   Linus Lüssing   batman-adv: Modif...
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
  /**
   * batadv_tt_global_del_orig_node - remove orig_node from a global tt entry
   * @bat_priv: the bat priv with all the soft interface information
   * @tt_global_entry: the global entry to remove the orig_node from
   * @orig_node: the originator announcing the client
   * @message: message to append to the log on deletion
   *
   * Remove the given orig_node and its according orig_entry from the given
   * global tt entry.
   */
a513088d0   Sven Eckelmann   batman-adv: Prefi...
1584
  static void
1d8ab8d3c   Linus Lüssing   batman-adv: Modif...
1585
1586
1587
1588
  batadv_tt_global_del_orig_node(struct batadv_priv *bat_priv,
  			       struct batadv_tt_global_entry *tt_global_entry,
  			       struct batadv_orig_node *orig_node,
  			       const char *message)
db08e6e55   Simon Wunderlich   batman-adv: allow...
1589
1590
  {
  	struct hlist_head *head;
b67bfe0d4   Sasha Levin   hlist: drop the n...
1591
  	struct hlist_node *safe;
56303d34a   Sven Eckelmann   batman-adv: Prefi...
1592
  	struct batadv_tt_orig_list_entry *orig_entry;
160527890   Antonio Quartulli   batman-adv: print...
1593
  	unsigned short vid;
db08e6e55   Simon Wunderlich   batman-adv: allow...
1594
1595
1596
  
  	spin_lock_bh(&tt_global_entry->list_lock);
  	head = &tt_global_entry->orig_list;
b67bfe0d4   Sasha Levin   hlist: drop the n...
1597
  	hlist_for_each_entry_safe(orig_entry, safe, head, list) {
db08e6e55   Simon Wunderlich   batman-adv: allow...
1598
  		if (orig_entry->orig_node == orig_node) {
160527890   Antonio Quartulli   batman-adv: print...
1599
  			vid = tt_global_entry->common.vid;
39c75a51e   Sven Eckelmann   batman-adv: Prefi...
1600
  			batadv_dbg(BATADV_DBG_TT, bat_priv,
160527890   Antonio Quartulli   batman-adv: print...
1601
1602
  				   "Deleting %pM from global tt entry %pM (vid: %d): %s
  ",
1eda58bfc   Sven Eckelmann   batman-adv: Prefi...
1603
  				   orig_node->orig,
160527890   Antonio Quartulli   batman-adv: print...
1604
1605
  				   tt_global_entry->common.addr,
  				   BATADV_PRINT_VID(vid), message);
1d8ab8d3c   Linus Lüssing   batman-adv: Modif...
1606
1607
  			batadv_tt_global_del_orig_entry(tt_global_entry,
  							orig_entry);
db08e6e55   Simon Wunderlich   batman-adv: allow...
1608
1609
1610
1611
  		}
  	}
  	spin_unlock_bh(&tt_global_entry->list_lock);
  }
db08e6e55   Simon Wunderlich   batman-adv: allow...
1612
  /* If the client is to be deleted, we check if it is the last origantor entry
acd34afa8   Sven Eckelmann   batman-adv: Prefi...
1613
1614
   * within tt_global entry. If yes, we set the BATADV_TT_CLIENT_ROAM flag and the
   * timer, otherwise we simply remove the originator scheduled for deletion.
db08e6e55   Simon Wunderlich   batman-adv: allow...
1615
   */
a513088d0   Sven Eckelmann   batman-adv: Prefi...
1616
  static void
56303d34a   Sven Eckelmann   batman-adv: Prefi...
1617
1618
1619
1620
  batadv_tt_global_del_roaming(struct batadv_priv *bat_priv,
  			     struct batadv_tt_global_entry *tt_global_entry,
  			     struct batadv_orig_node *orig_node,
  			     const char *message)
db08e6e55   Simon Wunderlich   batman-adv: allow...
1621
1622
1623
  {
  	bool last_entry = true;
  	struct hlist_head *head;
56303d34a   Sven Eckelmann   batman-adv: Prefi...
1624
  	struct batadv_tt_orig_list_entry *orig_entry;
db08e6e55   Simon Wunderlich   batman-adv: allow...
1625
1626
1627
1628
1629
1630
1631
  
  	/* no local entry exists, case 1:
  	 * Check if this is the last one or if other entries exist.
  	 */
  
  	rcu_read_lock();
  	head = &tt_global_entry->orig_list;
b67bfe0d4   Sasha Levin   hlist: drop the n...
1632
  	hlist_for_each_entry_rcu(orig_entry, head, list) {
db08e6e55   Simon Wunderlich   batman-adv: allow...
1633
1634
1635
1636
1637
1638
1639
1640
1641
  		if (orig_entry->orig_node != orig_node) {
  			last_entry = false;
  			break;
  		}
  	}
  	rcu_read_unlock();
  
  	if (last_entry) {
  		/* its the last one, mark for roaming. */
acd34afa8   Sven Eckelmann   batman-adv: Prefi...
1642
  		tt_global_entry->common.flags |= BATADV_TT_CLIENT_ROAM;
db08e6e55   Simon Wunderlich   batman-adv: allow...
1643
1644
1645
1646
1647
  		tt_global_entry->roam_at = jiffies;
  	} else
  		/* there is another entry, we can simply delete this
  		 * one and can still use the other one.
  		 */
1d8ab8d3c   Linus Lüssing   batman-adv: Modif...
1648
1649
  		batadv_tt_global_del_orig_node(bat_priv, tt_global_entry,
  					       orig_node, message);
db08e6e55   Simon Wunderlich   batman-adv: allow...
1650
  }
c018ad3de   Antonio Quartulli   batman-adv: add t...
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
  /**
   * batadv_tt_global_del - remove a client from the global table
   * @bat_priv: the bat priv with all the soft interface information
   * @orig_node: an originator serving this client
   * @addr: the mac address of the client
   * @vid: VLAN identifier
   * @message: a message explaining the reason for deleting the client to print
   *  for debugging purpose
   * @roaming: true if the deletion has been triggered by a roaming event
   */
56303d34a   Sven Eckelmann   batman-adv: Prefi...
1661
1662
  static void batadv_tt_global_del(struct batadv_priv *bat_priv,
  				 struct batadv_orig_node *orig_node,
c018ad3de   Antonio Quartulli   batman-adv: add t...
1663
  				 const unsigned char *addr, unsigned short vid,
a513088d0   Sven Eckelmann   batman-adv: Prefi...
1664
  				 const char *message, bool roaming)
a73105b8d   Antonio Quartulli   batman-adv: impro...
1665
  {
170173bf3   Sven Eckelmann   batman-adv: Remov...
1666
  	struct batadv_tt_global_entry *tt_global_entry;
56303d34a   Sven Eckelmann   batman-adv: Prefi...
1667
  	struct batadv_tt_local_entry *local_entry = NULL;
a73105b8d   Antonio Quartulli   batman-adv: impro...
1668

c018ad3de   Antonio Quartulli   batman-adv: add t...
1669
  	tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr, vid);
db08e6e55   Simon Wunderlich   batman-adv: allow...
1670
  	if (!tt_global_entry)
7683fdc1e   Antonio Quartulli   batman-adv: prote...
1671
  		goto out;
a73105b8d   Antonio Quartulli   batman-adv: impro...
1672

db08e6e55   Simon Wunderlich   batman-adv: allow...
1673
  	if (!roaming) {
1d8ab8d3c   Linus Lüssing   batman-adv: Modif...
1674
1675
  		batadv_tt_global_del_orig_node(bat_priv, tt_global_entry,
  					       orig_node, message);
db08e6e55   Simon Wunderlich   batman-adv: allow...
1676
1677
  
  		if (hlist_empty(&tt_global_entry->orig_list))
be73b488d   Antonio Quartulli   batman-adv: refac...
1678
1679
  			batadv_tt_global_free(bat_priv, tt_global_entry,
  					      message);
db08e6e55   Simon Wunderlich   batman-adv: allow...
1680
1681
1682
  
  		goto out;
  	}
92f90f56c   Sven Eckelmann   batman-adv: refac...
1683
1684
1685
  
  	/* if we are deleting a global entry due to a roam
  	 * event, there are two possibilities:
db08e6e55   Simon Wunderlich   batman-adv: allow...
1686
1687
  	 * 1) the client roamed from node A to node B => if there
  	 *    is only one originator left for this client, we mark
acd34afa8   Sven Eckelmann   batman-adv: Prefi...
1688
  	 *    it with BATADV_TT_CLIENT_ROAM, we start a timer and we
92f90f56c   Sven Eckelmann   batman-adv: refac...
1689
1690
  	 *    wait for node B to claim it. In case of timeout
  	 *    the entry is purged.
db08e6e55   Simon Wunderlich   batman-adv: allow...
1691
1692
1693
  	 *
  	 *    If there are other originators left, we directly delete
  	 *    the originator.
92f90f56c   Sven Eckelmann   batman-adv: refac...
1694
  	 * 2) the client roamed to us => we can directly delete
9cfc7bd60   Sven Eckelmann   batman-adv: Refor...
1695
1696
  	 *    the global entry, since it is useless now.
  	 */
a513088d0   Sven Eckelmann   batman-adv: Prefi...
1697
  	local_entry = batadv_tt_local_hash_find(bat_priv,
c018ad3de   Antonio Quartulli   batman-adv: add t...
1698
1699
  						tt_global_entry->common.addr,
  						vid);
a513088d0   Sven Eckelmann   batman-adv: Prefi...
1700
  	if (local_entry) {
db08e6e55   Simon Wunderlich   batman-adv: allow...
1701
  		/* local entry exists, case 2: client roamed to us. */
a513088d0   Sven Eckelmann   batman-adv: Prefi...
1702
  		batadv_tt_global_del_orig_list(tt_global_entry);
be73b488d   Antonio Quartulli   batman-adv: refac...
1703
  		batadv_tt_global_free(bat_priv, tt_global_entry, message);
db08e6e55   Simon Wunderlich   batman-adv: allow...
1704
1705
  	} else
  		/* no local entry exists, case 1: check for roaming */
a513088d0   Sven Eckelmann   batman-adv: Prefi...
1706
1707
  		batadv_tt_global_del_roaming(bat_priv, tt_global_entry,
  					     orig_node, message);
92f90f56c   Sven Eckelmann   batman-adv: refac...
1708

92f90f56c   Sven Eckelmann   batman-adv: refac...
1709

cc47f66e6   Antonio Quartulli   batman-adv: impro...
1710
  out:
7683fdc1e   Antonio Quartulli   batman-adv: prote...
1711
  	if (tt_global_entry)
a513088d0   Sven Eckelmann   batman-adv: Prefi...
1712
1713
1714
  		batadv_tt_global_entry_free_ref(tt_global_entry);
  	if (local_entry)
  		batadv_tt_local_entry_free_ref(local_entry);
a73105b8d   Antonio Quartulli   batman-adv: impro...
1715
  }
95fb130d6   Antonio Quartulli   batman-adv: make ...
1716
1717
1718
1719
1720
1721
1722
1723
1724
  /**
   * batadv_tt_global_del_orig - remove all the TT global entries belonging to the
   *  given originator matching the provided vid
   * @bat_priv: the bat priv with all the soft interface information
   * @orig_node: the originator owning the entries to remove
   * @match_vid: the VLAN identifier to match. If negative all the entries will be
   *  removed
   * @message: debug message to print as "reason"
   */
56303d34a   Sven Eckelmann   batman-adv: Prefi...
1725
1726
  void batadv_tt_global_del_orig(struct batadv_priv *bat_priv,
  			       struct batadv_orig_node *orig_node,
95fb130d6   Antonio Quartulli   batman-adv: make ...
1727
  			       int32_t match_vid,
56303d34a   Sven Eckelmann   batman-adv: Prefi...
1728
  			       const char *message)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1729
  {
56303d34a   Sven Eckelmann   batman-adv: Prefi...
1730
1731
  	struct batadv_tt_global_entry *tt_global;
  	struct batadv_tt_common_entry *tt_common_entry;
c90681b85   Antonio Quartulli   batman-adv: fixed...
1732
  	uint32_t i;
807736f6e   Sven Eckelmann   batman-adv: Split...
1733
  	struct batadv_hashtable *hash = bat_priv->tt.global_hash;
b67bfe0d4   Sasha Levin   hlist: drop the n...
1734
  	struct hlist_node *safe;
a73105b8d   Antonio Quartulli   batman-adv: impro...
1735
  	struct hlist_head *head;
7683fdc1e   Antonio Quartulli   batman-adv: prote...
1736
  	spinlock_t *list_lock; /* protects write access to the hash lists */
160527890   Antonio Quartulli   batman-adv: print...
1737
  	unsigned short vid;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1738

6e8014947   Simon Wunderlich   batman-adv: add s...
1739
1740
  	if (!hash)
  		return;
a73105b8d   Antonio Quartulli   batman-adv: impro...
1741
1742
  	for (i = 0; i < hash->size; i++) {
  		head = &hash->table[i];
7683fdc1e   Antonio Quartulli   batman-adv: prote...
1743
  		list_lock = &hash->list_locks[i];
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1744

7683fdc1e   Antonio Quartulli   batman-adv: prote...
1745
  		spin_lock_bh(list_lock);
b67bfe0d4   Sasha Levin   hlist: drop the n...
1746
  		hlist_for_each_entry_safe(tt_common_entry, safe,
7c64fd98c   Sven Eckelmann   batman-adv: Fix i...
1747
  					  head, hash_entry) {
95fb130d6   Antonio Quartulli   batman-adv: make ...
1748
1749
1750
  			/* remove only matching entries */
  			if (match_vid >= 0 && tt_common_entry->vid != match_vid)
  				continue;
56303d34a   Sven Eckelmann   batman-adv: Prefi...
1751
1752
1753
  			tt_global = container_of(tt_common_entry,
  						 struct batadv_tt_global_entry,
  						 common);
db08e6e55   Simon Wunderlich   batman-adv: allow...
1754

1d8ab8d3c   Linus Lüssing   batman-adv: Modif...
1755
1756
  			batadv_tt_global_del_orig_node(bat_priv, tt_global,
  						       orig_node, message);
db08e6e55   Simon Wunderlich   batman-adv: allow...
1757

56303d34a   Sven Eckelmann   batman-adv: Prefi...
1758
  			if (hlist_empty(&tt_global->orig_list)) {
160527890   Antonio Quartulli   batman-adv: print...
1759
  				vid = tt_global->common.vid;
39c75a51e   Sven Eckelmann   batman-adv: Prefi...
1760
  				batadv_dbg(BATADV_DBG_TT, bat_priv,
160527890   Antonio Quartulli   batman-adv: print...
1761
1762
1763
1764
  					   "Deleting global tt entry %pM (vid: %d): %s
  ",
  					   tt_global->common.addr,
  					   BATADV_PRINT_VID(vid), message);
b67bfe0d4   Sasha Levin   hlist: drop the n...
1765
  				hlist_del_rcu(&tt_common_entry->hash_entry);
56303d34a   Sven Eckelmann   batman-adv: Prefi...
1766
  				batadv_tt_global_entry_free_ref(tt_global);
7683fdc1e   Antonio Quartulli   batman-adv: prote...
1767
  			}
a73105b8d   Antonio Quartulli   batman-adv: impro...
1768
  		}
7683fdc1e   Antonio Quartulli   batman-adv: prote...
1769
  		spin_unlock_bh(list_lock);
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1770
  	}
e17931d1a   Linus Lüssing   batman-adv: intro...
1771
  	orig_node->capa_initialized &= ~BATADV_ORIG_CAPA_HAS_TT;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1772
  }
30cfd02b6   Antonio Quartulli   batman-adv: detec...
1773
1774
  static bool batadv_tt_global_to_purge(struct batadv_tt_global_entry *tt_global,
  				      char **msg)
cc47f66e6   Antonio Quartulli   batman-adv: impro...
1775
  {
30cfd02b6   Antonio Quartulli   batman-adv: detec...
1776
1777
1778
  	bool purge = false;
  	unsigned long roam_timeout = BATADV_TT_CLIENT_ROAM_TIMEOUT;
  	unsigned long temp_timeout = BATADV_TT_CLIENT_TEMP_TIMEOUT;
42d0b044b   Sven Eckelmann   batman-adv: Prefi...
1779

30cfd02b6   Antonio Quartulli   batman-adv: detec...
1780
1781
1782
1783
1784
1785
  	if ((tt_global->common.flags & BATADV_TT_CLIENT_ROAM) &&
  	    batadv_has_timed_out(tt_global->roam_at, roam_timeout)) {
  		purge = true;
  		*msg = "Roaming timeout
  ";
  	}
42d0b044b   Sven Eckelmann   batman-adv: Prefi...
1786

30cfd02b6   Antonio Quartulli   batman-adv: detec...
1787
1788
1789
1790
1791
  	if ((tt_global->common.flags & BATADV_TT_CLIENT_TEMP) &&
  	    batadv_has_timed_out(tt_global->common.added_at, temp_timeout)) {
  		purge = true;
  		*msg = "Temporary client timeout
  ";
42d0b044b   Sven Eckelmann   batman-adv: Prefi...
1792
  	}
30cfd02b6   Antonio Quartulli   batman-adv: detec...
1793
1794
  
  	return purge;
42d0b044b   Sven Eckelmann   batman-adv: Prefi...
1795
  }
30cfd02b6   Antonio Quartulli   batman-adv: detec...
1796
  static void batadv_tt_global_purge(struct batadv_priv *bat_priv)
42d0b044b   Sven Eckelmann   batman-adv: Prefi...
1797
  {
807736f6e   Sven Eckelmann   batman-adv: Split...
1798
  	struct batadv_hashtable *hash = bat_priv->tt.global_hash;
cc47f66e6   Antonio Quartulli   batman-adv: impro...
1799
  	struct hlist_head *head;
b67bfe0d4   Sasha Levin   hlist: drop the n...
1800
  	struct hlist_node *node_tmp;
7683fdc1e   Antonio Quartulli   batman-adv: prote...
1801
  	spinlock_t *list_lock; /* protects write access to the hash lists */
c90681b85   Antonio Quartulli   batman-adv: fixed...
1802
  	uint32_t i;
30cfd02b6   Antonio Quartulli   batman-adv: detec...
1803
1804
1805
  	char *msg = NULL;
  	struct batadv_tt_common_entry *tt_common;
  	struct batadv_tt_global_entry *tt_global;
cc47f66e6   Antonio Quartulli   batman-adv: impro...
1806

cc47f66e6   Antonio Quartulli   batman-adv: impro...
1807
1808
  	for (i = 0; i < hash->size; i++) {
  		head = &hash->table[i];
7683fdc1e   Antonio Quartulli   batman-adv: prote...
1809
  		list_lock = &hash->list_locks[i];
cc47f66e6   Antonio Quartulli   batman-adv: impro...
1810

7683fdc1e   Antonio Quartulli   batman-adv: prote...
1811
  		spin_lock_bh(list_lock);
b67bfe0d4   Sasha Levin   hlist: drop the n...
1812
  		hlist_for_each_entry_safe(tt_common, node_tmp, head,
30cfd02b6   Antonio Quartulli   batman-adv: detec...
1813
1814
1815
1816
1817
1818
1819
1820
1821
  					  hash_entry) {
  			tt_global = container_of(tt_common,
  						 struct batadv_tt_global_entry,
  						 common);
  
  			if (!batadv_tt_global_to_purge(tt_global, &msg))
  				continue;
  
  			batadv_dbg(BATADV_DBG_TT, bat_priv,
160527890   Antonio Quartulli   batman-adv: print...
1822
1823
1824
1825
1826
  				   "Deleting global tt entry %pM (vid: %d): %s
  ",
  				   tt_global->common.addr,
  				   BATADV_PRINT_VID(tt_global->common.vid),
  				   msg);
30cfd02b6   Antonio Quartulli   batman-adv: detec...
1827

b67bfe0d4   Sasha Levin   hlist: drop the n...
1828
  			hlist_del_rcu(&tt_common->hash_entry);
30cfd02b6   Antonio Quartulli   batman-adv: detec...
1829
1830
1831
  
  			batadv_tt_global_entry_free_ref(tt_global);
  		}
7683fdc1e   Antonio Quartulli   batman-adv: prote...
1832
  		spin_unlock_bh(list_lock);
cc47f66e6   Antonio Quartulli   batman-adv: impro...
1833
  	}
cc47f66e6   Antonio Quartulli   batman-adv: impro...
1834
  }
56303d34a   Sven Eckelmann   batman-adv: Prefi...
1835
  static void batadv_tt_global_table_free(struct batadv_priv *bat_priv)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1836
  {
5bf74e9ca   Sven Eckelmann   batman-adv: Prefi...
1837
  	struct batadv_hashtable *hash;
7683fdc1e   Antonio Quartulli   batman-adv: prote...
1838
  	spinlock_t *list_lock; /* protects write access to the hash lists */
56303d34a   Sven Eckelmann   batman-adv: Prefi...
1839
1840
  	struct batadv_tt_common_entry *tt_common_entry;
  	struct batadv_tt_global_entry *tt_global;
b67bfe0d4   Sasha Levin   hlist: drop the n...
1841
  	struct hlist_node *node_tmp;
7683fdc1e   Antonio Quartulli   batman-adv: prote...
1842
  	struct hlist_head *head;
c90681b85   Antonio Quartulli   batman-adv: fixed...
1843
  	uint32_t i;
7683fdc1e   Antonio Quartulli   batman-adv: prote...
1844

807736f6e   Sven Eckelmann   batman-adv: Split...
1845
  	if (!bat_priv->tt.global_hash)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1846
  		return;
807736f6e   Sven Eckelmann   batman-adv: Split...
1847
  	hash = bat_priv->tt.global_hash;
7683fdc1e   Antonio Quartulli   batman-adv: prote...
1848
1849
1850
1851
1852
1853
  
  	for (i = 0; i < hash->size; i++) {
  		head = &hash->table[i];
  		list_lock = &hash->list_locks[i];
  
  		spin_lock_bh(list_lock);
b67bfe0d4   Sasha Levin   hlist: drop the n...
1854
  		hlist_for_each_entry_safe(tt_common_entry, node_tmp,
7683fdc1e   Antonio Quartulli   batman-adv: prote...
1855
  					  head, hash_entry) {
b67bfe0d4   Sasha Levin   hlist: drop the n...
1856
  			hlist_del_rcu(&tt_common_entry->hash_entry);
56303d34a   Sven Eckelmann   batman-adv: Prefi...
1857
1858
1859
1860
  			tt_global = container_of(tt_common_entry,
  						 struct batadv_tt_global_entry,
  						 common);
  			batadv_tt_global_entry_free_ref(tt_global);
7683fdc1e   Antonio Quartulli   batman-adv: prote...
1861
1862
1863
  		}
  		spin_unlock_bh(list_lock);
  	}
1a8eaf073   Sven Eckelmann   batman-adv: Prefi...
1864
  	batadv_hash_destroy(hash);
7683fdc1e   Antonio Quartulli   batman-adv: prote...
1865

807736f6e   Sven Eckelmann   batman-adv: Split...
1866
  	bat_priv->tt.global_hash = NULL;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1867
  }
56303d34a   Sven Eckelmann   batman-adv: Prefi...
1868
1869
1870
  static bool
  _batadv_is_ap_isolated(struct batadv_tt_local_entry *tt_local_entry,
  		       struct batadv_tt_global_entry *tt_global_entry)
59b699cde   Antonio Quartulli   batman-adv: imple...
1871
1872
  {
  	bool ret = false;
acd34afa8   Sven Eckelmann   batman-adv: Prefi...
1873
1874
  	if (tt_local_entry->common.flags & BATADV_TT_CLIENT_WIFI &&
  	    tt_global_entry->common.flags & BATADV_TT_CLIENT_WIFI)
59b699cde   Antonio Quartulli   batman-adv: imple...
1875
  		ret = true;
2d2fcc2a3   Antonio Quartulli   batman-adv: exten...
1876
1877
1878
1879
  	/* check if the two clients are marked as isolated */
  	if (tt_local_entry->common.flags & BATADV_TT_CLIENT_ISOLA &&
  	    tt_global_entry->common.flags & BATADV_TT_CLIENT_ISOLA)
  		ret = true;
59b699cde   Antonio Quartulli   batman-adv: imple...
1880
1881
  	return ret;
  }
c018ad3de   Antonio Quartulli   batman-adv: add t...
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
  /**
   * batadv_transtable_search - get the mesh destination for a given client
   * @bat_priv: the bat priv with all the soft interface information
   * @src: mac address of the source client
   * @addr: mac address of the destination client
   * @vid: VLAN identifier
   *
   * Returns a pointer to the originator that was selected as destination in the
   * mesh for contacting the client 'addr', NULL otherwise.
   * In case of multiple originators serving the same client, the function returns
   * the best one (best in terms of metric towards the destination node).
   *
   * If the two clients are AP isolated the function returns NULL.
   */
56303d34a   Sven Eckelmann   batman-adv: Prefi...
1896
1897
  struct batadv_orig_node *batadv_transtable_search(struct batadv_priv *bat_priv,
  						  const uint8_t *src,
c018ad3de   Antonio Quartulli   batman-adv: add t...
1898
1899
  						  const uint8_t *addr,
  						  unsigned short vid)
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1900
  {
56303d34a   Sven Eckelmann   batman-adv: Prefi...
1901
1902
1903
  	struct batadv_tt_local_entry *tt_local_entry = NULL;
  	struct batadv_tt_global_entry *tt_global_entry = NULL;
  	struct batadv_orig_node *orig_node = NULL;
981d89002   Sven Eckelmann   batman-adv: Mark ...
1904
  	struct batadv_tt_orig_list_entry *best_entry;
b8cbd81d0   Antonio Quartulli   batman-adv: make ...
1905

eceb22ae0   Antonio Quartulli   batman-adv: creat...
1906
  	if (src && batadv_vlan_ap_isola_get(bat_priv, vid)) {
c018ad3de   Antonio Quartulli   batman-adv: add t...
1907
  		tt_local_entry = batadv_tt_local_hash_find(bat_priv, src, vid);
068ee6e20   Antonio Quartulli   batman-adv: roami...
1908
1909
  		if (!tt_local_entry ||
  		    (tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING))
3d393e473   Antonio Quartulli   batman-adv: imple...
1910
1911
  			goto out;
  	}
7aadf889e   Marek Lindner   batman-adv: remov...
1912

c018ad3de   Antonio Quartulli   batman-adv: add t...
1913
  	tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr, vid);
2dafb49d8   Antonio Quartulli   batman-adv: renam...
1914
  	if (!tt_global_entry)
7b36e8eef   Marek Lindner   batman-adv: Corre...
1915
  		goto out;
7aadf889e   Marek Lindner   batman-adv: remov...
1916

3d393e473   Antonio Quartulli   batman-adv: imple...
1917
  	/* check whether the clients should not communicate due to AP
9cfc7bd60   Sven Eckelmann   batman-adv: Refor...
1918
1919
  	 * isolation
  	 */
a513088d0   Sven Eckelmann   batman-adv: Prefi...
1920
1921
  	if (tt_local_entry &&
  	    _batadv_is_ap_isolated(tt_local_entry, tt_global_entry))
3d393e473   Antonio Quartulli   batman-adv: imple...
1922
  		goto out;
db08e6e55   Simon Wunderlich   batman-adv: allow...
1923
  	rcu_read_lock();
4627456a7   Antonio Quartulli   batman-adv: adapt...
1924
  	best_entry = batadv_transtable_best_orig(bat_priv, tt_global_entry);
db08e6e55   Simon Wunderlich   batman-adv: allow...
1925
  	/* found anything? */
981d89002   Sven Eckelmann   batman-adv: Mark ...
1926
1927
  	if (best_entry)
  		orig_node = best_entry->orig_node;
db08e6e55   Simon Wunderlich   batman-adv: allow...
1928
1929
1930
  	if (orig_node && !atomic_inc_not_zero(&orig_node->refcount))
  		orig_node = NULL;
  	rcu_read_unlock();
981d89002   Sven Eckelmann   batman-adv: Mark ...
1931

7b36e8eef   Marek Lindner   batman-adv: Corre...
1932
  out:
3d393e473   Antonio Quartulli   batman-adv: imple...
1933
  	if (tt_global_entry)
a513088d0   Sven Eckelmann   batman-adv: Prefi...
1934
  		batadv_tt_global_entry_free_ref(tt_global_entry);
3d393e473   Antonio Quartulli   batman-adv: imple...
1935
  	if (tt_local_entry)
a513088d0   Sven Eckelmann   batman-adv: Prefi...
1936
  		batadv_tt_local_entry_free_ref(tt_local_entry);
3d393e473   Antonio Quartulli   batman-adv: imple...
1937

7b36e8eef   Marek Lindner   batman-adv: Corre...
1938
  	return orig_node;
c6c8fea29   Sven Eckelmann   net: Add batman-a...
1939
  }
a73105b8d   Antonio Quartulli   batman-adv: impro...
1940

ced72933a   Antonio Quartulli   batman-adv: use C...
1941
1942
1943
1944
  /**
   * batadv_tt_global_crc - calculates the checksum of the local table belonging
   *  to the given orig_node
   * @bat_priv: the bat priv with all the soft interface information
0ffa9e8d8   Antonio Quartulli   batman-adv: use v...
1945
   * @orig_node: originator for which the CRC should be computed
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
1946
   * @vid: VLAN identifier for which the CRC32 has to be computed
0ffa9e8d8   Antonio Quartulli   batman-adv: use v...
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
   *
   * This function computes the checksum for the global table corresponding to a
   * specific originator. In particular, the checksum is computed as follows: For
   * each client connected to the originator the CRC32C of the MAC address and the
   * VID is computed and then all the CRC32Cs of the various clients are xor'ed
   * together.
   *
   * The idea behind is that CRC32C should be used as much as possible in order to
   * produce a unique hash of the table, but since the order which is used to feed
   * the CRC32C function affects the result and since every node in the network
   * probably sorts the clients differently, the hash function cannot be directly
   * computed over the entire table. Hence the CRC32C is used only on
   * the single client entry, while all the results are then xor'ed together
   * because the XOR operation can combine them all while trying to reduce the
   * noise as much as possible.
   *
   * Returns the checksum of the global table of a given originator.
ced72933a   Antonio Quartulli   batman-adv: use C...
1964
1965
   */
  static uint32_t batadv_tt_global_crc(struct batadv_priv *bat_priv,
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
1966
1967
  				     struct batadv_orig_node *orig_node,
  				     unsigned short vid)
a73105b8d   Antonio Quartulli   batman-adv: impro...
1968
  {
807736f6e   Sven Eckelmann   batman-adv: Split...
1969
  	struct batadv_hashtable *hash = bat_priv->tt.global_hash;
56303d34a   Sven Eckelmann   batman-adv: Prefi...
1970
1971
  	struct batadv_tt_common_entry *tt_common;
  	struct batadv_tt_global_entry *tt_global;
a73105b8d   Antonio Quartulli   batman-adv: impro...
1972
  	struct hlist_head *head;
0ffa9e8d8   Antonio Quartulli   batman-adv: use v...
1973
  	uint32_t i, crc_tmp, crc = 0;
0eb01568f   Antonio Quartulli   batman-adv: inclu...
1974
  	uint8_t flags;
a30e22ca8   Antonio Quartulli   batman-adv: fix T...
1975
  	__be16 tmp_vid;
a73105b8d   Antonio Quartulli   batman-adv: impro...
1976
1977
1978
1979
1980
  
  	for (i = 0; i < hash->size; i++) {
  		head = &hash->table[i];
  
  		rcu_read_lock();
b67bfe0d4   Sasha Levin   hlist: drop the n...
1981
  		hlist_for_each_entry_rcu(tt_common, head, hash_entry) {
56303d34a   Sven Eckelmann   batman-adv: Prefi...
1982
1983
1984
  			tt_global = container_of(tt_common,
  						 struct batadv_tt_global_entry,
  						 common);
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
1985
1986
1987
1988
1989
  			/* compute the CRC only for entries belonging to the
  			 * VLAN identified by the vid passed as parameter
  			 */
  			if (tt_common->vid != vid)
  				continue;
db08e6e55   Simon Wunderlich   batman-adv: allow...
1990
1991
1992
1993
1994
  			/* Roaming clients are in the global table for
  			 * consistency only. They don't have to be
  			 * taken into account while computing the
  			 * global crc
  			 */
acd34afa8   Sven Eckelmann   batman-adv: Prefi...
1995
  			if (tt_common->flags & BATADV_TT_CLIENT_ROAM)
db08e6e55   Simon Wunderlich   batman-adv: allow...
1996
  				continue;
30cfd02b6   Antonio Quartulli   batman-adv: detec...
1997
1998
1999
2000
2001
2002
  			/* Temporary clients have not been announced yet, so
  			 * they have to be skipped while computing the global
  			 * crc
  			 */
  			if (tt_common->flags & BATADV_TT_CLIENT_TEMP)
  				continue;
db08e6e55   Simon Wunderlich   batman-adv: allow...
2003
2004
2005
2006
  
  			/* find out if this global entry is announced by this
  			 * originator
  			 */
56303d34a   Sven Eckelmann   batman-adv: Prefi...
2007
  			if (!batadv_tt_global_entry_has_orig(tt_global,
a513088d0   Sven Eckelmann   batman-adv: Prefi...
2008
  							     orig_node))
db08e6e55   Simon Wunderlich   batman-adv: allow...
2009
  				continue;
a30e22ca8   Antonio Quartulli   batman-adv: fix T...
2010
2011
2012
2013
2014
  			/* use network order to read the VID: this ensures that
  			 * every node reads the bytes in the same order.
  			 */
  			tmp_vid = htons(tt_common->vid);
  			crc_tmp = crc32c(0, &tmp_vid, sizeof(tmp_vid));
0eb01568f   Antonio Quartulli   batman-adv: inclu...
2015
2016
2017
2018
2019
2020
  
  			/* compute the CRC on flags that have to be kept in sync
  			 * among nodes
  			 */
  			flags = tt_common->flags & BATADV_TT_SYNC_MASK;
  			crc_tmp = crc32c(crc_tmp, &flags, sizeof(flags));
0ffa9e8d8   Antonio Quartulli   batman-adv: use v...
2021
  			crc ^= crc32c(crc_tmp, tt_common->addr, ETH_ALEN);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2022
2023
2024
  		}
  		rcu_read_unlock();
  	}
ced72933a   Antonio Quartulli   batman-adv: use C...
2025
  	return crc;
a73105b8d   Antonio Quartulli   batman-adv: impro...
2026
  }
ced72933a   Antonio Quartulli   batman-adv: use C...
2027
2028
2029
  /**
   * batadv_tt_local_crc - calculates the checksum of the local table
   * @bat_priv: the bat priv with all the soft interface information
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2030
   * @vid: VLAN identifier for which the CRC32 has to be computed
0ffa9e8d8   Antonio Quartulli   batman-adv: use v...
2031
2032
2033
2034
2035
   *
   * For details about the computation, please refer to the documentation for
   * batadv_tt_global_crc().
   *
   * Returns the checksum of the local table
ced72933a   Antonio Quartulli   batman-adv: use C...
2036
   */
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2037
2038
  static uint32_t batadv_tt_local_crc(struct batadv_priv *bat_priv,
  				    unsigned short vid)
a73105b8d   Antonio Quartulli   batman-adv: impro...
2039
  {
807736f6e   Sven Eckelmann   batman-adv: Split...
2040
  	struct batadv_hashtable *hash = bat_priv->tt.local_hash;
56303d34a   Sven Eckelmann   batman-adv: Prefi...
2041
  	struct batadv_tt_common_entry *tt_common;
a73105b8d   Antonio Quartulli   batman-adv: impro...
2042
  	struct hlist_head *head;
0ffa9e8d8   Antonio Quartulli   batman-adv: use v...
2043
  	uint32_t i, crc_tmp, crc = 0;
0eb01568f   Antonio Quartulli   batman-adv: inclu...
2044
  	uint8_t flags;
a30e22ca8   Antonio Quartulli   batman-adv: fix T...
2045
  	__be16 tmp_vid;
a73105b8d   Antonio Quartulli   batman-adv: impro...
2046
2047
2048
2049
2050
  
  	for (i = 0; i < hash->size; i++) {
  		head = &hash->table[i];
  
  		rcu_read_lock();
b67bfe0d4   Sasha Levin   hlist: drop the n...
2051
  		hlist_for_each_entry_rcu(tt_common, head, hash_entry) {
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2052
2053
2054
2055
2056
  			/* compute the CRC only for entries belonging to the
  			 * VLAN identified by vid
  			 */
  			if (tt_common->vid != vid)
  				continue;
058d0e269   Antonio Quartulli   batman-adv: keep ...
2057
  			/* not yet committed clients have not to be taken into
9cfc7bd60   Sven Eckelmann   batman-adv: Refor...
2058
2059
  			 * account while computing the CRC
  			 */
acd34afa8   Sven Eckelmann   batman-adv: Prefi...
2060
  			if (tt_common->flags & BATADV_TT_CLIENT_NEW)
058d0e269   Antonio Quartulli   batman-adv: keep ...
2061
  				continue;
ced72933a   Antonio Quartulli   batman-adv: use C...
2062

a30e22ca8   Antonio Quartulli   batman-adv: fix T...
2063
2064
2065
2066
2067
  			/* use network order to read the VID: this ensures that
  			 * every node reads the bytes in the same order.
  			 */
  			tmp_vid = htons(tt_common->vid);
  			crc_tmp = crc32c(0, &tmp_vid, sizeof(tmp_vid));
0eb01568f   Antonio Quartulli   batman-adv: inclu...
2068
2069
2070
2071
2072
2073
  
  			/* compute the CRC on flags that have to be kept in sync
  			 * among nodes
  			 */
  			flags = tt_common->flags & BATADV_TT_SYNC_MASK;
  			crc_tmp = crc32c(crc_tmp, &flags, sizeof(flags));
0ffa9e8d8   Antonio Quartulli   batman-adv: use v...
2074
  			crc ^= crc32c(crc_tmp, tt_common->addr, ETH_ALEN);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2075
  		}
a73105b8d   Antonio Quartulli   batman-adv: impro...
2076
2077
  		rcu_read_unlock();
  	}
ced72933a   Antonio Quartulli   batman-adv: use C...
2078
  	return crc;
a73105b8d   Antonio Quartulli   batman-adv: impro...
2079
  }
56303d34a   Sven Eckelmann   batman-adv: Prefi...
2080
  static void batadv_tt_req_list_free(struct batadv_priv *bat_priv)
a73105b8d   Antonio Quartulli   batman-adv: impro...
2081
  {
56303d34a   Sven Eckelmann   batman-adv: Prefi...
2082
  	struct batadv_tt_req_node *node, *safe;
a73105b8d   Antonio Quartulli   batman-adv: impro...
2083

807736f6e   Sven Eckelmann   batman-adv: Split...
2084
  	spin_lock_bh(&bat_priv->tt.req_list_lock);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2085

807736f6e   Sven Eckelmann   batman-adv: Split...
2086
  	list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) {
a73105b8d   Antonio Quartulli   batman-adv: impro...
2087
2088
2089
  		list_del(&node->list);
  		kfree(node);
  	}
807736f6e   Sven Eckelmann   batman-adv: Split...
2090
  	spin_unlock_bh(&bat_priv->tt.req_list_lock);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2091
  }
56303d34a   Sven Eckelmann   batman-adv: Prefi...
2092
2093
  static void batadv_tt_save_orig_buffer(struct batadv_priv *bat_priv,
  				       struct batadv_orig_node *orig_node,
e8cf234a4   Antonio Quartulli   batman-adv: make ...
2094
2095
  				       const void *tt_buff,
  				       uint16_t tt_buff_len)
a73105b8d   Antonio Quartulli   batman-adv: impro...
2096
  {
a73105b8d   Antonio Quartulli   batman-adv: impro...
2097
  	/* Replace the old buffer only if I received something in the
9cfc7bd60   Sven Eckelmann   batman-adv: Refor...
2098
2099
  	 * last OGM (the OGM could carry no changes)
  	 */
a73105b8d   Antonio Quartulli   batman-adv: impro...
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
  	spin_lock_bh(&orig_node->tt_buff_lock);
  	if (tt_buff_len > 0) {
  		kfree(orig_node->tt_buff);
  		orig_node->tt_buff_len = 0;
  		orig_node->tt_buff = kmalloc(tt_buff_len, GFP_ATOMIC);
  		if (orig_node->tt_buff) {
  			memcpy(orig_node->tt_buff, tt_buff, tt_buff_len);
  			orig_node->tt_buff_len = tt_buff_len;
  		}
  	}
  	spin_unlock_bh(&orig_node->tt_buff_lock);
  }
56303d34a   Sven Eckelmann   batman-adv: Prefi...
2112
  static void batadv_tt_req_purge(struct batadv_priv *bat_priv)
a73105b8d   Antonio Quartulli   batman-adv: impro...
2113
  {
56303d34a   Sven Eckelmann   batman-adv: Prefi...
2114
  	struct batadv_tt_req_node *node, *safe;
a73105b8d   Antonio Quartulli   batman-adv: impro...
2115

807736f6e   Sven Eckelmann   batman-adv: Split...
2116
2117
  	spin_lock_bh(&bat_priv->tt.req_list_lock);
  	list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) {
42d0b044b   Sven Eckelmann   batman-adv: Prefi...
2118
2119
  		if (batadv_has_timed_out(node->issued_at,
  					 BATADV_TT_REQUEST_TIMEOUT)) {
a73105b8d   Antonio Quartulli   batman-adv: impro...
2120
2121
2122
2123
  			list_del(&node->list);
  			kfree(node);
  		}
  	}
807736f6e   Sven Eckelmann   batman-adv: Split...
2124
  	spin_unlock_bh(&bat_priv->tt.req_list_lock);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2125
2126
2127
  }
  
  /* returns the pointer to the new tt_req_node struct if no request
9cfc7bd60   Sven Eckelmann   batman-adv: Refor...
2128
2129
   * has already been issued for this orig_node, NULL otherwise
   */
56303d34a   Sven Eckelmann   batman-adv: Prefi...
2130
2131
2132
  static struct batadv_tt_req_node *
  batadv_new_tt_req_node(struct batadv_priv *bat_priv,
  		       struct batadv_orig_node *orig_node)
a73105b8d   Antonio Quartulli   batman-adv: impro...
2133
  {
56303d34a   Sven Eckelmann   batman-adv: Prefi...
2134
  	struct batadv_tt_req_node *tt_req_node_tmp, *tt_req_node = NULL;
a73105b8d   Antonio Quartulli   batman-adv: impro...
2135

807736f6e   Sven Eckelmann   batman-adv: Split...
2136
2137
  	spin_lock_bh(&bat_priv->tt.req_list_lock);
  	list_for_each_entry(tt_req_node_tmp, &bat_priv->tt.req_list, list) {
1eda58bfc   Sven Eckelmann   batman-adv: Prefi...
2138
2139
  		if (batadv_compare_eth(tt_req_node_tmp, orig_node) &&
  		    !batadv_has_timed_out(tt_req_node_tmp->issued_at,
42d0b044b   Sven Eckelmann   batman-adv: Prefi...
2140
  					  BATADV_TT_REQUEST_TIMEOUT))
a73105b8d   Antonio Quartulli   batman-adv: impro...
2141
2142
2143
2144
2145
2146
  			goto unlock;
  	}
  
  	tt_req_node = kmalloc(sizeof(*tt_req_node), GFP_ATOMIC);
  	if (!tt_req_node)
  		goto unlock;
8fdd01530   Antonio Quartulli   batman-adv: prefe...
2147
  	ether_addr_copy(tt_req_node->addr, orig_node->orig);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2148
  	tt_req_node->issued_at = jiffies;
807736f6e   Sven Eckelmann   batman-adv: Split...
2149
  	list_add(&tt_req_node->list, &bat_priv->tt.req_list);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2150
  unlock:
807736f6e   Sven Eckelmann   batman-adv: Split...
2151
  	spin_unlock_bh(&bat_priv->tt.req_list_lock);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2152
2153
  	return tt_req_node;
  }
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2154
2155
2156
2157
2158
2159
2160
2161
  /**
   * batadv_tt_local_valid - verify that given tt entry is a valid one
   * @entry_ptr: to be checked local tt entry
   * @data_ptr: not used but definition required to satisfy the callback prototype
   *
   * Returns 1 if the entry is a valid, 0 otherwise.
   */
  static int batadv_tt_local_valid(const void *entry_ptr, const void *data_ptr)
058d0e269   Antonio Quartulli   batman-adv: keep ...
2162
  {
56303d34a   Sven Eckelmann   batman-adv: Prefi...
2163
  	const struct batadv_tt_common_entry *tt_common_entry = entry_ptr;
058d0e269   Antonio Quartulli   batman-adv: keep ...
2164

acd34afa8   Sven Eckelmann   batman-adv: Prefi...
2165
  	if (tt_common_entry->flags & BATADV_TT_CLIENT_NEW)
058d0e269   Antonio Quartulli   batman-adv: keep ...
2166
2167
2168
  		return 0;
  	return 1;
  }
a513088d0   Sven Eckelmann   batman-adv: Prefi...
2169
2170
  static int batadv_tt_global_valid(const void *entry_ptr,
  				  const void *data_ptr)
a73105b8d   Antonio Quartulli   batman-adv: impro...
2171
  {
56303d34a   Sven Eckelmann   batman-adv: Prefi...
2172
2173
2174
  	const struct batadv_tt_common_entry *tt_common_entry = entry_ptr;
  	const struct batadv_tt_global_entry *tt_global_entry;
  	const struct batadv_orig_node *orig_node = data_ptr;
a73105b8d   Antonio Quartulli   batman-adv: impro...
2175

30cfd02b6   Antonio Quartulli   batman-adv: detec...
2176
2177
  	if (tt_common_entry->flags & BATADV_TT_CLIENT_ROAM ||
  	    tt_common_entry->flags & BATADV_TT_CLIENT_TEMP)
cc47f66e6   Antonio Quartulli   batman-adv: impro...
2178
  		return 0;
56303d34a   Sven Eckelmann   batman-adv: Prefi...
2179
2180
  	tt_global_entry = container_of(tt_common_entry,
  				       struct batadv_tt_global_entry,
48100bac8   Antonio Quartulli   batman-adv: creat...
2181
  				       common);
a513088d0   Sven Eckelmann   batman-adv: Prefi...
2182
  	return batadv_tt_global_entry_has_orig(tt_global_entry, orig_node);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2183
  }
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2184
  /**
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2185
2186
   * batadv_tt_tvlv_generate - fill the tvlv buff with the tt entries from the
   *  specified tt hash
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2187
2188
2189
   * @bat_priv: the bat priv with all the soft interface information
   * @hash: hash table containing the tt entries
   * @tt_len: expected tvlv tt data buffer length in number of bytes
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2190
   * @tvlv_buff: pointer to the buffer to fill with the TT data
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2191
2192
   * @valid_cb: function to filter tt change entries
   * @cb_data: data passed to the filter function as argument
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2193
   */
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2194
2195
2196
2197
2198
  static void batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
  				    struct batadv_hashtable *hash,
  				    void *tvlv_buff, uint16_t tt_len,
  				    int (*valid_cb)(const void *, const void *),
  				    void *cb_data)
a73105b8d   Antonio Quartulli   batman-adv: impro...
2199
  {
56303d34a   Sven Eckelmann   batman-adv: Prefi...
2200
  	struct batadv_tt_common_entry *tt_common_entry;
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2201
  	struct batadv_tvlv_tt_change *tt_change;
a73105b8d   Antonio Quartulli   batman-adv: impro...
2202
  	struct hlist_head *head;
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2203
  	uint16_t tt_tot, tt_num_entries = 0;
c90681b85   Antonio Quartulli   batman-adv: fixed...
2204
  	uint32_t i;
a73105b8d   Antonio Quartulli   batman-adv: impro...
2205

298e6e685   Antonio Quartulli   batman-adv: imple...
2206
  	tt_tot = batadv_tt_entries(tt_len);
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2207
  	tt_change = (struct batadv_tvlv_tt_change *)tvlv_buff;
a73105b8d   Antonio Quartulli   batman-adv: impro...
2208
2209
2210
2211
  
  	rcu_read_lock();
  	for (i = 0; i < hash->size; i++) {
  		head = &hash->table[i];
b67bfe0d4   Sasha Levin   hlist: drop the n...
2212
  		hlist_for_each_entry_rcu(tt_common_entry,
a73105b8d   Antonio Quartulli   batman-adv: impro...
2213
  					 head, hash_entry) {
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2214
  			if (tt_tot == tt_num_entries)
a73105b8d   Antonio Quartulli   batman-adv: impro...
2215
  				break;
48100bac8   Antonio Quartulli   batman-adv: creat...
2216
  			if ((valid_cb) && (!valid_cb(tt_common_entry, cb_data)))
a73105b8d   Antonio Quartulli   batman-adv: impro...
2217
  				continue;
8fdd01530   Antonio Quartulli   batman-adv: prefe...
2218
  			ether_addr_copy(tt_change->addr, tt_common_entry->addr);
27b37ebfa   Antonio Quartulli   batman-adv: corre...
2219
  			tt_change->flags = tt_common_entry->flags;
c018ad3de   Antonio Quartulli   batman-adv: add t...
2220
  			tt_change->vid = htons(tt_common_entry->vid);
ca6630464   Antonio Quartulli   batman-adv: fix a...
2221
2222
  			memset(tt_change->reserved, 0,
  			       sizeof(tt_change->reserved));
a73105b8d   Antonio Quartulli   batman-adv: impro...
2223

335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2224
  			tt_num_entries++;
a73105b8d   Antonio Quartulli   batman-adv: impro...
2225
2226
2227
2228
  			tt_change++;
  		}
  	}
  	rcu_read_unlock();
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2229
  }
a73105b8d   Antonio Quartulli   batman-adv: impro...
2230

7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
  /**
   * batadv_tt_global_check_crc - check if all the CRCs are correct
   * @orig_node: originator for which the CRCs have to be checked
   * @tt_vlan: pointer to the first tvlv VLAN entry
   * @num_vlan: number of tvlv VLAN entries
   * @create: if true, create VLAN objects if not found
   *
   * Return true if all the received CRCs match the locally stored ones, false
   * otherwise
   */
  static bool batadv_tt_global_check_crc(struct batadv_orig_node *orig_node,
  				       struct batadv_tvlv_tt_vlan_data *tt_vlan,
  				       uint16_t num_vlan)
  {
  	struct batadv_tvlv_tt_vlan_data *tt_vlan_tmp;
  	struct batadv_orig_node_vlan *vlan;
91c2b1a9f   Antonio Quartulli   batman-adv: relea...
2247
  	uint32_t crc;
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
  	int i;
  
  	/* check if each received CRC matches the locally stored one */
  	for (i = 0; i < num_vlan; i++) {
  		tt_vlan_tmp = tt_vlan + i;
  
  		/* if orig_node is a backbone node for this VLAN, don't check
  		 * the CRC as we ignore all the global entries over it
  		 */
  		if (batadv_bla_is_backbone_gw_orig(orig_node->bat_priv,
cfd4f7570   Antonio Quartulli   batman-adv: make ...
2258
2259
  						   orig_node->orig,
  						   ntohs(tt_vlan_tmp->vid)))
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2260
2261
2262
2263
2264
2265
  			continue;
  
  		vlan = batadv_orig_node_vlan_get(orig_node,
  						 ntohs(tt_vlan_tmp->vid));
  		if (!vlan)
  			return false;
91c2b1a9f   Antonio Quartulli   batman-adv: relea...
2266
2267
2268
2269
  		crc = vlan->tt.crc;
  		batadv_orig_node_vlan_free_ref(vlan);
  
  		if (crc != ntohl(tt_vlan_tmp->crc))
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
  			return false;
  	}
  
  	return true;
  }
  
  /**
   * batadv_tt_local_update_crc - update all the local CRCs
   * @bat_priv: the bat priv with all the soft interface information
   */
  static void batadv_tt_local_update_crc(struct batadv_priv *bat_priv)
  {
  	struct batadv_softif_vlan *vlan;
  
  	/* recompute the global CRC for each VLAN */
  	rcu_read_lock();
  	hlist_for_each_entry_rcu(vlan, &bat_priv->softif_vlan_list, list) {
  		vlan->tt.crc = batadv_tt_local_crc(bat_priv, vlan->vid);
  	}
  	rcu_read_unlock();
  }
  
  /**
   * batadv_tt_global_update_crc - update all the global CRCs for this orig_node
   * @bat_priv: the bat priv with all the soft interface information
   * @orig_node: the orig_node for which the CRCs have to be updated
   */
  static void batadv_tt_global_update_crc(struct batadv_priv *bat_priv,
  					struct batadv_orig_node *orig_node)
  {
  	struct batadv_orig_node_vlan *vlan;
  	uint32_t crc;
  
  	/* recompute the global CRC for each VLAN */
  	rcu_read_lock();
  	list_for_each_entry_rcu(vlan, &orig_node->vlan_list, list) {
  		/* if orig_node is a backbone node for this VLAN, don't compute
  		 * the CRC as we ignore all the global entries over it
  		 */
cfd4f7570   Antonio Quartulli   batman-adv: make ...
2309
2310
  		if (batadv_bla_is_backbone_gw_orig(bat_priv, orig_node->orig,
  						   vlan->vid))
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2311
2312
2313
2314
2315
2316
  			continue;
  
  		crc = batadv_tt_global_crc(bat_priv, orig_node, vlan->vid);
  		vlan->tt.crc = crc;
  	}
  	rcu_read_unlock();
a73105b8d   Antonio Quartulli   batman-adv: impro...
2317
  }
ced72933a   Antonio Quartulli   batman-adv: use C...
2318
2319
2320
2321
2322
  /**
   * batadv_send_tt_request - send a TT Request message to a given node
   * @bat_priv: the bat priv with all the soft interface information
   * @dst_orig_node: the destination of the message
   * @ttvn: the version number that the source of the message is looking for
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2323
2324
   * @tt_vlan: pointer to the first tvlv VLAN object to request
   * @num_vlan: number of tvlv VLAN entries
ced72933a   Antonio Quartulli   batman-adv: use C...
2325
2326
2327
   * @full_table: ask for the entire translation table if true, while only for the
   *  last TT diff otherwise
   */
56303d34a   Sven Eckelmann   batman-adv: Prefi...
2328
2329
  static int batadv_send_tt_request(struct batadv_priv *bat_priv,
  				  struct batadv_orig_node *dst_orig_node,
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2330
2331
2332
  				  uint8_t ttvn,
  				  struct batadv_tvlv_tt_vlan_data *tt_vlan,
  				  uint16_t num_vlan, bool full_table)
a73105b8d   Antonio Quartulli   batman-adv: impro...
2333
  {
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2334
  	struct batadv_tvlv_tt_data *tvlv_tt_data = NULL;
56303d34a   Sven Eckelmann   batman-adv: Prefi...
2335
  	struct batadv_tt_req_node *tt_req_node = NULL;
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2336
2337
  	struct batadv_tvlv_tt_vlan_data *tt_vlan_req;
  	struct batadv_hard_iface *primary_if;
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2338
  	bool ret = false;
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2339
  	int i, size;
a73105b8d   Antonio Quartulli   batman-adv: impro...
2340

e5d89254b   Sven Eckelmann   batman-adv: Prefi...
2341
  	primary_if = batadv_primary_if_get_selected(bat_priv);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2342
2343
2344
2345
  	if (!primary_if)
  		goto out;
  
  	/* The new tt_req will be issued only if I'm not waiting for a
9cfc7bd60   Sven Eckelmann   batman-adv: Refor...
2346
2347
  	 * reply from the same orig_node yet
  	 */
a513088d0   Sven Eckelmann   batman-adv: Prefi...
2348
  	tt_req_node = batadv_new_tt_req_node(bat_priv, dst_orig_node);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2349
2350
  	if (!tt_req_node)
  		goto out;
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2351
2352
  	size = sizeof(*tvlv_tt_data) + sizeof(*tt_vlan_req) * num_vlan;
  	tvlv_tt_data = kzalloc(size, GFP_ATOMIC);
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2353
  	if (!tvlv_tt_data)
a73105b8d   Antonio Quartulli   batman-adv: impro...
2354
  		goto out;
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2355
2356
  	tvlv_tt_data->flags = BATADV_TT_REQUEST;
  	tvlv_tt_data->ttvn = ttvn;
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
  	tvlv_tt_data->num_vlan = htons(num_vlan);
  
  	/* send all the CRCs within the request. This is needed by intermediate
  	 * nodes to ensure they have the correct table before replying
  	 */
  	tt_vlan_req = (struct batadv_tvlv_tt_vlan_data *)(tvlv_tt_data + 1);
  	for (i = 0; i < num_vlan; i++) {
  		tt_vlan_req->vid = tt_vlan->vid;
  		tt_vlan_req->crc = tt_vlan->crc;
  
  		tt_vlan_req++;
  		tt_vlan++;
  	}
a73105b8d   Antonio Quartulli   batman-adv: impro...
2370
2371
  
  	if (full_table)
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2372
  		tvlv_tt_data->flags |= BATADV_TT_FULL_TABLE;
a73105b8d   Antonio Quartulli   batman-adv: impro...
2373

bb351ba0b   Martin Hundebøll   batman-adv: Add w...
2374
2375
  	batadv_dbg(BATADV_DBG_TT, bat_priv, "Sending TT_REQUEST to %pM [%c]
  ",
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2376
  		   dst_orig_node->orig, full_table ? 'F' : '.');
a73105b8d   Antonio Quartulli   batman-adv: impro...
2377

d69909d2f   Sven Eckelmann   batman-adv: Prefi...
2378
  	batadv_inc_counter(bat_priv, BATADV_CNT_TT_REQUEST_TX);
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2379
2380
  	batadv_tvlv_unicast_send(bat_priv, primary_if->net_dev->dev_addr,
  				 dst_orig_node->orig, BATADV_TVLV_TT, 1,
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2381
  				 tvlv_tt_data, size);
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2382
  	ret = true;
a73105b8d   Antonio Quartulli   batman-adv: impro...
2383
2384
  
  out:
a73105b8d   Antonio Quartulli   batman-adv: impro...
2385
  	if (primary_if)
e5d89254b   Sven Eckelmann   batman-adv: Prefi...
2386
  		batadv_hardif_free_ref(primary_if);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2387
  	if (ret && tt_req_node) {
807736f6e   Sven Eckelmann   batman-adv: Split...
2388
  		spin_lock_bh(&bat_priv->tt.req_list_lock);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2389
  		list_del(&tt_req_node->list);
807736f6e   Sven Eckelmann   batman-adv: Split...
2390
  		spin_unlock_bh(&bat_priv->tt.req_list_lock);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2391
2392
  		kfree(tt_req_node);
  	}
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2393
  	kfree(tvlv_tt_data);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2394
2395
  	return ret;
  }
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
  /**
   * batadv_send_other_tt_response - send reply to tt request concerning another
   *  node's translation table
   * @bat_priv: the bat priv with all the soft interface information
   * @tt_data: tt data containing the tt request information
   * @req_src: mac address of tt request sender
   * @req_dst: mac address of tt request recipient
   *
   * Returns true if tt request reply was sent, false otherwise.
   */
  static bool batadv_send_other_tt_response(struct batadv_priv *bat_priv,
  					  struct batadv_tvlv_tt_data *tt_data,
  					  uint8_t *req_src, uint8_t *req_dst)
a73105b8d   Antonio Quartulli   batman-adv: impro...
2409
  {
170173bf3   Sven Eckelmann   batman-adv: Remov...
2410
  	struct batadv_orig_node *req_dst_orig_node;
56303d34a   Sven Eckelmann   batman-adv: Prefi...
2411
  	struct batadv_orig_node *res_dst_orig_node = NULL;
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2412
  	struct batadv_tvlv_tt_change *tt_change;
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2413
  	struct batadv_tvlv_tt_data *tvlv_tt_data = NULL;
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2414
  	struct batadv_tvlv_tt_vlan_data *tt_vlan;
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2415
  	bool ret = false, full_table;
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2416
2417
2418
  	uint8_t orig_ttvn, req_ttvn;
  	uint16_t tvlv_len;
  	int32_t tt_len;
a73105b8d   Antonio Quartulli   batman-adv: impro...
2419

39c75a51e   Sven Eckelmann   batman-adv: Prefi...
2420
  	batadv_dbg(BATADV_DBG_TT, bat_priv,
1eda58bfc   Sven Eckelmann   batman-adv: Prefi...
2421
2422
  		   "Received TT_REQUEST from %pM for ttvn: %u (%pM) [%c]
  ",
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2423
2424
  		   req_src, tt_data->ttvn, req_dst,
  		   (tt_data->flags & BATADV_TT_FULL_TABLE ? 'F' : '.'));
a73105b8d   Antonio Quartulli   batman-adv: impro...
2425
2426
  
  	/* Let's get the orig node of the REAL destination */
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2427
  	req_dst_orig_node = batadv_orig_hash_find(bat_priv, req_dst);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2428
2429
  	if (!req_dst_orig_node)
  		goto out;
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2430
  	res_dst_orig_node = batadv_orig_hash_find(bat_priv, req_src);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2431
2432
  	if (!res_dst_orig_node)
  		goto out;
a73105b8d   Antonio Quartulli   batman-adv: impro...
2433
  	orig_ttvn = (uint8_t)atomic_read(&req_dst_orig_node->last_ttvn);
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2434
  	req_ttvn = tt_data->ttvn;
a73105b8d   Antonio Quartulli   batman-adv: impro...
2435

7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2436
  	tt_vlan = (struct batadv_tvlv_tt_vlan_data *)(tt_data + 1);
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2437
  	/* this node doesn't have the requested data */
a73105b8d   Antonio Quartulli   batman-adv: impro...
2438
  	if (orig_ttvn != req_ttvn ||
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2439
2440
  	    !batadv_tt_global_check_crc(req_dst_orig_node, tt_vlan,
  					ntohs(tt_data->num_vlan)))
a73105b8d   Antonio Quartulli   batman-adv: impro...
2441
  		goto out;
015758d00   Antonio Quartulli   batman-adv: corre...
2442
  	/* If the full table has been explicitly requested */
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2443
  	if (tt_data->flags & BATADV_TT_FULL_TABLE ||
a73105b8d   Antonio Quartulli   batman-adv: impro...
2444
2445
2446
2447
  	    !req_dst_orig_node->tt_buff)
  		full_table = true;
  	else
  		full_table = false;
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2448
2449
  	/* TT fragmentation hasn't been implemented yet, so send as many
  	 * TT entries fit a single packet as possible only
9cfc7bd60   Sven Eckelmann   batman-adv: Refor...
2450
  	 */
a73105b8d   Antonio Quartulli   batman-adv: impro...
2451
2452
2453
  	if (!full_table) {
  		spin_lock_bh(&req_dst_orig_node->tt_buff_lock);
  		tt_len = req_dst_orig_node->tt_buff_len;
a73105b8d   Antonio Quartulli   batman-adv: impro...
2454

7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2455
2456
2457
2458
2459
  		tvlv_len = batadv_tt_prepare_tvlv_global_data(req_dst_orig_node,
  							      &tvlv_tt_data,
  							      &tt_change,
  							      &tt_len);
  		if (!tt_len)
a73105b8d   Antonio Quartulli   batman-adv: impro...
2460
  			goto unlock;
a73105b8d   Antonio Quartulli   batman-adv: impro...
2461
  		/* Copy the last orig_node's OGM buffer */
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2462
  		memcpy(tt_change, req_dst_orig_node->tt_buff,
a73105b8d   Antonio Quartulli   batman-adv: impro...
2463
  		       req_dst_orig_node->tt_buff_len);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2464
2465
  		spin_unlock_bh(&req_dst_orig_node->tt_buff_lock);
  	} else {
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2466
2467
2468
2469
2470
2471
2472
2473
2474
  		/* allocate the tvlv, put the tt_data and all the tt_vlan_data
  		 * in the initial part
  		 */
  		tt_len = -1;
  		tvlv_len = batadv_tt_prepare_tvlv_global_data(req_dst_orig_node,
  							      &tvlv_tt_data,
  							      &tt_change,
  							      &tt_len);
  		if (!tt_len)
a73105b8d   Antonio Quartulli   batman-adv: impro...
2475
  			goto out;
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2476
2477
2478
2479
2480
2481
  
  		/* fill the rest of the tvlv with the real TT entries */
  		batadv_tt_tvlv_generate(bat_priv, bat_priv->tt.global_hash,
  					tt_change, tt_len,
  					batadv_tt_global_valid,
  					req_dst_orig_node);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2482
  	}
a19d3d85e   Marek Lindner   batman-adv: limit...
2483
2484
2485
2486
2487
2488
2489
2490
2491
  	/* Don't send the response, if larger than fragmented packet. */
  	tt_len = sizeof(struct batadv_unicast_tvlv_packet) + tvlv_len;
  	if (tt_len > atomic_read(&bat_priv->packet_size_max)) {
  		net_ratelimited_function(batadv_info, bat_priv->soft_iface,
  					 "Ignoring TT_REQUEST from %pM; Response size exceeds max packet size.
  ",
  					 res_dst_orig_node->orig);
  		goto out;
  	}
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2492
2493
  	tvlv_tt_data->flags = BATADV_TT_RESPONSE;
  	tvlv_tt_data->ttvn = req_ttvn;
a73105b8d   Antonio Quartulli   batman-adv: impro...
2494
2495
  
  	if (full_table)
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2496
  		tvlv_tt_data->flags |= BATADV_TT_FULL_TABLE;
a73105b8d   Antonio Quartulli   batman-adv: impro...
2497

39c75a51e   Sven Eckelmann   batman-adv: Prefi...
2498
  	batadv_dbg(BATADV_DBG_TT, bat_priv,
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2499
2500
2501
2502
  		   "Sending TT_RESPONSE %pM for %pM [%c] (ttvn: %u)
  ",
  		   res_dst_orig_node->orig, req_dst_orig_node->orig,
  		   full_table ? 'F' : '.', req_ttvn);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2503

d69909d2f   Sven Eckelmann   batman-adv: Prefi...
2504
  	batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX);
f8214865a   Martin Hundebøll   batman-adv: Add g...
2505

335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2506
  	batadv_tvlv_unicast_send(bat_priv, req_dst_orig_node->orig,
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2507
2508
  				 req_src, BATADV_TVLV_TT, 1, tvlv_tt_data,
  				 tvlv_len);
e91ecfc64   Martin Hundebøll   batman-adv: Move ...
2509

335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2510
  	ret = true;
a73105b8d   Antonio Quartulli   batman-adv: impro...
2511
2512
2513
2514
2515
2516
2517
  	goto out;
  
  unlock:
  	spin_unlock_bh(&req_dst_orig_node->tt_buff_lock);
  
  out:
  	if (res_dst_orig_node)
7d211efc5   Sven Eckelmann   batman-adv: Prefi...
2518
  		batadv_orig_node_free_ref(res_dst_orig_node);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2519
  	if (req_dst_orig_node)
7d211efc5   Sven Eckelmann   batman-adv: Prefi...
2520
  		batadv_orig_node_free_ref(req_dst_orig_node);
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2521
  	kfree(tvlv_tt_data);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2522
  	return ret;
a73105b8d   Antonio Quartulli   batman-adv: impro...
2523
  }
964126901   Sven Eckelmann   batman-adv: Prefi...
2524

335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
  /**
   * batadv_send_my_tt_response - send reply to tt request concerning this node's
   *  translation table
   * @bat_priv: the bat priv with all the soft interface information
   * @tt_data: tt data containing the tt request information
   * @req_src: mac address of tt request sender
   *
   * Returns true if tt request reply was sent, false otherwise.
   */
  static bool batadv_send_my_tt_response(struct batadv_priv *bat_priv,
  				       struct batadv_tvlv_tt_data *tt_data,
  				       uint8_t *req_src)
a73105b8d   Antonio Quartulli   batman-adv: impro...
2537
  {
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2538
  	struct batadv_tvlv_tt_data *tvlv_tt_data = NULL;
56303d34a   Sven Eckelmann   batman-adv: Prefi...
2539
  	struct batadv_hard_iface *primary_if = NULL;
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2540
2541
  	struct batadv_tvlv_tt_change *tt_change;
  	struct batadv_orig_node *orig_node;
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2542
  	uint8_t my_ttvn, req_ttvn;
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2543
  	uint16_t tvlv_len;
a73105b8d   Antonio Quartulli   batman-adv: impro...
2544
  	bool full_table;
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2545
  	int32_t tt_len;
a73105b8d   Antonio Quartulli   batman-adv: impro...
2546

39c75a51e   Sven Eckelmann   batman-adv: Prefi...
2547
  	batadv_dbg(BATADV_DBG_TT, bat_priv,
1eda58bfc   Sven Eckelmann   batman-adv: Prefi...
2548
2549
  		   "Received TT_REQUEST from %pM for ttvn: %u (me) [%c]
  ",
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2550
2551
  		   req_src, tt_data->ttvn,
  		   (tt_data->flags & BATADV_TT_FULL_TABLE ? 'F' : '.'));
a73105b8d   Antonio Quartulli   batman-adv: impro...
2552

a70a9aa99   Antonio Quartulli   batman-adv: lock ...
2553
  	spin_lock_bh(&bat_priv->tt.commit_lock);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2554

807736f6e   Sven Eckelmann   batman-adv: Split...
2555
  	my_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn);
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2556
  	req_ttvn = tt_data->ttvn;
a73105b8d   Antonio Quartulli   batman-adv: impro...
2557

335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2558
  	orig_node = batadv_orig_hash_find(bat_priv, req_src);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2559
2560
  	if (!orig_node)
  		goto out;
e5d89254b   Sven Eckelmann   batman-adv: Prefi...
2561
  	primary_if = batadv_primary_if_get_selected(bat_priv);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2562
2563
2564
2565
  	if (!primary_if)
  		goto out;
  
  	/* If the full table has been explicitly requested or the gap
9cfc7bd60   Sven Eckelmann   batman-adv: Refor...
2566
2567
  	 * is too big send the whole local translation table
  	 */
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2568
  	if (tt_data->flags & BATADV_TT_FULL_TABLE || my_ttvn != req_ttvn ||
807736f6e   Sven Eckelmann   batman-adv: Split...
2569
  	    !bat_priv->tt.last_changeset)
a73105b8d   Antonio Quartulli   batman-adv: impro...
2570
2571
2572
  		full_table = true;
  	else
  		full_table = false;
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2573
2574
  	/* TT fragmentation hasn't been implemented yet, so send as many
  	 * TT entries fit a single packet as possible only
9cfc7bd60   Sven Eckelmann   batman-adv: Refor...
2575
  	 */
a73105b8d   Antonio Quartulli   batman-adv: impro...
2576
  	if (!full_table) {
807736f6e   Sven Eckelmann   batman-adv: Split...
2577
  		spin_lock_bh(&bat_priv->tt.last_changeset_lock);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2578

7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2579
2580
2581
2582
2583
2584
  		tt_len = bat_priv->tt.last_changeset_len;
  		tvlv_len = batadv_tt_prepare_tvlv_local_data(bat_priv,
  							     &tvlv_tt_data,
  							     &tt_change,
  							     &tt_len);
  		if (!tt_len)
a73105b8d   Antonio Quartulli   batman-adv: impro...
2585
  			goto unlock;
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2586
  		/* Copy the last orig_node's OGM buffer */
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2587
  		memcpy(tt_change, bat_priv->tt.last_changeset,
807736f6e   Sven Eckelmann   batman-adv: Split...
2588
2589
  		       bat_priv->tt.last_changeset_len);
  		spin_unlock_bh(&bat_priv->tt.last_changeset_lock);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2590
  	} else {
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2591
  		req_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn);
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2592
2593
2594
2595
2596
2597
2598
2599
2600
  		/* allocate the tvlv, put the tt_data and all the tt_vlan_data
  		 * in the initial part
  		 */
  		tt_len = -1;
  		tvlv_len = batadv_tt_prepare_tvlv_local_data(bat_priv,
  							     &tvlv_tt_data,
  							     &tt_change,
  							     &tt_len);
  		if (!tt_len)
a73105b8d   Antonio Quartulli   batman-adv: impro...
2601
  			goto out;
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2602
2603
2604
2605
2606
  
  		/* fill the rest of the tvlv with the real TT entries */
  		batadv_tt_tvlv_generate(bat_priv, bat_priv->tt.local_hash,
  					tt_change, tt_len,
  					batadv_tt_local_valid, NULL);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2607
  	}
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2608
2609
  	tvlv_tt_data->flags = BATADV_TT_RESPONSE;
  	tvlv_tt_data->ttvn = req_ttvn;
a73105b8d   Antonio Quartulli   batman-adv: impro...
2610
2611
  
  	if (full_table)
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2612
  		tvlv_tt_data->flags |= BATADV_TT_FULL_TABLE;
a73105b8d   Antonio Quartulli   batman-adv: impro...
2613

39c75a51e   Sven Eckelmann   batman-adv: Prefi...
2614
  	batadv_dbg(BATADV_DBG_TT, bat_priv,
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2615
2616
2617
  		   "Sending TT_RESPONSE to %pM [%c] (ttvn: %u)
  ",
  		   orig_node->orig, full_table ? 'F' : '.', req_ttvn);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2618

d69909d2f   Sven Eckelmann   batman-adv: Prefi...
2619
  	batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX);
f8214865a   Martin Hundebøll   batman-adv: Add g...
2620

335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2621
  	batadv_tvlv_unicast_send(bat_priv, primary_if->net_dev->dev_addr,
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2622
2623
  				 req_src, BATADV_TVLV_TT, 1, tvlv_tt_data,
  				 tvlv_len);
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2624

a73105b8d   Antonio Quartulli   batman-adv: impro...
2625
2626
2627
  	goto out;
  
  unlock:
807736f6e   Sven Eckelmann   batman-adv: Split...
2628
  	spin_unlock_bh(&bat_priv->tt.last_changeset_lock);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2629
  out:
a70a9aa99   Antonio Quartulli   batman-adv: lock ...
2630
  	spin_unlock_bh(&bat_priv->tt.commit_lock);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2631
  	if (orig_node)
7d211efc5   Sven Eckelmann   batman-adv: Prefi...
2632
  		batadv_orig_node_free_ref(orig_node);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2633
  	if (primary_if)
e5d89254b   Sven Eckelmann   batman-adv: Prefi...
2634
  		batadv_hardif_free_ref(primary_if);
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2635
2636
  	kfree(tvlv_tt_data);
  	/* The packet was for this host, so it doesn't need to be re-routed */
a73105b8d   Antonio Quartulli   batman-adv: impro...
2637
2638
  	return true;
  }
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
  /**
   * batadv_send_tt_response - send reply to tt request
   * @bat_priv: the bat priv with all the soft interface information
   * @tt_data: tt data containing the tt request information
   * @req_src: mac address of tt request sender
   * @req_dst: mac address of tt request recipient
   *
   * Returns true if tt request reply was sent, false otherwise.
   */
  static bool batadv_send_tt_response(struct batadv_priv *bat_priv,
  				    struct batadv_tvlv_tt_data *tt_data,
  				    uint8_t *req_src, uint8_t *req_dst)
a73105b8d   Antonio Quartulli   batman-adv: impro...
2651
  {
cfd4f7570   Antonio Quartulli   batman-adv: make ...
2652
  	if (batadv_is_my_mac(bat_priv, req_dst))
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2653
  		return batadv_send_my_tt_response(bat_priv, tt_data, req_src);
cfd4f7570   Antonio Quartulli   batman-adv: make ...
2654
  	else
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2655
2656
  		return batadv_send_other_tt_response(bat_priv, tt_data,
  						     req_src, req_dst);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2657
  }
56303d34a   Sven Eckelmann   batman-adv: Prefi...
2658
2659
  static void _batadv_tt_update_changes(struct batadv_priv *bat_priv,
  				      struct batadv_orig_node *orig_node,
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2660
  				      struct batadv_tvlv_tt_change *tt_change,
a513088d0   Sven Eckelmann   batman-adv: Prefi...
2661
  				      uint16_t tt_num_changes, uint8_t ttvn)
a73105b8d   Antonio Quartulli   batman-adv: impro...
2662
2663
  {
  	int i;
a513088d0   Sven Eckelmann   batman-adv: Prefi...
2664
  	int roams;
a73105b8d   Antonio Quartulli   batman-adv: impro...
2665
2666
  
  	for (i = 0; i < tt_num_changes; i++) {
acd34afa8   Sven Eckelmann   batman-adv: Prefi...
2667
2668
  		if ((tt_change + i)->flags & BATADV_TT_CLIENT_DEL) {
  			roams = (tt_change + i)->flags & BATADV_TT_CLIENT_ROAM;
a513088d0   Sven Eckelmann   batman-adv: Prefi...
2669
2670
  			batadv_tt_global_del(bat_priv, orig_node,
  					     (tt_change + i)->addr,
c018ad3de   Antonio Quartulli   batman-adv: add t...
2671
  					     ntohs((tt_change + i)->vid),
d4f446925   Antonio Quartulli   batman-adv: beaut...
2672
2673
  					     "tt removed by changes",
  					     roams);
08c36d3e8   Sven Eckelmann   batman-adv: Prefi...
2674
  		} else {
08c36d3e8   Sven Eckelmann   batman-adv: Prefi...
2675
  			if (!batadv_tt_global_add(bat_priv, orig_node,
d4f446925   Antonio Quartulli   batman-adv: beaut...
2676
  						  (tt_change + i)->addr,
c018ad3de   Antonio Quartulli   batman-adv: add t...
2677
  						  ntohs((tt_change + i)->vid),
d4f446925   Antonio Quartulli   batman-adv: beaut...
2678
  						  (tt_change + i)->flags, ttvn))
a73105b8d   Antonio Quartulli   batman-adv: impro...
2679
2680
2681
2682
2683
2684
2685
  				/* In case of problem while storing a
  				 * global_entry, we stop the updating
  				 * procedure without committing the
  				 * ttvn change. This will avoid to send
  				 * corrupted data on tt_request
  				 */
  				return;
08c36d3e8   Sven Eckelmann   batman-adv: Prefi...
2686
  		}
a73105b8d   Antonio Quartulli   batman-adv: impro...
2687
  	}
e17931d1a   Linus Lüssing   batman-adv: intro...
2688
  	orig_node->capa_initialized |= BATADV_ORIG_CAPA_HAS_TT;
a73105b8d   Antonio Quartulli   batman-adv: impro...
2689
  }
56303d34a   Sven Eckelmann   batman-adv: Prefi...
2690
  static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv,
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2691
2692
2693
  				  struct batadv_tvlv_tt_change *tt_change,
  				  uint8_t ttvn, uint8_t *resp_src,
  				  uint16_t num_entries)
a73105b8d   Antonio Quartulli   batman-adv: impro...
2694
  {
170173bf3   Sven Eckelmann   batman-adv: Remov...
2695
  	struct batadv_orig_node *orig_node;
a73105b8d   Antonio Quartulli   batman-adv: impro...
2696

335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2697
  	orig_node = batadv_orig_hash_find(bat_priv, resp_src);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2698
2699
2700
2701
  	if (!orig_node)
  		goto out;
  
  	/* Purge the old table first.. */
95fb130d6   Antonio Quartulli   batman-adv: make ...
2702
2703
  	batadv_tt_global_del_orig(bat_priv, orig_node, -1,
  				  "Received full table");
a73105b8d   Antonio Quartulli   batman-adv: impro...
2704

7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2705
2706
  	_batadv_tt_update_changes(bat_priv, orig_node, tt_change, num_entries,
  				  ttvn);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2707
2708
2709
2710
2711
2712
  
  	spin_lock_bh(&orig_node->tt_buff_lock);
  	kfree(orig_node->tt_buff);
  	orig_node->tt_buff_len = 0;
  	orig_node->tt_buff = NULL;
  	spin_unlock_bh(&orig_node->tt_buff_lock);
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2713
  	atomic_set(&orig_node->last_ttvn, ttvn);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2714
2715
2716
  
  out:
  	if (orig_node)
7d211efc5   Sven Eckelmann   batman-adv: Prefi...
2717
  		batadv_orig_node_free_ref(orig_node);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2718
  }
56303d34a   Sven Eckelmann   batman-adv: Prefi...
2719
2720
  static void batadv_tt_update_changes(struct batadv_priv *bat_priv,
  				     struct batadv_orig_node *orig_node,
a513088d0   Sven Eckelmann   batman-adv: Prefi...
2721
  				     uint16_t tt_num_changes, uint8_t ttvn,
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2722
  				     struct batadv_tvlv_tt_change *tt_change)
a73105b8d   Antonio Quartulli   batman-adv: impro...
2723
  {
a513088d0   Sven Eckelmann   batman-adv: Prefi...
2724
2725
  	_batadv_tt_update_changes(bat_priv, orig_node, tt_change,
  				  tt_num_changes, ttvn);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2726

e8cf234a4   Antonio Quartulli   batman-adv: make ...
2727
2728
  	batadv_tt_save_orig_buffer(bat_priv, orig_node, tt_change,
  				   batadv_tt_len(tt_num_changes));
a73105b8d   Antonio Quartulli   batman-adv: impro...
2729
2730
  	atomic_set(&orig_node->last_ttvn, ttvn);
  }
c018ad3de   Antonio Quartulli   batman-adv: add t...
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
  /**
   * batadv_is_my_client - check if a client is served by the local node
   * @bat_priv: the bat priv with all the soft interface information
   * @addr: the mac adress of the client to check
   * @vid: VLAN identifier
   *
   * Returns true if the client is served by this node, false otherwise.
   */
  bool batadv_is_my_client(struct batadv_priv *bat_priv, const uint8_t *addr,
  			 unsigned short vid)
a73105b8d   Antonio Quartulli   batman-adv: impro...
2741
  {
170173bf3   Sven Eckelmann   batman-adv: Remov...
2742
  	struct batadv_tt_local_entry *tt_local_entry;
7683fdc1e   Antonio Quartulli   batman-adv: prote...
2743
  	bool ret = false;
a73105b8d   Antonio Quartulli   batman-adv: impro...
2744

c018ad3de   Antonio Quartulli   batman-adv: add t...
2745
  	tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr, vid);
7683fdc1e   Antonio Quartulli   batman-adv: prote...
2746
2747
  	if (!tt_local_entry)
  		goto out;
058d0e269   Antonio Quartulli   batman-adv: keep ...
2748
  	/* Check if the client has been logically deleted (but is kept for
9cfc7bd60   Sven Eckelmann   batman-adv: Refor...
2749
2750
  	 * consistency purpose)
  	 */
7c1fd91da   Antonio Quartulli   batman-adv: subst...
2751
2752
  	if ((tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING) ||
  	    (tt_local_entry->common.flags & BATADV_TT_CLIENT_ROAM))
058d0e269   Antonio Quartulli   batman-adv: keep ...
2753
  		goto out;
7683fdc1e   Antonio Quartulli   batman-adv: prote...
2754
2755
  	ret = true;
  out:
a73105b8d   Antonio Quartulli   batman-adv: impro...
2756
  	if (tt_local_entry)
a513088d0   Sven Eckelmann   batman-adv: Prefi...
2757
  		batadv_tt_local_entry_free_ref(tt_local_entry);
7683fdc1e   Antonio Quartulli   batman-adv: prote...
2758
  	return ret;
a73105b8d   Antonio Quartulli   batman-adv: impro...
2759
  }
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
  /**
   * batadv_handle_tt_response - process incoming tt reply
   * @bat_priv: the bat priv with all the soft interface information
   * @tt_data: tt data containing the tt request information
   * @resp_src: mac address of tt reply sender
   * @num_entries: number of tt change entries appended to the tt data
   */
  static void batadv_handle_tt_response(struct batadv_priv *bat_priv,
  				      struct batadv_tvlv_tt_data *tt_data,
  				      uint8_t *resp_src, uint16_t num_entries)
a73105b8d   Antonio Quartulli   batman-adv: impro...
2770
  {
56303d34a   Sven Eckelmann   batman-adv: Prefi...
2771
2772
  	struct batadv_tt_req_node *node, *safe;
  	struct batadv_orig_node *orig_node = NULL;
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2773
  	struct batadv_tvlv_tt_change *tt_change;
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2774
2775
  	uint8_t *tvlv_ptr = (uint8_t *)tt_data;
  	uint16_t change_offset;
a73105b8d   Antonio Quartulli   batman-adv: impro...
2776

39c75a51e   Sven Eckelmann   batman-adv: Prefi...
2777
  	batadv_dbg(BATADV_DBG_TT, bat_priv,
1eda58bfc   Sven Eckelmann   batman-adv: Prefi...
2778
2779
  		   "Received TT_RESPONSE from %pM for ttvn %d t_size: %d [%c]
  ",
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2780
2781
  		   resp_src, tt_data->ttvn, num_entries,
  		   (tt_data->flags & BATADV_TT_FULL_TABLE ? 'F' : '.'));
a73105b8d   Antonio Quartulli   batman-adv: impro...
2782

335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2783
  	orig_node = batadv_orig_hash_find(bat_priv, resp_src);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2784
2785
  	if (!orig_node)
  		goto out;
a70a9aa99   Antonio Quartulli   batman-adv: lock ...
2786
  	spin_lock_bh(&orig_node->tt_lock);
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2787
2788
2789
2790
2791
2792
  	change_offset = sizeof(struct batadv_tvlv_tt_vlan_data);
  	change_offset *= ntohs(tt_data->num_vlan);
  	change_offset += sizeof(*tt_data);
  	tvlv_ptr += change_offset;
  
  	tt_change = (struct batadv_tvlv_tt_change *)tvlv_ptr;
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2793
  	if (tt_data->flags & BATADV_TT_FULL_TABLE) {
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2794
2795
  		batadv_tt_fill_gtable(bat_priv, tt_change, tt_data->ttvn,
  				      resp_src, num_entries);
964126901   Sven Eckelmann   batman-adv: Prefi...
2796
  	} else {
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2797
2798
  		batadv_tt_update_changes(bat_priv, orig_node, num_entries,
  					 tt_data->ttvn, tt_change);
964126901   Sven Eckelmann   batman-adv: Prefi...
2799
  	}
a73105b8d   Antonio Quartulli   batman-adv: impro...
2800

a70a9aa99   Antonio Quartulli   batman-adv: lock ...
2801
  	/* Recalculate the CRC for this orig_node and store it */
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2802
  	batadv_tt_global_update_crc(bat_priv, orig_node);
a70a9aa99   Antonio Quartulli   batman-adv: lock ...
2803
2804
  
  	spin_unlock_bh(&orig_node->tt_lock);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2805
  	/* Delete the tt_req_node from pending tt_requests list */
807736f6e   Sven Eckelmann   batman-adv: Split...
2806
2807
  	spin_lock_bh(&bat_priv->tt.req_list_lock);
  	list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) {
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
2808
  		if (!batadv_compare_eth(node->addr, resp_src))
a73105b8d   Antonio Quartulli   batman-adv: impro...
2809
2810
2811
2812
  			continue;
  		list_del(&node->list);
  		kfree(node);
  	}
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2813

807736f6e   Sven Eckelmann   batman-adv: Split...
2814
  	spin_unlock_bh(&bat_priv->tt.req_list_lock);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2815
2816
  out:
  	if (orig_node)
7d211efc5   Sven Eckelmann   batman-adv: Prefi...
2817
  		batadv_orig_node_free_ref(orig_node);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2818
  }
56303d34a   Sven Eckelmann   batman-adv: Prefi...
2819
  static void batadv_tt_roam_list_free(struct batadv_priv *bat_priv)
a73105b8d   Antonio Quartulli   batman-adv: impro...
2820
  {
56303d34a   Sven Eckelmann   batman-adv: Prefi...
2821
  	struct batadv_tt_roam_node *node, *safe;
a73105b8d   Antonio Quartulli   batman-adv: impro...
2822

807736f6e   Sven Eckelmann   batman-adv: Split...
2823
  	spin_lock_bh(&bat_priv->tt.roam_list_lock);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2824

807736f6e   Sven Eckelmann   batman-adv: Split...
2825
  	list_for_each_entry_safe(node, safe, &bat_priv->tt.roam_list, list) {
cc47f66e6   Antonio Quartulli   batman-adv: impro...
2826
2827
2828
  		list_del(&node->list);
  		kfree(node);
  	}
807736f6e   Sven Eckelmann   batman-adv: Split...
2829
  	spin_unlock_bh(&bat_priv->tt.roam_list_lock);
cc47f66e6   Antonio Quartulli   batman-adv: impro...
2830
  }
56303d34a   Sven Eckelmann   batman-adv: Prefi...
2831
  static void batadv_tt_roam_purge(struct batadv_priv *bat_priv)
cc47f66e6   Antonio Quartulli   batman-adv: impro...
2832
  {
56303d34a   Sven Eckelmann   batman-adv: Prefi...
2833
  	struct batadv_tt_roam_node *node, *safe;
cc47f66e6   Antonio Quartulli   batman-adv: impro...
2834

807736f6e   Sven Eckelmann   batman-adv: Split...
2835
2836
  	spin_lock_bh(&bat_priv->tt.roam_list_lock);
  	list_for_each_entry_safe(node, safe, &bat_priv->tt.roam_list, list) {
42d0b044b   Sven Eckelmann   batman-adv: Prefi...
2837
2838
  		if (!batadv_has_timed_out(node->first_time,
  					  BATADV_ROAMING_MAX_TIME))
cc47f66e6   Antonio Quartulli   batman-adv: impro...
2839
2840
2841
2842
2843
  			continue;
  
  		list_del(&node->list);
  		kfree(node);
  	}
807736f6e   Sven Eckelmann   batman-adv: Split...
2844
  	spin_unlock_bh(&bat_priv->tt.roam_list_lock);
cc47f66e6   Antonio Quartulli   batman-adv: impro...
2845
2846
2847
2848
2849
2850
  }
  
  /* This function checks whether the client already reached the
   * maximum number of possible roaming phases. In this case the ROAMING_ADV
   * will not be sent.
   *
9cfc7bd60   Sven Eckelmann   batman-adv: Refor...
2851
2852
   * returns true if the ROAMING_ADV can be sent, false otherwise
   */
56303d34a   Sven Eckelmann   batman-adv: Prefi...
2853
  static bool batadv_tt_check_roam_count(struct batadv_priv *bat_priv,
a513088d0   Sven Eckelmann   batman-adv: Prefi...
2854
  				       uint8_t *client)
cc47f66e6   Antonio Quartulli   batman-adv: impro...
2855
  {
56303d34a   Sven Eckelmann   batman-adv: Prefi...
2856
  	struct batadv_tt_roam_node *tt_roam_node;
cc47f66e6   Antonio Quartulli   batman-adv: impro...
2857
  	bool ret = false;
807736f6e   Sven Eckelmann   batman-adv: Split...
2858
  	spin_lock_bh(&bat_priv->tt.roam_list_lock);
cc47f66e6   Antonio Quartulli   batman-adv: impro...
2859
  	/* The new tt_req will be issued only if I'm not waiting for a
9cfc7bd60   Sven Eckelmann   batman-adv: Refor...
2860
2861
  	 * reply from the same orig_node yet
  	 */
807736f6e   Sven Eckelmann   batman-adv: Split...
2862
  	list_for_each_entry(tt_roam_node, &bat_priv->tt.roam_list, list) {
1eda58bfc   Sven Eckelmann   batman-adv: Prefi...
2863
  		if (!batadv_compare_eth(tt_roam_node->addr, client))
cc47f66e6   Antonio Quartulli   batman-adv: impro...
2864
  			continue;
1eda58bfc   Sven Eckelmann   batman-adv: Prefi...
2865
  		if (batadv_has_timed_out(tt_roam_node->first_time,
42d0b044b   Sven Eckelmann   batman-adv: Prefi...
2866
  					 BATADV_ROAMING_MAX_TIME))
cc47f66e6   Antonio Quartulli   batman-adv: impro...
2867
  			continue;
3e34819e0   Sven Eckelmann   batman-adv: Prefi...
2868
  		if (!batadv_atomic_dec_not_zero(&tt_roam_node->counter))
cc47f66e6   Antonio Quartulli   batman-adv: impro...
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
  			/* Sorry, you roamed too many times! */
  			goto unlock;
  		ret = true;
  		break;
  	}
  
  	if (!ret) {
  		tt_roam_node = kmalloc(sizeof(*tt_roam_node), GFP_ATOMIC);
  		if (!tt_roam_node)
  			goto unlock;
  
  		tt_roam_node->first_time = jiffies;
42d0b044b   Sven Eckelmann   batman-adv: Prefi...
2881
2882
  		atomic_set(&tt_roam_node->counter,
  			   BATADV_ROAMING_MAX_COUNT - 1);
8fdd01530   Antonio Quartulli   batman-adv: prefe...
2883
  		ether_addr_copy(tt_roam_node->addr, client);
cc47f66e6   Antonio Quartulli   batman-adv: impro...
2884

807736f6e   Sven Eckelmann   batman-adv: Split...
2885
  		list_add(&tt_roam_node->list, &bat_priv->tt.roam_list);
cc47f66e6   Antonio Quartulli   batman-adv: impro...
2886
2887
2888
2889
  		ret = true;
  	}
  
  unlock:
807736f6e   Sven Eckelmann   batman-adv: Split...
2890
  	spin_unlock_bh(&bat_priv->tt.roam_list_lock);
cc47f66e6   Antonio Quartulli   batman-adv: impro...
2891
2892
  	return ret;
  }
c018ad3de   Antonio Quartulli   batman-adv: add t...
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
  /**
   * batadv_send_roam_adv - send a roaming advertisement message
   * @bat_priv: the bat priv with all the soft interface information
   * @client: mac address of the roaming client
   * @vid: VLAN identifier
   * @orig_node: message destination
   *
   * Send a ROAMING_ADV message to the node which was previously serving this
   * client. This is done to inform the node that from now on all traffic destined
   * for this particular roamed client has to be forwarded to the sender of the
   * roaming message.
   */
56303d34a   Sven Eckelmann   batman-adv: Prefi...
2905
  static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client,
c018ad3de   Antonio Quartulli   batman-adv: add t...
2906
  				 unsigned short vid,
56303d34a   Sven Eckelmann   batman-adv: Prefi...
2907
  				 struct batadv_orig_node *orig_node)
cc47f66e6   Antonio Quartulli   batman-adv: impro...
2908
  {
56303d34a   Sven Eckelmann   batman-adv: Prefi...
2909
  	struct batadv_hard_iface *primary_if;
122edaa05   Marek Lindner   batman-adv: tvlv ...
2910
2911
2912
2913
2914
  	struct batadv_tvlv_roam_adv tvlv_roam;
  
  	primary_if = batadv_primary_if_get_selected(bat_priv);
  	if (!primary_if)
  		goto out;
cc47f66e6   Antonio Quartulli   batman-adv: impro...
2915
2916
  
  	/* before going on we have to check whether the client has
9cfc7bd60   Sven Eckelmann   batman-adv: Refor...
2917
2918
  	 * already roamed to us too many times
  	 */
a513088d0   Sven Eckelmann   batman-adv: Prefi...
2919
  	if (!batadv_tt_check_roam_count(bat_priv, client))
cc47f66e6   Antonio Quartulli   batman-adv: impro...
2920
  		goto out;
39c75a51e   Sven Eckelmann   batman-adv: Prefi...
2921
  	batadv_dbg(BATADV_DBG_TT, bat_priv,
160527890   Antonio Quartulli   batman-adv: print...
2922
2923
2924
  		   "Sending ROAMING_ADV to %pM (client %pM, vid: %d)
  ",
  		   orig_node->orig, client, BATADV_PRINT_VID(vid));
cc47f66e6   Antonio Quartulli   batman-adv: impro...
2925

d69909d2f   Sven Eckelmann   batman-adv: Prefi...
2926
  	batadv_inc_counter(bat_priv, BATADV_CNT_TT_ROAM_ADV_TX);
f8214865a   Martin Hundebøll   batman-adv: Add g...
2927

122edaa05   Marek Lindner   batman-adv: tvlv ...
2928
  	memcpy(tvlv_roam.client, client, sizeof(tvlv_roam.client));
c018ad3de   Antonio Quartulli   batman-adv: add t...
2929
  	tvlv_roam.vid = htons(vid);
122edaa05   Marek Lindner   batman-adv: tvlv ...
2930
2931
2932
2933
  
  	batadv_tvlv_unicast_send(bat_priv, primary_if->net_dev->dev_addr,
  				 orig_node->orig, BATADV_TVLV_ROAM, 1,
  				 &tvlv_roam, sizeof(tvlv_roam));
cc47f66e6   Antonio Quartulli   batman-adv: impro...
2934
2935
  
  out:
122edaa05   Marek Lindner   batman-adv: tvlv ...
2936
2937
  	if (primary_if)
  		batadv_hardif_free_ref(primary_if);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2938
  }
a513088d0   Sven Eckelmann   batman-adv: Prefi...
2939
  static void batadv_tt_purge(struct work_struct *work)
a73105b8d   Antonio Quartulli   batman-adv: impro...
2940
  {
56303d34a   Sven Eckelmann   batman-adv: Prefi...
2941
  	struct delayed_work *delayed_work;
807736f6e   Sven Eckelmann   batman-adv: Split...
2942
  	struct batadv_priv_tt *priv_tt;
56303d34a   Sven Eckelmann   batman-adv: Prefi...
2943
2944
2945
  	struct batadv_priv *bat_priv;
  
  	delayed_work = container_of(work, struct delayed_work, work);
807736f6e   Sven Eckelmann   batman-adv: Split...
2946
2947
  	priv_tt = container_of(delayed_work, struct batadv_priv_tt, work);
  	bat_priv = container_of(priv_tt, struct batadv_priv, tt);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2948

a19d3d85e   Marek Lindner   batman-adv: limit...
2949
  	batadv_tt_local_purge(bat_priv, BATADV_TT_LOCAL_TIMEOUT);
30cfd02b6   Antonio Quartulli   batman-adv: detec...
2950
  	batadv_tt_global_purge(bat_priv);
a513088d0   Sven Eckelmann   batman-adv: Prefi...
2951
2952
  	batadv_tt_req_purge(bat_priv);
  	batadv_tt_roam_purge(bat_priv);
a73105b8d   Antonio Quartulli   batman-adv: impro...
2953

724144420   Antonio Quartulli   batman-adv: a del...
2954
2955
  	queue_delayed_work(batadv_event_workqueue, &bat_priv->tt.work,
  			   msecs_to_jiffies(BATADV_TT_WORK_PERIOD));
a73105b8d   Antonio Quartulli   batman-adv: impro...
2956
  }
cc47f66e6   Antonio Quartulli   batman-adv: impro...
2957

56303d34a   Sven Eckelmann   batman-adv: Prefi...
2958
  void batadv_tt_free(struct batadv_priv *bat_priv)
cc47f66e6   Antonio Quartulli   batman-adv: impro...
2959
  {
e1bf0c140   Marek Lindner   batman-adv: tvlv ...
2960
2961
  	batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_TT, 1);
  	batadv_tvlv_handler_unregister(bat_priv, BATADV_TVLV_TT, 1);
807736f6e   Sven Eckelmann   batman-adv: Split...
2962
  	cancel_delayed_work_sync(&bat_priv->tt.work);
cc47f66e6   Antonio Quartulli   batman-adv: impro...
2963

a513088d0   Sven Eckelmann   batman-adv: Prefi...
2964
2965
2966
2967
2968
  	batadv_tt_local_table_free(bat_priv);
  	batadv_tt_global_table_free(bat_priv);
  	batadv_tt_req_list_free(bat_priv);
  	batadv_tt_changes_list_free(bat_priv);
  	batadv_tt_roam_list_free(bat_priv);
cc47f66e6   Antonio Quartulli   batman-adv: impro...
2969

807736f6e   Sven Eckelmann   batman-adv: Split...
2970
  	kfree(bat_priv->tt.last_changeset);
cc47f66e6   Antonio Quartulli   batman-adv: impro...
2971
  }
058d0e269   Antonio Quartulli   batman-adv: keep ...
2972

7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2973
2974
2975
2976
2977
2978
2979
  /**
   * batadv_tt_local_set_flags - set or unset the specified flags on the local
   *  table and possibly count them in the TT size
   * @bat_priv: the bat priv with all the soft interface information
   * @flags: the flag to switch
   * @enable: whether to set or unset the flag
   * @count: whether to increase the TT size by the number of changed entries
9cfc7bd60   Sven Eckelmann   batman-adv: Refor...
2980
   */
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2981
2982
  static void batadv_tt_local_set_flags(struct batadv_priv *bat_priv,
  				      uint16_t flags, bool enable, bool count)
058d0e269   Antonio Quartulli   batman-adv: keep ...
2983
  {
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2984
2985
  	struct batadv_hashtable *hash = bat_priv->tt.local_hash;
  	struct batadv_tt_common_entry *tt_common_entry;
697f25314   Antonio Quartulli   batman-adv: gener...
2986
  	uint16_t changed_num = 0;
058d0e269   Antonio Quartulli   batman-adv: keep ...
2987
  	struct hlist_head *head;
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2988
  	uint32_t i;
058d0e269   Antonio Quartulli   batman-adv: keep ...
2989
2990
  
  	if (!hash)
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
2991
  		return;
058d0e269   Antonio Quartulli   batman-adv: keep ...
2992
2993
2994
2995
2996
  
  	for (i = 0; i < hash->size; i++) {
  		head = &hash->table[i];
  
  		rcu_read_lock();
b67bfe0d4   Sasha Levin   hlist: drop the n...
2997
  		hlist_for_each_entry_rcu(tt_common_entry,
058d0e269   Antonio Quartulli   batman-adv: keep ...
2998
  					 head, hash_entry) {
697f25314   Antonio Quartulli   batman-adv: gener...
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
  			if (enable) {
  				if ((tt_common_entry->flags & flags) == flags)
  					continue;
  				tt_common_entry->flags |= flags;
  			} else {
  				if (!(tt_common_entry->flags & flags))
  					continue;
  				tt_common_entry->flags &= ~flags;
  			}
  			changed_num++;
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
3009
3010
3011
3012
3013
3014
  
  			if (!count)
  				continue;
  
  			batadv_tt_local_size_inc(bat_priv,
  						 tt_common_entry->vid);
058d0e269   Antonio Quartulli   batman-adv: keep ...
3015
3016
3017
  		}
  		rcu_read_unlock();
  	}
058d0e269   Antonio Quartulli   batman-adv: keep ...
3018
  }
acd34afa8   Sven Eckelmann   batman-adv: Prefi...
3019
  /* Purge out all the tt local entries marked with BATADV_TT_CLIENT_PENDING */
56303d34a   Sven Eckelmann   batman-adv: Prefi...
3020
  static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv)
058d0e269   Antonio Quartulli   batman-adv: keep ...
3021
  {
807736f6e   Sven Eckelmann   batman-adv: Split...
3022
  	struct batadv_hashtable *hash = bat_priv->tt.local_hash;
56303d34a   Sven Eckelmann   batman-adv: Prefi...
3023
3024
  	struct batadv_tt_common_entry *tt_common;
  	struct batadv_tt_local_entry *tt_local;
b67bfe0d4   Sasha Levin   hlist: drop the n...
3025
  	struct hlist_node *node_tmp;
058d0e269   Antonio Quartulli   batman-adv: keep ...
3026
3027
  	struct hlist_head *head;
  	spinlock_t *list_lock; /* protects write access to the hash lists */
c90681b85   Antonio Quartulli   batman-adv: fixed...
3028
  	uint32_t i;
058d0e269   Antonio Quartulli   batman-adv: keep ...
3029
3030
3031
3032
3033
3034
3035
3036
3037
  
  	if (!hash)
  		return;
  
  	for (i = 0; i < hash->size; i++) {
  		head = &hash->table[i];
  		list_lock = &hash->list_locks[i];
  
  		spin_lock_bh(list_lock);
b67bfe0d4   Sasha Levin   hlist: drop the n...
3038
  		hlist_for_each_entry_safe(tt_common, node_tmp, head,
acd34afa8   Sven Eckelmann   batman-adv: Prefi...
3039
3040
  					  hash_entry) {
  			if (!(tt_common->flags & BATADV_TT_CLIENT_PENDING))
058d0e269   Antonio Quartulli   batman-adv: keep ...
3041
  				continue;
39c75a51e   Sven Eckelmann   batman-adv: Prefi...
3042
  			batadv_dbg(BATADV_DBG_TT, bat_priv,
160527890   Antonio Quartulli   batman-adv: print...
3043
3044
3045
3046
  				   "Deleting local tt entry (%pM, vid: %d): pending
  ",
  				   tt_common->addr,
  				   BATADV_PRINT_VID(tt_common->vid));
058d0e269   Antonio Quartulli   batman-adv: keep ...
3047

7ea7b4a14   Antonio Quartulli   batman-adv: make ...
3048
  			batadv_tt_local_size_dec(bat_priv, tt_common->vid);
b67bfe0d4   Sasha Levin   hlist: drop the n...
3049
  			hlist_del_rcu(&tt_common->hash_entry);
56303d34a   Sven Eckelmann   batman-adv: Prefi...
3050
3051
3052
3053
  			tt_local = container_of(tt_common,
  						struct batadv_tt_local_entry,
  						common);
  			batadv_tt_local_entry_free_ref(tt_local);
058d0e269   Antonio Quartulli   batman-adv: keep ...
3054
3055
3056
  		}
  		spin_unlock_bh(list_lock);
  	}
058d0e269   Antonio Quartulli   batman-adv: keep ...
3057
  }
e1bf0c140   Marek Lindner   batman-adv: tvlv ...
3058
  /**
a19d3d85e   Marek Lindner   batman-adv: limit...
3059
3060
   * batadv_tt_local_commit_changes_nolock - commit all pending local tt changes
   *  which have been queued in the time since the last commit
e1bf0c140   Marek Lindner   batman-adv: tvlv ...
3061
   * @bat_priv: the bat priv with all the soft interface information
a19d3d85e   Marek Lindner   batman-adv: limit...
3062
3063
   *
   * Caller must hold tt->commit_lock.
e1bf0c140   Marek Lindner   batman-adv: tvlv ...
3064
   */
a19d3d85e   Marek Lindner   batman-adv: limit...
3065
  static void batadv_tt_local_commit_changes_nolock(struct batadv_priv *bat_priv)
058d0e269   Antonio Quartulli   batman-adv: keep ...
3066
  {
c5caf4ef3   Linus Lüssing   batman-adv: Multi...
3067
3068
  	/* Update multicast addresses in local translation table */
  	batadv_mcast_mla_update(bat_priv);
e1bf0c140   Marek Lindner   batman-adv: tvlv ...
3069
3070
3071
  	if (atomic_read(&bat_priv->tt.local_changes) < 1) {
  		if (!batadv_atomic_dec_not_zero(&bat_priv->tt.ogm_append_cnt))
  			batadv_tt_tvlv_container_update(bat_priv);
a19d3d85e   Marek Lindner   batman-adv: limit...
3072
  		return;
e1bf0c140   Marek Lindner   batman-adv: tvlv ...
3073
  	}
be9aa4c1e   Marek Lindner   batman-adv: turn ...
3074

7ea7b4a14   Antonio Quartulli   batman-adv: make ...
3075
  	batadv_tt_local_set_flags(bat_priv, BATADV_TT_CLIENT_NEW, false, true);
be9aa4c1e   Marek Lindner   batman-adv: turn ...
3076

a513088d0   Sven Eckelmann   batman-adv: Prefi...
3077
  	batadv_tt_local_purge_pending_clients(bat_priv);
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
3078
  	batadv_tt_local_update_crc(bat_priv);
058d0e269   Antonio Quartulli   batman-adv: keep ...
3079
3080
  
  	/* Increment the TTVN only once per OGM interval */
807736f6e   Sven Eckelmann   batman-adv: Split...
3081
  	atomic_inc(&bat_priv->tt.vn);
39c75a51e   Sven Eckelmann   batman-adv: Prefi...
3082
  	batadv_dbg(BATADV_DBG_TT, bat_priv,
1eda58bfc   Sven Eckelmann   batman-adv: Prefi...
3083
3084
  		   "Local changes committed, updating to ttvn %u
  ",
807736f6e   Sven Eckelmann   batman-adv: Split...
3085
  		   (uint8_t)atomic_read(&bat_priv->tt.vn));
be9aa4c1e   Marek Lindner   batman-adv: turn ...
3086
3087
  
  	/* reset the sending counter */
807736f6e   Sven Eckelmann   batman-adv: Split...
3088
  	atomic_set(&bat_priv->tt.ogm_append_cnt, BATADV_TT_OGM_APPEND_MAX);
e1bf0c140   Marek Lindner   batman-adv: tvlv ...
3089
  	batadv_tt_tvlv_container_update(bat_priv);
a19d3d85e   Marek Lindner   batman-adv: limit...
3090
  }
a70a9aa99   Antonio Quartulli   batman-adv: lock ...
3091

a19d3d85e   Marek Lindner   batman-adv: limit...
3092
3093
3094
3095
3096
3097
3098
3099
3100
  /**
   * batadv_tt_local_commit_changes - commit all pending local tt changes which
   *  have been queued in the time since the last commit
   * @bat_priv: the bat priv with all the soft interface information
   */
  void batadv_tt_local_commit_changes(struct batadv_priv *bat_priv)
  {
  	spin_lock_bh(&bat_priv->tt.commit_lock);
  	batadv_tt_local_commit_changes_nolock(bat_priv);
a70a9aa99   Antonio Quartulli   batman-adv: lock ...
3101
  	spin_unlock_bh(&bat_priv->tt.commit_lock);
058d0e269   Antonio Quartulli   batman-adv: keep ...
3102
  }
59b699cde   Antonio Quartulli   batman-adv: imple...
3103

56303d34a   Sven Eckelmann   batman-adv: Prefi...
3104
  bool batadv_is_ap_isolated(struct batadv_priv *bat_priv, uint8_t *src,
b8cbd81d0   Antonio Quartulli   batman-adv: make ...
3105
  			   uint8_t *dst, unsigned short vid)
59b699cde   Antonio Quartulli   batman-adv: imple...
3106
  {
56303d34a   Sven Eckelmann   batman-adv: Prefi...
3107
3108
  	struct batadv_tt_local_entry *tt_local_entry = NULL;
  	struct batadv_tt_global_entry *tt_global_entry = NULL;
b8cbd81d0   Antonio Quartulli   batman-adv: make ...
3109
  	struct batadv_softif_vlan *vlan;
5870adc68   Marek Lindner   batman-adv: only ...
3110
  	bool ret = false;
59b699cde   Antonio Quartulli   batman-adv: imple...
3111

b8cbd81d0   Antonio Quartulli   batman-adv: make ...
3112
3113
  	vlan = batadv_softif_vlan_get(bat_priv, vid);
  	if (!vlan || !atomic_read(&vlan->ap_isolation))
5870adc68   Marek Lindner   batman-adv: only ...
3114
  		goto out;
59b699cde   Antonio Quartulli   batman-adv: imple...
3115

b8cbd81d0   Antonio Quartulli   batman-adv: make ...
3116
  	tt_local_entry = batadv_tt_local_hash_find(bat_priv, dst, vid);
59b699cde   Antonio Quartulli   batman-adv: imple...
3117
3118
  	if (!tt_local_entry)
  		goto out;
b8cbd81d0   Antonio Quartulli   batman-adv: make ...
3119
  	tt_global_entry = batadv_tt_global_hash_find(bat_priv, src, vid);
59b699cde   Antonio Quartulli   batman-adv: imple...
3120
3121
  	if (!tt_global_entry)
  		goto out;
1f129fefd   Antonio Quartulli   batman-adv: fix c...
3122
  	if (!_batadv_is_ap_isolated(tt_local_entry, tt_global_entry))
59b699cde   Antonio Quartulli   batman-adv: imple...
3123
  		goto out;
5870adc68   Marek Lindner   batman-adv: only ...
3124
  	ret = true;
59b699cde   Antonio Quartulli   batman-adv: imple...
3125
3126
  
  out:
b8cbd81d0   Antonio Quartulli   batman-adv: make ...
3127
3128
  	if (vlan)
  		batadv_softif_vlan_free_ref(vlan);
59b699cde   Antonio Quartulli   batman-adv: imple...
3129
  	if (tt_global_entry)
a513088d0   Sven Eckelmann   batman-adv: Prefi...
3130
  		batadv_tt_global_entry_free_ref(tt_global_entry);
59b699cde   Antonio Quartulli   batman-adv: imple...
3131
  	if (tt_local_entry)
a513088d0   Sven Eckelmann   batman-adv: Prefi...
3132
  		batadv_tt_local_entry_free_ref(tt_local_entry);
59b699cde   Antonio Quartulli   batman-adv: imple...
3133
3134
  	return ret;
  }
a943cac14   Marek Lindner   batman-adv: merge...
3135

e1bf0c140   Marek Lindner   batman-adv: tvlv ...
3136
3137
3138
3139
3140
  /**
   * batadv_tt_update_orig - update global translation table with new tt
   *  information received via ogms
   * @bat_priv: the bat priv with all the soft interface information
   * @orig: the orig_node of the ogm
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
3141
3142
3143
   * @tt_vlan: pointer to the first tvlv VLAN entry
   * @tt_num_vlan: number of tvlv VLAN entries
   * @tt_change: pointer to the first entry in the TT buffer
e1bf0c140   Marek Lindner   batman-adv: tvlv ...
3144
3145
   * @tt_num_changes: number of tt changes inside the tt buffer
   * @ttvn: translation table version number of this changeset
ced72933a   Antonio Quartulli   batman-adv: use C...
3146
   * @tt_crc: crc32 checksum of orig node's translation table
e1bf0c140   Marek Lindner   batman-adv: tvlv ...
3147
3148
3149
   */
  static void batadv_tt_update_orig(struct batadv_priv *bat_priv,
  				  struct batadv_orig_node *orig_node,
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
3150
3151
3152
  				  const void *tt_buff, uint16_t tt_num_vlan,
  				  struct batadv_tvlv_tt_change *tt_change,
  				  uint16_t tt_num_changes, uint8_t ttvn)
a943cac14   Marek Lindner   batman-adv: merge...
3153
3154
  {
  	uint8_t orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
3155
  	struct batadv_tvlv_tt_vlan_data *tt_vlan;
a943cac14   Marek Lindner   batman-adv: merge...
3156
  	bool full_table = true;
e17931d1a   Linus Lüssing   batman-adv: intro...
3157
  	bool has_tt_init;
a943cac14   Marek Lindner   batman-adv: merge...
3158

7ea7b4a14   Antonio Quartulli   batman-adv: make ...
3159
  	tt_vlan = (struct batadv_tvlv_tt_vlan_data *)tt_buff;
e17931d1a   Linus Lüssing   batman-adv: intro...
3160
  	has_tt_init = orig_node->capa_initialized & BATADV_ORIG_CAPA_HAS_TT;
170715788   Antonio Quartulli   batman-adv: add t...
3161
  	/* orig table not initialised AND first diff is in the OGM OR the ttvn
9cfc7bd60   Sven Eckelmann   batman-adv: Refor...
3162
3163
  	 * increased by one -> we can apply the attached changes
  	 */
e17931d1a   Linus Lüssing   batman-adv: intro...
3164
  	if ((!has_tt_init && ttvn == 1) || ttvn - orig_ttvn == 1) {
a943cac14   Marek Lindner   batman-adv: merge...
3165
  		/* the OGM could not contain the changes due to their size or
42d0b044b   Sven Eckelmann   batman-adv: Prefi...
3166
3167
  		 * because they have already been sent BATADV_TT_OGM_APPEND_MAX
  		 * times.
9cfc7bd60   Sven Eckelmann   batman-adv: Refor...
3168
3169
  		 * In this case send a tt request
  		 */
a943cac14   Marek Lindner   batman-adv: merge...
3170
3171
3172
3173
  		if (!tt_num_changes) {
  			full_table = false;
  			goto request_table;
  		}
a70a9aa99   Antonio Quartulli   batman-adv: lock ...
3174
  		spin_lock_bh(&orig_node->tt_lock);
a513088d0   Sven Eckelmann   batman-adv: Prefi...
3175
  		batadv_tt_update_changes(bat_priv, orig_node, tt_num_changes,
964126901   Sven Eckelmann   batman-adv: Prefi...
3176
  					 ttvn, tt_change);
a943cac14   Marek Lindner   batman-adv: merge...
3177
3178
3179
  
  		/* Even if we received the precomputed crc with the OGM, we
  		 * prefer to recompute it to spot any possible inconsistency
9cfc7bd60   Sven Eckelmann   batman-adv: Refor...
3180
3181
  		 * in the global table
  		 */
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
3182
  		batadv_tt_global_update_crc(bat_priv, orig_node);
a943cac14   Marek Lindner   batman-adv: merge...
3183

a70a9aa99   Antonio Quartulli   batman-adv: lock ...
3184
  		spin_unlock_bh(&orig_node->tt_lock);
a943cac14   Marek Lindner   batman-adv: merge...
3185
3186
3187
3188
3189
3190
3191
  		/* The ttvn alone is not enough to guarantee consistency
  		 * because a single value could represent different states
  		 * (due to the wrap around). Thus a node has to check whether
  		 * the resulting table (after applying the changes) is still
  		 * consistent or not. E.g. a node could disconnect while its
  		 * ttvn is X and reconnect on ttvn = X + TTVN_MAX: in this case
  		 * checking the CRC value is mandatory to detect the
9cfc7bd60   Sven Eckelmann   batman-adv: Refor...
3192
3193
  		 * inconsistency
  		 */
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
3194
3195
  		if (!batadv_tt_global_check_crc(orig_node, tt_vlan,
  						tt_num_vlan))
a943cac14   Marek Lindner   batman-adv: merge...
3196
  			goto request_table;
a943cac14   Marek Lindner   batman-adv: merge...
3197
3198
  	} else {
  		/* if we missed more than one change or our tables are not
9cfc7bd60   Sven Eckelmann   batman-adv: Refor...
3199
3200
  		 * in sync anymore -> request fresh tt data
  		 */
e17931d1a   Linus Lüssing   batman-adv: intro...
3201
  		if (!has_tt_init || ttvn != orig_ttvn ||
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
3202
3203
  		    !batadv_tt_global_check_crc(orig_node, tt_vlan,
  						tt_num_vlan)) {
a943cac14   Marek Lindner   batman-adv: merge...
3204
  request_table:
39c75a51e   Sven Eckelmann   batman-adv: Prefi...
3205
  			batadv_dbg(BATADV_DBG_TT, bat_priv,
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
3206
3207
3208
3209
  				   "TT inconsistency for %pM. Need to retrieve the correct information (ttvn: %u last_ttvn: %u num_changes: %u)
  ",
  				   orig_node->orig, ttvn, orig_ttvn,
  				   tt_num_changes);
a513088d0   Sven Eckelmann   batman-adv: Prefi...
3210
  			batadv_send_tt_request(bat_priv, orig_node, ttvn,
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
3211
3212
  					       tt_vlan, tt_num_vlan,
  					       full_table);
a943cac14   Marek Lindner   batman-adv: merge...
3213
3214
3215
3216
  			return;
  		}
  	}
  }
3275e7cc8   Antonio Quartulli   batman-adv: impro...
3217

c018ad3de   Antonio Quartulli   batman-adv: add t...
3218
3219
3220
3221
3222
3223
3224
3225
3226
  /**
   * batadv_tt_global_client_is_roaming - check if a client is marked as roaming
   * @bat_priv: the bat priv with all the soft interface information
   * @addr: the mac address of the client to check
   * @vid: VLAN identifier
   *
   * Returns true if we know that the client has moved from its old originator
   * to another one. This entry is still kept for consistency purposes and will be
   * deleted later by a DEL or because of timeout
3275e7cc8   Antonio Quartulli   batman-adv: impro...
3227
   */
56303d34a   Sven Eckelmann   batman-adv: Prefi...
3228
  bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv,
c018ad3de   Antonio Quartulli   batman-adv: add t...
3229
  					uint8_t *addr, unsigned short vid)
3275e7cc8   Antonio Quartulli   batman-adv: impro...
3230
  {
56303d34a   Sven Eckelmann   batman-adv: Prefi...
3231
  	struct batadv_tt_global_entry *tt_global_entry;
3275e7cc8   Antonio Quartulli   batman-adv: impro...
3232
  	bool ret = false;
c018ad3de   Antonio Quartulli   batman-adv: add t...
3233
  	tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr, vid);
3275e7cc8   Antonio Quartulli   batman-adv: impro...
3234
3235
  	if (!tt_global_entry)
  		goto out;
c1d07431b   Antonio Quartulli   batman-adv: don't...
3236
  	ret = tt_global_entry->common.flags & BATADV_TT_CLIENT_ROAM;
a513088d0   Sven Eckelmann   batman-adv: Prefi...
3237
  	batadv_tt_global_entry_free_ref(tt_global_entry);
3275e7cc8   Antonio Quartulli   batman-adv: impro...
3238
3239
3240
  out:
  	return ret;
  }
30cfd02b6   Antonio Quartulli   batman-adv: detec...
3241

7c1fd91da   Antonio Quartulli   batman-adv: subst...
3242
3243
3244
  /**
   * batadv_tt_local_client_is_roaming - tells whether the client is roaming
   * @bat_priv: the bat priv with all the soft interface information
c018ad3de   Antonio Quartulli   batman-adv: add t...
3245
3246
   * @addr: the mac address of the local client to query
   * @vid: VLAN identifier
7c1fd91da   Antonio Quartulli   batman-adv: subst...
3247
3248
3249
3250
3251
3252
   *
   * Returns true if the local client is known to be roaming (it is not served by
   * this node anymore) or not. If yes, the client is still present in the table
   * to keep the latter consistent with the node TTVN
   */
  bool batadv_tt_local_client_is_roaming(struct batadv_priv *bat_priv,
c018ad3de   Antonio Quartulli   batman-adv: add t...
3253
  				       uint8_t *addr, unsigned short vid)
7c1fd91da   Antonio Quartulli   batman-adv: subst...
3254
3255
3256
  {
  	struct batadv_tt_local_entry *tt_local_entry;
  	bool ret = false;
c018ad3de   Antonio Quartulli   batman-adv: add t...
3257
  	tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr, vid);
7c1fd91da   Antonio Quartulli   batman-adv: subst...
3258
3259
3260
3261
3262
3263
3264
  	if (!tt_local_entry)
  		goto out;
  
  	ret = tt_local_entry->common.flags & BATADV_TT_CLIENT_ROAM;
  	batadv_tt_local_entry_free_ref(tt_local_entry);
  out:
  	return ret;
7c1fd91da   Antonio Quartulli   batman-adv: subst...
3265
  }
30cfd02b6   Antonio Quartulli   batman-adv: detec...
3266
3267
  bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv,
  					  struct batadv_orig_node *orig_node,
c018ad3de   Antonio Quartulli   batman-adv: add t...
3268
  					  const unsigned char *addr,
160527890   Antonio Quartulli   batman-adv: print...
3269
  					  unsigned short vid)
30cfd02b6   Antonio Quartulli   batman-adv: detec...
3270
3271
  {
  	bool ret = false;
160527890   Antonio Quartulli   batman-adv: print...
3272
  	if (!batadv_tt_global_add(bat_priv, orig_node, addr, vid,
30cfd02b6   Antonio Quartulli   batman-adv: detec...
3273
3274
3275
3276
3277
  				  BATADV_TT_CLIENT_TEMP,
  				  atomic_read(&orig_node->last_ttvn)))
  		goto out;
  
  	batadv_dbg(BATADV_DBG_TT, bat_priv,
160527890   Antonio Quartulli   batman-adv: print...
3278
3279
3280
  		   "Added temporary global client (addr: %pM, vid: %d, orig: %pM)
  ",
  		   addr, BATADV_PRINT_VID(vid), orig_node->orig);
30cfd02b6   Antonio Quartulli   batman-adv: detec...
3281
3282
3283
3284
  	ret = true;
  out:
  	return ret;
  }
e1bf0c140   Marek Lindner   batman-adv: tvlv ...
3285
3286
  
  /**
a19d3d85e   Marek Lindner   batman-adv: limit...
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
   * batadv_tt_local_resize_to_mtu - resize the local translation table fit the
   *  maximum packet size that can be transported through the mesh
   * @soft_iface: netdev struct of the mesh interface
   *
   * Remove entries older than 'timeout' and half timeout if more entries need
   * to be removed.
   */
  void batadv_tt_local_resize_to_mtu(struct net_device *soft_iface)
  {
  	struct batadv_priv *bat_priv = netdev_priv(soft_iface);
  	int packet_size_max = atomic_read(&bat_priv->packet_size_max);
  	int table_size, timeout = BATADV_TT_LOCAL_TIMEOUT / 2;
  	bool reduced = false;
  
  	spin_lock_bh(&bat_priv->tt.commit_lock);
  
  	while (true) {
  		table_size = batadv_tt_local_table_transmit_size(bat_priv);
  		if (packet_size_max >= table_size)
  			break;
  
  		batadv_tt_local_purge(bat_priv, timeout);
  		batadv_tt_local_purge_pending_clients(bat_priv);
  
  		timeout /= 2;
  		reduced = true;
  		net_ratelimited_function(batadv_info, soft_iface,
  					 "Forced to purge local tt entries to fit new maximum fragment MTU (%i)
  ",
  					 packet_size_max);
  	}
  
  	/* commit these changes immediately, to avoid synchronization problem
  	 * with the TTVN
  	 */
  	if (reduced)
  		batadv_tt_local_commit_changes_nolock(bat_priv);
  
  	spin_unlock_bh(&bat_priv->tt.commit_lock);
  }
  
  /**
e1bf0c140   Marek Lindner   batman-adv: tvlv ...
3329
3330
3331
3332
3333
3334
3335
3336
3337
   * batadv_tt_tvlv_ogm_handler_v1 - process incoming tt tvlv container
   * @bat_priv: the bat priv with all the soft interface information
   * @orig: the orig_node of the ogm
   * @flags: flags indicating the tvlv state (see batadv_tvlv_handler_flags)
   * @tvlv_value: tvlv buffer containing the gateway data
   * @tvlv_value_len: tvlv buffer length
   */
  static void batadv_tt_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv,
  					  struct batadv_orig_node *orig,
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
3338
  					  uint8_t flags, void *tvlv_value,
e1bf0c140   Marek Lindner   batman-adv: tvlv ...
3339
3340
  					  uint16_t tvlv_value_len)
  {
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
3341
3342
  	struct batadv_tvlv_tt_vlan_data *tt_vlan;
  	struct batadv_tvlv_tt_change *tt_change;
e1bf0c140   Marek Lindner   batman-adv: tvlv ...
3343
  	struct batadv_tvlv_tt_data *tt_data;
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
3344
  	uint16_t num_entries, num_vlan;
e1bf0c140   Marek Lindner   batman-adv: tvlv ...
3345
3346
3347
3348
3349
3350
  
  	if (tvlv_value_len < sizeof(*tt_data))
  		return;
  
  	tt_data = (struct batadv_tvlv_tt_data *)tvlv_value;
  	tvlv_value_len -= sizeof(*tt_data);
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
3351
3352
3353
3354
3355
3356
3357
3358
  	num_vlan = ntohs(tt_data->num_vlan);
  
  	if (tvlv_value_len < sizeof(*tt_vlan) * num_vlan)
  		return;
  
  	tt_vlan = (struct batadv_tvlv_tt_vlan_data *)(tt_data + 1);
  	tt_change = (struct batadv_tvlv_tt_change *)(tt_vlan + num_vlan);
  	tvlv_value_len -= sizeof(*tt_vlan) * num_vlan;
298e6e685   Antonio Quartulli   batman-adv: imple...
3359
  	num_entries = batadv_tt_entries(tvlv_value_len);
e1bf0c140   Marek Lindner   batman-adv: tvlv ...
3360

7ea7b4a14   Antonio Quartulli   batman-adv: make ...
3361
3362
  	batadv_tt_update_orig(bat_priv, orig, tt_vlan, num_vlan, tt_change,
  			      num_entries, tt_data->ttvn);
e1bf0c140   Marek Lindner   batman-adv: tvlv ...
3363
3364
3365
  }
  
  /**
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
   * batadv_tt_tvlv_unicast_handler_v1 - process incoming (unicast) tt tvlv
   *  container
   * @bat_priv: the bat priv with all the soft interface information
   * @src: mac address of tt tvlv sender
   * @dst: mac address of tt tvlv recipient
   * @tvlv_value: tvlv buffer containing the tt data
   * @tvlv_value_len: tvlv buffer length
   *
   * Returns NET_RX_DROP if the tt tvlv is to be re-routed, NET_RX_SUCCESS
   * otherwise.
   */
  static int batadv_tt_tvlv_unicast_handler_v1(struct batadv_priv *bat_priv,
  					     uint8_t *src, uint8_t *dst,
  					     void *tvlv_value,
  					     uint16_t tvlv_value_len)
  {
  	struct batadv_tvlv_tt_data *tt_data;
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
3383
  	uint16_t tt_vlan_len, tt_num_entries;
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
3384
3385
3386
3387
3388
3389
3390
3391
  	char tt_flag;
  	bool ret;
  
  	if (tvlv_value_len < sizeof(*tt_data))
  		return NET_RX_SUCCESS;
  
  	tt_data = (struct batadv_tvlv_tt_data *)tvlv_value;
  	tvlv_value_len -= sizeof(*tt_data);
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
3392
3393
3394
3395
3396
3397
3398
3399
  	tt_vlan_len = sizeof(struct batadv_tvlv_tt_vlan_data);
  	tt_vlan_len *= ntohs(tt_data->num_vlan);
  
  	if (tvlv_value_len < tt_vlan_len)
  		return NET_RX_SUCCESS;
  
  	tvlv_value_len -= tt_vlan_len;
  	tt_num_entries = batadv_tt_entries(tvlv_value_len);
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
  
  	switch (tt_data->flags & BATADV_TT_DATA_TYPE_MASK) {
  	case BATADV_TT_REQUEST:
  		batadv_inc_counter(bat_priv, BATADV_CNT_TT_REQUEST_RX);
  
  		/* If this node cannot provide a TT response the tt_request is
  		 * forwarded
  		 */
  		ret = batadv_send_tt_response(bat_priv, tt_data, src, dst);
  		if (!ret) {
  			if (tt_data->flags & BATADV_TT_FULL_TABLE)
  				tt_flag = 'F';
  			else
  				tt_flag = '.';
  
  			batadv_dbg(BATADV_DBG_TT, bat_priv,
  				   "Routing TT_REQUEST to %pM [%c]
  ",
  				   dst, tt_flag);
  			/* tvlv API will re-route the packet */
  			return NET_RX_DROP;
  		}
  		break;
  	case BATADV_TT_RESPONSE:
  		batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_RX);
  
  		if (batadv_is_my_mac(bat_priv, dst)) {
  			batadv_handle_tt_response(bat_priv, tt_data,
7ea7b4a14   Antonio Quartulli   batman-adv: make ...
3428
  						  src, tt_num_entries);
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
  			return NET_RX_SUCCESS;
  		}
  
  		if (tt_data->flags & BATADV_TT_FULL_TABLE)
  			tt_flag =  'F';
  		else
  			tt_flag = '.';
  
  		batadv_dbg(BATADV_DBG_TT, bat_priv,
  			   "Routing TT_RESPONSE to %pM [%c]
  ", dst, tt_flag);
  
  		/* tvlv API will re-route the packet */
  		return NET_RX_DROP;
  	}
  
  	return NET_RX_SUCCESS;
  }
  
  /**
122edaa05   Marek Lindner   batman-adv: tvlv ...
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
   * batadv_roam_tvlv_unicast_handler_v1 - process incoming tt roam tvlv container
   * @bat_priv: the bat priv with all the soft interface information
   * @src: mac address of tt tvlv sender
   * @dst: mac address of tt tvlv recipient
   * @tvlv_value: tvlv buffer containing the tt data
   * @tvlv_value_len: tvlv buffer length
   *
   * Returns NET_RX_DROP if the tt roam tvlv is to be re-routed, NET_RX_SUCCESS
   * otherwise.
   */
  static int batadv_roam_tvlv_unicast_handler_v1(struct batadv_priv *bat_priv,
  					       uint8_t *src, uint8_t *dst,
  					       void *tvlv_value,
  					       uint16_t tvlv_value_len)
  {
  	struct batadv_tvlv_roam_adv *roaming_adv;
  	struct batadv_orig_node *orig_node = NULL;
  
  	/* If this node is not the intended recipient of the
  	 * roaming advertisement the packet is forwarded
  	 * (the tvlv API will re-route the packet).
  	 */
  	if (!batadv_is_my_mac(bat_priv, dst))
  		return NET_RX_DROP;
122edaa05   Marek Lindner   batman-adv: tvlv ...
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
  	if (tvlv_value_len < sizeof(*roaming_adv))
  		goto out;
  
  	orig_node = batadv_orig_hash_find(bat_priv, src);
  	if (!orig_node)
  		goto out;
  
  	batadv_inc_counter(bat_priv, BATADV_CNT_TT_ROAM_ADV_RX);
  	roaming_adv = (struct batadv_tvlv_roam_adv *)tvlv_value;
  
  	batadv_dbg(BATADV_DBG_TT, bat_priv,
  		   "Received ROAMING_ADV from %pM (client %pM)
  ",
  		   src, roaming_adv->client);
  
  	batadv_tt_global_add(bat_priv, orig_node, roaming_adv->client,
c018ad3de   Antonio Quartulli   batman-adv: add t...
3489
  			     ntohs(roaming_adv->vid), BATADV_TT_CLIENT_ROAM,
122edaa05   Marek Lindner   batman-adv: tvlv ...
3490
3491
3492
3493
3494
3495
3496
3497
3498
  			     atomic_read(&orig_node->last_ttvn) + 1);
  
  out:
  	if (orig_node)
  		batadv_orig_node_free_ref(orig_node);
  	return NET_RX_SUCCESS;
  }
  
  /**
e1bf0c140   Marek Lindner   batman-adv: tvlv ...
3499
3500
3501
3502
3503
3504
3505
3506
   * batadv_tt_init - initialise the translation table internals
   * @bat_priv: the bat priv with all the soft interface information
   *
   * Return 0 on success or negative error number in case of failure.
   */
  int batadv_tt_init(struct batadv_priv *bat_priv)
  {
  	int ret;
0eb01568f   Antonio Quartulli   batman-adv: inclu...
3507
3508
  	/* synchronized flags must be remote */
  	BUILD_BUG_ON(!(BATADV_TT_SYNC_MASK & BATADV_TT_REMOTE_MASK));
e1bf0c140   Marek Lindner   batman-adv: tvlv ...
3509
3510
3511
3512
3513
3514
3515
3516
3517
  	ret = batadv_tt_local_init(bat_priv);
  	if (ret < 0)
  		return ret;
  
  	ret = batadv_tt_global_init(bat_priv);
  	if (ret < 0)
  		return ret;
  
  	batadv_tvlv_handler_register(bat_priv, batadv_tt_tvlv_ogm_handler_v1,
335fbe0f5   Marek Lindner   batman-adv: tvlv ...
3518
3519
  				     batadv_tt_tvlv_unicast_handler_v1,
  				     BATADV_TVLV_TT, 1, BATADV_NO_FLAGS);
e1bf0c140   Marek Lindner   batman-adv: tvlv ...
3520

122edaa05   Marek Lindner   batman-adv: tvlv ...
3521
3522
3523
  	batadv_tvlv_handler_register(bat_priv, NULL,
  				     batadv_roam_tvlv_unicast_handler_v1,
  				     BATADV_TVLV_ROAM, 1, BATADV_NO_FLAGS);
e1bf0c140   Marek Lindner   batman-adv: tvlv ...
3524
3525
3526
3527
3528
3529
  	INIT_DELAYED_WORK(&bat_priv->tt.work, batadv_tt_purge);
  	queue_delayed_work(batadv_event_workqueue, &bat_priv->tt.work,
  			   msecs_to_jiffies(BATADV_TT_WORK_PERIOD));
  
  	return 1;
  }
42cb0bef0   Antonio Quartulli   batman-adv: set t...
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
  
  /**
   * batadv_tt_global_is_isolated - check if a client is marked as isolated
   * @bat_priv: the bat priv with all the soft interface information
   * @addr: the mac address of the client
   * @vid: the identifier of the VLAN where this client is connected
   *
   * Returns true if the client is marked with the TT_CLIENT_ISOLA flag, false
   * otherwise
   */
  bool batadv_tt_global_is_isolated(struct batadv_priv *bat_priv,
  				  const uint8_t *addr, unsigned short vid)
  {
  	struct batadv_tt_global_entry *tt;
  	bool ret;
  
  	tt = batadv_tt_global_hash_find(bat_priv, addr, vid);
  	if (!tt)
  		return false;
  
  	ret = tt->common.flags & BATADV_TT_CLIENT_ISOLA;
  
  	batadv_tt_global_entry_free_ref(tt);
  
  	return ret;
  }