blob: b4b20ad1ed9a94b7c6b622febc93ba35d2b2c299 [file] [log] [blame]
Sven Eckelmann7db7d9f2017-11-19 15:05:11 +01001// SPDX-License-Identifier: GPL-2.0
Sven Eckelmannac79cbb2017-01-01 00:00:00 +01002/* Copyright (C) 2007-2017 B.A.T.M.A.N. contributors:
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00003 *
Antonio Quartulli35c133a2012-03-14 13:03:01 +01004 * Marek Lindner, Simon Wunderlich, Antonio Quartulli
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
Antonio Quartulliebf38fb2013-11-03 20:40:48 +010016 * along with this program; if not, see <http://www.gnu.org/licenses/>.
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +000017 */
18
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +000019#include "translation-table.h"
Sven Eckelmann1e2c2a42015-04-17 19:40:28 +020020#include "main.h"
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +000021
Sven Eckelmann1e2c2a42015-04-17 19:40:28 +020022#include <linux/atomic.h>
Linus Lüssingac4eebd2015-06-16 17:10:24 +020023#include <linux/bitops.h>
Sven Eckelmannecc36f52017-11-19 17:12:03 +010024#include <linux/build_bug.h>
Sven Eckelmann1e2c2a42015-04-17 19:40:28 +020025#include <linux/byteorder/generic.h>
Sven Eckelmann86452f82016-06-25 16:44:06 +020026#include <linux/cache.h>
Sven Eckelmann1e2c2a42015-04-17 19:40:28 +020027#include <linux/compiler.h>
Antonio Quartulliced72932013-04-24 16:37:51 +020028#include <linux/crc32c.h>
Sven Eckelmann1e2c2a42015-04-17 19:40:28 +020029#include <linux/errno.h>
30#include <linux/etherdevice.h>
Sven Eckelmannb92b94a2017-11-19 17:12:02 +010031#include <linux/gfp.h>
Sven Eckelmann1e2c2a42015-04-17 19:40:28 +020032#include <linux/if_ether.h>
Sven Eckelmann86452f82016-06-25 16:44:06 +020033#include <linux/init.h>
Sven Eckelmann1e2c2a42015-04-17 19:40:28 +020034#include <linux/jhash.h>
35#include <linux/jiffies.h>
36#include <linux/kernel.h>
Sven Eckelmann6e8ef692016-01-16 10:29:50 +010037#include <linux/kref.h>
Sven Eckelmann1e2c2a42015-04-17 19:40:28 +020038#include <linux/list.h>
39#include <linux/lockdep.h>
Sven Eckelmann3a644692017-11-19 17:12:04 +010040#include <linux/net.h>
Sven Eckelmann1e2c2a42015-04-17 19:40:28 +020041#include <linux/netdevice.h>
Matthias Schifferd34f0552016-07-03 13:31:37 +020042#include <linux/netlink.h>
Sven Eckelmann1e2c2a42015-04-17 19:40:28 +020043#include <linux/rculist.h>
44#include <linux/rcupdate.h>
45#include <linux/seq_file.h>
Matthias Schifferd34f0552016-07-03 13:31:37 +020046#include <linux/skbuff.h>
Sven Eckelmann1e2c2a42015-04-17 19:40:28 +020047#include <linux/slab.h>
48#include <linux/spinlock.h>
49#include <linux/stddef.h>
50#include <linux/string.h>
51#include <linux/workqueue.h>
Matthias Schifferd34f0552016-07-03 13:31:37 +020052#include <net/genetlink.h>
53#include <net/netlink.h>
54#include <net/sock.h>
55#include <uapi/linux/batman_adv.h>
Sven Eckelmann1e2c2a42015-04-17 19:40:28 +020056
57#include "bridge_loop_avoidance.h"
58#include "hard-interface.h"
59#include "hash.h"
Sven Eckelmannba412082016-05-15 23:48:31 +020060#include "log.h"
Matthias Schifferd34f0552016-07-03 13:31:37 +020061#include "netlink.h"
Sven Eckelmann1e2c2a42015-04-17 19:40:28 +020062#include "originator.h"
63#include "packet.h"
64#include "soft-interface.h"
Markus Pargmann1f8dce42016-05-15 11:07:43 +020065#include "tvlv.h"
Antonio Quartullia73105b2011-04-27 14:27:44 +020066
Sven Eckelmann86452f82016-06-25 16:44:06 +020067static struct kmem_cache *batadv_tl_cache __read_mostly;
68static struct kmem_cache *batadv_tg_cache __read_mostly;
69static struct kmem_cache *batadv_tt_orig_cache __read_mostly;
70static struct kmem_cache *batadv_tt_change_cache __read_mostly;
71static struct kmem_cache *batadv_tt_req_cache __read_mostly;
72static struct kmem_cache *batadv_tt_roam_cache __read_mostly;
73
Antonio Quartullidec05072012-11-10 11:00:32 +010074/* hash class keys */
75static struct lock_class_key batadv_tt_local_hash_lock_class_key;
76static struct lock_class_key batadv_tt_global_hash_lock_class_key;
77
Sven Eckelmann6b5e9712015-05-26 18:34:26 +020078static void batadv_send_roam_adv(struct batadv_priv *bat_priv, u8 *client,
Antonio Quartullic018ad32013-06-04 12:11:39 +020079 unsigned short vid,
Sven Eckelmann56303d32012-06-05 22:31:31 +020080 struct batadv_orig_node *orig_node);
Sven Eckelmanna5130882012-05-16 20:23:16 +020081static void batadv_tt_purge(struct work_struct *work);
82static void
Sven Eckelmann56303d32012-06-05 22:31:31 +020083batadv_tt_global_del_orig_list(struct batadv_tt_global_entry *tt_global_entry);
Antonio Quartulli30cfd022012-07-05 23:38:29 +020084static void batadv_tt_global_del(struct batadv_priv *bat_priv,
85 struct batadv_orig_node *orig_node,
86 const unsigned char *addr,
Antonio Quartullic018ad32013-06-04 12:11:39 +020087 unsigned short vid, const char *message,
88 bool roaming);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +000089
Sven Eckelmann62fe7102015-09-15 19:00:48 +020090/**
Antonio Quartullid15cd622015-11-17 16:40:52 +080091 * batadv_compare_tt - check if two TT entries are the same
92 * @node: the list element pointer of the first TT entry
93 * @data2: pointer to the tt_common_entry of the second TT entry
Sven Eckelmann62fe7102015-09-15 19:00:48 +020094 *
Antonio Quartullid15cd622015-11-17 16:40:52 +080095 * Compare the MAC address and the VLAN ID of the two TT entries and check if
96 * they are the same TT client.
Sven Eckelmann4b426b12016-02-22 21:02:39 +010097 * Return: true if the two TT clients are the same, false otherwise
Sven Eckelmann62fe7102015-09-15 19:00:48 +020098 */
Sven Eckelmann4b426b12016-02-22 21:02:39 +010099static bool batadv_compare_tt(const struct hlist_node *node, const void *data2)
Marek Lindner7aadf882011-02-18 12:28:09 +0000100{
Sven Eckelmann56303d32012-06-05 22:31:31 +0200101 const void *data1 = container_of(node, struct batadv_tt_common_entry,
Sven Eckelmann747e4222011-05-14 23:14:50 +0200102 hash_entry);
Marek Lindner4c718952015-08-06 10:38:54 +0200103 const struct batadv_tt_common_entry *tt1 = data1;
104 const struct batadv_tt_common_entry *tt2 = data2;
Marek Lindner7aadf882011-02-18 12:28:09 +0000105
Marek Lindner4c718952015-08-06 10:38:54 +0200106 return (tt1->vid == tt2->vid) && batadv_compare_eth(data1, data2);
Marek Lindner7aadf882011-02-18 12:28:09 +0000107}
108
Antonio Quartullic018ad32013-06-04 12:11:39 +0200109/**
110 * batadv_choose_tt - return the index of the tt entry in the hash table
111 * @data: pointer to the tt_common_entry object to map
112 * @size: the size of the hash table
113 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +0200114 * Return: the hash index where the object represented by 'data' should be
Antonio Quartullic018ad32013-06-04 12:11:39 +0200115 * stored at.
116 */
Sven Eckelmann6b5e9712015-05-26 18:34:26 +0200117static inline u32 batadv_choose_tt(const void *data, u32 size)
Antonio Quartullic018ad32013-06-04 12:11:39 +0200118{
119 struct batadv_tt_common_entry *tt;
Sven Eckelmann6b5e9712015-05-26 18:34:26 +0200120 u32 hash = 0;
Antonio Quartullic018ad32013-06-04 12:11:39 +0200121
122 tt = (struct batadv_tt_common_entry *)data;
Sven Eckelmann36fd61c2015-03-01 09:46:18 +0100123 hash = jhash(&tt->addr, ETH_ALEN, hash);
124 hash = jhash(&tt->vid, sizeof(tt->vid), hash);
Antonio Quartullic018ad32013-06-04 12:11:39 +0200125
126 return hash % size;
127}
128
129/**
130 * batadv_tt_hash_find - look for a client in the given hash table
131 * @hash: the hash table to search
132 * @addr: the mac address of the client to look for
133 * @vid: VLAN identifier
134 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +0200135 * Return: a pointer to the tt_common struct belonging to the searched client if
Antonio Quartullic018ad32013-06-04 12:11:39 +0200136 * found, NULL otherwise.
137 */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200138static struct batadv_tt_common_entry *
Sven Eckelmann6b5e9712015-05-26 18:34:26 +0200139batadv_tt_hash_find(struct batadv_hashtable *hash, const u8 *addr,
Antonio Quartullic018ad32013-06-04 12:11:39 +0200140 unsigned short vid)
Marek Lindner7aadf882011-02-18 12:28:09 +0000141{
Marek Lindner7aadf882011-02-18 12:28:09 +0000142 struct hlist_head *head;
Antonio Quartullic018ad32013-06-04 12:11:39 +0200143 struct batadv_tt_common_entry to_search, *tt, *tt_tmp = NULL;
Sven Eckelmann6b5e9712015-05-26 18:34:26 +0200144 u32 index;
Marek Lindner7aadf882011-02-18 12:28:09 +0000145
146 if (!hash)
147 return NULL;
148
Antonio Quartulli8fdd0152014-01-22 00:42:11 +0100149 ether_addr_copy(to_search.addr, addr);
Antonio Quartullic018ad32013-06-04 12:11:39 +0200150 to_search.vid = vid;
151
152 index = batadv_choose_tt(&to_search, hash->size);
Marek Lindner7aadf882011-02-18 12:28:09 +0000153 head = &hash->table[index];
154
155 rcu_read_lock();
Antonio Quartullic018ad32013-06-04 12:11:39 +0200156 hlist_for_each_entry_rcu(tt, head, hash_entry) {
157 if (!batadv_compare_eth(tt, addr))
Marek Lindner7aadf882011-02-18 12:28:09 +0000158 continue;
159
Antonio Quartullic018ad32013-06-04 12:11:39 +0200160 if (tt->vid != vid)
Antonio Quartulli7683fdc2011-04-27 14:28:07 +0200161 continue;
162
Sven Eckelmann92dcdf02016-01-16 10:29:57 +0100163 if (!kref_get_unless_zero(&tt->refcount))
Antonio Quartullic018ad32013-06-04 12:11:39 +0200164 continue;
165
166 tt_tmp = tt;
Marek Lindner7aadf882011-02-18 12:28:09 +0000167 break;
168 }
169 rcu_read_unlock();
170
Antonio Quartullic018ad32013-06-04 12:11:39 +0200171 return tt_tmp;
Antonio Quartulli48100ba2011-10-30 12:17:33 +0100172}
173
Antonio Quartullic018ad32013-06-04 12:11:39 +0200174/**
175 * batadv_tt_local_hash_find - search the local table for a given client
176 * @bat_priv: the bat priv with all the soft interface information
177 * @addr: the mac address of the client to look for
178 * @vid: VLAN identifier
179 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +0200180 * Return: a pointer to the corresponding tt_local_entry struct if the client is
Antonio Quartullic018ad32013-06-04 12:11:39 +0200181 * found, NULL otherwise.
182 */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200183static struct batadv_tt_local_entry *
Sven Eckelmann6b5e9712015-05-26 18:34:26 +0200184batadv_tt_local_hash_find(struct batadv_priv *bat_priv, const u8 *addr,
Antonio Quartullic018ad32013-06-04 12:11:39 +0200185 unsigned short vid)
Antonio Quartulli48100ba2011-10-30 12:17:33 +0100186{
Sven Eckelmann56303d32012-06-05 22:31:31 +0200187 struct batadv_tt_common_entry *tt_common_entry;
188 struct batadv_tt_local_entry *tt_local_entry = NULL;
Antonio Quartulli48100ba2011-10-30 12:17:33 +0100189
Antonio Quartullic018ad32013-06-04 12:11:39 +0200190 tt_common_entry = batadv_tt_hash_find(bat_priv->tt.local_hash, addr,
191 vid);
Antonio Quartulli48100ba2011-10-30 12:17:33 +0100192 if (tt_common_entry)
193 tt_local_entry = container_of(tt_common_entry,
Sven Eckelmann56303d32012-06-05 22:31:31 +0200194 struct batadv_tt_local_entry,
195 common);
Antonio Quartulli48100ba2011-10-30 12:17:33 +0100196 return tt_local_entry;
Marek Lindner7aadf882011-02-18 12:28:09 +0000197}
198
Antonio Quartullic018ad32013-06-04 12:11:39 +0200199/**
200 * batadv_tt_global_hash_find - search the global table for a given client
201 * @bat_priv: the bat priv with all the soft interface information
202 * @addr: the mac address of the client to look for
203 * @vid: VLAN identifier
204 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +0200205 * Return: a pointer to the corresponding tt_global_entry struct if the client
Antonio Quartullic018ad32013-06-04 12:11:39 +0200206 * is found, NULL otherwise.
207 */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200208static struct batadv_tt_global_entry *
Sven Eckelmann6b5e9712015-05-26 18:34:26 +0200209batadv_tt_global_hash_find(struct batadv_priv *bat_priv, const u8 *addr,
Antonio Quartullic018ad32013-06-04 12:11:39 +0200210 unsigned short vid)
Marek Lindner7aadf882011-02-18 12:28:09 +0000211{
Sven Eckelmann56303d32012-06-05 22:31:31 +0200212 struct batadv_tt_common_entry *tt_common_entry;
213 struct batadv_tt_global_entry *tt_global_entry = NULL;
Marek Lindner7aadf882011-02-18 12:28:09 +0000214
Antonio Quartullic018ad32013-06-04 12:11:39 +0200215 tt_common_entry = batadv_tt_hash_find(bat_priv->tt.global_hash, addr,
216 vid);
Antonio Quartulli48100ba2011-10-30 12:17:33 +0100217 if (tt_common_entry)
218 tt_global_entry = container_of(tt_common_entry,
Sven Eckelmann56303d32012-06-05 22:31:31 +0200219 struct batadv_tt_global_entry,
220 common);
Antonio Quartulli48100ba2011-10-30 12:17:33 +0100221 return tt_global_entry;
Marek Lindner7aadf882011-02-18 12:28:09 +0000222}
223
Sven Eckelmann92dcdf02016-01-16 10:29:57 +0100224/**
Sven Eckelmann86452f82016-06-25 16:44:06 +0200225 * batadv_tt_local_entry_free_rcu - free the tt_local_entry
226 * @rcu: rcu pointer of the tt_local_entry
227 */
228static void batadv_tt_local_entry_free_rcu(struct rcu_head *rcu)
229{
230 struct batadv_tt_local_entry *tt_local_entry;
231
232 tt_local_entry = container_of(rcu, struct batadv_tt_local_entry,
233 common.rcu);
234
235 kmem_cache_free(batadv_tl_cache, tt_local_entry);
236}
237
238/**
Sven Eckelmann92dcdf02016-01-16 10:29:57 +0100239 * batadv_tt_local_entry_release - release tt_local_entry from lists and queue
240 * for free after rcu grace period
241 * @ref: kref pointer of the nc_node
242 */
243static void batadv_tt_local_entry_release(struct kref *ref)
Antonio Quartulli7683fdc2011-04-27 14:28:07 +0200244{
Sven Eckelmann92dcdf02016-01-16 10:29:57 +0100245 struct batadv_tt_local_entry *tt_local_entry;
246
247 tt_local_entry = container_of(ref, struct batadv_tt_local_entry,
248 common.refcount);
249
Sven Eckelmanna33d9702016-03-11 16:44:05 +0100250 batadv_softif_vlan_put(tt_local_entry->vlan);
251
Sven Eckelmann86452f82016-06-25 16:44:06 +0200252 call_rcu(&tt_local_entry->common.rcu, batadv_tt_local_entry_free_rcu);
Antonio Quartulli7683fdc2011-04-27 14:28:07 +0200253}
254
Antonio Quartulli21026052013-05-07 00:29:22 +0200255/**
Sven Eckelmann95c0db92016-01-17 11:01:25 +0100256 * batadv_tt_local_entry_put - decrement the tt_local_entry refcounter and
Sven Eckelmann92dcdf02016-01-16 10:29:57 +0100257 * possibly release it
258 * @tt_local_entry: tt_local_entry to be free'd
259 */
260static void
Sven Eckelmann95c0db92016-01-17 11:01:25 +0100261batadv_tt_local_entry_put(struct batadv_tt_local_entry *tt_local_entry)
Sven Eckelmann92dcdf02016-01-16 10:29:57 +0100262{
263 kref_put(&tt_local_entry->common.refcount,
264 batadv_tt_local_entry_release);
265}
266
267/**
Sven Eckelmann86452f82016-06-25 16:44:06 +0200268 * batadv_tt_global_entry_free_rcu - free the tt_global_entry
269 * @rcu: rcu pointer of the tt_global_entry
270 */
271static void batadv_tt_global_entry_free_rcu(struct rcu_head *rcu)
272{
273 struct batadv_tt_global_entry *tt_global_entry;
274
275 tt_global_entry = container_of(rcu, struct batadv_tt_global_entry,
276 common.rcu);
277
278 kmem_cache_free(batadv_tg_cache, tt_global_entry);
279}
280
281/**
Sven Eckelmann92dcdf02016-01-16 10:29:57 +0100282 * batadv_tt_global_entry_release - release tt_global_entry from lists and queue
283 * for free after rcu grace period
284 * @ref: kref pointer of the nc_node
285 */
286static void batadv_tt_global_entry_release(struct kref *ref)
287{
288 struct batadv_tt_global_entry *tt_global_entry;
289
290 tt_global_entry = container_of(ref, struct batadv_tt_global_entry,
291 common.refcount);
292
293 batadv_tt_global_del_orig_list(tt_global_entry);
Sven Eckelmann86452f82016-06-25 16:44:06 +0200294
295 call_rcu(&tt_global_entry->common.rcu, batadv_tt_global_entry_free_rcu);
Sven Eckelmann92dcdf02016-01-16 10:29:57 +0100296}
297
298/**
Sven Eckelmann5dafd8a2016-01-17 11:01:26 +0100299 * batadv_tt_global_entry_put - decrement the tt_global_entry refcounter and
300 * possibly release it
Sven Eckelmann92dcdf02016-01-16 10:29:57 +0100301 * @tt_global_entry: tt_global_entry to be free'd
Antonio Quartulli21026052013-05-07 00:29:22 +0200302 */
Sven Eckelmanna5130882012-05-16 20:23:16 +0200303static void
Sven Eckelmann5dafd8a2016-01-17 11:01:26 +0100304batadv_tt_global_entry_put(struct batadv_tt_global_entry *tt_global_entry)
Antonio Quartulli7683fdc2011-04-27 14:28:07 +0200305{
Sven Eckelmann92dcdf02016-01-16 10:29:57 +0100306 kref_put(&tt_global_entry->common.refcount,
307 batadv_tt_global_entry_release);
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +0200308}
309
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +0100310/**
311 * batadv_tt_global_hash_count - count the number of orig entries
Antonio Quartullid15cd622015-11-17 16:40:52 +0800312 * @bat_priv: the bat priv with all the soft interface information
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +0100313 * @addr: the mac address of the client to count entries for
314 * @vid: VLAN identifier
315 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +0200316 * Return: the number of originators advertising the given address/data
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +0100317 * (excluding ourself).
318 */
319int batadv_tt_global_hash_count(struct batadv_priv *bat_priv,
Sven Eckelmann6b5e9712015-05-26 18:34:26 +0200320 const u8 *addr, unsigned short vid)
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +0100321{
322 struct batadv_tt_global_entry *tt_global_entry;
323 int count;
324
325 tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr, vid);
326 if (!tt_global_entry)
327 return 0;
328
329 count = atomic_read(&tt_global_entry->orig_list_count);
Sven Eckelmann5dafd8a2016-01-17 11:01:26 +0100330 batadv_tt_global_entry_put(tt_global_entry);
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +0100331
332 return count;
333}
334
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +0200335/**
336 * batadv_tt_local_size_mod - change the size by v of the local table identified
337 * by vid
338 * @bat_priv: the bat priv with all the soft interface information
339 * @vid: the VLAN identifier of the sub-table to change
340 * @v: the amount to sum to the local table size
341 */
342static void batadv_tt_local_size_mod(struct batadv_priv *bat_priv,
343 unsigned short vid, int v)
344{
345 struct batadv_softif_vlan *vlan;
346
347 vlan = batadv_softif_vlan_get(bat_priv, vid);
348 if (!vlan)
349 return;
350
351 atomic_add(v, &vlan->tt.num_entries);
352
Sven Eckelmann9c3bf082016-01-17 11:01:21 +0100353 batadv_softif_vlan_put(vlan);
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +0200354}
355
356/**
357 * batadv_tt_local_size_inc - increase by one the local table size for the given
358 * vid
359 * @bat_priv: the bat priv with all the soft interface information
360 * @vid: the VLAN identifier
361 */
362static void batadv_tt_local_size_inc(struct batadv_priv *bat_priv,
363 unsigned short vid)
364{
365 batadv_tt_local_size_mod(bat_priv, vid, 1);
366}
367
368/**
369 * batadv_tt_local_size_dec - decrease by one the local table size for the given
370 * vid
371 * @bat_priv: the bat priv with all the soft interface information
372 * @vid: the VLAN identifier
373 */
374static void batadv_tt_local_size_dec(struct batadv_priv *bat_priv,
375 unsigned short vid)
376{
377 batadv_tt_local_size_mod(bat_priv, vid, -1);
378}
379
380/**
Antonio Quartullid15cd622015-11-17 16:40:52 +0800381 * batadv_tt_global_size_mod - change the size by v of the global table
382 * for orig_node identified by vid
383 * @orig_node: the originator for which the table has to be modified
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +0200384 * @vid: the VLAN identifier
385 * @v: the amount to sum to the global table size
386 */
387static void batadv_tt_global_size_mod(struct batadv_orig_node *orig_node,
388 unsigned short vid, int v)
389{
390 struct batadv_orig_node_vlan *vlan;
391
392 vlan = batadv_orig_node_vlan_new(orig_node, vid);
393 if (!vlan)
394 return;
395
396 if (atomic_add_return(v, &vlan->tt.num_entries) == 0) {
397 spin_lock_bh(&orig_node->vlan_list_lock);
Sven Eckelmann3db15202016-01-31 13:28:00 +0100398 if (!hlist_unhashed(&vlan->list)) {
399 hlist_del_init_rcu(&vlan->list);
Sven Eckelmann21754e22016-01-17 11:01:24 +0100400 batadv_orig_node_vlan_put(vlan);
Sven Eckelmann3db15202016-01-31 13:28:00 +0100401 }
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +0200402 spin_unlock_bh(&orig_node->vlan_list_lock);
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +0200403 }
404
Sven Eckelmann21754e22016-01-17 11:01:24 +0100405 batadv_orig_node_vlan_put(vlan);
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +0200406}
407
408/**
409 * batadv_tt_global_size_inc - increase by one the global table size for the
410 * given vid
411 * @orig_node: the originator which global table size has to be decreased
412 * @vid: the vlan identifier
413 */
414static void batadv_tt_global_size_inc(struct batadv_orig_node *orig_node,
415 unsigned short vid)
416{
417 batadv_tt_global_size_mod(orig_node, vid, 1);
418}
419
420/**
421 * batadv_tt_global_size_dec - decrease by one the global table size for the
422 * given vid
423 * @orig_node: the originator which global table size has to be decreased
424 * @vid: the vlan identifier
425 */
426static void batadv_tt_global_size_dec(struct batadv_orig_node *orig_node,
427 unsigned short vid)
428{
429 batadv_tt_global_size_mod(orig_node, vid, -1);
430}
431
Sven Eckelmann42eff6a2016-01-05 12:06:20 +0100432/**
Sven Eckelmann86452f82016-06-25 16:44:06 +0200433 * batadv_tt_orig_list_entry_free_rcu - free the orig_entry
434 * @rcu: rcu pointer of the orig_entry
435 */
436static void batadv_tt_orig_list_entry_free_rcu(struct rcu_head *rcu)
437{
438 struct batadv_tt_orig_list_entry *orig_entry;
439
440 orig_entry = container_of(rcu, struct batadv_tt_orig_list_entry, rcu);
441
442 kmem_cache_free(batadv_tt_orig_cache, orig_entry);
443}
444
445/**
Sven Eckelmann42eff6a2016-01-05 12:06:20 +0100446 * batadv_tt_orig_list_entry_release - release tt orig entry from lists and
447 * queue for free after rcu grace period
Sven Eckelmann6e8ef692016-01-16 10:29:50 +0100448 * @ref: kref pointer of the tt orig entry
Sven Eckelmann42eff6a2016-01-05 12:06:20 +0100449 */
Sven Eckelmann6e8ef692016-01-16 10:29:50 +0100450static void batadv_tt_orig_list_entry_release(struct kref *ref)
Sven Eckelmann42eff6a2016-01-05 12:06:20 +0100451{
Sven Eckelmann6e8ef692016-01-16 10:29:50 +0100452 struct batadv_tt_orig_list_entry *orig_entry;
453
454 orig_entry = container_of(ref, struct batadv_tt_orig_list_entry,
455 refcount);
456
Sven Eckelmann5d967312016-01-17 11:01:09 +0100457 batadv_orig_node_put(orig_entry->orig_node);
Sven Eckelmann86452f82016-06-25 16:44:06 +0200458 call_rcu(&orig_entry->rcu, batadv_tt_orig_list_entry_free_rcu);
Sven Eckelmann42eff6a2016-01-05 12:06:20 +0100459}
460
Sven Eckelmann6e8ef692016-01-16 10:29:50 +0100461/**
Sven Eckelmann7e2366c2016-01-17 11:01:27 +0100462 * batadv_tt_orig_list_entry_put - decrement the tt orig entry refcounter and
463 * possibly release it
Sven Eckelmann6e8ef692016-01-16 10:29:50 +0100464 * @orig_entry: tt orig entry to be free'd
465 */
Sven Eckelmanna5130882012-05-16 20:23:16 +0200466static void
Sven Eckelmann7e2366c2016-01-17 11:01:27 +0100467batadv_tt_orig_list_entry_put(struct batadv_tt_orig_list_entry *orig_entry)
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +0200468{
Sven Eckelmann6e8ef692016-01-16 10:29:50 +0100469 kref_put(&orig_entry->refcount, batadv_tt_orig_list_entry_release);
Antonio Quartulli7683fdc2011-04-27 14:28:07 +0200470}
471
Antonio Quartulli3abe4ad2013-04-03 11:15:33 +0200472/**
473 * batadv_tt_local_event - store a local TT event (ADD/DEL)
474 * @bat_priv: the bat priv with all the soft interface information
475 * @tt_local_entry: the TT entry involved in the event
476 * @event_flags: flags to store in the event structure
477 */
Sven Eckelmann56303d32012-06-05 22:31:31 +0200478static void batadv_tt_local_event(struct batadv_priv *bat_priv,
Antonio Quartulli3abe4ad2013-04-03 11:15:33 +0200479 struct batadv_tt_local_entry *tt_local_entry,
Sven Eckelmann6b5e9712015-05-26 18:34:26 +0200480 u8 event_flags)
Antonio Quartullia73105b2011-04-27 14:27:44 +0200481{
Sven Eckelmann56303d32012-06-05 22:31:31 +0200482 struct batadv_tt_change_node *tt_change_node, *entry, *safe;
Antonio Quartulli3abe4ad2013-04-03 11:15:33 +0200483 struct batadv_tt_common_entry *common = &tt_local_entry->common;
Sven Eckelmann6b5e9712015-05-26 18:34:26 +0200484 u8 flags = common->flags | event_flags;
Antonio Quartulli3b643de2012-05-25 00:00:42 +0200485 bool event_removed = false;
486 bool del_op_requested, del_op_entry;
Antonio Quartullia73105b2011-04-27 14:27:44 +0200487
Sven Eckelmann86452f82016-06-25 16:44:06 +0200488 tt_change_node = kmem_cache_alloc(batadv_tt_change_cache, GFP_ATOMIC);
Antonio Quartullia73105b2011-04-27 14:27:44 +0200489 if (!tt_change_node)
490 return;
491
Antonio Quartulliff66c972011-06-30 01:14:00 +0200492 tt_change_node->change.flags = flags;
Antonio Quartullica663042013-12-15 13:26:55 +0100493 memset(tt_change_node->change.reserved, 0,
494 sizeof(tt_change_node->change.reserved));
Antonio Quartulli8fdd0152014-01-22 00:42:11 +0100495 ether_addr_copy(tt_change_node->change.addr, common->addr);
Antonio Quartullic018ad32013-06-04 12:11:39 +0200496 tt_change_node->change.vid = htons(common->vid);
Antonio Quartullia73105b2011-04-27 14:27:44 +0200497
Sven Eckelmannacd34af2012-06-03 22:19:21 +0200498 del_op_requested = flags & BATADV_TT_CLIENT_DEL;
Antonio Quartulli3b643de2012-05-25 00:00:42 +0200499
500 /* check for ADD+DEL or DEL+ADD events */
Sven Eckelmann807736f2012-07-15 22:26:51 +0200501 spin_lock_bh(&bat_priv->tt.changes_list_lock);
502 list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list,
Antonio Quartulli3b643de2012-05-25 00:00:42 +0200503 list) {
Antonio Quartulli3abe4ad2013-04-03 11:15:33 +0200504 if (!batadv_compare_eth(entry->change.addr, common->addr))
Antonio Quartulli3b643de2012-05-25 00:00:42 +0200505 continue;
506
507 /* DEL+ADD in the same orig interval have no effect and can be
508 * removed to avoid silly behaviour on the receiver side. The
509 * other way around (ADD+DEL) can happen in case of roaming of
510 * a client still in the NEW state. Roaming of NEW clients is
511 * now possible due to automatically recognition of "temporary"
512 * clients
513 */
Sven Eckelmannacd34af2012-06-03 22:19:21 +0200514 del_op_entry = entry->change.flags & BATADV_TT_CLIENT_DEL;
Antonio Quartulli3b643de2012-05-25 00:00:42 +0200515 if (!del_op_requested && del_op_entry)
516 goto del;
517 if (del_op_requested && !del_op_entry)
518 goto del;
Antonio Quartulli3c4f7ab2013-10-13 02:50:19 +0200519
520 /* this is a second add in the same originator interval. It
521 * means that flags have been changed: update them!
522 */
523 if (!del_op_requested && !del_op_entry)
524 entry->change.flags = flags;
525
Antonio Quartulli3b643de2012-05-25 00:00:42 +0200526 continue;
527del:
528 list_del(&entry->list);
Sven Eckelmann86452f82016-06-25 16:44:06 +0200529 kmem_cache_free(batadv_tt_change_cache, entry);
530 kmem_cache_free(batadv_tt_change_cache, tt_change_node);
Antonio Quartulli3b643de2012-05-25 00:00:42 +0200531 event_removed = true;
532 goto unlock;
533 }
534
Antonio Quartullia73105b2011-04-27 14:27:44 +0200535 /* track the change in the OGMinterval list */
Sven Eckelmann807736f2012-07-15 22:26:51 +0200536 list_add_tail(&tt_change_node->list, &bat_priv->tt.changes_list);
Antonio Quartulli3b643de2012-05-25 00:00:42 +0200537
538unlock:
Sven Eckelmann807736f2012-07-15 22:26:51 +0200539 spin_unlock_bh(&bat_priv->tt.changes_list_lock);
Antonio Quartullia73105b2011-04-27 14:27:44 +0200540
Antonio Quartulli3b643de2012-05-25 00:00:42 +0200541 if (event_removed)
Sven Eckelmann807736f2012-07-15 22:26:51 +0200542 atomic_dec(&bat_priv->tt.local_changes);
Antonio Quartulli3b643de2012-05-25 00:00:42 +0200543 else
Sven Eckelmann807736f2012-07-15 22:26:51 +0200544 atomic_inc(&bat_priv->tt.local_changes);
Antonio Quartullia73105b2011-04-27 14:27:44 +0200545}
546
Marek Lindner335fbe02013-04-23 21:40:02 +0800547/**
548 * batadv_tt_len - compute length in bytes of given number of tt changes
549 * @changes_num: number of tt changes
550 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +0200551 * Return: computed length in bytes.
Marek Lindner335fbe02013-04-23 21:40:02 +0800552 */
553static int batadv_tt_len(int changes_num)
Antonio Quartullia73105b2011-04-27 14:27:44 +0200554{
Marek Lindner335fbe02013-04-23 21:40:02 +0800555 return changes_num * sizeof(struct batadv_tvlv_tt_change);
Antonio Quartullia73105b2011-04-27 14:27:44 +0200556}
557
Antonio Quartulli298e6e62013-05-28 13:14:27 +0200558/**
559 * batadv_tt_entries - compute the number of entries fitting in tt_len bytes
560 * @tt_len: available space
561 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +0200562 * Return: the number of entries.
Antonio Quartulli298e6e62013-05-28 13:14:27 +0200563 */
Sven Eckelmann6b5e9712015-05-26 18:34:26 +0200564static u16 batadv_tt_entries(u16 tt_len)
Antonio Quartulli298e6e62013-05-28 13:14:27 +0200565{
566 return tt_len / batadv_tt_len(1);
567}
568
Marek Lindnera19d3d82013-05-27 15:33:25 +0800569/**
570 * batadv_tt_local_table_transmit_size - calculates the local translation table
571 * size when transmitted over the air
572 * @bat_priv: the bat priv with all the soft interface information
573 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +0200574 * Return: local translation table size in bytes.
Marek Lindnera19d3d82013-05-27 15:33:25 +0800575 */
576static int batadv_tt_local_table_transmit_size(struct batadv_priv *bat_priv)
577{
Sven Eckelmann4f248cf2015-06-09 20:50:49 +0200578 u16 num_vlan = 0;
579 u16 tt_local_entries = 0;
Marek Lindnera19d3d82013-05-27 15:33:25 +0800580 struct batadv_softif_vlan *vlan;
581 int hdr_size;
582
583 rcu_read_lock();
584 hlist_for_each_entry_rcu(vlan, &bat_priv->softif_vlan_list, list) {
585 num_vlan++;
586 tt_local_entries += atomic_read(&vlan->tt.num_entries);
587 }
588 rcu_read_unlock();
589
590 /* header size of tvlv encapsulated tt response payload */
591 hdr_size = sizeof(struct batadv_unicast_tvlv_packet);
592 hdr_size += sizeof(struct batadv_tvlv_hdr);
593 hdr_size += sizeof(struct batadv_tvlv_tt_data);
594 hdr_size += num_vlan * sizeof(struct batadv_tvlv_tt_vlan_data);
595
596 return hdr_size + batadv_tt_len(tt_local_entries);
597}
598
Sven Eckelmann56303d32012-06-05 22:31:31 +0200599static int batadv_tt_local_init(struct batadv_priv *bat_priv)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000600{
Sven Eckelmann807736f2012-07-15 22:26:51 +0200601 if (bat_priv->tt.local_hash)
Sven Eckelmann5346c352012-05-05 13:27:28 +0200602 return 0;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000603
Sven Eckelmann807736f2012-07-15 22:26:51 +0200604 bat_priv->tt.local_hash = batadv_hash_new(1024);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000605
Sven Eckelmann807736f2012-07-15 22:26:51 +0200606 if (!bat_priv->tt.local_hash)
Sven Eckelmann5346c352012-05-05 13:27:28 +0200607 return -ENOMEM;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000608
Antonio Quartullidec05072012-11-10 11:00:32 +0100609 batadv_hash_set_lock_class(bat_priv->tt.local_hash,
610 &batadv_tt_local_hash_lock_class_key);
611
Sven Eckelmann5346c352012-05-05 13:27:28 +0200612 return 0;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000613}
614
Antonio Quartulli068ee6e2012-09-23 22:38:37 +0200615static void batadv_tt_global_free(struct batadv_priv *bat_priv,
616 struct batadv_tt_global_entry *tt_global,
617 const char *message)
618{
619 batadv_dbg(BATADV_DBG_TT, bat_priv,
Antonio Quartulli16052782013-06-04 12:11:41 +0200620 "Deleting global tt entry %pM (vid: %d): %s\n",
621 tt_global->common.addr,
Sven Eckelmannf7a2bd62017-02-22 17:16:42 +0100622 batadv_print_vid(tt_global->common.vid), message);
Antonio Quartulli068ee6e2012-09-23 22:38:37 +0200623
624 batadv_hash_remove(bat_priv->tt.global_hash, batadv_compare_tt,
Antonio Quartullic018ad32013-06-04 12:11:39 +0200625 batadv_choose_tt, &tt_global->common);
Sven Eckelmann5dafd8a2016-01-17 11:01:26 +0100626 batadv_tt_global_entry_put(tt_global);
Antonio Quartulli068ee6e2012-09-23 22:38:37 +0200627}
628
Antonio Quartullic018ad32013-06-04 12:11:39 +0200629/**
630 * batadv_tt_local_add - add a new client to the local table or update an
631 * existing client
632 * @soft_iface: netdev struct of the mesh interface
633 * @addr: the mac address of the client to add
634 * @vid: VLAN identifier
635 * @ifindex: index of the interface where the client is connected to (useful to
636 * identify wireless clients)
Antonio Quartulli9464d072013-11-16 12:03:48 +0100637 * @mark: the value contained in the skb->mark field of the received packet (if
638 * any)
Marek Lindnera19d3d82013-05-27 15:33:25 +0800639 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +0200640 * Return: true if the client was successfully added, false otherwise.
Antonio Quartullic018ad32013-06-04 12:11:39 +0200641 */
Sven Eckelmann6b5e9712015-05-26 18:34:26 +0200642bool batadv_tt_local_add(struct net_device *soft_iface, const u8 *addr,
643 unsigned short vid, int ifindex, u32 mark)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000644{
Sven Eckelmann56303d32012-06-05 22:31:31 +0200645 struct batadv_priv *bat_priv = netdev_priv(soft_iface);
Sven Eckelmann170173b2012-10-07 12:02:22 +0200646 struct batadv_tt_local_entry *tt_local;
Linus Lüssingc5caf4e2014-02-15 17:47:49 +0100647 struct batadv_tt_global_entry *tt_global = NULL;
Andrew Lunn2cd45a02016-04-21 12:57:27 +0200648 struct net *net = dev_net(soft_iface);
Antonio Quartulli35df3b22014-05-08 17:13:15 +0200649 struct batadv_softif_vlan *vlan;
Antonio Quartulli0c69aec2013-10-13 02:50:18 +0200650 struct net_device *in_dev = NULL;
Sven Eckelmann10b1bbb2016-09-30 15:21:03 +0200651 struct batadv_hard_iface *in_hardif = NULL;
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +0200652 struct hlist_head *head;
Sven Eckelmann56303d32012-06-05 22:31:31 +0200653 struct batadv_tt_orig_list_entry *orig_entry;
Marek Lindnera19d3d82013-05-27 15:33:25 +0800654 int hash_added, table_size, packet_size_max;
Sven Eckelmann4f248cf2015-06-09 20:50:49 +0200655 bool ret = false;
656 bool roamed_back = false;
Sven Eckelmann6b5e9712015-05-26 18:34:26 +0200657 u8 remote_flags;
658 u32 match_mark;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000659
Antonio Quartulli0c69aec2013-10-13 02:50:18 +0200660 if (ifindex != BATADV_NULL_IFINDEX)
Andrew Lunn2cd45a02016-04-21 12:57:27 +0200661 in_dev = dev_get_by_index(net, ifindex);
Antonio Quartulli0c69aec2013-10-13 02:50:18 +0200662
Sven Eckelmann10b1bbb2016-09-30 15:21:03 +0200663 if (in_dev)
664 in_hardif = batadv_hardif_get_by_netdev(in_dev);
665
Antonio Quartullic018ad32013-06-04 12:11:39 +0200666 tt_local = batadv_tt_local_hash_find(bat_priv, addr, vid);
Linus Lüssingc5caf4e2014-02-15 17:47:49 +0100667
668 if (!is_multicast_ether_addr(addr))
669 tt_global = batadv_tt_global_hash_find(bat_priv, addr, vid);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000670
Antonio Quartulli47c94652012-09-23 22:38:35 +0200671 if (tt_local) {
672 tt_local->last_seen = jiffies;
Antonio Quartulli068ee6e2012-09-23 22:38:37 +0200673 if (tt_local->common.flags & BATADV_TT_CLIENT_PENDING) {
674 batadv_dbg(BATADV_DBG_TT, bat_priv,
Antonio Quartulli16052782013-06-04 12:11:41 +0200675 "Re-adding pending client %pM (vid: %d)\n",
Sven Eckelmannf7a2bd62017-02-22 17:16:42 +0100676 addr, batadv_print_vid(vid));
Antonio Quartulli068ee6e2012-09-23 22:38:37 +0200677 /* whatever the reason why the PENDING flag was set,
678 * this is a client which was enqueued to be removed in
679 * this orig_interval. Since it popped up again, the
680 * flag can be reset like it was never enqueued
681 */
682 tt_local->common.flags &= ~BATADV_TT_CLIENT_PENDING;
683 goto add_event;
684 }
685
686 if (tt_local->common.flags & BATADV_TT_CLIENT_ROAM) {
687 batadv_dbg(BATADV_DBG_TT, bat_priv,
Antonio Quartulli16052782013-06-04 12:11:41 +0200688 "Roaming client %pM (vid: %d) came back to its original location\n",
Sven Eckelmannf7a2bd62017-02-22 17:16:42 +0100689 addr, batadv_print_vid(vid));
Antonio Quartulli068ee6e2012-09-23 22:38:37 +0200690 /* the ROAM flag is set because this client roamed away
691 * and the node got a roaming_advertisement message. Now
692 * that the client popped up again at its original
693 * location such flag can be unset
694 */
695 tt_local->common.flags &= ~BATADV_TT_CLIENT_ROAM;
696 roamed_back = true;
697 }
698 goto check_roaming;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000699 }
700
Marek Lindnera19d3d82013-05-27 15:33:25 +0800701 /* Ignore the client if we cannot send it in a full table response. */
702 table_size = batadv_tt_local_table_transmit_size(bat_priv);
703 table_size += batadv_tt_len(1);
704 packet_size_max = atomic_read(&bat_priv->packet_size_max);
705 if (table_size > packet_size_max) {
706 net_ratelimited_function(batadv_info, soft_iface,
707 "Local translation table size (%i) exceeds maximum packet size (%i); Ignoring new local tt entry: %pM\n",
708 table_size, packet_size_max, addr);
709 goto out;
710 }
711
Sven Eckelmann86452f82016-06-25 16:44:06 +0200712 tt_local = kmem_cache_alloc(batadv_tl_cache, GFP_ATOMIC);
Antonio Quartulli47c94652012-09-23 22:38:35 +0200713 if (!tt_local)
Antonio Quartulli7683fdc2011-04-27 14:28:07 +0200714 goto out;
Antonio Quartullia73105b2011-04-27 14:27:44 +0200715
Antonio Quartulli35df3b22014-05-08 17:13:15 +0200716 /* increase the refcounter of the related vlan */
717 vlan = batadv_softif_vlan_get(bat_priv, vid);
Simon Wunderlich0b3dd7d2016-06-26 11:16:09 +0200718 if (!vlan) {
719 net_ratelimited_function(batadv_info, soft_iface,
720 "adding TT local entry %pM to non-existent VLAN %d\n",
Sven Eckelmannf7a2bd62017-02-22 17:16:42 +0100721 addr, batadv_print_vid(vid));
Sven Eckelmann86452f82016-06-25 16:44:06 +0200722 kmem_cache_free(batadv_tl_cache, tt_local);
Sven Eckelmannfd7dec22015-08-18 13:37:01 +0200723 tt_local = NULL;
Marek Lindner354136b2015-06-09 21:24:36 +0800724 goto out;
Sven Eckelmannfd7dec22015-08-18 13:37:01 +0200725 }
Antonio Quartulli35df3b22014-05-08 17:13:15 +0200726
Sven Eckelmann39c75a52012-06-03 22:19:22 +0200727 batadv_dbg(BATADV_DBG_TT, bat_priv,
Antonio Quartulli16052782013-06-04 12:11:41 +0200728 "Creating new local tt entry: %pM (vid: %d, ttvn: %d)\n",
Sven Eckelmannf7a2bd62017-02-22 17:16:42 +0100729 addr, batadv_print_vid(vid),
Sven Eckelmann6b5e9712015-05-26 18:34:26 +0200730 (u8)atomic_read(&bat_priv->tt.vn));
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000731
Antonio Quartulli8fdd0152014-01-22 00:42:11 +0100732 ether_addr_copy(tt_local->common.addr, addr);
Antonio Quartulli8425ec62012-11-19 09:01:44 +0100733 /* The local entry has to be marked as NEW to avoid to send it in
734 * a full table response going out before the next ttvn increment
735 * (consistency check)
736 */
737 tt_local->common.flags = BATADV_TT_CLIENT_NEW;
Antonio Quartullic018ad32013-06-04 12:11:39 +0200738 tt_local->common.vid = vid;
Sven Eckelmann10b1bbb2016-09-30 15:21:03 +0200739 if (batadv_is_wifi_hardif(in_hardif))
Antonio Quartulli47c94652012-09-23 22:38:35 +0200740 tt_local->common.flags |= BATADV_TT_CLIENT_WIFI;
Sven Eckelmann92dcdf02016-01-16 10:29:57 +0100741 kref_init(&tt_local->common.refcount);
Antonio Quartulli47c94652012-09-23 22:38:35 +0200742 tt_local->last_seen = jiffies;
743 tt_local->common.added_at = tt_local->last_seen;
Sven Eckelmanna33d9702016-03-11 16:44:05 +0100744 tt_local->vlan = vlan;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000745
Linus Lüssingc5caf4e2014-02-15 17:47:49 +0100746 /* the batman interface mac and multicast addresses should never be
747 * purged
748 */
749 if (batadv_compare_eth(addr, soft_iface->dev_addr) ||
750 is_multicast_ether_addr(addr))
Antonio Quartulli47c94652012-09-23 22:38:35 +0200751 tt_local->common.flags |= BATADV_TT_CLIENT_NOPURGE;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000752
Sven Eckelmanne3387b22016-07-15 17:39:22 +0200753 kref_get(&tt_local->common.refcount);
Sven Eckelmann807736f2012-07-15 22:26:51 +0200754 hash_added = batadv_hash_add(bat_priv->tt.local_hash, batadv_compare_tt,
Antonio Quartullic018ad32013-06-04 12:11:39 +0200755 batadv_choose_tt, &tt_local->common,
Antonio Quartulli47c94652012-09-23 22:38:35 +0200756 &tt_local->common.hash_entry);
Simon Wunderlich80b3f582011-11-02 20:26:45 +0100757
758 if (unlikely(hash_added != 0)) {
759 /* remove the reference for the hash */
Sven Eckelmann95c0db92016-01-17 11:01:25 +0100760 batadv_tt_local_entry_put(tt_local);
Simon Wunderlich80b3f582011-11-02 20:26:45 +0100761 goto out;
762 }
763
Antonio Quartulli068ee6e2012-09-23 22:38:37 +0200764add_event:
Antonio Quartulli3abe4ad2013-04-03 11:15:33 +0200765 batadv_tt_local_event(bat_priv, tt_local, BATADV_NO_FLAGS);
Antonio Quartulliff66c972011-06-30 01:14:00 +0200766
Antonio Quartulli068ee6e2012-09-23 22:38:37 +0200767check_roaming:
768 /* Check whether it is a roaming, but don't do anything if the roaming
769 * process has already been handled
770 */
771 if (tt_global && !(tt_global->common.flags & BATADV_TT_CLIENT_ROAM)) {
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +0200772 /* These node are probably going to update their tt table */
Antonio Quartulli47c94652012-09-23 22:38:35 +0200773 head = &tt_global->orig_list;
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +0200774 rcu_read_lock();
Sasha Levinb67bfe02013-02-27 17:06:00 -0800775 hlist_for_each_entry_rcu(orig_entry, head, list) {
Antonio Quartulli47c94652012-09-23 22:38:35 +0200776 batadv_send_roam_adv(bat_priv, tt_global->common.addr,
Antonio Quartullic018ad32013-06-04 12:11:39 +0200777 tt_global->common.vid,
Sven Eckelmanna5130882012-05-16 20:23:16 +0200778 orig_entry->orig_node);
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +0200779 }
780 rcu_read_unlock();
Antonio Quartulli068ee6e2012-09-23 22:38:37 +0200781 if (roamed_back) {
782 batadv_tt_global_free(bat_priv, tt_global,
783 "Roaming canceled");
784 tt_global = NULL;
785 } else {
786 /* The global entry has to be marked as ROAMING and
787 * has to be kept for consistency purpose
788 */
789 tt_global->common.flags |= BATADV_TT_CLIENT_ROAM;
790 tt_global->roam_at = jiffies;
791 }
Antonio Quartulli7683fdc2011-04-27 14:28:07 +0200792 }
Antonio Quartulli068ee6e2012-09-23 22:38:37 +0200793
Antonio Quartulli3c4f7ab2013-10-13 02:50:19 +0200794 /* store the current remote flags before altering them. This helps
795 * understanding is flags are changing or not
796 */
797 remote_flags = tt_local->common.flags & BATADV_TT_REMOTE_MASK;
Marek Lindnera19d3d82013-05-27 15:33:25 +0800798
Sven Eckelmann10b1bbb2016-09-30 15:21:03 +0200799 if (batadv_is_wifi_hardif(in_hardif))
Antonio Quartulli3c4f7ab2013-10-13 02:50:19 +0200800 tt_local->common.flags |= BATADV_TT_CLIENT_WIFI;
801 else
802 tt_local->common.flags &= ~BATADV_TT_CLIENT_WIFI;
803
Antonio Quartulli9464d072013-11-16 12:03:48 +0100804 /* check the mark in the skb: if it's equal to the configured
805 * isolation_mark, it means the packet is coming from an isolated
806 * non-mesh client
807 */
808 match_mark = (mark & bat_priv->isolation_mark_mask);
809 if (bat_priv->isolation_mark_mask &&
810 match_mark == bat_priv->isolation_mark)
811 tt_local->common.flags |= BATADV_TT_CLIENT_ISOLA;
812 else
813 tt_local->common.flags &= ~BATADV_TT_CLIENT_ISOLA;
814
Antonio Quartulli3c4f7ab2013-10-13 02:50:19 +0200815 /* if any "dynamic" flag has been modified, resend an ADD event for this
816 * entry so that all the nodes can get the new flags
817 */
818 if (remote_flags ^ (tt_local->common.flags & BATADV_TT_REMOTE_MASK))
819 batadv_tt_local_event(bat_priv, tt_local, BATADV_NO_FLAGS);
820
821 ret = true;
Antonio Quartulli7683fdc2011-04-27 14:28:07 +0200822out:
Sven Eckelmann10b1bbb2016-09-30 15:21:03 +0200823 if (in_hardif)
824 batadv_hardif_put(in_hardif);
Antonio Quartulli0c69aec2013-10-13 02:50:18 +0200825 if (in_dev)
826 dev_put(in_dev);
Antonio Quartulli47c94652012-09-23 22:38:35 +0200827 if (tt_local)
Sven Eckelmann95c0db92016-01-17 11:01:25 +0100828 batadv_tt_local_entry_put(tt_local);
Antonio Quartulli47c94652012-09-23 22:38:35 +0200829 if (tt_global)
Sven Eckelmann5dafd8a2016-01-17 11:01:26 +0100830 batadv_tt_global_entry_put(tt_global);
Marek Lindnera19d3d82013-05-27 15:33:25 +0800831 return ret;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000832}
833
Marek Lindnere1bf0c12013-04-23 21:40:01 +0800834/**
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +0200835 * batadv_tt_prepare_tvlv_global_data - prepare the TVLV TT header to send
836 * within a TT Response directed to another node
837 * @orig_node: originator for which the TT data has to be prepared
838 * @tt_data: uninitialised pointer to the address of the TVLV buffer
839 * @tt_change: uninitialised pointer to the address of the area where the TT
840 * changed can be stored
841 * @tt_len: pointer to the length to reserve to the tt_change. if -1 this
842 * function reserves the amount of space needed to send the entire global TT
843 * table. In case of success the value is updated with the real amount of
844 * reserved bytes
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +0200845 * Allocate the needed amount of memory for the entire TT TVLV and write its
846 * header made up by one tvlv_tt_data object and a series of tvlv_tt_vlan_data
847 * objects, one per active VLAN served by the originator node.
848 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +0200849 * Return: the size of the allocated buffer or 0 in case of failure.
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +0200850 */
Sven Eckelmann6b5e9712015-05-26 18:34:26 +0200851static u16
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +0200852batadv_tt_prepare_tvlv_global_data(struct batadv_orig_node *orig_node,
853 struct batadv_tvlv_tt_data **tt_data,
854 struct batadv_tvlv_tt_change **tt_change,
Sven Eckelmann6b5e9712015-05-26 18:34:26 +0200855 s32 *tt_len)
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +0200856{
Sven Eckelmann4f248cf2015-06-09 20:50:49 +0200857 u16 num_vlan = 0;
858 u16 num_entries = 0;
859 u16 change_offset;
860 u16 tvlv_len;
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +0200861 struct batadv_tvlv_tt_vlan_data *tt_vlan;
862 struct batadv_orig_node_vlan *vlan;
Sven Eckelmann6b5e9712015-05-26 18:34:26 +0200863 u8 *tt_change_ptr;
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +0200864
865 rcu_read_lock();
Marek Lindnerd0fa4f32015-06-22 00:30:22 +0800866 hlist_for_each_entry_rcu(vlan, &orig_node->vlan_list, list) {
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +0200867 num_vlan++;
868 num_entries += atomic_read(&vlan->tt.num_entries);
869 }
870
871 change_offset = sizeof(**tt_data);
872 change_offset += num_vlan * sizeof(*tt_vlan);
873
874 /* if tt_len is negative, allocate the space needed by the full table */
875 if (*tt_len < 0)
876 *tt_len = batadv_tt_len(num_entries);
877
878 tvlv_len = *tt_len;
879 tvlv_len += change_offset;
880
881 *tt_data = kmalloc(tvlv_len, GFP_ATOMIC);
882 if (!*tt_data) {
883 *tt_len = 0;
884 goto out;
885 }
886
887 (*tt_data)->flags = BATADV_NO_FLAGS;
888 (*tt_data)->ttvn = atomic_read(&orig_node->last_ttvn);
889 (*tt_data)->num_vlan = htons(num_vlan);
890
891 tt_vlan = (struct batadv_tvlv_tt_vlan_data *)(*tt_data + 1);
Marek Lindnerd0fa4f32015-06-22 00:30:22 +0800892 hlist_for_each_entry_rcu(vlan, &orig_node->vlan_list, list) {
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +0200893 tt_vlan->vid = htons(vlan->vid);
894 tt_vlan->crc = htonl(vlan->tt.crc);
895
896 tt_vlan++;
897 }
898
Sven Eckelmann6b5e9712015-05-26 18:34:26 +0200899 tt_change_ptr = (u8 *)*tt_data + change_offset;
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +0200900 *tt_change = (struct batadv_tvlv_tt_change *)tt_change_ptr;
901
902out:
903 rcu_read_unlock();
904 return tvlv_len;
905}
906
907/**
908 * batadv_tt_prepare_tvlv_local_data - allocate and prepare the TT TVLV for this
909 * node
910 * @bat_priv: the bat priv with all the soft interface information
911 * @tt_data: uninitialised pointer to the address of the TVLV buffer
912 * @tt_change: uninitialised pointer to the address of the area where the TT
913 * changes can be stored
914 * @tt_len: pointer to the length to reserve to the tt_change. if -1 this
915 * function reserves the amount of space needed to send the entire local TT
916 * table. In case of success the value is updated with the real amount of
917 * reserved bytes
918 *
919 * Allocate the needed amount of memory for the entire TT TVLV and write its
920 * header made up by one tvlv_tt_data object and a series of tvlv_tt_vlan_data
921 * objects, one per active VLAN.
922 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +0200923 * Return: the size of the allocated buffer or 0 in case of failure.
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +0200924 */
Sven Eckelmann6b5e9712015-05-26 18:34:26 +0200925static u16
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +0200926batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv,
927 struct batadv_tvlv_tt_data **tt_data,
928 struct batadv_tvlv_tt_change **tt_change,
Sven Eckelmann6b5e9712015-05-26 18:34:26 +0200929 s32 *tt_len)
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +0200930{
931 struct batadv_tvlv_tt_vlan_data *tt_vlan;
932 struct batadv_softif_vlan *vlan;
Sven Eckelmann4f248cf2015-06-09 20:50:49 +0200933 u16 num_vlan = 0;
934 u16 num_entries = 0;
935 u16 tvlv_len;
Sven Eckelmann6b5e9712015-05-26 18:34:26 +0200936 u8 *tt_change_ptr;
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +0200937 int change_offset;
938
939 rcu_read_lock();
940 hlist_for_each_entry_rcu(vlan, &bat_priv->softif_vlan_list, list) {
941 num_vlan++;
942 num_entries += atomic_read(&vlan->tt.num_entries);
943 }
944
945 change_offset = sizeof(**tt_data);
946 change_offset += num_vlan * sizeof(*tt_vlan);
947
948 /* if tt_len is negative, allocate the space needed by the full table */
949 if (*tt_len < 0)
950 *tt_len = batadv_tt_len(num_entries);
951
952 tvlv_len = *tt_len;
953 tvlv_len += change_offset;
954
955 *tt_data = kmalloc(tvlv_len, GFP_ATOMIC);
956 if (!*tt_data) {
957 tvlv_len = 0;
958 goto out;
959 }
960
961 (*tt_data)->flags = BATADV_NO_FLAGS;
962 (*tt_data)->ttvn = atomic_read(&bat_priv->tt.vn);
963 (*tt_data)->num_vlan = htons(num_vlan);
964
965 tt_vlan = (struct batadv_tvlv_tt_vlan_data *)(*tt_data + 1);
966 hlist_for_each_entry_rcu(vlan, &bat_priv->softif_vlan_list, list) {
967 tt_vlan->vid = htons(vlan->vid);
968 tt_vlan->crc = htonl(vlan->tt.crc);
969
970 tt_vlan++;
971 }
972
Sven Eckelmann6b5e9712015-05-26 18:34:26 +0200973 tt_change_ptr = (u8 *)*tt_data + change_offset;
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +0200974 *tt_change = (struct batadv_tvlv_tt_change *)tt_change_ptr;
975
976out:
977 rcu_read_unlock();
978 return tvlv_len;
979}
980
981/**
Marek Lindnere1bf0c12013-04-23 21:40:01 +0800982 * batadv_tt_tvlv_container_update - update the translation table tvlv container
983 * after local tt changes have been committed
984 * @bat_priv: the bat priv with all the soft interface information
985 */
986static void batadv_tt_tvlv_container_update(struct batadv_priv *bat_priv)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000987{
Marek Lindnere1bf0c12013-04-23 21:40:01 +0800988 struct batadv_tt_change_node *entry, *safe;
989 struct batadv_tvlv_tt_data *tt_data;
990 struct batadv_tvlv_tt_change *tt_change;
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +0200991 int tt_diff_len, tt_change_len = 0;
Sven Eckelmann4f248cf2015-06-09 20:50:49 +0200992 int tt_diff_entries_num = 0;
993 int tt_diff_entries_count = 0;
Sven Eckelmann6b5e9712015-05-26 18:34:26 +0200994 u16 tvlv_len;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +0000995
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +0200996 tt_diff_entries_num = atomic_read(&bat_priv->tt.local_changes);
997 tt_diff_len = batadv_tt_len(tt_diff_entries_num);
Marek Lindnerbe9aa4c2012-05-07 04:22:05 +0800998
999 /* if we have too many changes for one packet don't send any
1000 * and wait for the tt table request which will be fragmented
1001 */
Marek Lindnere1bf0c12013-04-23 21:40:01 +08001002 if (tt_diff_len > bat_priv->soft_iface->mtu)
1003 tt_diff_len = 0;
Marek Lindnerbe9aa4c2012-05-07 04:22:05 +08001004
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02001005 tvlv_len = batadv_tt_prepare_tvlv_local_data(bat_priv, &tt_data,
1006 &tt_change, &tt_diff_len);
1007 if (!tvlv_len)
Marek Lindnere1bf0c12013-04-23 21:40:01 +08001008 return;
Marek Lindnerbe9aa4c2012-05-07 04:22:05 +08001009
Marek Lindnere1bf0c12013-04-23 21:40:01 +08001010 tt_data->flags = BATADV_TT_OGM_DIFF;
Marek Lindnerbe9aa4c2012-05-07 04:22:05 +08001011
Marek Lindnere1bf0c12013-04-23 21:40:01 +08001012 if (tt_diff_len == 0)
1013 goto container_register;
Marek Lindnerbe9aa4c2012-05-07 04:22:05 +08001014
Sven Eckelmann807736f2012-07-15 22:26:51 +02001015 spin_lock_bh(&bat_priv->tt.changes_list_lock);
1016 atomic_set(&bat_priv->tt.local_changes, 0);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001017
Sven Eckelmann807736f2012-07-15 22:26:51 +02001018 list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list,
Sven Eckelmann7c64fd92012-02-28 10:55:36 +01001019 list) {
Marek Lindnere1bf0c12013-04-23 21:40:01 +08001020 if (tt_diff_entries_count < tt_diff_entries_num) {
1021 memcpy(tt_change + tt_diff_entries_count,
1022 &entry->change,
1023 sizeof(struct batadv_tvlv_tt_change));
1024 tt_diff_entries_count++;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001025 }
Antonio Quartullia73105b2011-04-27 14:27:44 +02001026 list_del(&entry->list);
Sven Eckelmann86452f82016-06-25 16:44:06 +02001027 kmem_cache_free(batadv_tt_change_cache, entry);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001028 }
Sven Eckelmann807736f2012-07-15 22:26:51 +02001029 spin_unlock_bh(&bat_priv->tt.changes_list_lock);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001030
Antonio Quartullia73105b2011-04-27 14:27:44 +02001031 /* Keep the buffer for possible tt_request */
Sven Eckelmann807736f2012-07-15 22:26:51 +02001032 spin_lock_bh(&bat_priv->tt.last_changeset_lock);
1033 kfree(bat_priv->tt.last_changeset);
1034 bat_priv->tt.last_changeset_len = 0;
1035 bat_priv->tt.last_changeset = NULL;
Marek Lindnere1bf0c12013-04-23 21:40:01 +08001036 tt_change_len = batadv_tt_len(tt_diff_entries_count);
Marek Lindnerbe9aa4c2012-05-07 04:22:05 +08001037 /* check whether this new OGM has no changes due to size problems */
Marek Lindnere1bf0c12013-04-23 21:40:01 +08001038 if (tt_diff_entries_count > 0) {
Marek Lindnerbe9aa4c2012-05-07 04:22:05 +08001039 /* if kmalloc() fails we will reply with the full table
Antonio Quartullia73105b2011-04-27 14:27:44 +02001040 * instead of providing the diff
1041 */
Marek Lindnere1bf0c12013-04-23 21:40:01 +08001042 bat_priv->tt.last_changeset = kzalloc(tt_diff_len, GFP_ATOMIC);
Sven Eckelmann807736f2012-07-15 22:26:51 +02001043 if (bat_priv->tt.last_changeset) {
Marek Lindnere1bf0c12013-04-23 21:40:01 +08001044 memcpy(bat_priv->tt.last_changeset,
1045 tt_change, tt_change_len);
1046 bat_priv->tt.last_changeset_len = tt_diff_len;
Antonio Quartullia73105b2011-04-27 14:27:44 +02001047 }
1048 }
Sven Eckelmann807736f2012-07-15 22:26:51 +02001049 spin_unlock_bh(&bat_priv->tt.last_changeset_lock);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001050
Marek Lindnere1bf0c12013-04-23 21:40:01 +08001051container_register:
1052 batadv_tvlv_container_register(bat_priv, BATADV_TVLV_TT, 1, tt_data,
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02001053 tvlv_len);
Marek Lindnere1bf0c12013-04-23 21:40:01 +08001054 kfree(tt_data);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001055}
1056
Sven Eckelmanndc1cbd12016-07-16 09:31:20 +02001057#ifdef CONFIG_BATMAN_ADV_DEBUGFS
Sven Eckelmann08c36d32012-05-12 02:09:39 +02001058int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001059{
1060 struct net_device *net_dev = (struct net_device *)seq->private;
Sven Eckelmann56303d32012-06-05 22:31:31 +02001061 struct batadv_priv *bat_priv = netdev_priv(net_dev);
Sven Eckelmann807736f2012-07-15 22:26:51 +02001062 struct batadv_hashtable *hash = bat_priv->tt.local_hash;
Sven Eckelmann56303d32012-06-05 22:31:31 +02001063 struct batadv_tt_common_entry *tt_common_entry;
Antonio Quartulli85766a82012-11-08 22:16:16 +01001064 struct batadv_tt_local_entry *tt_local;
Sven Eckelmann56303d32012-06-05 22:31:31 +02001065 struct batadv_hard_iface *primary_if;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001066 struct hlist_head *head;
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02001067 u32 i;
Antonio Quartulli85766a82012-11-08 22:16:16 +01001068 int last_seen_secs;
1069 int last_seen_msecs;
1070 unsigned long last_seen_jiffies;
1071 bool no_purge;
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02001072 u16 np_flag = BATADV_TT_CLIENT_NOPURGE;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001073
Marek Lindner30da63a2012-08-03 17:15:46 +02001074 primary_if = batadv_seq_print_text_primary_if_get(seq);
1075 if (!primary_if)
Marek Lindner32ae9b22011-04-20 15:40:58 +02001076 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001077
Sven Eckelmann86ceb362012-03-07 09:07:45 +01001078 seq_printf(seq,
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02001079 "Locally retrieved addresses (from %s) announced via TT (TTVN: %u):\n",
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02001080 net_dev->name, (u8)atomic_read(&bat_priv->tt.vn));
Antonio Quartulli925a6f32016-03-12 10:30:18 +01001081 seq_puts(seq,
1082 " Client VID Flags Last seen (CRC )\n");
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001083
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001084 for (i = 0; i < hash->size; i++) {
1085 head = &hash->table[i];
1086
Marek Lindner7aadf882011-02-18 12:28:09 +00001087 rcu_read_lock();
Sasha Levinb67bfe02013-02-27 17:06:00 -08001088 hlist_for_each_entry_rcu(tt_common_entry,
Marek Lindner7aadf882011-02-18 12:28:09 +00001089 head, hash_entry) {
Antonio Quartulli85766a82012-11-08 22:16:16 +01001090 tt_local = container_of(tt_common_entry,
1091 struct batadv_tt_local_entry,
1092 common);
1093 last_seen_jiffies = jiffies - tt_local->last_seen;
1094 last_seen_msecs = jiffies_to_msecs(last_seen_jiffies);
1095 last_seen_secs = last_seen_msecs / 1000;
1096 last_seen_msecs = last_seen_msecs % 1000;
1097
1098 no_purge = tt_common_entry->flags & np_flag;
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02001099 seq_printf(seq,
Antonio Quartullidd24ddb2013-11-16 12:03:49 +01001100 " * %pM %4i [%c%c%c%c%c%c] %3u.%03u (%#.8x)\n",
Sven Eckelmann7c64fd92012-02-28 10:55:36 +01001101 tt_common_entry->addr,
Sven Eckelmannf7a2bd62017-02-22 17:16:42 +01001102 batadv_print_vid(tt_common_entry->vid),
Sven Eckelmanna2f2b6c2015-04-23 18:22:24 +02001103 ((tt_common_entry->flags &
1104 BATADV_TT_CLIENT_ROAM) ? 'R' : '.'),
Antonio Quartulli85766a82012-11-08 22:16:16 +01001105 no_purge ? 'P' : '.',
Sven Eckelmanna2f2b6c2015-04-23 18:22:24 +02001106 ((tt_common_entry->flags &
1107 BATADV_TT_CLIENT_NEW) ? 'N' : '.'),
1108 ((tt_common_entry->flags &
1109 BATADV_TT_CLIENT_PENDING) ? 'X' : '.'),
1110 ((tt_common_entry->flags &
1111 BATADV_TT_CLIENT_WIFI) ? 'W' : '.'),
1112 ((tt_common_entry->flags &
1113 BATADV_TT_CLIENT_ISOLA) ? 'I' : '.'),
Antonio Quartullia7966d92013-01-24 11:41:39 +01001114 no_purge ? 0 : last_seen_secs,
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02001115 no_purge ? 0 : last_seen_msecs,
Sven Eckelmanna33d9702016-03-11 16:44:05 +01001116 tt_local->vlan->tt.crc);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001117 }
Marek Lindner7aadf882011-02-18 12:28:09 +00001118 rcu_read_unlock();
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001119 }
Marek Lindner32ae9b22011-04-20 15:40:58 +02001120out:
1121 if (primary_if)
Sven Eckelmann82047ad2016-01-17 11:01:10 +01001122 batadv_hardif_put(primary_if);
Marek Lindner30da63a2012-08-03 17:15:46 +02001123 return 0;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001124}
Sven Eckelmanndc1cbd12016-07-16 09:31:20 +02001125#endif
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001126
Matthias Schifferd34f0552016-07-03 13:31:37 +02001127/**
1128 * batadv_tt_local_dump_entry - Dump one TT local entry into a message
1129 * @msg :Netlink message to dump into
1130 * @portid: Port making netlink request
1131 * @seq: Sequence number of netlink message
1132 * @bat_priv: The bat priv with all the soft interface information
1133 * @common: tt local & tt global common data
1134 *
1135 * Return: Error code, or 0 on success
1136 */
1137static int
1138batadv_tt_local_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
1139 struct batadv_priv *bat_priv,
1140 struct batadv_tt_common_entry *common)
1141{
1142 void *hdr;
1143 struct batadv_softif_vlan *vlan;
1144 struct batadv_tt_local_entry *local;
1145 unsigned int last_seen_msecs;
1146 u32 crc;
1147
1148 local = container_of(common, struct batadv_tt_local_entry, common);
1149 last_seen_msecs = jiffies_to_msecs(jiffies - local->last_seen);
1150
1151 vlan = batadv_softif_vlan_get(bat_priv, common->vid);
1152 if (!vlan)
1153 return 0;
1154
1155 crc = vlan->tt.crc;
1156
1157 batadv_softif_vlan_put(vlan);
1158
1159 hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family,
1160 NLM_F_MULTI,
1161 BATADV_CMD_GET_TRANSTABLE_LOCAL);
1162 if (!hdr)
1163 return -ENOBUFS;
1164
1165 if (nla_put(msg, BATADV_ATTR_TT_ADDRESS, ETH_ALEN, common->addr) ||
1166 nla_put_u32(msg, BATADV_ATTR_TT_CRC32, crc) ||
1167 nla_put_u16(msg, BATADV_ATTR_TT_VID, common->vid) ||
1168 nla_put_u32(msg, BATADV_ATTR_TT_FLAGS, common->flags))
1169 goto nla_put_failure;
1170
1171 if (!(common->flags & BATADV_TT_CLIENT_NOPURGE) &&
1172 nla_put_u32(msg, BATADV_ATTR_LAST_SEEN_MSECS, last_seen_msecs))
1173 goto nla_put_failure;
1174
1175 genlmsg_end(msg, hdr);
1176 return 0;
1177
1178 nla_put_failure:
1179 genlmsg_cancel(msg, hdr);
1180 return -EMSGSIZE;
1181}
1182
1183/**
1184 * batadv_tt_local_dump_bucket - Dump one TT local bucket into a message
1185 * @msg: Netlink message to dump into
1186 * @portid: Port making netlink request
1187 * @seq: Sequence number of netlink message
1188 * @bat_priv: The bat priv with all the soft interface information
1189 * @head: Pointer to the list containing the local tt entries
1190 * @idx_s: Number of entries to skip
1191 *
1192 * Return: Error code, or 0 on success
1193 */
1194static int
1195batadv_tt_local_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq,
1196 struct batadv_priv *bat_priv,
1197 struct hlist_head *head, int *idx_s)
1198{
1199 struct batadv_tt_common_entry *common;
1200 int idx = 0;
1201
1202 rcu_read_lock();
1203 hlist_for_each_entry_rcu(common, head, hash_entry) {
1204 if (idx++ < *idx_s)
1205 continue;
1206
1207 if (batadv_tt_local_dump_entry(msg, portid, seq, bat_priv,
1208 common)) {
1209 rcu_read_unlock();
1210 *idx_s = idx - 1;
1211 return -EMSGSIZE;
1212 }
1213 }
1214 rcu_read_unlock();
1215
1216 *idx_s = 0;
1217 return 0;
1218}
1219
1220/**
1221 * batadv_tt_local_dump - Dump TT local entries into a message
1222 * @msg: Netlink message to dump into
1223 * @cb: Parameters from query
1224 *
1225 * Return: Error code, or 0 on success
1226 */
1227int batadv_tt_local_dump(struct sk_buff *msg, struct netlink_callback *cb)
1228{
1229 struct net *net = sock_net(cb->skb->sk);
1230 struct net_device *soft_iface;
1231 struct batadv_priv *bat_priv;
1232 struct batadv_hard_iface *primary_if = NULL;
1233 struct batadv_hashtable *hash;
1234 struct hlist_head *head;
1235 int ret;
1236 int ifindex;
1237 int bucket = cb->args[0];
1238 int idx = cb->args[1];
1239 int portid = NETLINK_CB(cb->skb).portid;
1240
1241 ifindex = batadv_netlink_get_ifindex(cb->nlh, BATADV_ATTR_MESH_IFINDEX);
1242 if (!ifindex)
1243 return -EINVAL;
1244
1245 soft_iface = dev_get_by_index(net, ifindex);
1246 if (!soft_iface || !batadv_softif_is_valid(soft_iface)) {
1247 ret = -ENODEV;
1248 goto out;
1249 }
1250
1251 bat_priv = netdev_priv(soft_iface);
1252
1253 primary_if = batadv_primary_if_get_selected(bat_priv);
1254 if (!primary_if || primary_if->if_status != BATADV_IF_ACTIVE) {
1255 ret = -ENOENT;
1256 goto out;
1257 }
1258
1259 hash = bat_priv->tt.local_hash;
1260
1261 while (bucket < hash->size) {
1262 head = &hash->table[bucket];
1263
1264 if (batadv_tt_local_dump_bucket(msg, portid, cb->nlh->nlmsg_seq,
1265 bat_priv, head, &idx))
1266 break;
1267
1268 bucket++;
1269 }
1270
1271 ret = msg->len;
1272
1273 out:
1274 if (primary_if)
1275 batadv_hardif_put(primary_if);
1276 if (soft_iface)
1277 dev_put(soft_iface);
1278
1279 cb->args[0] = bucket;
1280 cb->args[1] = idx;
1281
1282 return ret;
1283}
1284
Sven Eckelmann56303d32012-06-05 22:31:31 +02001285static void
1286batadv_tt_local_set_pending(struct batadv_priv *bat_priv,
1287 struct batadv_tt_local_entry *tt_local_entry,
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02001288 u16 flags, const char *message)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001289{
Antonio Quartulli3abe4ad2013-04-03 11:15:33 +02001290 batadv_tt_local_event(bat_priv, tt_local_entry, flags);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001291
Antonio Quartulli015758d2011-07-09 17:52:13 +02001292 /* The local client has to be marked as "pending to be removed" but has
1293 * to be kept in the table in order to send it in a full table
Sven Eckelmann9cfc7bd2012-05-12 02:09:43 +02001294 * response issued before the net ttvn increment (consistency check)
1295 */
Sven Eckelmannacd34af2012-06-03 22:19:21 +02001296 tt_local_entry->common.flags |= BATADV_TT_CLIENT_PENDING;
Antonio Quartullic566dbb2012-01-06 21:31:34 +01001297
Sven Eckelmann39c75a52012-06-03 22:19:22 +02001298 batadv_dbg(BATADV_DBG_TT, bat_priv,
Antonio Quartulli16052782013-06-04 12:11:41 +02001299 "Local tt entry (%pM, vid: %d) pending to be removed: %s\n",
1300 tt_local_entry->common.addr,
Sven Eckelmannf7a2bd62017-02-22 17:16:42 +01001301 batadv_print_vid(tt_local_entry->common.vid), message);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001302}
1303
Antonio Quartulli7f91d062012-08-27 11:44:43 +02001304/**
1305 * batadv_tt_local_remove - logically remove an entry from the local table
1306 * @bat_priv: the bat priv with all the soft interface information
1307 * @addr: the MAC address of the client to remove
Antonio Quartullic018ad32013-06-04 12:11:39 +02001308 * @vid: VLAN identifier
Antonio Quartulli7f91d062012-08-27 11:44:43 +02001309 * @message: message to append to the log on deletion
1310 * @roaming: true if the deletion is due to a roaming event
1311 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +02001312 * Return: the flags assigned to the local entry before being deleted
Antonio Quartulli7f91d062012-08-27 11:44:43 +02001313 */
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02001314u16 batadv_tt_local_remove(struct batadv_priv *bat_priv, const u8 *addr,
1315 unsigned short vid, const char *message,
1316 bool roaming)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001317{
Sven Eckelmann170173b2012-10-07 12:02:22 +02001318 struct batadv_tt_local_entry *tt_local_entry;
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02001319 u16 flags, curr_flags = BATADV_NO_FLAGS;
Marek Lindneref727062015-06-17 20:01:36 +08001320 void *tt_entry_exists;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001321
Antonio Quartullic018ad32013-06-04 12:11:39 +02001322 tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr, vid);
Antonio Quartulli7683fdc2011-04-27 14:28:07 +02001323 if (!tt_local_entry)
1324 goto out;
1325
Antonio Quartulli7f91d062012-08-27 11:44:43 +02001326 curr_flags = tt_local_entry->common.flags;
1327
Sven Eckelmannacd34af2012-06-03 22:19:21 +02001328 flags = BATADV_TT_CLIENT_DEL;
Antonio Quartulli068ee6e2012-09-23 22:38:37 +02001329 /* if this global entry addition is due to a roaming, the node has to
1330 * mark the local entry as "roamed" in order to correctly reroute
1331 * packets later
1332 */
Antonio Quartulli7c1fd912012-09-23 22:38:34 +02001333 if (roaming) {
Sven Eckelmannacd34af2012-06-03 22:19:21 +02001334 flags |= BATADV_TT_CLIENT_ROAM;
Antonio Quartulli7c1fd912012-09-23 22:38:34 +02001335 /* mark the local client as ROAMed */
1336 tt_local_entry->common.flags |= BATADV_TT_CLIENT_ROAM;
1337 }
Sven Eckelmann42d0b042012-06-03 22:19:17 +02001338
Antonio Quartulli068ee6e2012-09-23 22:38:37 +02001339 if (!(tt_local_entry->common.flags & BATADV_TT_CLIENT_NEW)) {
1340 batadv_tt_local_set_pending(bat_priv, tt_local_entry, flags,
1341 message);
1342 goto out;
1343 }
1344 /* if this client has been added right now, it is possible to
1345 * immediately purge it
1346 */
Antonio Quartulli3abe4ad2013-04-03 11:15:33 +02001347 batadv_tt_local_event(bat_priv, tt_local_entry, BATADV_TT_CLIENT_DEL);
Marek Lindneref727062015-06-17 20:01:36 +08001348
1349 tt_entry_exists = batadv_hash_remove(bat_priv->tt.local_hash,
1350 batadv_compare_tt,
1351 batadv_choose_tt,
1352 &tt_local_entry->common);
1353 if (!tt_entry_exists)
1354 goto out;
1355
1356 /* extra call to free the local tt entry */
Sven Eckelmann95c0db92016-01-17 11:01:25 +01001357 batadv_tt_local_entry_put(tt_local_entry);
Antonio Quartulli7f91d062012-08-27 11:44:43 +02001358
Antonio Quartulli7683fdc2011-04-27 14:28:07 +02001359out:
1360 if (tt_local_entry)
Sven Eckelmann95c0db92016-01-17 11:01:25 +01001361 batadv_tt_local_entry_put(tt_local_entry);
Antonio Quartulli7f91d062012-08-27 11:44:43 +02001362
1363 return curr_flags;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001364}
1365
Marek Lindnera19d3d82013-05-27 15:33:25 +08001366/**
1367 * batadv_tt_local_purge_list - purge inactive tt local entries
1368 * @bat_priv: the bat priv with all the soft interface information
1369 * @head: pointer to the list containing the local tt entries
1370 * @timeout: parameter deciding whether a given tt local entry is considered
1371 * inactive or not
1372 */
Sven Eckelmann56303d32012-06-05 22:31:31 +02001373static void batadv_tt_local_purge_list(struct batadv_priv *bat_priv,
Marek Lindnera19d3d82013-05-27 15:33:25 +08001374 struct hlist_head *head,
1375 int timeout)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001376{
Sven Eckelmann56303d32012-06-05 22:31:31 +02001377 struct batadv_tt_local_entry *tt_local_entry;
1378 struct batadv_tt_common_entry *tt_common_entry;
Sasha Levinb67bfe02013-02-27 17:06:00 -08001379 struct hlist_node *node_tmp;
Sven Eckelmannacd34af2012-06-03 22:19:21 +02001380
Sasha Levinb67bfe02013-02-27 17:06:00 -08001381 hlist_for_each_entry_safe(tt_common_entry, node_tmp, head,
Sven Eckelmannacd34af2012-06-03 22:19:21 +02001382 hash_entry) {
1383 tt_local_entry = container_of(tt_common_entry,
Sven Eckelmann56303d32012-06-05 22:31:31 +02001384 struct batadv_tt_local_entry,
1385 common);
Sven Eckelmannacd34af2012-06-03 22:19:21 +02001386 if (tt_local_entry->common.flags & BATADV_TT_CLIENT_NOPURGE)
1387 continue;
1388
1389 /* entry already marked for deletion */
1390 if (tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING)
1391 continue;
1392
Marek Lindnera19d3d82013-05-27 15:33:25 +08001393 if (!batadv_has_timed_out(tt_local_entry->last_seen, timeout))
Sven Eckelmannacd34af2012-06-03 22:19:21 +02001394 continue;
1395
1396 batadv_tt_local_set_pending(bat_priv, tt_local_entry,
1397 BATADV_TT_CLIENT_DEL, "timed out");
1398 }
1399}
1400
Marek Lindnera19d3d82013-05-27 15:33:25 +08001401/**
1402 * batadv_tt_local_purge - purge inactive tt local entries
1403 * @bat_priv: the bat priv with all the soft interface information
1404 * @timeout: parameter deciding whether a given tt local entry is considered
1405 * inactive or not
1406 */
1407static void batadv_tt_local_purge(struct batadv_priv *bat_priv,
1408 int timeout)
Sven Eckelmannacd34af2012-06-03 22:19:21 +02001409{
Sven Eckelmann807736f2012-07-15 22:26:51 +02001410 struct batadv_hashtable *hash = bat_priv->tt.local_hash;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001411 struct hlist_head *head;
Antonio Quartulli7683fdc2011-04-27 14:28:07 +02001412 spinlock_t *list_lock; /* protects write access to the hash lists */
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02001413 u32 i;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001414
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001415 for (i = 0; i < hash->size; i++) {
1416 head = &hash->table[i];
Antonio Quartulli7683fdc2011-04-27 14:28:07 +02001417 list_lock = &hash->list_locks[i];
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001418
Antonio Quartulli7683fdc2011-04-27 14:28:07 +02001419 spin_lock_bh(list_lock);
Marek Lindnera19d3d82013-05-27 15:33:25 +08001420 batadv_tt_local_purge_list(bat_priv, head, timeout);
Antonio Quartulli7683fdc2011-04-27 14:28:07 +02001421 spin_unlock_bh(list_lock);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001422 }
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001423}
1424
Sven Eckelmann56303d32012-06-05 22:31:31 +02001425static void batadv_tt_local_table_free(struct batadv_priv *bat_priv)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001426{
Sven Eckelmann5bf74e92012-06-05 22:31:28 +02001427 struct batadv_hashtable *hash;
Antonio Quartullia73105b2011-04-27 14:27:44 +02001428 spinlock_t *list_lock; /* protects write access to the hash lists */
Sven Eckelmann56303d32012-06-05 22:31:31 +02001429 struct batadv_tt_common_entry *tt_common_entry;
1430 struct batadv_tt_local_entry *tt_local;
Sasha Levinb67bfe02013-02-27 17:06:00 -08001431 struct hlist_node *node_tmp;
Antonio Quartulli7683fdc2011-04-27 14:28:07 +02001432 struct hlist_head *head;
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02001433 u32 i;
Antonio Quartullia73105b2011-04-27 14:27:44 +02001434
Sven Eckelmann807736f2012-07-15 22:26:51 +02001435 if (!bat_priv->tt.local_hash)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001436 return;
1437
Sven Eckelmann807736f2012-07-15 22:26:51 +02001438 hash = bat_priv->tt.local_hash;
Antonio Quartullia73105b2011-04-27 14:27:44 +02001439
1440 for (i = 0; i < hash->size; i++) {
1441 head = &hash->table[i];
1442 list_lock = &hash->list_locks[i];
1443
1444 spin_lock_bh(list_lock);
Sasha Levinb67bfe02013-02-27 17:06:00 -08001445 hlist_for_each_entry_safe(tt_common_entry, node_tmp,
Antonio Quartullia73105b2011-04-27 14:27:44 +02001446 head, hash_entry) {
Sasha Levinb67bfe02013-02-27 17:06:00 -08001447 hlist_del_rcu(&tt_common_entry->hash_entry);
Sven Eckelmann56303d32012-06-05 22:31:31 +02001448 tt_local = container_of(tt_common_entry,
1449 struct batadv_tt_local_entry,
1450 common);
Antonio Quartulli35df3b22014-05-08 17:13:15 +02001451
Sven Eckelmann95c0db92016-01-17 11:01:25 +01001452 batadv_tt_local_entry_put(tt_local);
Antonio Quartullia73105b2011-04-27 14:27:44 +02001453 }
1454 spin_unlock_bh(list_lock);
1455 }
1456
Sven Eckelmann1a8eaf02012-05-12 02:09:32 +02001457 batadv_hash_destroy(hash);
Antonio Quartullia73105b2011-04-27 14:27:44 +02001458
Sven Eckelmann807736f2012-07-15 22:26:51 +02001459 bat_priv->tt.local_hash = NULL;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001460}
1461
Sven Eckelmann56303d32012-06-05 22:31:31 +02001462static int batadv_tt_global_init(struct batadv_priv *bat_priv)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001463{
Sven Eckelmann807736f2012-07-15 22:26:51 +02001464 if (bat_priv->tt.global_hash)
Sven Eckelmann5346c352012-05-05 13:27:28 +02001465 return 0;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001466
Sven Eckelmann807736f2012-07-15 22:26:51 +02001467 bat_priv->tt.global_hash = batadv_hash_new(1024);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001468
Sven Eckelmann807736f2012-07-15 22:26:51 +02001469 if (!bat_priv->tt.global_hash)
Sven Eckelmann5346c352012-05-05 13:27:28 +02001470 return -ENOMEM;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001471
Antonio Quartullidec05072012-11-10 11:00:32 +01001472 batadv_hash_set_lock_class(bat_priv->tt.global_hash,
1473 &batadv_tt_global_hash_lock_class_key);
1474
Sven Eckelmann5346c352012-05-05 13:27:28 +02001475 return 0;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001476}
1477
Sven Eckelmann56303d32012-06-05 22:31:31 +02001478static void batadv_tt_changes_list_free(struct batadv_priv *bat_priv)
Antonio Quartullia73105b2011-04-27 14:27:44 +02001479{
Sven Eckelmann56303d32012-06-05 22:31:31 +02001480 struct batadv_tt_change_node *entry, *safe;
Antonio Quartullia73105b2011-04-27 14:27:44 +02001481
Sven Eckelmann807736f2012-07-15 22:26:51 +02001482 spin_lock_bh(&bat_priv->tt.changes_list_lock);
Antonio Quartullia73105b2011-04-27 14:27:44 +02001483
Sven Eckelmann807736f2012-07-15 22:26:51 +02001484 list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list,
Antonio Quartullia73105b2011-04-27 14:27:44 +02001485 list) {
1486 list_del(&entry->list);
Sven Eckelmann86452f82016-06-25 16:44:06 +02001487 kmem_cache_free(batadv_tt_change_cache, entry);
Antonio Quartullia73105b2011-04-27 14:27:44 +02001488 }
1489
Sven Eckelmann807736f2012-07-15 22:26:51 +02001490 atomic_set(&bat_priv->tt.local_changes, 0);
1491 spin_unlock_bh(&bat_priv->tt.changes_list_lock);
Antonio Quartullia73105b2011-04-27 14:27:44 +02001492}
1493
Sven Eckelmann62fe7102015-09-15 19:00:48 +02001494/**
Antonio Quartullid15cd622015-11-17 16:40:52 +08001495 * batadv_tt_global_orig_entry_find - find a TT orig_list_entry
1496 * @entry: the TT global entry where the orig_list_entry has to be
1497 * extracted from
1498 * @orig_node: the originator for which the orig_list_entry has to be found
Sven Eckelmann62fe7102015-09-15 19:00:48 +02001499 *
Antonio Quartullid15cd622015-11-17 16:40:52 +08001500 * retrieve the orig_tt_list_entry belonging to orig_node from the
Antonio Quartullid657e622012-07-01 14:09:12 +02001501 * batadv_tt_global_entry list
1502 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +02001503 * Return: it with an increased refcounter, NULL if not found
Antonio Quartullid657e622012-07-01 14:09:12 +02001504 */
1505static struct batadv_tt_orig_list_entry *
1506batadv_tt_global_orig_entry_find(const struct batadv_tt_global_entry *entry,
1507 const struct batadv_orig_node *orig_node)
1508{
1509 struct batadv_tt_orig_list_entry *tmp_orig_entry, *orig_entry = NULL;
1510 const struct hlist_head *head;
Antonio Quartullid657e622012-07-01 14:09:12 +02001511
1512 rcu_read_lock();
1513 head = &entry->orig_list;
Sasha Levinb67bfe02013-02-27 17:06:00 -08001514 hlist_for_each_entry_rcu(tmp_orig_entry, head, list) {
Antonio Quartullid657e622012-07-01 14:09:12 +02001515 if (tmp_orig_entry->orig_node != orig_node)
1516 continue;
Sven Eckelmann6e8ef692016-01-16 10:29:50 +01001517 if (!kref_get_unless_zero(&tmp_orig_entry->refcount))
Antonio Quartullid657e622012-07-01 14:09:12 +02001518 continue;
1519
1520 orig_entry = tmp_orig_entry;
1521 break;
1522 }
1523 rcu_read_unlock();
1524
1525 return orig_entry;
1526}
1527
Sven Eckelmann62fe7102015-09-15 19:00:48 +02001528/**
Antonio Quartullid15cd622015-11-17 16:40:52 +08001529 * batadv_tt_global_entry_has_orig - check if a TT global entry is also handled
1530 * by a given originator
1531 * @entry: the TT global entry to check
1532 * @orig_node: the originator to search in the list
Sven Eckelmann62fe7102015-09-15 19:00:48 +02001533 *
1534 * find out if an orig_node is already in the list of a tt_global_entry.
1535 *
1536 * Return: true if found, false otherwise
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02001537 */
Sven Eckelmann56303d32012-06-05 22:31:31 +02001538static bool
1539batadv_tt_global_entry_has_orig(const struct batadv_tt_global_entry *entry,
1540 const struct batadv_orig_node *orig_node)
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02001541{
Antonio Quartullid657e622012-07-01 14:09:12 +02001542 struct batadv_tt_orig_list_entry *orig_entry;
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02001543 bool found = false;
1544
Antonio Quartullid657e622012-07-01 14:09:12 +02001545 orig_entry = batadv_tt_global_orig_entry_find(entry, orig_node);
1546 if (orig_entry) {
1547 found = true;
Sven Eckelmann7e2366c2016-01-17 11:01:27 +01001548 batadv_tt_orig_list_entry_put(orig_entry);
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02001549 }
Antonio Quartullid657e622012-07-01 14:09:12 +02001550
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02001551 return found;
1552}
1553
Linus Lüssing54e22f22017-07-06 07:02:25 +02001554/**
1555 * batadv_tt_global_sync_flags - update TT sync flags
1556 * @tt_global: the TT global entry to update sync flags in
1557 *
1558 * Updates the sync flag bits in the tt_global flag attribute with a logical
1559 * OR of all sync flags from any of its TT orig entries.
1560 */
1561static void
1562batadv_tt_global_sync_flags(struct batadv_tt_global_entry *tt_global)
1563{
1564 struct batadv_tt_orig_list_entry *orig_entry;
1565 const struct hlist_head *head;
1566 u16 flags = BATADV_NO_FLAGS;
1567
1568 rcu_read_lock();
1569 head = &tt_global->orig_list;
1570 hlist_for_each_entry_rcu(orig_entry, head, list)
1571 flags |= orig_entry->flags;
1572 rcu_read_unlock();
1573
1574 flags |= tt_global->common.flags & (~BATADV_TT_SYNC_MASK);
1575 tt_global->common.flags = flags;
1576}
1577
1578/**
1579 * batadv_tt_global_orig_entry_add - add or update a TT orig entry
1580 * @tt_global: the TT global entry to add an orig entry in
1581 * @orig_node: the originator to add an orig entry for
1582 * @ttvn: translation table version number of this changeset
1583 * @flags: TT sync flags
1584 */
Sven Eckelmanna5130882012-05-16 20:23:16 +02001585static void
Antonio Quartullid657e622012-07-01 14:09:12 +02001586batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global,
Linus Lüssing54e22f22017-07-06 07:02:25 +02001587 struct batadv_orig_node *orig_node, int ttvn,
1588 u8 flags)
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02001589{
Sven Eckelmann56303d32012-06-05 22:31:31 +02001590 struct batadv_tt_orig_list_entry *orig_entry;
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02001591
Antonio Quartullid657e622012-07-01 14:09:12 +02001592 orig_entry = batadv_tt_global_orig_entry_find(tt_global, orig_node);
Antonio Quartulli30cfd022012-07-05 23:38:29 +02001593 if (orig_entry) {
1594 /* refresh the ttvn: the current value could be a bogus one that
1595 * was added during a "temporary client detection"
1596 */
1597 orig_entry->ttvn = ttvn;
Linus Lüssing54e22f22017-07-06 07:02:25 +02001598 orig_entry->flags = flags;
1599 goto sync_flags;
Antonio Quartulli30cfd022012-07-05 23:38:29 +02001600 }
Antonio Quartullid657e622012-07-01 14:09:12 +02001601
Sven Eckelmann86452f82016-06-25 16:44:06 +02001602 orig_entry = kmem_cache_zalloc(batadv_tt_orig_cache, GFP_ATOMIC);
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02001603 if (!orig_entry)
Antonio Quartullid657e622012-07-01 14:09:12 +02001604 goto out;
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02001605
1606 INIT_HLIST_NODE(&orig_entry->list);
Sven Eckelmann7c124392016-01-16 10:29:56 +01001607 kref_get(&orig_node->refcount);
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02001608 batadv_tt_global_size_inc(orig_node, tt_global->common.vid);
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02001609 orig_entry->orig_node = orig_node;
1610 orig_entry->ttvn = ttvn;
Linus Lüssing54e22f22017-07-06 07:02:25 +02001611 orig_entry->flags = flags;
Sven Eckelmann6e8ef692016-01-16 10:29:50 +01001612 kref_init(&orig_entry->refcount);
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02001613
Antonio Quartullid657e622012-07-01 14:09:12 +02001614 spin_lock_bh(&tt_global->list_lock);
Sven Eckelmann23f55482016-07-15 17:39:18 +02001615 kref_get(&orig_entry->refcount);
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02001616 hlist_add_head_rcu(&orig_entry->list,
Antonio Quartullid657e622012-07-01 14:09:12 +02001617 &tt_global->orig_list);
1618 spin_unlock_bh(&tt_global->list_lock);
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +01001619 atomic_inc(&tt_global->orig_list_count);
1620
Linus Lüssing54e22f22017-07-06 07:02:25 +02001621sync_flags:
1622 batadv_tt_global_sync_flags(tt_global);
Antonio Quartullid657e622012-07-01 14:09:12 +02001623out:
1624 if (orig_entry)
Sven Eckelmann7e2366c2016-01-17 11:01:27 +01001625 batadv_tt_orig_list_entry_put(orig_entry);
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02001626}
1627
Antonio Quartullid4ff40f2013-04-18 15:13:01 +02001628/**
1629 * batadv_tt_global_add - add a new TT global entry or update an existing one
1630 * @bat_priv: the bat priv with all the soft interface information
1631 * @orig_node: the originator announcing the client
1632 * @tt_addr: the mac address of the non-mesh client
Antonio Quartullic018ad32013-06-04 12:11:39 +02001633 * @vid: VLAN identifier
Antonio Quartullid4ff40f2013-04-18 15:13:01 +02001634 * @flags: TT flags that have to be set for this non-mesh client
1635 * @ttvn: the tt version number ever announcing this non-mesh client
1636 *
1637 * Add a new TT global entry for the given originator. If the entry already
1638 * exists add a new reference to the given originator (a global entry can have
1639 * references to multiple originators) and adjust the flags attribute to reflect
1640 * the function argument.
1641 * If a TT local entry exists for this non-mesh client remove it.
1642 *
1643 * The caller must hold orig_node refcount.
Antonio Quartulli1e5d49f2013-05-05 19:32:38 +02001644 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +02001645 * Return: true if the new entry has been added, false otherwise
Antonio Quartullid4ff40f2013-04-18 15:13:01 +02001646 */
Antonio Quartulli1e5d49f2013-05-05 19:32:38 +02001647static bool batadv_tt_global_add(struct batadv_priv *bat_priv,
1648 struct batadv_orig_node *orig_node,
Antonio Quartullic018ad32013-06-04 12:11:39 +02001649 const unsigned char *tt_addr,
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02001650 unsigned short vid, u16 flags, u8 ttvn)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001651{
Sven Eckelmann170173b2012-10-07 12:02:22 +02001652 struct batadv_tt_global_entry *tt_global_entry;
1653 struct batadv_tt_local_entry *tt_local_entry;
Antonio Quartulli1e5d49f2013-05-05 19:32:38 +02001654 bool ret = false;
Simon Wunderlich80b3f582011-11-02 20:26:45 +01001655 int hash_added;
Sven Eckelmann56303d32012-06-05 22:31:31 +02001656 struct batadv_tt_common_entry *common;
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02001657 u16 local_flags;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001658
Antonio Quartullicfd4f752013-08-07 18:28:56 +02001659 /* ignore global entries from backbone nodes */
1660 if (batadv_bla_is_backbone_gw_orig(bat_priv, orig_node->orig, vid))
1661 return true;
1662
Antonio Quartullic018ad32013-06-04 12:11:39 +02001663 tt_global_entry = batadv_tt_global_hash_find(bat_priv, tt_addr, vid);
1664 tt_local_entry = batadv_tt_local_hash_find(bat_priv, tt_addr, vid);
Antonio Quartulli068ee6e2012-09-23 22:38:37 +02001665
1666 /* if the node already has a local client for this entry, it has to wait
1667 * for a roaming advertisement instead of manually messing up the global
1668 * table
1669 */
1670 if ((flags & BATADV_TT_CLIENT_TEMP) && tt_local_entry &&
1671 !(tt_local_entry->common.flags & BATADV_TT_CLIENT_NEW))
1672 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001673
Antonio Quartullia73105b2011-04-27 14:27:44 +02001674 if (!tt_global_entry) {
Sven Eckelmann86452f82016-06-25 16:44:06 +02001675 tt_global_entry = kmem_cache_zalloc(batadv_tg_cache,
1676 GFP_ATOMIC);
Antonio Quartullia73105b2011-04-27 14:27:44 +02001677 if (!tt_global_entry)
Antonio Quartulli7683fdc2011-04-27 14:28:07 +02001678 goto out;
1679
Sven Eckelmannc0a55922012-05-12 13:48:55 +02001680 common = &tt_global_entry->common;
Antonio Quartulli8fdd0152014-01-22 00:42:11 +01001681 ether_addr_copy(common->addr, tt_addr);
Antonio Quartullic018ad32013-06-04 12:11:39 +02001682 common->vid = vid;
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02001683
Antonio Quartullid4f44692012-05-25 00:00:54 +02001684 common->flags = flags;
Antonio Quartullicc47f662011-04-27 14:27:57 +02001685 tt_global_entry->roam_at = 0;
Antonio Quartullifdf79322012-08-24 17:54:07 +02001686 /* node must store current time in case of roaming. This is
1687 * needed to purge this entry out on timeout (if nobody claims
1688 * it)
1689 */
1690 if (flags & BATADV_TT_CLIENT_ROAM)
1691 tt_global_entry->roam_at = jiffies;
Sven Eckelmann92dcdf02016-01-16 10:29:57 +01001692 kref_init(&common->refcount);
Antonio Quartulli30cfd022012-07-05 23:38:29 +02001693 common->added_at = jiffies;
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02001694
1695 INIT_HLIST_HEAD(&tt_global_entry->orig_list);
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +01001696 atomic_set(&tt_global_entry->orig_list_count, 0);
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02001697 spin_lock_init(&tt_global_entry->list_lock);
Antonio Quartulli7683fdc2011-04-27 14:28:07 +02001698
Sven Eckelmann15d5ffd2016-07-15 17:39:23 +02001699 kref_get(&common->refcount);
Sven Eckelmann807736f2012-07-15 22:26:51 +02001700 hash_added = batadv_hash_add(bat_priv->tt.global_hash,
Sven Eckelmanna5130882012-05-16 20:23:16 +02001701 batadv_compare_tt,
Antonio Quartullic018ad32013-06-04 12:11:39 +02001702 batadv_choose_tt, common,
Sven Eckelmanna5130882012-05-16 20:23:16 +02001703 &common->hash_entry);
Simon Wunderlich80b3f582011-11-02 20:26:45 +01001704
1705 if (unlikely(hash_added != 0)) {
1706 /* remove the reference for the hash */
Sven Eckelmann5dafd8a2016-01-17 11:01:26 +01001707 batadv_tt_global_entry_put(tt_global_entry);
Simon Wunderlich80b3f582011-11-02 20:26:45 +01001708 goto out_remove;
1709 }
Antonio Quartullia73105b2011-04-27 14:27:44 +02001710 } else {
Antonio Quartulli068ee6e2012-09-23 22:38:37 +02001711 common = &tt_global_entry->common;
Antonio Quartulli30cfd022012-07-05 23:38:29 +02001712 /* If there is already a global entry, we can use this one for
1713 * our processing.
Antonio Quartulli068ee6e2012-09-23 22:38:37 +02001714 * But if we are trying to add a temporary client then here are
1715 * two options at this point:
1716 * 1) the global client is not a temporary client: the global
1717 * client has to be left as it is, temporary information
1718 * should never override any already known client state
1719 * 2) the global client is a temporary client: purge the
1720 * originator list and add the new one orig_entry
Antonio Quartulli30cfd022012-07-05 23:38:29 +02001721 */
Antonio Quartulli068ee6e2012-09-23 22:38:37 +02001722 if (flags & BATADV_TT_CLIENT_TEMP) {
1723 if (!(common->flags & BATADV_TT_CLIENT_TEMP))
1724 goto out;
1725 if (batadv_tt_global_entry_has_orig(tt_global_entry,
1726 orig_node))
1727 goto out_remove;
1728 batadv_tt_global_del_orig_list(tt_global_entry);
1729 goto add_orig_entry;
1730 }
Antonio Quartulli30cfd022012-07-05 23:38:29 +02001731
1732 /* if the client was temporary added before receiving the first
Simon Wunderlicha6cb3902015-09-02 20:09:55 +02001733 * OGM announcing it, we have to clear the TEMP flag. Also,
1734 * remove the previous temporary orig node and re-add it
1735 * if required. If the orig entry changed, the new one which
1736 * is a non-temporary entry is preferred.
Antonio Quartulli30cfd022012-07-05 23:38:29 +02001737 */
Simon Wunderlicha6cb3902015-09-02 20:09:55 +02001738 if (common->flags & BATADV_TT_CLIENT_TEMP) {
1739 batadv_tt_global_del_orig_list(tt_global_entry);
1740 common->flags &= ~BATADV_TT_CLIENT_TEMP;
1741 }
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02001742
Antonio Quartullie9c001362012-11-07 15:05:33 +01001743 /* the change can carry possible "attribute" flags like the
Linus Lüssing54e22f22017-07-06 07:02:25 +02001744 * TT_CLIENT_TEMP, therefore they have to be copied in the
Antonio Quartullie9c001362012-11-07 15:05:33 +01001745 * client entry
1746 */
Linus Lüssing54e22f22017-07-06 07:02:25 +02001747 common->flags |= flags & (~BATADV_TT_SYNC_MASK);
Antonio Quartullie9c001362012-11-07 15:05:33 +01001748
Sven Eckelmannacd34af2012-06-03 22:19:21 +02001749 /* If there is the BATADV_TT_CLIENT_ROAM flag set, there is only
1750 * one originator left in the list and we previously received a
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02001751 * delete + roaming change for this originator.
1752 *
1753 * We should first delete the old originator before adding the
1754 * new one.
1755 */
Antonio Quartulli068ee6e2012-09-23 22:38:37 +02001756 if (common->flags & BATADV_TT_CLIENT_ROAM) {
Sven Eckelmanna5130882012-05-16 20:23:16 +02001757 batadv_tt_global_del_orig_list(tt_global_entry);
Antonio Quartulli068ee6e2012-09-23 22:38:37 +02001758 common->flags &= ~BATADV_TT_CLIENT_ROAM;
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02001759 tt_global_entry->roam_at = 0;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001760 }
1761 }
Antonio Quartulli068ee6e2012-09-23 22:38:37 +02001762add_orig_entry:
Antonio Quartulli30cfd022012-07-05 23:38:29 +02001763 /* add the new orig_entry (if needed) or update it */
Linus Lüssing54e22f22017-07-06 07:02:25 +02001764 batadv_tt_global_orig_entry_add(tt_global_entry, orig_node, ttvn,
1765 flags & BATADV_TT_SYNC_MASK);
Antonio Quartullia73105b2011-04-27 14:27:44 +02001766
Sven Eckelmann39c75a52012-06-03 22:19:22 +02001767 batadv_dbg(BATADV_DBG_TT, bat_priv,
Antonio Quartulli16052782013-06-04 12:11:41 +02001768 "Creating new global tt entry: %pM (vid: %d, via %pM)\n",
Sven Eckelmannf7a2bd62017-02-22 17:16:42 +01001769 common->addr, batadv_print_vid(common->vid),
Antonio Quartulli16052782013-06-04 12:11:41 +02001770 orig_node->orig);
Antonio Quartulli1e5d49f2013-05-05 19:32:38 +02001771 ret = true;
Antonio Quartullia73105b2011-04-27 14:27:44 +02001772
Simon Wunderlich80b3f582011-11-02 20:26:45 +01001773out_remove:
Linus Lüssingc5caf4e2014-02-15 17:47:49 +01001774 /* Do not remove multicast addresses from the local hash on
1775 * global additions
1776 */
1777 if (is_multicast_ether_addr(tt_addr))
1778 goto out;
Antonio Quartulli7f91d062012-08-27 11:44:43 +02001779
Antonio Quartullia73105b2011-04-27 14:27:44 +02001780 /* remove address from local hash if present */
Antonio Quartullic018ad32013-06-04 12:11:39 +02001781 local_flags = batadv_tt_local_remove(bat_priv, tt_addr, vid,
Antonio Quartulli7f91d062012-08-27 11:44:43 +02001782 "global tt received",
Antonio Quartullic1d07432013-01-15 22:17:19 +10001783 flags & BATADV_TT_CLIENT_ROAM);
Antonio Quartulli7f91d062012-08-27 11:44:43 +02001784 tt_global_entry->common.flags |= local_flags & BATADV_TT_CLIENT_WIFI;
1785
Antonio Quartulli068ee6e2012-09-23 22:38:37 +02001786 if (!(flags & BATADV_TT_CLIENT_ROAM))
1787 /* this is a normal global add. Therefore the client is not in a
1788 * roaming state anymore.
1789 */
1790 tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_ROAM;
1791
Antonio Quartulli7683fdc2011-04-27 14:28:07 +02001792out:
1793 if (tt_global_entry)
Sven Eckelmann5dafd8a2016-01-17 11:01:26 +01001794 batadv_tt_global_entry_put(tt_global_entry);
Antonio Quartulli068ee6e2012-09-23 22:38:37 +02001795 if (tt_local_entry)
Sven Eckelmann95c0db92016-01-17 11:01:25 +01001796 batadv_tt_local_entry_put(tt_local_entry);
Antonio Quartulli7683fdc2011-04-27 14:28:07 +02001797 return ret;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001798}
1799
Simon Wunderlich1b371d12014-01-15 21:17:54 +01001800/**
1801 * batadv_transtable_best_orig - Get best originator list entry from tt entry
Antonio Quartulli46274562013-09-03 11:10:24 +02001802 * @bat_priv: the bat priv with all the soft interface information
Sven Eckelmann981d8902012-10-07 13:34:15 +02001803 * @tt_global_entry: global translation table entry to be analyzed
1804 *
1805 * This functon assumes the caller holds rcu_read_lock().
Sven Eckelmann62fe7102015-09-15 19:00:48 +02001806 * Return: best originator list entry or NULL on errors.
Sven Eckelmann981d8902012-10-07 13:34:15 +02001807 */
1808static struct batadv_tt_orig_list_entry *
Antonio Quartulli46274562013-09-03 11:10:24 +02001809batadv_transtable_best_orig(struct batadv_priv *bat_priv,
1810 struct batadv_tt_global_entry *tt_global_entry)
Sven Eckelmann981d8902012-10-07 13:34:15 +02001811{
Antonio Quartulli46274562013-09-03 11:10:24 +02001812 struct batadv_neigh_node *router, *best_router = NULL;
Antonio Quartulli29824a52016-05-25 23:27:31 +08001813 struct batadv_algo_ops *bao = bat_priv->algo_ops;
Sven Eckelmann981d8902012-10-07 13:34:15 +02001814 struct hlist_head *head;
Sven Eckelmann981d8902012-10-07 13:34:15 +02001815 struct batadv_tt_orig_list_entry *orig_entry, *best_entry = NULL;
Sven Eckelmann981d8902012-10-07 13:34:15 +02001816
1817 head = &tt_global_entry->orig_list;
Sasha Levinb67bfe02013-02-27 17:06:00 -08001818 hlist_for_each_entry_rcu(orig_entry, head, list) {
Simon Wunderlich7351a4822013-11-13 19:14:47 +01001819 router = batadv_orig_router_get(orig_entry->orig_node,
1820 BATADV_IF_DEFAULT);
Sven Eckelmann981d8902012-10-07 13:34:15 +02001821 if (!router)
1822 continue;
1823
Antonio Quartulli46274562013-09-03 11:10:24 +02001824 if (best_router &&
Antonio Quartulli29824a52016-05-25 23:27:31 +08001825 bao->neigh.cmp(router, BATADV_IF_DEFAULT, best_router,
1826 BATADV_IF_DEFAULT) <= 0) {
Sven Eckelmann25bb2502016-01-17 11:01:11 +01001827 batadv_neigh_node_put(router);
Antonio Quartulli46274562013-09-03 11:10:24 +02001828 continue;
Sven Eckelmann981d8902012-10-07 13:34:15 +02001829 }
1830
Antonio Quartulli46274562013-09-03 11:10:24 +02001831 /* release the refcount for the "old" best */
1832 if (best_router)
Sven Eckelmann25bb2502016-01-17 11:01:11 +01001833 batadv_neigh_node_put(best_router);
Antonio Quartulli46274562013-09-03 11:10:24 +02001834
1835 best_entry = orig_entry;
1836 best_router = router;
Sven Eckelmann981d8902012-10-07 13:34:15 +02001837 }
1838
Antonio Quartulli46274562013-09-03 11:10:24 +02001839 if (best_router)
Sven Eckelmann25bb2502016-01-17 11:01:11 +01001840 batadv_neigh_node_put(best_router);
Antonio Quartulli46274562013-09-03 11:10:24 +02001841
Sven Eckelmann981d8902012-10-07 13:34:15 +02001842 return best_entry;
1843}
1844
Sven Eckelmanndc1cbd12016-07-16 09:31:20 +02001845#ifdef CONFIG_BATMAN_ADV_DEBUGFS
Simon Wunderlich1b371d12014-01-15 21:17:54 +01001846/**
1847 * batadv_tt_global_print_entry - print all orig nodes who announce the address
1848 * for this global entry
Antonio Quartulli46274562013-09-03 11:10:24 +02001849 * @bat_priv: the bat priv with all the soft interface information
Sven Eckelmann981d8902012-10-07 13:34:15 +02001850 * @tt_global_entry: global translation table entry to be printed
1851 * @seq: debugfs table seq_file struct
1852 *
1853 * This functon assumes the caller holds rcu_read_lock().
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02001854 */
Sven Eckelmanna5130882012-05-16 20:23:16 +02001855static void
Antonio Quartulli46274562013-09-03 11:10:24 +02001856batadv_tt_global_print_entry(struct batadv_priv *bat_priv,
1857 struct batadv_tt_global_entry *tt_global_entry,
Sven Eckelmanna5130882012-05-16 20:23:16 +02001858 struct seq_file *seq)
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02001859{
Sven Eckelmann981d8902012-10-07 13:34:15 +02001860 struct batadv_tt_orig_list_entry *orig_entry, *best_entry;
Sven Eckelmann56303d32012-06-05 22:31:31 +02001861 struct batadv_tt_common_entry *tt_common_entry;
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02001862 struct batadv_orig_node_vlan *vlan;
1863 struct hlist_head *head;
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02001864 u8 last_ttvn;
1865 u16 flags;
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02001866
1867 tt_common_entry = &tt_global_entry->common;
Sven Eckelmann981d8902012-10-07 13:34:15 +02001868 flags = tt_common_entry->flags;
1869
Antonio Quartulli46274562013-09-03 11:10:24 +02001870 best_entry = batadv_transtable_best_orig(bat_priv, tt_global_entry);
Sven Eckelmann981d8902012-10-07 13:34:15 +02001871 if (best_entry) {
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02001872 vlan = batadv_orig_node_vlan_get(best_entry->orig_node,
1873 tt_common_entry->vid);
1874 if (!vlan) {
1875 seq_printf(seq,
1876 " * Cannot retrieve VLAN %d for originator %pM\n",
Sven Eckelmannf7a2bd62017-02-22 17:16:42 +01001877 batadv_print_vid(tt_common_entry->vid),
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02001878 best_entry->orig_node->orig);
1879 goto print_list;
1880 }
1881
Sven Eckelmann981d8902012-10-07 13:34:15 +02001882 last_ttvn = atomic_read(&best_entry->orig_node->last_ttvn);
Antonio Quartullif9d8a532012-11-19 09:01:42 +01001883 seq_printf(seq,
Antonio Quartullidd24ddb2013-11-16 12:03:49 +01001884 " %c %pM %4i (%3u) via %pM (%3u) (%#.8x) [%c%c%c%c]\n",
Sven Eckelmann981d8902012-10-07 13:34:15 +02001885 '*', tt_global_entry->common.addr,
Sven Eckelmannf7a2bd62017-02-22 17:16:42 +01001886 batadv_print_vid(tt_global_entry->common.vid),
Sven Eckelmann981d8902012-10-07 13:34:15 +02001887 best_entry->ttvn, best_entry->orig_node->orig,
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02001888 last_ttvn, vlan->tt.crc,
Sven Eckelmanna2f2b6c2015-04-23 18:22:24 +02001889 ((flags & BATADV_TT_CLIENT_ROAM) ? 'R' : '.'),
1890 ((flags & BATADV_TT_CLIENT_WIFI) ? 'W' : '.'),
1891 ((flags & BATADV_TT_CLIENT_ISOLA) ? 'I' : '.'),
1892 ((flags & BATADV_TT_CLIENT_TEMP) ? 'T' : '.'));
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02001893
Sven Eckelmann21754e22016-01-17 11:01:24 +01001894 batadv_orig_node_vlan_put(vlan);
Sven Eckelmann981d8902012-10-07 13:34:15 +02001895 }
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02001896
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02001897print_list:
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02001898 head = &tt_global_entry->orig_list;
1899
Sasha Levinb67bfe02013-02-27 17:06:00 -08001900 hlist_for_each_entry_rcu(orig_entry, head, list) {
Sven Eckelmann981d8902012-10-07 13:34:15 +02001901 if (best_entry == orig_entry)
1902 continue;
1903
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02001904 vlan = batadv_orig_node_vlan_get(orig_entry->orig_node,
1905 tt_common_entry->vid);
1906 if (!vlan) {
1907 seq_printf(seq,
1908 " + Cannot retrieve VLAN %d for originator %pM\n",
Sven Eckelmannf7a2bd62017-02-22 17:16:42 +01001909 batadv_print_vid(tt_common_entry->vid),
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02001910 orig_entry->orig_node->orig);
1911 continue;
1912 }
1913
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02001914 last_ttvn = atomic_read(&orig_entry->orig_node->last_ttvn);
Antonio Quartulli16052782013-06-04 12:11:41 +02001915 seq_printf(seq,
Antonio Quartullidd24ddb2013-11-16 12:03:49 +01001916 " %c %pM %4d (%3u) via %pM (%3u) (%#.8x) [%c%c%c%c]\n",
Sven Eckelmann981d8902012-10-07 13:34:15 +02001917 '+', tt_global_entry->common.addr,
Sven Eckelmannf7a2bd62017-02-22 17:16:42 +01001918 batadv_print_vid(tt_global_entry->common.vid),
Sven Eckelmann981d8902012-10-07 13:34:15 +02001919 orig_entry->ttvn, orig_entry->orig_node->orig,
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02001920 last_ttvn, vlan->tt.crc,
Sven Eckelmanna2f2b6c2015-04-23 18:22:24 +02001921 ((flags & BATADV_TT_CLIENT_ROAM) ? 'R' : '.'),
1922 ((flags & BATADV_TT_CLIENT_WIFI) ? 'W' : '.'),
1923 ((flags & BATADV_TT_CLIENT_ISOLA) ? 'I' : '.'),
1924 ((flags & BATADV_TT_CLIENT_TEMP) ? 'T' : '.'));
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02001925
Sven Eckelmann21754e22016-01-17 11:01:24 +01001926 batadv_orig_node_vlan_put(vlan);
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02001927 }
1928}
1929
Sven Eckelmann08c36d32012-05-12 02:09:39 +02001930int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001931{
1932 struct net_device *net_dev = (struct net_device *)seq->private;
Sven Eckelmann56303d32012-06-05 22:31:31 +02001933 struct batadv_priv *bat_priv = netdev_priv(net_dev);
Sven Eckelmann807736f2012-07-15 22:26:51 +02001934 struct batadv_hashtable *hash = bat_priv->tt.global_hash;
Sven Eckelmann56303d32012-06-05 22:31:31 +02001935 struct batadv_tt_common_entry *tt_common_entry;
1936 struct batadv_tt_global_entry *tt_global;
1937 struct batadv_hard_iface *primary_if;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001938 struct hlist_head *head;
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02001939 u32 i;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001940
Marek Lindner30da63a2012-08-03 17:15:46 +02001941 primary_if = batadv_seq_print_text_primary_if_get(seq);
1942 if (!primary_if)
Marek Lindner32ae9b22011-04-20 15:40:58 +02001943 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001944
Antonio Quartulli2dafb492011-05-05 08:42:45 +02001945 seq_printf(seq,
1946 "Globally announced TT entries received via the mesh %s\n",
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001947 net_dev->name);
Antonio Quartulli925a6f32016-03-12 10:30:18 +01001948 seq_puts(seq,
1949 " Client VID (TTVN) Originator (Curr TTVN) (CRC ) Flags\n");
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001950
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001951 for (i = 0; i < hash->size; i++) {
1952 head = &hash->table[i];
1953
Marek Lindner7aadf882011-02-18 12:28:09 +00001954 rcu_read_lock();
Sasha Levinb67bfe02013-02-27 17:06:00 -08001955 hlist_for_each_entry_rcu(tt_common_entry,
Marek Lindner7aadf882011-02-18 12:28:09 +00001956 head, hash_entry) {
Sven Eckelmann56303d32012-06-05 22:31:31 +02001957 tt_global = container_of(tt_common_entry,
1958 struct batadv_tt_global_entry,
1959 common);
Antonio Quartulli46274562013-09-03 11:10:24 +02001960 batadv_tt_global_print_entry(bat_priv, tt_global, seq);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001961 }
Marek Lindner7aadf882011-02-18 12:28:09 +00001962 rcu_read_unlock();
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001963 }
Marek Lindner32ae9b22011-04-20 15:40:58 +02001964out:
1965 if (primary_if)
Sven Eckelmann82047ad2016-01-17 11:01:10 +01001966 batadv_hardif_put(primary_if);
Marek Lindner30da63a2012-08-03 17:15:46 +02001967 return 0;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001968}
Sven Eckelmanndc1cbd12016-07-16 09:31:20 +02001969#endif
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00001970
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +01001971/**
Matthias Schifferd34f0552016-07-03 13:31:37 +02001972 * batadv_tt_global_dump_subentry - Dump all TT local entries into a message
1973 * @msg: Netlink message to dump into
1974 * @portid: Port making netlink request
1975 * @seq: Sequence number of netlink message
1976 * @common: tt local & tt global common data
1977 * @orig: Originator node announcing a non-mesh client
1978 * @best: Is the best originator for the TT entry
1979 *
1980 * Return: Error code, or 0 on success
1981 */
1982static int
1983batadv_tt_global_dump_subentry(struct sk_buff *msg, u32 portid, u32 seq,
1984 struct batadv_tt_common_entry *common,
1985 struct batadv_tt_orig_list_entry *orig,
1986 bool best)
1987{
Linus Lüssing54e22f22017-07-06 07:02:25 +02001988 u16 flags = (common->flags & (~BATADV_TT_SYNC_MASK)) | orig->flags;
Matthias Schifferd34f0552016-07-03 13:31:37 +02001989 void *hdr;
1990 struct batadv_orig_node_vlan *vlan;
1991 u8 last_ttvn;
1992 u32 crc;
1993
1994 vlan = batadv_orig_node_vlan_get(orig->orig_node,
1995 common->vid);
1996 if (!vlan)
1997 return 0;
1998
1999 crc = vlan->tt.crc;
2000
2001 batadv_orig_node_vlan_put(vlan);
2002
2003 hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family,
2004 NLM_F_MULTI,
2005 BATADV_CMD_GET_TRANSTABLE_GLOBAL);
2006 if (!hdr)
2007 return -ENOBUFS;
2008
2009 last_ttvn = atomic_read(&orig->orig_node->last_ttvn);
2010
2011 if (nla_put(msg, BATADV_ATTR_TT_ADDRESS, ETH_ALEN, common->addr) ||
2012 nla_put(msg, BATADV_ATTR_ORIG_ADDRESS, ETH_ALEN,
2013 orig->orig_node->orig) ||
2014 nla_put_u8(msg, BATADV_ATTR_TT_TTVN, orig->ttvn) ||
2015 nla_put_u8(msg, BATADV_ATTR_TT_LAST_TTVN, last_ttvn) ||
2016 nla_put_u32(msg, BATADV_ATTR_TT_CRC32, crc) ||
2017 nla_put_u16(msg, BATADV_ATTR_TT_VID, common->vid) ||
Linus Lüssing54e22f22017-07-06 07:02:25 +02002018 nla_put_u32(msg, BATADV_ATTR_TT_FLAGS, flags))
Matthias Schifferd34f0552016-07-03 13:31:37 +02002019 goto nla_put_failure;
2020
2021 if (best && nla_put_flag(msg, BATADV_ATTR_FLAG_BEST))
2022 goto nla_put_failure;
2023
2024 genlmsg_end(msg, hdr);
2025 return 0;
2026
2027 nla_put_failure:
2028 genlmsg_cancel(msg, hdr);
2029 return -EMSGSIZE;
2030}
2031
2032/**
2033 * batadv_tt_global_dump_entry - Dump one TT global entry into a message
2034 * @msg: Netlink message to dump into
2035 * @portid: Port making netlink request
2036 * @seq: Sequence number of netlink message
2037 * @bat_priv: The bat priv with all the soft interface information
2038 * @common: tt local & tt global common data
2039 * @sub_s: Number of entries to skip
2040 *
2041 * This function assumes the caller holds rcu_read_lock().
2042 *
2043 * Return: Error code, or 0 on success
2044 */
2045static int
2046batadv_tt_global_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
2047 struct batadv_priv *bat_priv,
2048 struct batadv_tt_common_entry *common, int *sub_s)
2049{
2050 struct batadv_tt_orig_list_entry *orig_entry, *best_entry;
2051 struct batadv_tt_global_entry *global;
2052 struct hlist_head *head;
2053 int sub = 0;
2054 bool best;
2055
2056 global = container_of(common, struct batadv_tt_global_entry, common);
2057 best_entry = batadv_transtable_best_orig(bat_priv, global);
2058 head = &global->orig_list;
2059
2060 hlist_for_each_entry_rcu(orig_entry, head, list) {
2061 if (sub++ < *sub_s)
2062 continue;
2063
2064 best = (orig_entry == best_entry);
2065
2066 if (batadv_tt_global_dump_subentry(msg, portid, seq, common,
2067 orig_entry, best)) {
2068 *sub_s = sub - 1;
2069 return -EMSGSIZE;
2070 }
2071 }
2072
2073 *sub_s = 0;
2074 return 0;
2075}
2076
2077/**
2078 * batadv_tt_global_dump_bucket - Dump one TT local bucket into a message
2079 * @msg: Netlink message to dump into
2080 * @portid: Port making netlink request
2081 * @seq: Sequence number of netlink message
2082 * @bat_priv: The bat priv with all the soft interface information
2083 * @head: Pointer to the list containing the global tt entries
2084 * @idx_s: Number of entries to skip
2085 * @sub: Number of entries to skip
2086 *
2087 * Return: Error code, or 0 on success
2088 */
2089static int
2090batadv_tt_global_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq,
2091 struct batadv_priv *bat_priv,
2092 struct hlist_head *head, int *idx_s, int *sub)
2093{
2094 struct batadv_tt_common_entry *common;
2095 int idx = 0;
2096
2097 rcu_read_lock();
2098 hlist_for_each_entry_rcu(common, head, hash_entry) {
2099 if (idx++ < *idx_s)
2100 continue;
2101
2102 if (batadv_tt_global_dump_entry(msg, portid, seq, bat_priv,
2103 common, sub)) {
2104 rcu_read_unlock();
2105 *idx_s = idx - 1;
2106 return -EMSGSIZE;
2107 }
2108 }
2109 rcu_read_unlock();
2110
2111 *idx_s = 0;
2112 *sub = 0;
2113 return 0;
2114}
2115
2116/**
2117 * batadv_tt_global_dump - Dump TT global entries into a message
2118 * @msg: Netlink message to dump into
2119 * @cb: Parameters from query
2120 *
2121 * Return: Error code, or length of message on success
2122 */
2123int batadv_tt_global_dump(struct sk_buff *msg, struct netlink_callback *cb)
2124{
2125 struct net *net = sock_net(cb->skb->sk);
2126 struct net_device *soft_iface;
2127 struct batadv_priv *bat_priv;
2128 struct batadv_hard_iface *primary_if = NULL;
2129 struct batadv_hashtable *hash;
2130 struct hlist_head *head;
2131 int ret;
2132 int ifindex;
2133 int bucket = cb->args[0];
2134 int idx = cb->args[1];
2135 int sub = cb->args[2];
2136 int portid = NETLINK_CB(cb->skb).portid;
2137
2138 ifindex = batadv_netlink_get_ifindex(cb->nlh, BATADV_ATTR_MESH_IFINDEX);
2139 if (!ifindex)
2140 return -EINVAL;
2141
2142 soft_iface = dev_get_by_index(net, ifindex);
2143 if (!soft_iface || !batadv_softif_is_valid(soft_iface)) {
2144 ret = -ENODEV;
2145 goto out;
2146 }
2147
2148 bat_priv = netdev_priv(soft_iface);
2149
2150 primary_if = batadv_primary_if_get_selected(bat_priv);
2151 if (!primary_if || primary_if->if_status != BATADV_IF_ACTIVE) {
2152 ret = -ENOENT;
2153 goto out;
2154 }
2155
2156 hash = bat_priv->tt.global_hash;
2157
2158 while (bucket < hash->size) {
2159 head = &hash->table[bucket];
2160
2161 if (batadv_tt_global_dump_bucket(msg, portid,
2162 cb->nlh->nlmsg_seq, bat_priv,
2163 head, &idx, &sub))
2164 break;
2165
2166 bucket++;
2167 }
2168
2169 ret = msg->len;
2170
2171 out:
2172 if (primary_if)
2173 batadv_hardif_put(primary_if);
2174 if (soft_iface)
2175 dev_put(soft_iface);
2176
2177 cb->args[0] = bucket;
2178 cb->args[1] = idx;
2179 cb->args[2] = sub;
2180
2181 return ret;
2182}
2183
2184/**
Marek Lindner433ff98f2015-06-18 16:11:07 +08002185 * _batadv_tt_global_del_orig_entry - remove and free an orig_entry
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +01002186 * @tt_global_entry: the global entry to remove the orig_entry from
2187 * @orig_entry: the orig entry to remove and free
2188 *
2189 * Remove an orig_entry from its list in the given tt_global_entry and
2190 * free this orig_entry afterwards.
Marek Lindner433ff98f2015-06-18 16:11:07 +08002191 *
2192 * Caller must hold tt_global_entry->list_lock and ensure orig_entry->list is
2193 * part of a list.
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +01002194 */
2195static void
Marek Lindner433ff98f2015-06-18 16:11:07 +08002196_batadv_tt_global_del_orig_entry(struct batadv_tt_global_entry *tt_global_entry,
2197 struct batadv_tt_orig_list_entry *orig_entry)
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +01002198{
Sven Eckelmann2c72d652015-06-21 14:45:14 +02002199 lockdep_assert_held(&tt_global_entry->list_lock);
2200
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +01002201 batadv_tt_global_size_dec(orig_entry->orig_node,
2202 tt_global_entry->common.vid);
2203 atomic_dec(&tt_global_entry->orig_list_count);
Marek Lindner433ff98f2015-06-18 16:11:07 +08002204 /* requires holding tt_global_entry->list_lock and orig_entry->list
2205 * being part of a list
2206 */
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +01002207 hlist_del_rcu(&orig_entry->list);
Sven Eckelmann7e2366c2016-01-17 11:01:27 +01002208 batadv_tt_orig_list_entry_put(orig_entry);
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +01002209}
2210
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02002211/* deletes the orig list of a tt_global_entry */
Sven Eckelmanna5130882012-05-16 20:23:16 +02002212static void
Sven Eckelmann56303d32012-06-05 22:31:31 +02002213batadv_tt_global_del_orig_list(struct batadv_tt_global_entry *tt_global_entry)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00002214{
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02002215 struct hlist_head *head;
Sasha Levinb67bfe02013-02-27 17:06:00 -08002216 struct hlist_node *safe;
Sven Eckelmann56303d32012-06-05 22:31:31 +02002217 struct batadv_tt_orig_list_entry *orig_entry;
Antonio Quartullia73105b2011-04-27 14:27:44 +02002218
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02002219 spin_lock_bh(&tt_global_entry->list_lock);
2220 head = &tt_global_entry->orig_list;
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +01002221 hlist_for_each_entry_safe(orig_entry, safe, head, list)
Marek Lindner433ff98f2015-06-18 16:11:07 +08002222 _batadv_tt_global_del_orig_entry(tt_global_entry, orig_entry);
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02002223 spin_unlock_bh(&tt_global_entry->list_lock);
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02002224}
2225
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +01002226/**
2227 * batadv_tt_global_del_orig_node - remove orig_node from a global tt entry
2228 * @bat_priv: the bat priv with all the soft interface information
2229 * @tt_global_entry: the global entry to remove the orig_node from
2230 * @orig_node: the originator announcing the client
2231 * @message: message to append to the log on deletion
2232 *
2233 * Remove the given orig_node and its according orig_entry from the given
2234 * global tt entry.
2235 */
Sven Eckelmanna5130882012-05-16 20:23:16 +02002236static void
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +01002237batadv_tt_global_del_orig_node(struct batadv_priv *bat_priv,
2238 struct batadv_tt_global_entry *tt_global_entry,
2239 struct batadv_orig_node *orig_node,
2240 const char *message)
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02002241{
2242 struct hlist_head *head;
Sasha Levinb67bfe02013-02-27 17:06:00 -08002243 struct hlist_node *safe;
Sven Eckelmann56303d32012-06-05 22:31:31 +02002244 struct batadv_tt_orig_list_entry *orig_entry;
Antonio Quartulli16052782013-06-04 12:11:41 +02002245 unsigned short vid;
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02002246
2247 spin_lock_bh(&tt_global_entry->list_lock);
2248 head = &tt_global_entry->orig_list;
Sasha Levinb67bfe02013-02-27 17:06:00 -08002249 hlist_for_each_entry_safe(orig_entry, safe, head, list) {
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02002250 if (orig_entry->orig_node == orig_node) {
Antonio Quartulli16052782013-06-04 12:11:41 +02002251 vid = tt_global_entry->common.vid;
Sven Eckelmann39c75a52012-06-03 22:19:22 +02002252 batadv_dbg(BATADV_DBG_TT, bat_priv,
Antonio Quartulli16052782013-06-04 12:11:41 +02002253 "Deleting %pM from global tt entry %pM (vid: %d): %s\n",
Sven Eckelmann1eda58b2012-05-12 13:48:58 +02002254 orig_node->orig,
Antonio Quartulli16052782013-06-04 12:11:41 +02002255 tt_global_entry->common.addr,
Sven Eckelmannf7a2bd62017-02-22 17:16:42 +01002256 batadv_print_vid(vid), message);
Marek Lindner433ff98f2015-06-18 16:11:07 +08002257 _batadv_tt_global_del_orig_entry(tt_global_entry,
2258 orig_entry);
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02002259 }
2260 }
2261 spin_unlock_bh(&tt_global_entry->list_lock);
2262}
2263
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02002264/* If the client is to be deleted, we check if it is the last origantor entry
Sven Eckelmannacd34af2012-06-03 22:19:21 +02002265 * within tt_global entry. If yes, we set the BATADV_TT_CLIENT_ROAM flag and the
2266 * timer, otherwise we simply remove the originator scheduled for deletion.
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02002267 */
Sven Eckelmanna5130882012-05-16 20:23:16 +02002268static void
Sven Eckelmann56303d32012-06-05 22:31:31 +02002269batadv_tt_global_del_roaming(struct batadv_priv *bat_priv,
2270 struct batadv_tt_global_entry *tt_global_entry,
2271 struct batadv_orig_node *orig_node,
2272 const char *message)
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02002273{
2274 bool last_entry = true;
2275 struct hlist_head *head;
Sven Eckelmann56303d32012-06-05 22:31:31 +02002276 struct batadv_tt_orig_list_entry *orig_entry;
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02002277
2278 /* no local entry exists, case 1:
2279 * Check if this is the last one or if other entries exist.
2280 */
2281
2282 rcu_read_lock();
2283 head = &tt_global_entry->orig_list;
Sasha Levinb67bfe02013-02-27 17:06:00 -08002284 hlist_for_each_entry_rcu(orig_entry, head, list) {
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02002285 if (orig_entry->orig_node != orig_node) {
2286 last_entry = false;
2287 break;
2288 }
2289 }
2290 rcu_read_unlock();
2291
2292 if (last_entry) {
2293 /* its the last one, mark for roaming. */
Sven Eckelmannacd34af2012-06-03 22:19:21 +02002294 tt_global_entry->common.flags |= BATADV_TT_CLIENT_ROAM;
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02002295 tt_global_entry->roam_at = jiffies;
Sven Eckelmann1fda4c02017-02-22 17:16:40 +01002296 } else {
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02002297 /* there is another entry, we can simply delete this
2298 * one and can still use the other one.
2299 */
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +01002300 batadv_tt_global_del_orig_node(bat_priv, tt_global_entry,
2301 orig_node, message);
Sven Eckelmann1fda4c02017-02-22 17:16:40 +01002302 }
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02002303}
2304
Antonio Quartullic018ad32013-06-04 12:11:39 +02002305/**
2306 * batadv_tt_global_del - remove a client from the global table
2307 * @bat_priv: the bat priv with all the soft interface information
2308 * @orig_node: an originator serving this client
2309 * @addr: the mac address of the client
2310 * @vid: VLAN identifier
2311 * @message: a message explaining the reason for deleting the client to print
2312 * for debugging purpose
2313 * @roaming: true if the deletion has been triggered by a roaming event
2314 */
Sven Eckelmann56303d32012-06-05 22:31:31 +02002315static void batadv_tt_global_del(struct batadv_priv *bat_priv,
2316 struct batadv_orig_node *orig_node,
Antonio Quartullic018ad32013-06-04 12:11:39 +02002317 const unsigned char *addr, unsigned short vid,
Sven Eckelmanna5130882012-05-16 20:23:16 +02002318 const char *message, bool roaming)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00002319{
Sven Eckelmann170173b2012-10-07 12:02:22 +02002320 struct batadv_tt_global_entry *tt_global_entry;
Sven Eckelmann56303d32012-06-05 22:31:31 +02002321 struct batadv_tt_local_entry *local_entry = NULL;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00002322
Antonio Quartullic018ad32013-06-04 12:11:39 +02002323 tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr, vid);
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02002324 if (!tt_global_entry)
Antonio Quartulli7683fdc2011-04-27 14:28:07 +02002325 goto out;
Antonio Quartullia73105b2011-04-27 14:27:44 +02002326
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02002327 if (!roaming) {
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +01002328 batadv_tt_global_del_orig_node(bat_priv, tt_global_entry,
2329 orig_node, message);
Sven Eckelmann92f90f52011-12-22 20:31:12 +08002330
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02002331 if (hlist_empty(&tt_global_entry->orig_list))
Antonio Quartullibe73b482012-09-23 22:38:36 +02002332 batadv_tt_global_free(bat_priv, tt_global_entry,
2333 message);
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02002334
Sven Eckelmann92f90f52011-12-22 20:31:12 +08002335 goto out;
Antonio Quartullia73105b2011-04-27 14:27:44 +02002336 }
Sven Eckelmann92f90f52011-12-22 20:31:12 +08002337
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02002338 /* if we are deleting a global entry due to a roam
2339 * event, there are two possibilities:
2340 * 1) the client roamed from node A to node B => if there
2341 * is only one originator left for this client, we mark
Sven Eckelmannacd34af2012-06-03 22:19:21 +02002342 * it with BATADV_TT_CLIENT_ROAM, we start a timer and we
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02002343 * wait for node B to claim it. In case of timeout
2344 * the entry is purged.
2345 *
2346 * If there are other originators left, we directly delete
2347 * the originator.
2348 * 2) the client roamed to us => we can directly delete
Sven Eckelmann9cfc7bd2012-05-12 02:09:43 +02002349 * the global entry, since it is useless now.
2350 */
Sven Eckelmanna5130882012-05-16 20:23:16 +02002351 local_entry = batadv_tt_local_hash_find(bat_priv,
Antonio Quartullic018ad32013-06-04 12:11:39 +02002352 tt_global_entry->common.addr,
2353 vid);
Sven Eckelmanna5130882012-05-16 20:23:16 +02002354 if (local_entry) {
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02002355 /* local entry exists, case 2: client roamed to us. */
Sven Eckelmanna5130882012-05-16 20:23:16 +02002356 batadv_tt_global_del_orig_list(tt_global_entry);
Antonio Quartullibe73b482012-09-23 22:38:36 +02002357 batadv_tt_global_free(bat_priv, tt_global_entry, message);
Sven Eckelmann1fda4c02017-02-22 17:16:40 +01002358 } else {
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02002359 /* no local entry exists, case 1: check for roaming */
Sven Eckelmanna5130882012-05-16 20:23:16 +02002360 batadv_tt_global_del_roaming(bat_priv, tt_global_entry,
2361 orig_node, message);
Sven Eckelmann1fda4c02017-02-22 17:16:40 +01002362 }
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02002363
Antonio Quartullicc47f662011-04-27 14:27:57 +02002364out:
Antonio Quartulli7683fdc2011-04-27 14:28:07 +02002365 if (tt_global_entry)
Sven Eckelmann5dafd8a2016-01-17 11:01:26 +01002366 batadv_tt_global_entry_put(tt_global_entry);
Sven Eckelmanna5130882012-05-16 20:23:16 +02002367 if (local_entry)
Sven Eckelmann95c0db92016-01-17 11:01:25 +01002368 batadv_tt_local_entry_put(local_entry);
Antonio Quartullia73105b2011-04-27 14:27:44 +02002369}
2370
Antonio Quartulli95fb1302013-08-07 18:28:55 +02002371/**
2372 * batadv_tt_global_del_orig - remove all the TT global entries belonging to the
2373 * given originator matching the provided vid
2374 * @bat_priv: the bat priv with all the soft interface information
2375 * @orig_node: the originator owning the entries to remove
2376 * @match_vid: the VLAN identifier to match. If negative all the entries will be
2377 * removed
2378 * @message: debug message to print as "reason"
2379 */
Sven Eckelmann56303d32012-06-05 22:31:31 +02002380void batadv_tt_global_del_orig(struct batadv_priv *bat_priv,
2381 struct batadv_orig_node *orig_node,
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02002382 s32 match_vid,
Sven Eckelmann56303d32012-06-05 22:31:31 +02002383 const char *message)
Antonio Quartullia73105b2011-04-27 14:27:44 +02002384{
Sven Eckelmann56303d32012-06-05 22:31:31 +02002385 struct batadv_tt_global_entry *tt_global;
2386 struct batadv_tt_common_entry *tt_common_entry;
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02002387 u32 i;
Sven Eckelmann807736f2012-07-15 22:26:51 +02002388 struct batadv_hashtable *hash = bat_priv->tt.global_hash;
Sasha Levinb67bfe02013-02-27 17:06:00 -08002389 struct hlist_node *safe;
Antonio Quartullia73105b2011-04-27 14:27:44 +02002390 struct hlist_head *head;
Antonio Quartulli7683fdc2011-04-27 14:28:07 +02002391 spinlock_t *list_lock; /* protects write access to the hash lists */
Antonio Quartulli16052782013-06-04 12:11:41 +02002392 unsigned short vid;
Antonio Quartullia73105b2011-04-27 14:27:44 +02002393
Simon Wunderlich6e801492011-10-19 10:28:26 +02002394 if (!hash)
2395 return;
2396
Antonio Quartullia73105b2011-04-27 14:27:44 +02002397 for (i = 0; i < hash->size; i++) {
2398 head = &hash->table[i];
Antonio Quartulli7683fdc2011-04-27 14:28:07 +02002399 list_lock = &hash->list_locks[i];
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00002400
Antonio Quartulli7683fdc2011-04-27 14:28:07 +02002401 spin_lock_bh(list_lock);
Sasha Levinb67bfe02013-02-27 17:06:00 -08002402 hlist_for_each_entry_safe(tt_common_entry, safe,
Sven Eckelmann7c64fd92012-02-28 10:55:36 +01002403 head, hash_entry) {
Antonio Quartulli95fb1302013-08-07 18:28:55 +02002404 /* remove only matching entries */
2405 if (match_vid >= 0 && tt_common_entry->vid != match_vid)
2406 continue;
2407
Sven Eckelmann56303d32012-06-05 22:31:31 +02002408 tt_global = container_of(tt_common_entry,
2409 struct batadv_tt_global_entry,
2410 common);
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02002411
Linus Lüssing1d8ab8d2014-02-15 17:47:52 +01002412 batadv_tt_global_del_orig_node(bat_priv, tt_global,
2413 orig_node, message);
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02002414
Sven Eckelmann56303d32012-06-05 22:31:31 +02002415 if (hlist_empty(&tt_global->orig_list)) {
Antonio Quartulli16052782013-06-04 12:11:41 +02002416 vid = tt_global->common.vid;
Sven Eckelmann39c75a52012-06-03 22:19:22 +02002417 batadv_dbg(BATADV_DBG_TT, bat_priv,
Antonio Quartulli16052782013-06-04 12:11:41 +02002418 "Deleting global tt entry %pM (vid: %d): %s\n",
2419 tt_global->common.addr,
Sven Eckelmannf7a2bd62017-02-22 17:16:42 +01002420 batadv_print_vid(vid), message);
Sasha Levinb67bfe02013-02-27 17:06:00 -08002421 hlist_del_rcu(&tt_common_entry->hash_entry);
Sven Eckelmann5dafd8a2016-01-17 11:01:26 +01002422 batadv_tt_global_entry_put(tt_global);
Antonio Quartulli7683fdc2011-04-27 14:28:07 +02002423 }
Antonio Quartullia73105b2011-04-27 14:27:44 +02002424 }
Antonio Quartulli7683fdc2011-04-27 14:28:07 +02002425 spin_unlock_bh(list_lock);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00002426 }
Linus Lüssingac4eebd2015-06-16 17:10:24 +02002427 clear_bit(BATADV_ORIG_CAPA_HAS_TT, &orig_node->capa_initialized);
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00002428}
2429
Antonio Quartulli30cfd022012-07-05 23:38:29 +02002430static bool batadv_tt_global_to_purge(struct batadv_tt_global_entry *tt_global,
2431 char **msg)
Antonio Quartullicc47f662011-04-27 14:27:57 +02002432{
Antonio Quartulli30cfd022012-07-05 23:38:29 +02002433 bool purge = false;
2434 unsigned long roam_timeout = BATADV_TT_CLIENT_ROAM_TIMEOUT;
2435 unsigned long temp_timeout = BATADV_TT_CLIENT_TEMP_TIMEOUT;
Sven Eckelmann42d0b042012-06-03 22:19:17 +02002436
Antonio Quartulli30cfd022012-07-05 23:38:29 +02002437 if ((tt_global->common.flags & BATADV_TT_CLIENT_ROAM) &&
2438 batadv_has_timed_out(tt_global->roam_at, roam_timeout)) {
2439 purge = true;
2440 *msg = "Roaming timeout\n";
Sven Eckelmann42d0b042012-06-03 22:19:17 +02002441 }
Antonio Quartulli30cfd022012-07-05 23:38:29 +02002442
2443 if ((tt_global->common.flags & BATADV_TT_CLIENT_TEMP) &&
2444 batadv_has_timed_out(tt_global->common.added_at, temp_timeout)) {
2445 purge = true;
2446 *msg = "Temporary client timeout\n";
2447 }
2448
2449 return purge;
Sven Eckelmann42d0b042012-06-03 22:19:17 +02002450}
2451
Antonio Quartulli30cfd022012-07-05 23:38:29 +02002452static void batadv_tt_global_purge(struct batadv_priv *bat_priv)
Sven Eckelmann42d0b042012-06-03 22:19:17 +02002453{
Sven Eckelmann807736f2012-07-15 22:26:51 +02002454 struct batadv_hashtable *hash = bat_priv->tt.global_hash;
Antonio Quartullicc47f662011-04-27 14:27:57 +02002455 struct hlist_head *head;
Sasha Levinb67bfe02013-02-27 17:06:00 -08002456 struct hlist_node *node_tmp;
Antonio Quartulli7683fdc2011-04-27 14:28:07 +02002457 spinlock_t *list_lock; /* protects write access to the hash lists */
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02002458 u32 i;
Antonio Quartulli30cfd022012-07-05 23:38:29 +02002459 char *msg = NULL;
2460 struct batadv_tt_common_entry *tt_common;
2461 struct batadv_tt_global_entry *tt_global;
Antonio Quartullicc47f662011-04-27 14:27:57 +02002462
Antonio Quartullicc47f662011-04-27 14:27:57 +02002463 for (i = 0; i < hash->size; i++) {
2464 head = &hash->table[i];
Antonio Quartulli7683fdc2011-04-27 14:28:07 +02002465 list_lock = &hash->list_locks[i];
Antonio Quartullicc47f662011-04-27 14:27:57 +02002466
Antonio Quartulli7683fdc2011-04-27 14:28:07 +02002467 spin_lock_bh(list_lock);
Sasha Levinb67bfe02013-02-27 17:06:00 -08002468 hlist_for_each_entry_safe(tt_common, node_tmp, head,
Antonio Quartulli30cfd022012-07-05 23:38:29 +02002469 hash_entry) {
2470 tt_global = container_of(tt_common,
2471 struct batadv_tt_global_entry,
2472 common);
2473
2474 if (!batadv_tt_global_to_purge(tt_global, &msg))
2475 continue;
2476
2477 batadv_dbg(BATADV_DBG_TT, bat_priv,
Antonio Quartulli16052782013-06-04 12:11:41 +02002478 "Deleting global tt entry %pM (vid: %d): %s\n",
2479 tt_global->common.addr,
Sven Eckelmannf7a2bd62017-02-22 17:16:42 +01002480 batadv_print_vid(tt_global->common.vid),
Antonio Quartulli16052782013-06-04 12:11:41 +02002481 msg);
Antonio Quartulli30cfd022012-07-05 23:38:29 +02002482
Sasha Levinb67bfe02013-02-27 17:06:00 -08002483 hlist_del_rcu(&tt_common->hash_entry);
Antonio Quartulli30cfd022012-07-05 23:38:29 +02002484
Sven Eckelmann5dafd8a2016-01-17 11:01:26 +01002485 batadv_tt_global_entry_put(tt_global);
Antonio Quartulli30cfd022012-07-05 23:38:29 +02002486 }
Antonio Quartulli7683fdc2011-04-27 14:28:07 +02002487 spin_unlock_bh(list_lock);
Antonio Quartullicc47f662011-04-27 14:27:57 +02002488 }
Antonio Quartullicc47f662011-04-27 14:27:57 +02002489}
2490
Sven Eckelmann56303d32012-06-05 22:31:31 +02002491static void batadv_tt_global_table_free(struct batadv_priv *bat_priv)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00002492{
Sven Eckelmann5bf74e92012-06-05 22:31:28 +02002493 struct batadv_hashtable *hash;
Antonio Quartulli7683fdc2011-04-27 14:28:07 +02002494 spinlock_t *list_lock; /* protects write access to the hash lists */
Sven Eckelmann56303d32012-06-05 22:31:31 +02002495 struct batadv_tt_common_entry *tt_common_entry;
2496 struct batadv_tt_global_entry *tt_global;
Sasha Levinb67bfe02013-02-27 17:06:00 -08002497 struct hlist_node *node_tmp;
Antonio Quartulli7683fdc2011-04-27 14:28:07 +02002498 struct hlist_head *head;
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02002499 u32 i;
Antonio Quartulli7683fdc2011-04-27 14:28:07 +02002500
Sven Eckelmann807736f2012-07-15 22:26:51 +02002501 if (!bat_priv->tt.global_hash)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00002502 return;
2503
Sven Eckelmann807736f2012-07-15 22:26:51 +02002504 hash = bat_priv->tt.global_hash;
Antonio Quartulli7683fdc2011-04-27 14:28:07 +02002505
2506 for (i = 0; i < hash->size; i++) {
2507 head = &hash->table[i];
2508 list_lock = &hash->list_locks[i];
2509
2510 spin_lock_bh(list_lock);
Sasha Levinb67bfe02013-02-27 17:06:00 -08002511 hlist_for_each_entry_safe(tt_common_entry, node_tmp,
Antonio Quartulli7683fdc2011-04-27 14:28:07 +02002512 head, hash_entry) {
Sasha Levinb67bfe02013-02-27 17:06:00 -08002513 hlist_del_rcu(&tt_common_entry->hash_entry);
Sven Eckelmann56303d32012-06-05 22:31:31 +02002514 tt_global = container_of(tt_common_entry,
2515 struct batadv_tt_global_entry,
2516 common);
Sven Eckelmann5dafd8a2016-01-17 11:01:26 +01002517 batadv_tt_global_entry_put(tt_global);
Antonio Quartulli7683fdc2011-04-27 14:28:07 +02002518 }
2519 spin_unlock_bh(list_lock);
2520 }
2521
Sven Eckelmann1a8eaf02012-05-12 02:09:32 +02002522 batadv_hash_destroy(hash);
Antonio Quartulli7683fdc2011-04-27 14:28:07 +02002523
Sven Eckelmann807736f2012-07-15 22:26:51 +02002524 bat_priv->tt.global_hash = NULL;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00002525}
2526
Sven Eckelmann56303d32012-06-05 22:31:31 +02002527static bool
2528_batadv_is_ap_isolated(struct batadv_tt_local_entry *tt_local_entry,
2529 struct batadv_tt_global_entry *tt_global_entry)
Antonio Quartulli59b699c2011-07-07 15:35:36 +02002530{
Sven Eckelmannacd34af2012-06-03 22:19:21 +02002531 if (tt_local_entry->common.flags & BATADV_TT_CLIENT_WIFI &&
2532 tt_global_entry->common.flags & BATADV_TT_CLIENT_WIFI)
Simon Wunderlich75ae84a2017-06-01 17:11:26 +02002533 return true;
Antonio Quartulli59b699c2011-07-07 15:35:36 +02002534
Antonio Quartulli2d2fcc2a2013-11-16 12:03:50 +01002535 /* check if the two clients are marked as isolated */
2536 if (tt_local_entry->common.flags & BATADV_TT_CLIENT_ISOLA &&
2537 tt_global_entry->common.flags & BATADV_TT_CLIENT_ISOLA)
Simon Wunderlich75ae84a2017-06-01 17:11:26 +02002538 return true;
Antonio Quartulli2d2fcc2a2013-11-16 12:03:50 +01002539
Simon Wunderlich75ae84a2017-06-01 17:11:26 +02002540 return false;
Antonio Quartulli59b699c2011-07-07 15:35:36 +02002541}
2542
Antonio Quartullic018ad32013-06-04 12:11:39 +02002543/**
2544 * batadv_transtable_search - get the mesh destination for a given client
2545 * @bat_priv: the bat priv with all the soft interface information
2546 * @src: mac address of the source client
2547 * @addr: mac address of the destination client
2548 * @vid: VLAN identifier
2549 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +02002550 * Return: a pointer to the originator that was selected as destination in the
Antonio Quartullic018ad32013-06-04 12:11:39 +02002551 * mesh for contacting the client 'addr', NULL otherwise.
2552 * In case of multiple originators serving the same client, the function returns
2553 * the best one (best in terms of metric towards the destination node).
2554 *
2555 * If the two clients are AP isolated the function returns NULL.
2556 */
Sven Eckelmann56303d32012-06-05 22:31:31 +02002557struct batadv_orig_node *batadv_transtable_search(struct batadv_priv *bat_priv,
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02002558 const u8 *src,
2559 const u8 *addr,
Antonio Quartullic018ad32013-06-04 12:11:39 +02002560 unsigned short vid)
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00002561{
Sven Eckelmann56303d32012-06-05 22:31:31 +02002562 struct batadv_tt_local_entry *tt_local_entry = NULL;
2563 struct batadv_tt_global_entry *tt_global_entry = NULL;
2564 struct batadv_orig_node *orig_node = NULL;
Sven Eckelmann981d8902012-10-07 13:34:15 +02002565 struct batadv_tt_orig_list_entry *best_entry;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00002566
Antonio Quartullieceb22a2013-11-16 12:03:51 +01002567 if (src && batadv_vlan_ap_isola_get(bat_priv, vid)) {
Antonio Quartullic018ad32013-06-04 12:11:39 +02002568 tt_local_entry = batadv_tt_local_hash_find(bat_priv, src, vid);
Antonio Quartulli068ee6e2012-09-23 22:38:37 +02002569 if (!tt_local_entry ||
2570 (tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING))
Antonio Quartulli3d393e42011-07-07 15:35:37 +02002571 goto out;
2572 }
Marek Lindner7aadf882011-02-18 12:28:09 +00002573
Antonio Quartullic018ad32013-06-04 12:11:39 +02002574 tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr, vid);
Antonio Quartulli2dafb492011-05-05 08:42:45 +02002575 if (!tt_global_entry)
Marek Lindner7b36e8e2011-02-18 12:28:10 +00002576 goto out;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00002577
Antonio Quartulli3d393e42011-07-07 15:35:37 +02002578 /* check whether the clients should not communicate due to AP
Sven Eckelmann9cfc7bd2012-05-12 02:09:43 +02002579 * isolation
2580 */
Sven Eckelmanna5130882012-05-16 20:23:16 +02002581 if (tt_local_entry &&
2582 _batadv_is_ap_isolated(tt_local_entry, tt_global_entry))
Antonio Quartulli3d393e42011-07-07 15:35:37 +02002583 goto out;
2584
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02002585 rcu_read_lock();
Antonio Quartulli46274562013-09-03 11:10:24 +02002586 best_entry = batadv_transtable_best_orig(bat_priv, tt_global_entry);
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02002587 /* found anything? */
Sven Eckelmann981d8902012-10-07 13:34:15 +02002588 if (best_entry)
2589 orig_node = best_entry->orig_node;
Sven Eckelmann7c124392016-01-16 10:29:56 +01002590 if (orig_node && !kref_get_unless_zero(&orig_node->refcount))
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02002591 orig_node = NULL;
2592 rcu_read_unlock();
Sven Eckelmann981d8902012-10-07 13:34:15 +02002593
Marek Lindner7b36e8e2011-02-18 12:28:10 +00002594out:
Antonio Quartulli3d393e42011-07-07 15:35:37 +02002595 if (tt_global_entry)
Sven Eckelmann5dafd8a2016-01-17 11:01:26 +01002596 batadv_tt_global_entry_put(tt_global_entry);
Antonio Quartulli3d393e42011-07-07 15:35:37 +02002597 if (tt_local_entry)
Sven Eckelmann95c0db92016-01-17 11:01:25 +01002598 batadv_tt_local_entry_put(tt_local_entry);
Antonio Quartulli3d393e42011-07-07 15:35:37 +02002599
Marek Lindner7b36e8e2011-02-18 12:28:10 +00002600 return orig_node;
Sven Eckelmannc6c8fea2010-12-13 11:19:28 +00002601}
Antonio Quartullia73105b2011-04-27 14:27:44 +02002602
Antonio Quartulliced72932013-04-24 16:37:51 +02002603/**
2604 * batadv_tt_global_crc - calculates the checksum of the local table belonging
2605 * to the given orig_node
2606 * @bat_priv: the bat priv with all the soft interface information
Antonio Quartulli0ffa9e82013-06-04 12:11:40 +02002607 * @orig_node: originator for which the CRC should be computed
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02002608 * @vid: VLAN identifier for which the CRC32 has to be computed
Antonio Quartulli0ffa9e82013-06-04 12:11:40 +02002609 *
2610 * This function computes the checksum for the global table corresponding to a
2611 * specific originator. In particular, the checksum is computed as follows: For
2612 * each client connected to the originator the CRC32C of the MAC address and the
2613 * VID is computed and then all the CRC32Cs of the various clients are xor'ed
2614 * together.
2615 *
2616 * The idea behind is that CRC32C should be used as much as possible in order to
2617 * produce a unique hash of the table, but since the order which is used to feed
2618 * the CRC32C function affects the result and since every node in the network
2619 * probably sorts the clients differently, the hash function cannot be directly
2620 * computed over the entire table. Hence the CRC32C is used only on
2621 * the single client entry, while all the results are then xor'ed together
2622 * because the XOR operation can combine them all while trying to reduce the
2623 * noise as much as possible.
2624 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +02002625 * Return: the checksum of the global table of a given originator.
Antonio Quartulliced72932013-04-24 16:37:51 +02002626 */
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02002627static u32 batadv_tt_global_crc(struct batadv_priv *bat_priv,
2628 struct batadv_orig_node *orig_node,
2629 unsigned short vid)
Antonio Quartullia73105b2011-04-27 14:27:44 +02002630{
Sven Eckelmann807736f2012-07-15 22:26:51 +02002631 struct batadv_hashtable *hash = bat_priv->tt.global_hash;
Linus Lüssing54e22f22017-07-06 07:02:25 +02002632 struct batadv_tt_orig_list_entry *tt_orig;
Sven Eckelmann56303d32012-06-05 22:31:31 +02002633 struct batadv_tt_common_entry *tt_common;
2634 struct batadv_tt_global_entry *tt_global;
Antonio Quartullia73105b2011-04-27 14:27:44 +02002635 struct hlist_head *head;
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02002636 u32 i, crc_tmp, crc = 0;
2637 u8 flags;
Antonio Quartullia30e22c2014-02-11 17:05:06 +01002638 __be16 tmp_vid;
Antonio Quartullia73105b2011-04-27 14:27:44 +02002639
2640 for (i = 0; i < hash->size; i++) {
2641 head = &hash->table[i];
2642
2643 rcu_read_lock();
Sasha Levinb67bfe02013-02-27 17:06:00 -08002644 hlist_for_each_entry_rcu(tt_common, head, hash_entry) {
Sven Eckelmann56303d32012-06-05 22:31:31 +02002645 tt_global = container_of(tt_common,
2646 struct batadv_tt_global_entry,
2647 common);
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02002648 /* compute the CRC only for entries belonging to the
2649 * VLAN identified by the vid passed as parameter
2650 */
2651 if (tt_common->vid != vid)
2652 continue;
2653
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02002654 /* Roaming clients are in the global table for
2655 * consistency only. They don't have to be
2656 * taken into account while computing the
2657 * global crc
2658 */
Sven Eckelmannacd34af2012-06-03 22:19:21 +02002659 if (tt_common->flags & BATADV_TT_CLIENT_ROAM)
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02002660 continue;
Antonio Quartulli30cfd022012-07-05 23:38:29 +02002661 /* Temporary clients have not been announced yet, so
2662 * they have to be skipped while computing the global
2663 * crc
2664 */
2665 if (tt_common->flags & BATADV_TT_CLIENT_TEMP)
2666 continue;
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02002667
2668 /* find out if this global entry is announced by this
2669 * originator
2670 */
Linus Lüssing54e22f22017-07-06 07:02:25 +02002671 tt_orig = batadv_tt_global_orig_entry_find(tt_global,
2672 orig_node);
2673 if (!tt_orig)
Simon Wunderlichdb08e6e2011-10-22 20:12:51 +02002674 continue;
2675
Antonio Quartullia30e22c2014-02-11 17:05:06 +01002676 /* use network order to read the VID: this ensures that
2677 * every node reads the bytes in the same order.
2678 */
2679 tmp_vid = htons(tt_common->vid);
2680 crc_tmp = crc32c(0, &tmp_vid, sizeof(tmp_vid));
Antonio Quartulli0eb015682013-10-13 02:50:20 +02002681
2682 /* compute the CRC on flags that have to be kept in sync
2683 * among nodes
2684 */
Linus Lüssing54e22f22017-07-06 07:02:25 +02002685 flags = tt_orig->flags;
Antonio Quartulli0eb015682013-10-13 02:50:20 +02002686 crc_tmp = crc32c(crc_tmp, &flags, sizeof(flags));
2687
Antonio Quartulli0ffa9e82013-06-04 12:11:40 +02002688 crc ^= crc32c(crc_tmp, tt_common->addr, ETH_ALEN);
Linus Lüssing54e22f22017-07-06 07:02:25 +02002689
2690 batadv_tt_orig_list_entry_put(tt_orig);
Antonio Quartullia73105b2011-04-27 14:27:44 +02002691 }
2692 rcu_read_unlock();
2693 }
2694
Antonio Quartulliced72932013-04-24 16:37:51 +02002695 return crc;
Antonio Quartullia73105b2011-04-27 14:27:44 +02002696}
2697
Antonio Quartulliced72932013-04-24 16:37:51 +02002698/**
2699 * batadv_tt_local_crc - calculates the checksum of the local table
2700 * @bat_priv: the bat priv with all the soft interface information
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02002701 * @vid: VLAN identifier for which the CRC32 has to be computed
Antonio Quartulli0ffa9e82013-06-04 12:11:40 +02002702 *
2703 * For details about the computation, please refer to the documentation for
2704 * batadv_tt_global_crc().
2705 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +02002706 * Return: the checksum of the local table
Antonio Quartulliced72932013-04-24 16:37:51 +02002707 */
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02002708static u32 batadv_tt_local_crc(struct batadv_priv *bat_priv,
2709 unsigned short vid)
Antonio Quartullia73105b2011-04-27 14:27:44 +02002710{
Sven Eckelmann807736f2012-07-15 22:26:51 +02002711 struct batadv_hashtable *hash = bat_priv->tt.local_hash;
Sven Eckelmann56303d32012-06-05 22:31:31 +02002712 struct batadv_tt_common_entry *tt_common;
Antonio Quartullia73105b2011-04-27 14:27:44 +02002713 struct hlist_head *head;
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02002714 u32 i, crc_tmp, crc = 0;
2715 u8 flags;
Antonio Quartullia30e22c2014-02-11 17:05:06 +01002716 __be16 tmp_vid;
Antonio Quartullia73105b2011-04-27 14:27:44 +02002717
2718 for (i = 0; i < hash->size; i++) {
2719 head = &hash->table[i];
2720
2721 rcu_read_lock();
Sasha Levinb67bfe02013-02-27 17:06:00 -08002722 hlist_for_each_entry_rcu(tt_common, head, hash_entry) {
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02002723 /* compute the CRC only for entries belonging to the
2724 * VLAN identified by vid
2725 */
2726 if (tt_common->vid != vid)
2727 continue;
2728
Antonio Quartulli058d0e22011-07-07 01:40:58 +02002729 /* not yet committed clients have not to be taken into
Sven Eckelmann9cfc7bd2012-05-12 02:09:43 +02002730 * account while computing the CRC
2731 */
Sven Eckelmannacd34af2012-06-03 22:19:21 +02002732 if (tt_common->flags & BATADV_TT_CLIENT_NEW)
Antonio Quartulli058d0e22011-07-07 01:40:58 +02002733 continue;
Antonio Quartulliced72932013-04-24 16:37:51 +02002734
Antonio Quartullia30e22c2014-02-11 17:05:06 +01002735 /* use network order to read the VID: this ensures that
2736 * every node reads the bytes in the same order.
2737 */
2738 tmp_vid = htons(tt_common->vid);
2739 crc_tmp = crc32c(0, &tmp_vid, sizeof(tmp_vid));
Antonio Quartulli0eb015682013-10-13 02:50:20 +02002740
2741 /* compute the CRC on flags that have to be kept in sync
2742 * among nodes
2743 */
2744 flags = tt_common->flags & BATADV_TT_SYNC_MASK;
2745 crc_tmp = crc32c(crc_tmp, &flags, sizeof(flags));
2746
Antonio Quartulli0ffa9e82013-06-04 12:11:40 +02002747 crc ^= crc32c(crc_tmp, tt_common->addr, ETH_ALEN);
Antonio Quartullia73105b2011-04-27 14:27:44 +02002748 }
Antonio Quartullia73105b2011-04-27 14:27:44 +02002749 rcu_read_unlock();
2750 }
2751
Antonio Quartulliced72932013-04-24 16:37:51 +02002752 return crc;
Antonio Quartullia73105b2011-04-27 14:27:44 +02002753}
2754
Sven Eckelmann9c4604a2016-06-26 11:16:10 +02002755/**
2756 * batadv_tt_req_node_release - free tt_req node entry
2757 * @ref: kref pointer of the tt req_node entry
2758 */
2759static void batadv_tt_req_node_release(struct kref *ref)
2760{
2761 struct batadv_tt_req_node *tt_req_node;
2762
2763 tt_req_node = container_of(ref, struct batadv_tt_req_node, refcount);
2764
Sven Eckelmann86452f82016-06-25 16:44:06 +02002765 kmem_cache_free(batadv_tt_req_cache, tt_req_node);
Sven Eckelmann9c4604a2016-06-26 11:16:10 +02002766}
2767
2768/**
2769 * batadv_tt_req_node_put - decrement the tt_req_node refcounter and
2770 * possibly release it
2771 * @tt_req_node: tt_req_node to be free'd
2772 */
2773static void batadv_tt_req_node_put(struct batadv_tt_req_node *tt_req_node)
2774{
2775 kref_put(&tt_req_node->refcount, batadv_tt_req_node_release);
2776}
2777
Sven Eckelmann56303d32012-06-05 22:31:31 +02002778static void batadv_tt_req_list_free(struct batadv_priv *bat_priv)
Antonio Quartullia73105b2011-04-27 14:27:44 +02002779{
Marek Lindner7c26a532015-06-28 22:16:06 +08002780 struct batadv_tt_req_node *node;
2781 struct hlist_node *safe;
Antonio Quartullia73105b2011-04-27 14:27:44 +02002782
Sven Eckelmann807736f2012-07-15 22:26:51 +02002783 spin_lock_bh(&bat_priv->tt.req_list_lock);
Antonio Quartullia73105b2011-04-27 14:27:44 +02002784
Marek Lindner7c26a532015-06-28 22:16:06 +08002785 hlist_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) {
2786 hlist_del_init(&node->list);
Sven Eckelmann9c4604a2016-06-26 11:16:10 +02002787 batadv_tt_req_node_put(node);
Antonio Quartullia73105b2011-04-27 14:27:44 +02002788 }
2789
Sven Eckelmann807736f2012-07-15 22:26:51 +02002790 spin_unlock_bh(&bat_priv->tt.req_list_lock);
Antonio Quartullia73105b2011-04-27 14:27:44 +02002791}
2792
Sven Eckelmann56303d32012-06-05 22:31:31 +02002793static void batadv_tt_save_orig_buffer(struct batadv_priv *bat_priv,
2794 struct batadv_orig_node *orig_node,
Antonio Quartullie8cf2342013-05-28 13:14:28 +02002795 const void *tt_buff,
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02002796 u16 tt_buff_len)
Antonio Quartullia73105b2011-04-27 14:27:44 +02002797{
Antonio Quartullia73105b2011-04-27 14:27:44 +02002798 /* Replace the old buffer only if I received something in the
Sven Eckelmann9cfc7bd2012-05-12 02:09:43 +02002799 * last OGM (the OGM could carry no changes)
2800 */
Antonio Quartullia73105b2011-04-27 14:27:44 +02002801 spin_lock_bh(&orig_node->tt_buff_lock);
2802 if (tt_buff_len > 0) {
2803 kfree(orig_node->tt_buff);
2804 orig_node->tt_buff_len = 0;
2805 orig_node->tt_buff = kmalloc(tt_buff_len, GFP_ATOMIC);
2806 if (orig_node->tt_buff) {
2807 memcpy(orig_node->tt_buff, tt_buff, tt_buff_len);
2808 orig_node->tt_buff_len = tt_buff_len;
2809 }
2810 }
2811 spin_unlock_bh(&orig_node->tt_buff_lock);
2812}
2813
Sven Eckelmann56303d32012-06-05 22:31:31 +02002814static void batadv_tt_req_purge(struct batadv_priv *bat_priv)
Antonio Quartullia73105b2011-04-27 14:27:44 +02002815{
Marek Lindner7c26a532015-06-28 22:16:06 +08002816 struct batadv_tt_req_node *node;
2817 struct hlist_node *safe;
Antonio Quartullia73105b2011-04-27 14:27:44 +02002818
Sven Eckelmann807736f2012-07-15 22:26:51 +02002819 spin_lock_bh(&bat_priv->tt.req_list_lock);
Marek Lindner7c26a532015-06-28 22:16:06 +08002820 hlist_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) {
Sven Eckelmann42d0b042012-06-03 22:19:17 +02002821 if (batadv_has_timed_out(node->issued_at,
2822 BATADV_TT_REQUEST_TIMEOUT)) {
Marek Lindner7c26a532015-06-28 22:16:06 +08002823 hlist_del_init(&node->list);
Sven Eckelmann9c4604a2016-06-26 11:16:10 +02002824 batadv_tt_req_node_put(node);
Antonio Quartullia73105b2011-04-27 14:27:44 +02002825 }
2826 }
Sven Eckelmann807736f2012-07-15 22:26:51 +02002827 spin_unlock_bh(&bat_priv->tt.req_list_lock);
Antonio Quartullia73105b2011-04-27 14:27:44 +02002828}
2829
Marek Lindner383b8632015-06-18 16:24:24 +08002830/**
2831 * batadv_tt_req_node_new - search and possibly create a tt_req_node object
2832 * @bat_priv: the bat priv with all the soft interface information
2833 * @orig_node: orig node this request is being issued for
2834 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +02002835 * Return: the pointer to the new tt_req_node struct if no request
Marek Lindner383b8632015-06-18 16:24:24 +08002836 * has already been issued for this orig_node, NULL otherwise.
Sven Eckelmann9cfc7bd2012-05-12 02:09:43 +02002837 */
Sven Eckelmann56303d32012-06-05 22:31:31 +02002838static struct batadv_tt_req_node *
Marek Lindner383b8632015-06-18 16:24:24 +08002839batadv_tt_req_node_new(struct batadv_priv *bat_priv,
Sven Eckelmann56303d32012-06-05 22:31:31 +02002840 struct batadv_orig_node *orig_node)
Antonio Quartullia73105b2011-04-27 14:27:44 +02002841{
Sven Eckelmann56303d32012-06-05 22:31:31 +02002842 struct batadv_tt_req_node *tt_req_node_tmp, *tt_req_node = NULL;
Antonio Quartullia73105b2011-04-27 14:27:44 +02002843
Sven Eckelmann807736f2012-07-15 22:26:51 +02002844 spin_lock_bh(&bat_priv->tt.req_list_lock);
Marek Lindner7c26a532015-06-28 22:16:06 +08002845 hlist_for_each_entry(tt_req_node_tmp, &bat_priv->tt.req_list, list) {
Sven Eckelmann1eda58b2012-05-12 13:48:58 +02002846 if (batadv_compare_eth(tt_req_node_tmp, orig_node) &&
2847 !batadv_has_timed_out(tt_req_node_tmp->issued_at,
Sven Eckelmann42d0b042012-06-03 22:19:17 +02002848 BATADV_TT_REQUEST_TIMEOUT))
Antonio Quartullia73105b2011-04-27 14:27:44 +02002849 goto unlock;
2850 }
2851
Sven Eckelmann86452f82016-06-25 16:44:06 +02002852 tt_req_node = kmem_cache_alloc(batadv_tt_req_cache, GFP_ATOMIC);
Antonio Quartullia73105b2011-04-27 14:27:44 +02002853 if (!tt_req_node)
2854 goto unlock;
2855
Sven Eckelmann9c4604a2016-06-26 11:16:10 +02002856 kref_init(&tt_req_node->refcount);
Antonio Quartulli8fdd0152014-01-22 00:42:11 +01002857 ether_addr_copy(tt_req_node->addr, orig_node->orig);
Antonio Quartullia73105b2011-04-27 14:27:44 +02002858 tt_req_node->issued_at = jiffies;
2859
Sven Eckelmann9c4604a2016-06-26 11:16:10 +02002860 kref_get(&tt_req_node->refcount);
Marek Lindner7c26a532015-06-28 22:16:06 +08002861 hlist_add_head(&tt_req_node->list, &bat_priv->tt.req_list);
Antonio Quartullia73105b2011-04-27 14:27:44 +02002862unlock:
Sven Eckelmann807736f2012-07-15 22:26:51 +02002863 spin_unlock_bh(&bat_priv->tt.req_list_lock);
Antonio Quartullia73105b2011-04-27 14:27:44 +02002864 return tt_req_node;
2865}
2866
Marek Lindner335fbe02013-04-23 21:40:02 +08002867/**
2868 * batadv_tt_local_valid - verify that given tt entry is a valid one
2869 * @entry_ptr: to be checked local tt entry
2870 * @data_ptr: not used but definition required to satisfy the callback prototype
2871 *
Sven Eckelmann4b426b12016-02-22 21:02:39 +01002872 * Return: true if the entry is a valid, false otherwise.
Marek Lindner335fbe02013-04-23 21:40:02 +08002873 */
Sven Eckelmann4b426b12016-02-22 21:02:39 +01002874static bool batadv_tt_local_valid(const void *entry_ptr, const void *data_ptr)
Antonio Quartulli058d0e22011-07-07 01:40:58 +02002875{
Sven Eckelmann56303d32012-06-05 22:31:31 +02002876 const struct batadv_tt_common_entry *tt_common_entry = entry_ptr;
Antonio Quartulli058d0e22011-07-07 01:40:58 +02002877
Sven Eckelmannacd34af2012-06-03 22:19:21 +02002878 if (tt_common_entry->flags & BATADV_TT_CLIENT_NEW)
Sven Eckelmann4b426b12016-02-22 21:02:39 +01002879 return false;
2880 return true;
Antonio Quartulli058d0e22011-07-07 01:40:58 +02002881}
2882
Sven Eckelmann4b426b12016-02-22 21:02:39 +01002883static bool batadv_tt_global_valid(const void *entry_ptr,
2884 const void *data_ptr)
Antonio Quartullia73105b2011-04-27 14:27:44 +02002885{
Sven Eckelmann56303d32012-06-05 22:31:31 +02002886 const struct batadv_tt_common_entry *tt_common_entry = entry_ptr;
2887 const struct batadv_tt_global_entry *tt_global_entry;
2888 const struct batadv_orig_node *orig_node = data_ptr;
Antonio Quartullia73105b2011-04-27 14:27:44 +02002889
Antonio Quartulli30cfd022012-07-05 23:38:29 +02002890 if (tt_common_entry->flags & BATADV_TT_CLIENT_ROAM ||
2891 tt_common_entry->flags & BATADV_TT_CLIENT_TEMP)
Sven Eckelmann4b426b12016-02-22 21:02:39 +01002892 return false;
Antonio Quartullicc47f662011-04-27 14:27:57 +02002893
Sven Eckelmann56303d32012-06-05 22:31:31 +02002894 tt_global_entry = container_of(tt_common_entry,
2895 struct batadv_tt_global_entry,
Antonio Quartulli48100ba2011-10-30 12:17:33 +01002896 common);
2897
Sven Eckelmanna5130882012-05-16 20:23:16 +02002898 return batadv_tt_global_entry_has_orig(tt_global_entry, orig_node);
Antonio Quartullia73105b2011-04-27 14:27:44 +02002899}
2900
Marek Lindner335fbe02013-04-23 21:40:02 +08002901/**
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02002902 * batadv_tt_tvlv_generate - fill the tvlv buff with the tt entries from the
2903 * specified tt hash
Marek Lindner335fbe02013-04-23 21:40:02 +08002904 * @bat_priv: the bat priv with all the soft interface information
2905 * @hash: hash table containing the tt entries
2906 * @tt_len: expected tvlv tt data buffer length in number of bytes
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02002907 * @tvlv_buff: pointer to the buffer to fill with the TT data
Marek Lindner335fbe02013-04-23 21:40:02 +08002908 * @valid_cb: function to filter tt change entries
2909 * @cb_data: data passed to the filter function as argument
Marek Lindner335fbe02013-04-23 21:40:02 +08002910 */
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02002911static void batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
2912 struct batadv_hashtable *hash,
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02002913 void *tvlv_buff, u16 tt_len,
Sven Eckelmann4b426b12016-02-22 21:02:39 +01002914 bool (*valid_cb)(const void *,
2915 const void *),
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02002916 void *cb_data)
Antonio Quartullia73105b2011-04-27 14:27:44 +02002917{
Sven Eckelmann56303d32012-06-05 22:31:31 +02002918 struct batadv_tt_common_entry *tt_common_entry;
Marek Lindner335fbe02013-04-23 21:40:02 +08002919 struct batadv_tvlv_tt_change *tt_change;
Antonio Quartullia73105b2011-04-27 14:27:44 +02002920 struct hlist_head *head;
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02002921 u16 tt_tot, tt_num_entries = 0;
2922 u32 i;
Antonio Quartullia73105b2011-04-27 14:27:44 +02002923
Antonio Quartulli298e6e62013-05-28 13:14:27 +02002924 tt_tot = batadv_tt_entries(tt_len);
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02002925 tt_change = (struct batadv_tvlv_tt_change *)tvlv_buff;
Antonio Quartullia73105b2011-04-27 14:27:44 +02002926
2927 rcu_read_lock();
2928 for (i = 0; i < hash->size; i++) {
2929 head = &hash->table[i];
2930
Sasha Levinb67bfe02013-02-27 17:06:00 -08002931 hlist_for_each_entry_rcu(tt_common_entry,
Antonio Quartullia73105b2011-04-27 14:27:44 +02002932 head, hash_entry) {
Marek Lindner335fbe02013-04-23 21:40:02 +08002933 if (tt_tot == tt_num_entries)
Antonio Quartullia73105b2011-04-27 14:27:44 +02002934 break;
2935
Antonio Quartulli48100ba2011-10-30 12:17:33 +01002936 if ((valid_cb) && (!valid_cb(tt_common_entry, cb_data)))
Antonio Quartullia73105b2011-04-27 14:27:44 +02002937 continue;
2938
Antonio Quartulli8fdd0152014-01-22 00:42:11 +01002939 ether_addr_copy(tt_change->addr, tt_common_entry->addr);
Antonio Quartulli27b37eb2012-11-08 14:21:11 +01002940 tt_change->flags = tt_common_entry->flags;
Antonio Quartullic018ad32013-06-04 12:11:39 +02002941 tt_change->vid = htons(tt_common_entry->vid);
Antonio Quartullica663042013-12-15 13:26:55 +01002942 memset(tt_change->reserved, 0,
2943 sizeof(tt_change->reserved));
Antonio Quartullia73105b2011-04-27 14:27:44 +02002944
Marek Lindner335fbe02013-04-23 21:40:02 +08002945 tt_num_entries++;
Antonio Quartullia73105b2011-04-27 14:27:44 +02002946 tt_change++;
2947 }
2948 }
2949 rcu_read_unlock();
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02002950}
Antonio Quartullia73105b2011-04-27 14:27:44 +02002951
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02002952/**
2953 * batadv_tt_global_check_crc - check if all the CRCs are correct
2954 * @orig_node: originator for which the CRCs have to be checked
2955 * @tt_vlan: pointer to the first tvlv VLAN entry
2956 * @num_vlan: number of tvlv VLAN entries
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02002957 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +02002958 * Return: true if all the received CRCs match the locally stored ones, false
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02002959 * otherwise
2960 */
2961static bool batadv_tt_global_check_crc(struct batadv_orig_node *orig_node,
2962 struct batadv_tvlv_tt_vlan_data *tt_vlan,
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02002963 u16 num_vlan)
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02002964{
2965 struct batadv_tvlv_tt_vlan_data *tt_vlan_tmp;
2966 struct batadv_orig_node_vlan *vlan;
Simon Wunderlichc169c592015-09-02 20:09:56 +02002967 int i, orig_num_vlan;
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02002968 u32 crc;
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02002969
2970 /* check if each received CRC matches the locally stored one */
2971 for (i = 0; i < num_vlan; i++) {
2972 tt_vlan_tmp = tt_vlan + i;
2973
2974 /* if orig_node is a backbone node for this VLAN, don't check
2975 * the CRC as we ignore all the global entries over it
2976 */
2977 if (batadv_bla_is_backbone_gw_orig(orig_node->bat_priv,
Antonio Quartullicfd4f752013-08-07 18:28:56 +02002978 orig_node->orig,
2979 ntohs(tt_vlan_tmp->vid)))
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02002980 continue;
2981
2982 vlan = batadv_orig_node_vlan_get(orig_node,
2983 ntohs(tt_vlan_tmp->vid));
2984 if (!vlan)
2985 return false;
2986
Antonio Quartulli91c2b1a2014-01-28 02:06:47 +01002987 crc = vlan->tt.crc;
Sven Eckelmann21754e22016-01-17 11:01:24 +01002988 batadv_orig_node_vlan_put(vlan);
Antonio Quartulli91c2b1a2014-01-28 02:06:47 +01002989
2990 if (crc != ntohl(tt_vlan_tmp->crc))
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02002991 return false;
2992 }
2993
Simon Wunderlichc169c592015-09-02 20:09:56 +02002994 /* check if any excess VLANs exist locally for the originator
2995 * which are not mentioned in the TVLV from the originator.
2996 */
2997 rcu_read_lock();
2998 orig_num_vlan = 0;
2999 hlist_for_each_entry_rcu(vlan, &orig_node->vlan_list, list)
3000 orig_num_vlan++;
3001 rcu_read_unlock();
3002
3003 if (orig_num_vlan > num_vlan)
3004 return false;
3005
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003006 return true;
3007}
3008
3009/**
3010 * batadv_tt_local_update_crc - update all the local CRCs
3011 * @bat_priv: the bat priv with all the soft interface information
3012 */
3013static void batadv_tt_local_update_crc(struct batadv_priv *bat_priv)
3014{
3015 struct batadv_softif_vlan *vlan;
3016
3017 /* recompute the global CRC for each VLAN */
3018 rcu_read_lock();
3019 hlist_for_each_entry_rcu(vlan, &bat_priv->softif_vlan_list, list) {
3020 vlan->tt.crc = batadv_tt_local_crc(bat_priv, vlan->vid);
3021 }
3022 rcu_read_unlock();
3023}
3024
3025/**
3026 * batadv_tt_global_update_crc - update all the global CRCs for this orig_node
3027 * @bat_priv: the bat priv with all the soft interface information
3028 * @orig_node: the orig_node for which the CRCs have to be updated
3029 */
3030static void batadv_tt_global_update_crc(struct batadv_priv *bat_priv,
3031 struct batadv_orig_node *orig_node)
3032{
3033 struct batadv_orig_node_vlan *vlan;
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02003034 u32 crc;
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003035
3036 /* recompute the global CRC for each VLAN */
3037 rcu_read_lock();
Marek Lindnerd0fa4f32015-06-22 00:30:22 +08003038 hlist_for_each_entry_rcu(vlan, &orig_node->vlan_list, list) {
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003039 /* if orig_node is a backbone node for this VLAN, don't compute
3040 * the CRC as we ignore all the global entries over it
3041 */
Antonio Quartullicfd4f752013-08-07 18:28:56 +02003042 if (batadv_bla_is_backbone_gw_orig(bat_priv, orig_node->orig,
3043 vlan->vid))
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003044 continue;
3045
3046 crc = batadv_tt_global_crc(bat_priv, orig_node, vlan->vid);
3047 vlan->tt.crc = crc;
3048 }
3049 rcu_read_unlock();
Antonio Quartullia73105b2011-04-27 14:27:44 +02003050}
3051
Antonio Quartulliced72932013-04-24 16:37:51 +02003052/**
3053 * batadv_send_tt_request - send a TT Request message to a given node
3054 * @bat_priv: the bat priv with all the soft interface information
3055 * @dst_orig_node: the destination of the message
3056 * @ttvn: the version number that the source of the message is looking for
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003057 * @tt_vlan: pointer to the first tvlv VLAN object to request
3058 * @num_vlan: number of tvlv VLAN entries
Antonio Quartulliced72932013-04-24 16:37:51 +02003059 * @full_table: ask for the entire translation table if true, while only for the
3060 * last TT diff otherwise
Antonio Quartullid15cd622015-11-17 16:40:52 +08003061 *
3062 * Return: true if the TT Request was sent, false otherwise
Antonio Quartulliced72932013-04-24 16:37:51 +02003063 */
Sven Eckelmann4b426b12016-02-22 21:02:39 +01003064static bool batadv_send_tt_request(struct batadv_priv *bat_priv,
3065 struct batadv_orig_node *dst_orig_node,
3066 u8 ttvn,
3067 struct batadv_tvlv_tt_vlan_data *tt_vlan,
3068 u16 num_vlan, bool full_table)
Antonio Quartullia73105b2011-04-27 14:27:44 +02003069{
Marek Lindner335fbe02013-04-23 21:40:02 +08003070 struct batadv_tvlv_tt_data *tvlv_tt_data = NULL;
Sven Eckelmann56303d32012-06-05 22:31:31 +02003071 struct batadv_tt_req_node *tt_req_node = NULL;
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003072 struct batadv_tvlv_tt_vlan_data *tt_vlan_req;
3073 struct batadv_hard_iface *primary_if;
Marek Lindner335fbe02013-04-23 21:40:02 +08003074 bool ret = false;
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003075 int i, size;
Antonio Quartullia73105b2011-04-27 14:27:44 +02003076
Sven Eckelmanne5d89252012-05-12 13:48:54 +02003077 primary_if = batadv_primary_if_get_selected(bat_priv);
Antonio Quartullia73105b2011-04-27 14:27:44 +02003078 if (!primary_if)
3079 goto out;
3080
3081 /* The new tt_req will be issued only if I'm not waiting for a
Sven Eckelmann9cfc7bd2012-05-12 02:09:43 +02003082 * reply from the same orig_node yet
3083 */
Marek Lindner383b8632015-06-18 16:24:24 +08003084 tt_req_node = batadv_tt_req_node_new(bat_priv, dst_orig_node);
Antonio Quartullia73105b2011-04-27 14:27:44 +02003085 if (!tt_req_node)
3086 goto out;
3087
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003088 size = sizeof(*tvlv_tt_data) + sizeof(*tt_vlan_req) * num_vlan;
3089 tvlv_tt_data = kzalloc(size, GFP_ATOMIC);
Marek Lindner335fbe02013-04-23 21:40:02 +08003090 if (!tvlv_tt_data)
Antonio Quartullia73105b2011-04-27 14:27:44 +02003091 goto out;
3092
Marek Lindner335fbe02013-04-23 21:40:02 +08003093 tvlv_tt_data->flags = BATADV_TT_REQUEST;
3094 tvlv_tt_data->ttvn = ttvn;
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003095 tvlv_tt_data->num_vlan = htons(num_vlan);
3096
3097 /* send all the CRCs within the request. This is needed by intermediate
3098 * nodes to ensure they have the correct table before replying
3099 */
3100 tt_vlan_req = (struct batadv_tvlv_tt_vlan_data *)(tvlv_tt_data + 1);
3101 for (i = 0; i < num_vlan; i++) {
3102 tt_vlan_req->vid = tt_vlan->vid;
3103 tt_vlan_req->crc = tt_vlan->crc;
3104
3105 tt_vlan_req++;
3106 tt_vlan++;
3107 }
Antonio Quartullia73105b2011-04-27 14:27:44 +02003108
3109 if (full_table)
Marek Lindner335fbe02013-04-23 21:40:02 +08003110 tvlv_tt_data->flags |= BATADV_TT_FULL_TABLE;
Antonio Quartullia73105b2011-04-27 14:27:44 +02003111
Martin Hundebøllbb351ba2012-10-16 16:13:48 +02003112 batadv_dbg(BATADV_DBG_TT, bat_priv, "Sending TT_REQUEST to %pM [%c]\n",
Marek Lindner335fbe02013-04-23 21:40:02 +08003113 dst_orig_node->orig, full_table ? 'F' : '.');
Antonio Quartullia73105b2011-04-27 14:27:44 +02003114
Sven Eckelmannd69909d2012-06-03 22:19:20 +02003115 batadv_inc_counter(bat_priv, BATADV_CNT_TT_REQUEST_TX);
Marek Lindner335fbe02013-04-23 21:40:02 +08003116 batadv_tvlv_unicast_send(bat_priv, primary_if->net_dev->dev_addr,
3117 dst_orig_node->orig, BATADV_TVLV_TT, 1,
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003118 tvlv_tt_data, size);
Marek Lindner335fbe02013-04-23 21:40:02 +08003119 ret = true;
Antonio Quartullia73105b2011-04-27 14:27:44 +02003120
3121out:
Antonio Quartullia73105b2011-04-27 14:27:44 +02003122 if (primary_if)
Sven Eckelmann82047ad2016-01-17 11:01:10 +01003123 batadv_hardif_put(primary_if);
Sven Eckelmann9c4604a2016-06-26 11:16:10 +02003124
Antonio Quartullia73105b2011-04-27 14:27:44 +02003125 if (ret && tt_req_node) {
Sven Eckelmann807736f2012-07-15 22:26:51 +02003126 spin_lock_bh(&bat_priv->tt.req_list_lock);
Sven Eckelmann9c4604a2016-06-26 11:16:10 +02003127 if (!hlist_unhashed(&tt_req_node->list)) {
3128 hlist_del_init(&tt_req_node->list);
3129 batadv_tt_req_node_put(tt_req_node);
3130 }
Sven Eckelmann807736f2012-07-15 22:26:51 +02003131 spin_unlock_bh(&bat_priv->tt.req_list_lock);
Antonio Quartullia73105b2011-04-27 14:27:44 +02003132 }
Sven Eckelmann9c4604a2016-06-26 11:16:10 +02003133
3134 if (tt_req_node)
3135 batadv_tt_req_node_put(tt_req_node);
3136
Marek Lindner335fbe02013-04-23 21:40:02 +08003137 kfree(tvlv_tt_data);
Antonio Quartullia73105b2011-04-27 14:27:44 +02003138 return ret;
3139}
3140
Marek Lindner335fbe02013-04-23 21:40:02 +08003141/**
3142 * batadv_send_other_tt_response - send reply to tt request concerning another
3143 * node's translation table
3144 * @bat_priv: the bat priv with all the soft interface information
3145 * @tt_data: tt data containing the tt request information
3146 * @req_src: mac address of tt request sender
3147 * @req_dst: mac address of tt request recipient
3148 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +02003149 * Return: true if tt request reply was sent, false otherwise.
Marek Lindner335fbe02013-04-23 21:40:02 +08003150 */
3151static bool batadv_send_other_tt_response(struct batadv_priv *bat_priv,
3152 struct batadv_tvlv_tt_data *tt_data,
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02003153 u8 *req_src, u8 *req_dst)
Antonio Quartullia73105b2011-04-27 14:27:44 +02003154{
Sven Eckelmann170173b2012-10-07 12:02:22 +02003155 struct batadv_orig_node *req_dst_orig_node;
Sven Eckelmann56303d32012-06-05 22:31:31 +02003156 struct batadv_orig_node *res_dst_orig_node = NULL;
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003157 struct batadv_tvlv_tt_change *tt_change;
Marek Lindner335fbe02013-04-23 21:40:02 +08003158 struct batadv_tvlv_tt_data *tvlv_tt_data = NULL;
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003159 struct batadv_tvlv_tt_vlan_data *tt_vlan;
Marek Lindner335fbe02013-04-23 21:40:02 +08003160 bool ret = false, full_table;
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02003161 u8 orig_ttvn, req_ttvn;
3162 u16 tvlv_len;
3163 s32 tt_len;
Antonio Quartullia73105b2011-04-27 14:27:44 +02003164
Sven Eckelmann39c75a52012-06-03 22:19:22 +02003165 batadv_dbg(BATADV_DBG_TT, bat_priv,
Sven Eckelmann1eda58b2012-05-12 13:48:58 +02003166 "Received TT_REQUEST from %pM for ttvn: %u (%pM) [%c]\n",
Marek Lindner335fbe02013-04-23 21:40:02 +08003167 req_src, tt_data->ttvn, req_dst,
Sven Eckelmanna2f2b6c2015-04-23 18:22:24 +02003168 ((tt_data->flags & BATADV_TT_FULL_TABLE) ? 'F' : '.'));
Antonio Quartullia73105b2011-04-27 14:27:44 +02003169
3170 /* Let's get the orig node of the REAL destination */
Marek Lindner335fbe02013-04-23 21:40:02 +08003171 req_dst_orig_node = batadv_orig_hash_find(bat_priv, req_dst);
Antonio Quartullia73105b2011-04-27 14:27:44 +02003172 if (!req_dst_orig_node)
3173 goto out;
3174
Marek Lindner335fbe02013-04-23 21:40:02 +08003175 res_dst_orig_node = batadv_orig_hash_find(bat_priv, req_src);
Antonio Quartullia73105b2011-04-27 14:27:44 +02003176 if (!res_dst_orig_node)
3177 goto out;
3178
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02003179 orig_ttvn = (u8)atomic_read(&req_dst_orig_node->last_ttvn);
Marek Lindner335fbe02013-04-23 21:40:02 +08003180 req_ttvn = tt_data->ttvn;
Antonio Quartullia73105b2011-04-27 14:27:44 +02003181
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003182 tt_vlan = (struct batadv_tvlv_tt_vlan_data *)(tt_data + 1);
Marek Lindner335fbe02013-04-23 21:40:02 +08003183 /* this node doesn't have the requested data */
Antonio Quartullia73105b2011-04-27 14:27:44 +02003184 if (orig_ttvn != req_ttvn ||
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003185 !batadv_tt_global_check_crc(req_dst_orig_node, tt_vlan,
3186 ntohs(tt_data->num_vlan)))
Antonio Quartullia73105b2011-04-27 14:27:44 +02003187 goto out;
3188
Antonio Quartulli015758d2011-07-09 17:52:13 +02003189 /* If the full table has been explicitly requested */
Marek Lindner335fbe02013-04-23 21:40:02 +08003190 if (tt_data->flags & BATADV_TT_FULL_TABLE ||
Antonio Quartullia73105b2011-04-27 14:27:44 +02003191 !req_dst_orig_node->tt_buff)
3192 full_table = true;
3193 else
3194 full_table = false;
3195
Marek Lindner335fbe02013-04-23 21:40:02 +08003196 /* TT fragmentation hasn't been implemented yet, so send as many
3197 * TT entries fit a single packet as possible only
Sven Eckelmann9cfc7bd2012-05-12 02:09:43 +02003198 */
Antonio Quartullia73105b2011-04-27 14:27:44 +02003199 if (!full_table) {
3200 spin_lock_bh(&req_dst_orig_node->tt_buff_lock);
3201 tt_len = req_dst_orig_node->tt_buff_len;
Antonio Quartullia73105b2011-04-27 14:27:44 +02003202
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003203 tvlv_len = batadv_tt_prepare_tvlv_global_data(req_dst_orig_node,
3204 &tvlv_tt_data,
3205 &tt_change,
3206 &tt_len);
3207 if (!tt_len)
Antonio Quartullia73105b2011-04-27 14:27:44 +02003208 goto unlock;
3209
Antonio Quartullia73105b2011-04-27 14:27:44 +02003210 /* Copy the last orig_node's OGM buffer */
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003211 memcpy(tt_change, req_dst_orig_node->tt_buff,
Antonio Quartullia73105b2011-04-27 14:27:44 +02003212 req_dst_orig_node->tt_buff_len);
Antonio Quartullia73105b2011-04-27 14:27:44 +02003213 spin_unlock_bh(&req_dst_orig_node->tt_buff_lock);
3214 } else {
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003215 /* allocate the tvlv, put the tt_data and all the tt_vlan_data
3216 * in the initial part
3217 */
3218 tt_len = -1;
3219 tvlv_len = batadv_tt_prepare_tvlv_global_data(req_dst_orig_node,
3220 &tvlv_tt_data,
3221 &tt_change,
3222 &tt_len);
3223 if (!tt_len)
Antonio Quartullia73105b2011-04-27 14:27:44 +02003224 goto out;
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003225
3226 /* fill the rest of the tvlv with the real TT entries */
3227 batadv_tt_tvlv_generate(bat_priv, bat_priv->tt.global_hash,
3228 tt_change, tt_len,
3229 batadv_tt_global_valid,
3230 req_dst_orig_node);
Antonio Quartullia73105b2011-04-27 14:27:44 +02003231 }
3232
Marek Lindnera19d3d82013-05-27 15:33:25 +08003233 /* Don't send the response, if larger than fragmented packet. */
3234 tt_len = sizeof(struct batadv_unicast_tvlv_packet) + tvlv_len;
3235 if (tt_len > atomic_read(&bat_priv->packet_size_max)) {
3236 net_ratelimited_function(batadv_info, bat_priv->soft_iface,
3237 "Ignoring TT_REQUEST from %pM; Response size exceeds max packet size.\n",
3238 res_dst_orig_node->orig);
3239 goto out;
3240 }
3241
Marek Lindner335fbe02013-04-23 21:40:02 +08003242 tvlv_tt_data->flags = BATADV_TT_RESPONSE;
3243 tvlv_tt_data->ttvn = req_ttvn;
Antonio Quartullia73105b2011-04-27 14:27:44 +02003244
3245 if (full_table)
Marek Lindner335fbe02013-04-23 21:40:02 +08003246 tvlv_tt_data->flags |= BATADV_TT_FULL_TABLE;
Antonio Quartullia73105b2011-04-27 14:27:44 +02003247
Sven Eckelmann39c75a52012-06-03 22:19:22 +02003248 batadv_dbg(BATADV_DBG_TT, bat_priv,
Marek Lindner335fbe02013-04-23 21:40:02 +08003249 "Sending TT_RESPONSE %pM for %pM [%c] (ttvn: %u)\n",
3250 res_dst_orig_node->orig, req_dst_orig_node->orig,
3251 full_table ? 'F' : '.', req_ttvn);
Antonio Quartullia73105b2011-04-27 14:27:44 +02003252
Sven Eckelmannd69909d2012-06-03 22:19:20 +02003253 batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX);
Martin Hundebøllf8214862012-04-20 17:02:45 +02003254
Marek Lindner335fbe02013-04-23 21:40:02 +08003255 batadv_tvlv_unicast_send(bat_priv, req_dst_orig_node->orig,
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003256 req_src, BATADV_TVLV_TT, 1, tvlv_tt_data,
3257 tvlv_len);
Martin Hundebølle91ecfc2013-04-20 13:54:39 +02003258
Marek Lindner335fbe02013-04-23 21:40:02 +08003259 ret = true;
Antonio Quartullia73105b2011-04-27 14:27:44 +02003260 goto out;
3261
3262unlock:
3263 spin_unlock_bh(&req_dst_orig_node->tt_buff_lock);
3264
3265out:
3266 if (res_dst_orig_node)
Sven Eckelmann5d967312016-01-17 11:01:09 +01003267 batadv_orig_node_put(res_dst_orig_node);
Antonio Quartullia73105b2011-04-27 14:27:44 +02003268 if (req_dst_orig_node)
Sven Eckelmann5d967312016-01-17 11:01:09 +01003269 batadv_orig_node_put(req_dst_orig_node);
Marek Lindner335fbe02013-04-23 21:40:02 +08003270 kfree(tvlv_tt_data);
Antonio Quartullia73105b2011-04-27 14:27:44 +02003271 return ret;
Antonio Quartullia73105b2011-04-27 14:27:44 +02003272}
Sven Eckelmann96412692012-06-05 22:31:30 +02003273
Marek Lindner335fbe02013-04-23 21:40:02 +08003274/**
3275 * batadv_send_my_tt_response - send reply to tt request concerning this node's
3276 * translation table
3277 * @bat_priv: the bat priv with all the soft interface information
3278 * @tt_data: tt data containing the tt request information
3279 * @req_src: mac address of tt request sender
3280 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +02003281 * Return: true if tt request reply was sent, false otherwise.
Marek Lindner335fbe02013-04-23 21:40:02 +08003282 */
3283static bool batadv_send_my_tt_response(struct batadv_priv *bat_priv,
3284 struct batadv_tvlv_tt_data *tt_data,
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02003285 u8 *req_src)
Antonio Quartullia73105b2011-04-27 14:27:44 +02003286{
Marek Lindner335fbe02013-04-23 21:40:02 +08003287 struct batadv_tvlv_tt_data *tvlv_tt_data = NULL;
Sven Eckelmann56303d32012-06-05 22:31:31 +02003288 struct batadv_hard_iface *primary_if = NULL;
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003289 struct batadv_tvlv_tt_change *tt_change;
3290 struct batadv_orig_node *orig_node;
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02003291 u8 my_ttvn, req_ttvn;
3292 u16 tvlv_len;
Antonio Quartullia73105b2011-04-27 14:27:44 +02003293 bool full_table;
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02003294 s32 tt_len;
Antonio Quartullia73105b2011-04-27 14:27:44 +02003295
Sven Eckelmann39c75a52012-06-03 22:19:22 +02003296 batadv_dbg(BATADV_DBG_TT, bat_priv,
Sven Eckelmann1eda58b2012-05-12 13:48:58 +02003297 "Received TT_REQUEST from %pM for ttvn: %u (me) [%c]\n",
Marek Lindner335fbe02013-04-23 21:40:02 +08003298 req_src, tt_data->ttvn,
Sven Eckelmanna2f2b6c2015-04-23 18:22:24 +02003299 ((tt_data->flags & BATADV_TT_FULL_TABLE) ? 'F' : '.'));
Antonio Quartullia73105b2011-04-27 14:27:44 +02003300
Antonio Quartullia70a9aa2013-07-30 22:16:24 +02003301 spin_lock_bh(&bat_priv->tt.commit_lock);
Antonio Quartullia73105b2011-04-27 14:27:44 +02003302
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02003303 my_ttvn = (u8)atomic_read(&bat_priv->tt.vn);
Marek Lindner335fbe02013-04-23 21:40:02 +08003304 req_ttvn = tt_data->ttvn;
Antonio Quartullia73105b2011-04-27 14:27:44 +02003305
Marek Lindner335fbe02013-04-23 21:40:02 +08003306 orig_node = batadv_orig_hash_find(bat_priv, req_src);
Antonio Quartullia73105b2011-04-27 14:27:44 +02003307 if (!orig_node)
3308 goto out;
3309
Sven Eckelmanne5d89252012-05-12 13:48:54 +02003310 primary_if = batadv_primary_if_get_selected(bat_priv);
Antonio Quartullia73105b2011-04-27 14:27:44 +02003311 if (!primary_if)
3312 goto out;
3313
3314 /* If the full table has been explicitly requested or the gap
Sven Eckelmann9cfc7bd2012-05-12 02:09:43 +02003315 * is too big send the whole local translation table
3316 */
Marek Lindner335fbe02013-04-23 21:40:02 +08003317 if (tt_data->flags & BATADV_TT_FULL_TABLE || my_ttvn != req_ttvn ||
Sven Eckelmann807736f2012-07-15 22:26:51 +02003318 !bat_priv->tt.last_changeset)
Antonio Quartullia73105b2011-04-27 14:27:44 +02003319 full_table = true;
3320 else
3321 full_table = false;
3322
Marek Lindner335fbe02013-04-23 21:40:02 +08003323 /* TT fragmentation hasn't been implemented yet, so send as many
3324 * TT entries fit a single packet as possible only
Sven Eckelmann9cfc7bd2012-05-12 02:09:43 +02003325 */
Antonio Quartullia73105b2011-04-27 14:27:44 +02003326 if (!full_table) {
Sven Eckelmann807736f2012-07-15 22:26:51 +02003327 spin_lock_bh(&bat_priv->tt.last_changeset_lock);
Antonio Quartullia73105b2011-04-27 14:27:44 +02003328
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003329 tt_len = bat_priv->tt.last_changeset_len;
3330 tvlv_len = batadv_tt_prepare_tvlv_local_data(bat_priv,
3331 &tvlv_tt_data,
3332 &tt_change,
3333 &tt_len);
Sven Eckelmannc2d0f482016-11-30 21:47:09 +01003334 if (!tt_len || !tvlv_len)
Antonio Quartullia73105b2011-04-27 14:27:44 +02003335 goto unlock;
3336
Marek Lindner335fbe02013-04-23 21:40:02 +08003337 /* Copy the last orig_node's OGM buffer */
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003338 memcpy(tt_change, bat_priv->tt.last_changeset,
Sven Eckelmann807736f2012-07-15 22:26:51 +02003339 bat_priv->tt.last_changeset_len);
3340 spin_unlock_bh(&bat_priv->tt.last_changeset_lock);
Antonio Quartullia73105b2011-04-27 14:27:44 +02003341 } else {
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02003342 req_ttvn = (u8)atomic_read(&bat_priv->tt.vn);
Antonio Quartullia73105b2011-04-27 14:27:44 +02003343
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003344 /* allocate the tvlv, put the tt_data and all the tt_vlan_data
3345 * in the initial part
3346 */
3347 tt_len = -1;
3348 tvlv_len = batadv_tt_prepare_tvlv_local_data(bat_priv,
3349 &tvlv_tt_data,
3350 &tt_change,
3351 &tt_len);
Sven Eckelmannc2d0f482016-11-30 21:47:09 +01003352 if (!tt_len || !tvlv_len)
Antonio Quartullia73105b2011-04-27 14:27:44 +02003353 goto out;
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003354
3355 /* fill the rest of the tvlv with the real TT entries */
3356 batadv_tt_tvlv_generate(bat_priv, bat_priv->tt.local_hash,
3357 tt_change, tt_len,
3358 batadv_tt_local_valid, NULL);
Antonio Quartullia73105b2011-04-27 14:27:44 +02003359 }
3360
Marek Lindner335fbe02013-04-23 21:40:02 +08003361 tvlv_tt_data->flags = BATADV_TT_RESPONSE;
3362 tvlv_tt_data->ttvn = req_ttvn;
Antonio Quartullia73105b2011-04-27 14:27:44 +02003363
3364 if (full_table)
Marek Lindner335fbe02013-04-23 21:40:02 +08003365 tvlv_tt_data->flags |= BATADV_TT_FULL_TABLE;
Antonio Quartullia73105b2011-04-27 14:27:44 +02003366
Sven Eckelmann39c75a52012-06-03 22:19:22 +02003367 batadv_dbg(BATADV_DBG_TT, bat_priv,
Marek Lindner335fbe02013-04-23 21:40:02 +08003368 "Sending TT_RESPONSE to %pM [%c] (ttvn: %u)\n",
3369 orig_node->orig, full_table ? 'F' : '.', req_ttvn);
Antonio Quartullia73105b2011-04-27 14:27:44 +02003370
Sven Eckelmannd69909d2012-06-03 22:19:20 +02003371 batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX);
Martin Hundebøllf8214862012-04-20 17:02:45 +02003372
Marek Lindner335fbe02013-04-23 21:40:02 +08003373 batadv_tvlv_unicast_send(bat_priv, primary_if->net_dev->dev_addr,
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003374 req_src, BATADV_TVLV_TT, 1, tvlv_tt_data,
3375 tvlv_len);
Marek Lindner335fbe02013-04-23 21:40:02 +08003376
Antonio Quartullia73105b2011-04-27 14:27:44 +02003377 goto out;
3378
3379unlock:
Sven Eckelmann807736f2012-07-15 22:26:51 +02003380 spin_unlock_bh(&bat_priv->tt.last_changeset_lock);
Antonio Quartullia73105b2011-04-27 14:27:44 +02003381out:
Antonio Quartullia70a9aa2013-07-30 22:16:24 +02003382 spin_unlock_bh(&bat_priv->tt.commit_lock);
Antonio Quartullia73105b2011-04-27 14:27:44 +02003383 if (orig_node)
Sven Eckelmann5d967312016-01-17 11:01:09 +01003384 batadv_orig_node_put(orig_node);
Antonio Quartullia73105b2011-04-27 14:27:44 +02003385 if (primary_if)
Sven Eckelmann82047ad2016-01-17 11:01:10 +01003386 batadv_hardif_put(primary_if);
Marek Lindner335fbe02013-04-23 21:40:02 +08003387 kfree(tvlv_tt_data);
3388 /* The packet was for this host, so it doesn't need to be re-routed */
Antonio Quartullia73105b2011-04-27 14:27:44 +02003389 return true;
3390}
3391
Marek Lindner335fbe02013-04-23 21:40:02 +08003392/**
3393 * batadv_send_tt_response - send reply to tt request
3394 * @bat_priv: the bat priv with all the soft interface information
3395 * @tt_data: tt data containing the tt request information
3396 * @req_src: mac address of tt request sender
3397 * @req_dst: mac address of tt request recipient
3398 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +02003399 * Return: true if tt request reply was sent, false otherwise.
Marek Lindner335fbe02013-04-23 21:40:02 +08003400 */
3401static bool batadv_send_tt_response(struct batadv_priv *bat_priv,
3402 struct batadv_tvlv_tt_data *tt_data,
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02003403 u8 *req_src, u8 *req_dst)
Antonio Quartullia73105b2011-04-27 14:27:44 +02003404{
Antonio Quartullicfd4f752013-08-07 18:28:56 +02003405 if (batadv_is_my_mac(bat_priv, req_dst))
Marek Lindner335fbe02013-04-23 21:40:02 +08003406 return batadv_send_my_tt_response(bat_priv, tt_data, req_src);
Antonio Quartulli24820df2014-09-01 14:37:25 +02003407 return batadv_send_other_tt_response(bat_priv, tt_data, req_src,
3408 req_dst);
Antonio Quartullia73105b2011-04-27 14:27:44 +02003409}
3410
Sven Eckelmann56303d32012-06-05 22:31:31 +02003411static void _batadv_tt_update_changes(struct batadv_priv *bat_priv,
3412 struct batadv_orig_node *orig_node,
Marek Lindner335fbe02013-04-23 21:40:02 +08003413 struct batadv_tvlv_tt_change *tt_change,
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02003414 u16 tt_num_changes, u8 ttvn)
Antonio Quartullia73105b2011-04-27 14:27:44 +02003415{
3416 int i;
Sven Eckelmanna5130882012-05-16 20:23:16 +02003417 int roams;
Antonio Quartullia73105b2011-04-27 14:27:44 +02003418
3419 for (i = 0; i < tt_num_changes; i++) {
Sven Eckelmannacd34af2012-06-03 22:19:21 +02003420 if ((tt_change + i)->flags & BATADV_TT_CLIENT_DEL) {
3421 roams = (tt_change + i)->flags & BATADV_TT_CLIENT_ROAM;
Sven Eckelmanna5130882012-05-16 20:23:16 +02003422 batadv_tt_global_del(bat_priv, orig_node,
3423 (tt_change + i)->addr,
Antonio Quartullic018ad32013-06-04 12:11:39 +02003424 ntohs((tt_change + i)->vid),
Antonio Quartullid4f44692012-05-25 00:00:54 +02003425 "tt removed by changes",
3426 roams);
Sven Eckelmann08c36d32012-05-12 02:09:39 +02003427 } else {
Sven Eckelmann08c36d32012-05-12 02:09:39 +02003428 if (!batadv_tt_global_add(bat_priv, orig_node,
Antonio Quartullid4f44692012-05-25 00:00:54 +02003429 (tt_change + i)->addr,
Antonio Quartullic018ad32013-06-04 12:11:39 +02003430 ntohs((tt_change + i)->vid),
Antonio Quartullid4f44692012-05-25 00:00:54 +02003431 (tt_change + i)->flags, ttvn))
Antonio Quartullia73105b2011-04-27 14:27:44 +02003432 /* In case of problem while storing a
3433 * global_entry, we stop the updating
3434 * procedure without committing the
3435 * ttvn change. This will avoid to send
3436 * corrupted data on tt_request
3437 */
3438 return;
Sven Eckelmann08c36d32012-05-12 02:09:39 +02003439 }
Antonio Quartullia73105b2011-04-27 14:27:44 +02003440 }
Linus Lüssingac4eebd2015-06-16 17:10:24 +02003441 set_bit(BATADV_ORIG_CAPA_HAS_TT, &orig_node->capa_initialized);
Antonio Quartullia73105b2011-04-27 14:27:44 +02003442}
3443
Sven Eckelmann56303d32012-06-05 22:31:31 +02003444static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv,
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003445 struct batadv_tvlv_tt_change *tt_change,
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02003446 u8 ttvn, u8 *resp_src,
3447 u16 num_entries)
Antonio Quartullia73105b2011-04-27 14:27:44 +02003448{
Sven Eckelmann170173b2012-10-07 12:02:22 +02003449 struct batadv_orig_node *orig_node;
Antonio Quartullia73105b2011-04-27 14:27:44 +02003450
Marek Lindner335fbe02013-04-23 21:40:02 +08003451 orig_node = batadv_orig_hash_find(bat_priv, resp_src);
Antonio Quartullia73105b2011-04-27 14:27:44 +02003452 if (!orig_node)
3453 goto out;
3454
3455 /* Purge the old table first.. */
Antonio Quartulli95fb1302013-08-07 18:28:55 +02003456 batadv_tt_global_del_orig(bat_priv, orig_node, -1,
3457 "Received full table");
Antonio Quartullia73105b2011-04-27 14:27:44 +02003458
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003459 _batadv_tt_update_changes(bat_priv, orig_node, tt_change, num_entries,
3460 ttvn);
Antonio Quartullia73105b2011-04-27 14:27:44 +02003461
3462 spin_lock_bh(&orig_node->tt_buff_lock);
3463 kfree(orig_node->tt_buff);
3464 orig_node->tt_buff_len = 0;
3465 orig_node->tt_buff = NULL;
3466 spin_unlock_bh(&orig_node->tt_buff_lock);
3467
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003468 atomic_set(&orig_node->last_ttvn, ttvn);
Antonio Quartullia73105b2011-04-27 14:27:44 +02003469
3470out:
3471 if (orig_node)
Sven Eckelmann5d967312016-01-17 11:01:09 +01003472 batadv_orig_node_put(orig_node);
Antonio Quartullia73105b2011-04-27 14:27:44 +02003473}
3474
Sven Eckelmann56303d32012-06-05 22:31:31 +02003475static void batadv_tt_update_changes(struct batadv_priv *bat_priv,
3476 struct batadv_orig_node *orig_node,
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02003477 u16 tt_num_changes, u8 ttvn,
Marek Lindner335fbe02013-04-23 21:40:02 +08003478 struct batadv_tvlv_tt_change *tt_change)
Antonio Quartullia73105b2011-04-27 14:27:44 +02003479{
Sven Eckelmanna5130882012-05-16 20:23:16 +02003480 _batadv_tt_update_changes(bat_priv, orig_node, tt_change,
3481 tt_num_changes, ttvn);
Antonio Quartullia73105b2011-04-27 14:27:44 +02003482
Antonio Quartullie8cf2342013-05-28 13:14:28 +02003483 batadv_tt_save_orig_buffer(bat_priv, orig_node, tt_change,
3484 batadv_tt_len(tt_num_changes));
Antonio Quartullia73105b2011-04-27 14:27:44 +02003485 atomic_set(&orig_node->last_ttvn, ttvn);
3486}
3487
Antonio Quartullic018ad32013-06-04 12:11:39 +02003488/**
3489 * batadv_is_my_client - check if a client is served by the local node
3490 * @bat_priv: the bat priv with all the soft interface information
Antonio Quartulli3f687852014-11-02 11:29:56 +01003491 * @addr: the mac address of the client to check
Antonio Quartullic018ad32013-06-04 12:11:39 +02003492 * @vid: VLAN identifier
3493 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +02003494 * Return: true if the client is served by this node, false otherwise.
Antonio Quartullic018ad32013-06-04 12:11:39 +02003495 */
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02003496bool batadv_is_my_client(struct batadv_priv *bat_priv, const u8 *addr,
Antonio Quartullic018ad32013-06-04 12:11:39 +02003497 unsigned short vid)
Antonio Quartullia73105b2011-04-27 14:27:44 +02003498{
Sven Eckelmann170173b2012-10-07 12:02:22 +02003499 struct batadv_tt_local_entry *tt_local_entry;
Antonio Quartulli7683fdc2011-04-27 14:28:07 +02003500 bool ret = false;
Antonio Quartullia73105b2011-04-27 14:27:44 +02003501
Antonio Quartullic018ad32013-06-04 12:11:39 +02003502 tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr, vid);
Antonio Quartulli7683fdc2011-04-27 14:28:07 +02003503 if (!tt_local_entry)
3504 goto out;
Antonio Quartulli058d0e22011-07-07 01:40:58 +02003505 /* Check if the client has been logically deleted (but is kept for
Sven Eckelmann9cfc7bd2012-05-12 02:09:43 +02003506 * consistency purpose)
3507 */
Antonio Quartulli7c1fd912012-09-23 22:38:34 +02003508 if ((tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING) ||
3509 (tt_local_entry->common.flags & BATADV_TT_CLIENT_ROAM))
Antonio Quartulli058d0e22011-07-07 01:40:58 +02003510 goto out;
Antonio Quartulli7683fdc2011-04-27 14:28:07 +02003511 ret = true;
3512out:
Antonio Quartullia73105b2011-04-27 14:27:44 +02003513 if (tt_local_entry)
Sven Eckelmann95c0db92016-01-17 11:01:25 +01003514 batadv_tt_local_entry_put(tt_local_entry);
Antonio Quartulli7683fdc2011-04-27 14:28:07 +02003515 return ret;
Antonio Quartullia73105b2011-04-27 14:27:44 +02003516}
3517
Marek Lindner335fbe02013-04-23 21:40:02 +08003518/**
3519 * batadv_handle_tt_response - process incoming tt reply
3520 * @bat_priv: the bat priv with all the soft interface information
3521 * @tt_data: tt data containing the tt request information
3522 * @resp_src: mac address of tt reply sender
3523 * @num_entries: number of tt change entries appended to the tt data
3524 */
3525static void batadv_handle_tt_response(struct batadv_priv *bat_priv,
3526 struct batadv_tvlv_tt_data *tt_data,
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02003527 u8 *resp_src, u16 num_entries)
Antonio Quartullia73105b2011-04-27 14:27:44 +02003528{
Marek Lindner7c26a532015-06-28 22:16:06 +08003529 struct batadv_tt_req_node *node;
3530 struct hlist_node *safe;
Sven Eckelmann56303d32012-06-05 22:31:31 +02003531 struct batadv_orig_node *orig_node = NULL;
Marek Lindner335fbe02013-04-23 21:40:02 +08003532 struct batadv_tvlv_tt_change *tt_change;
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02003533 u8 *tvlv_ptr = (u8 *)tt_data;
3534 u16 change_offset;
Antonio Quartullia73105b2011-04-27 14:27:44 +02003535
Sven Eckelmann39c75a52012-06-03 22:19:22 +02003536 batadv_dbg(BATADV_DBG_TT, bat_priv,
Sven Eckelmann1eda58b2012-05-12 13:48:58 +02003537 "Received TT_RESPONSE from %pM for ttvn %d t_size: %d [%c]\n",
Marek Lindner335fbe02013-04-23 21:40:02 +08003538 resp_src, tt_data->ttvn, num_entries,
Sven Eckelmanna2f2b6c2015-04-23 18:22:24 +02003539 ((tt_data->flags & BATADV_TT_FULL_TABLE) ? 'F' : '.'));
Antonio Quartullia73105b2011-04-27 14:27:44 +02003540
Marek Lindner335fbe02013-04-23 21:40:02 +08003541 orig_node = batadv_orig_hash_find(bat_priv, resp_src);
Antonio Quartullia73105b2011-04-27 14:27:44 +02003542 if (!orig_node)
3543 goto out;
3544
Antonio Quartullia70a9aa2013-07-30 22:16:24 +02003545 spin_lock_bh(&orig_node->tt_lock);
3546
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003547 change_offset = sizeof(struct batadv_tvlv_tt_vlan_data);
3548 change_offset *= ntohs(tt_data->num_vlan);
3549 change_offset += sizeof(*tt_data);
3550 tvlv_ptr += change_offset;
3551
3552 tt_change = (struct batadv_tvlv_tt_change *)tvlv_ptr;
Marek Lindner335fbe02013-04-23 21:40:02 +08003553 if (tt_data->flags & BATADV_TT_FULL_TABLE) {
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003554 batadv_tt_fill_gtable(bat_priv, tt_change, tt_data->ttvn,
3555 resp_src, num_entries);
Sven Eckelmann96412692012-06-05 22:31:30 +02003556 } else {
Marek Lindner335fbe02013-04-23 21:40:02 +08003557 batadv_tt_update_changes(bat_priv, orig_node, num_entries,
3558 tt_data->ttvn, tt_change);
Sven Eckelmann96412692012-06-05 22:31:30 +02003559 }
Antonio Quartullia73105b2011-04-27 14:27:44 +02003560
Antonio Quartullia70a9aa2013-07-30 22:16:24 +02003561 /* Recalculate the CRC for this orig_node and store it */
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003562 batadv_tt_global_update_crc(bat_priv, orig_node);
Antonio Quartullia70a9aa2013-07-30 22:16:24 +02003563
3564 spin_unlock_bh(&orig_node->tt_lock);
3565
Antonio Quartullia73105b2011-04-27 14:27:44 +02003566 /* Delete the tt_req_node from pending tt_requests list */
Sven Eckelmann807736f2012-07-15 22:26:51 +02003567 spin_lock_bh(&bat_priv->tt.req_list_lock);
Marek Lindner7c26a532015-06-28 22:16:06 +08003568 hlist_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) {
Marek Lindner335fbe02013-04-23 21:40:02 +08003569 if (!batadv_compare_eth(node->addr, resp_src))
Antonio Quartullia73105b2011-04-27 14:27:44 +02003570 continue;
Marek Lindner7c26a532015-06-28 22:16:06 +08003571 hlist_del_init(&node->list);
Sven Eckelmann9c4604a2016-06-26 11:16:10 +02003572 batadv_tt_req_node_put(node);
Antonio Quartullia73105b2011-04-27 14:27:44 +02003573 }
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003574
Sven Eckelmann807736f2012-07-15 22:26:51 +02003575 spin_unlock_bh(&bat_priv->tt.req_list_lock);
Antonio Quartullia73105b2011-04-27 14:27:44 +02003576out:
3577 if (orig_node)
Sven Eckelmann5d967312016-01-17 11:01:09 +01003578 batadv_orig_node_put(orig_node);
Antonio Quartullia73105b2011-04-27 14:27:44 +02003579}
3580
Sven Eckelmann56303d32012-06-05 22:31:31 +02003581static void batadv_tt_roam_list_free(struct batadv_priv *bat_priv)
Antonio Quartullia73105b2011-04-27 14:27:44 +02003582{
Sven Eckelmann56303d32012-06-05 22:31:31 +02003583 struct batadv_tt_roam_node *node, *safe;
Antonio Quartullia73105b2011-04-27 14:27:44 +02003584
Sven Eckelmann807736f2012-07-15 22:26:51 +02003585 spin_lock_bh(&bat_priv->tt.roam_list_lock);
Antonio Quartullia73105b2011-04-27 14:27:44 +02003586
Sven Eckelmann807736f2012-07-15 22:26:51 +02003587 list_for_each_entry_safe(node, safe, &bat_priv->tt.roam_list, list) {
Antonio Quartullicc47f662011-04-27 14:27:57 +02003588 list_del(&node->list);
Sven Eckelmann86452f82016-06-25 16:44:06 +02003589 kmem_cache_free(batadv_tt_roam_cache, node);
Antonio Quartullicc47f662011-04-27 14:27:57 +02003590 }
3591
Sven Eckelmann807736f2012-07-15 22:26:51 +02003592 spin_unlock_bh(&bat_priv->tt.roam_list_lock);
Antonio Quartullicc47f662011-04-27 14:27:57 +02003593}
3594
Sven Eckelmann56303d32012-06-05 22:31:31 +02003595static void batadv_tt_roam_purge(struct batadv_priv *bat_priv)
Antonio Quartullicc47f662011-04-27 14:27:57 +02003596{
Sven Eckelmann56303d32012-06-05 22:31:31 +02003597 struct batadv_tt_roam_node *node, *safe;
Antonio Quartullicc47f662011-04-27 14:27:57 +02003598
Sven Eckelmann807736f2012-07-15 22:26:51 +02003599 spin_lock_bh(&bat_priv->tt.roam_list_lock);
3600 list_for_each_entry_safe(node, safe, &bat_priv->tt.roam_list, list) {
Sven Eckelmann42d0b042012-06-03 22:19:17 +02003601 if (!batadv_has_timed_out(node->first_time,
3602 BATADV_ROAMING_MAX_TIME))
Antonio Quartullicc47f662011-04-27 14:27:57 +02003603 continue;
3604
3605 list_del(&node->list);
Sven Eckelmann86452f82016-06-25 16:44:06 +02003606 kmem_cache_free(batadv_tt_roam_cache, node);
Antonio Quartullicc47f662011-04-27 14:27:57 +02003607 }
Sven Eckelmann807736f2012-07-15 22:26:51 +02003608 spin_unlock_bh(&bat_priv->tt.roam_list_lock);
Antonio Quartullicc47f662011-04-27 14:27:57 +02003609}
3610
Sven Eckelmann62fe7102015-09-15 19:00:48 +02003611/**
Antonio Quartullid15cd622015-11-17 16:40:52 +08003612 * batadv_tt_check_roam_count - check if a client has roamed too frequently
3613 * @bat_priv: the bat priv with all the soft interface information
3614 * @client: mac address of the roaming client
Sven Eckelmann62fe7102015-09-15 19:00:48 +02003615 *
3616 * This function checks whether the client already reached the
Antonio Quartullicc47f662011-04-27 14:27:57 +02003617 * maximum number of possible roaming phases. In this case the ROAMING_ADV
3618 * will not be sent.
3619 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +02003620 * Return: true if the ROAMING_ADV can be sent, false otherwise
Sven Eckelmann9cfc7bd2012-05-12 02:09:43 +02003621 */
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02003622static bool batadv_tt_check_roam_count(struct batadv_priv *bat_priv, u8 *client)
Antonio Quartullicc47f662011-04-27 14:27:57 +02003623{
Sven Eckelmann56303d32012-06-05 22:31:31 +02003624 struct batadv_tt_roam_node *tt_roam_node;
Antonio Quartullicc47f662011-04-27 14:27:57 +02003625 bool ret = false;
3626
Sven Eckelmann807736f2012-07-15 22:26:51 +02003627 spin_lock_bh(&bat_priv->tt.roam_list_lock);
Antonio Quartullicc47f662011-04-27 14:27:57 +02003628 /* The new tt_req will be issued only if I'm not waiting for a
Sven Eckelmann9cfc7bd2012-05-12 02:09:43 +02003629 * reply from the same orig_node yet
3630 */
Sven Eckelmann807736f2012-07-15 22:26:51 +02003631 list_for_each_entry(tt_roam_node, &bat_priv->tt.roam_list, list) {
Sven Eckelmann1eda58b2012-05-12 13:48:58 +02003632 if (!batadv_compare_eth(tt_roam_node->addr, client))
Antonio Quartullicc47f662011-04-27 14:27:57 +02003633 continue;
3634
Sven Eckelmann1eda58b2012-05-12 13:48:58 +02003635 if (batadv_has_timed_out(tt_roam_node->first_time,
Sven Eckelmann42d0b042012-06-03 22:19:17 +02003636 BATADV_ROAMING_MAX_TIME))
Antonio Quartullicc47f662011-04-27 14:27:57 +02003637 continue;
3638
Sven Eckelmann3e348192012-05-16 20:23:22 +02003639 if (!batadv_atomic_dec_not_zero(&tt_roam_node->counter))
Antonio Quartullicc47f662011-04-27 14:27:57 +02003640 /* Sorry, you roamed too many times! */
3641 goto unlock;
3642 ret = true;
3643 break;
3644 }
3645
3646 if (!ret) {
Sven Eckelmann86452f82016-06-25 16:44:06 +02003647 tt_roam_node = kmem_cache_alloc(batadv_tt_roam_cache,
3648 GFP_ATOMIC);
Antonio Quartullicc47f662011-04-27 14:27:57 +02003649 if (!tt_roam_node)
3650 goto unlock;
3651
3652 tt_roam_node->first_time = jiffies;
Sven Eckelmann42d0b042012-06-03 22:19:17 +02003653 atomic_set(&tt_roam_node->counter,
3654 BATADV_ROAMING_MAX_COUNT - 1);
Antonio Quartulli8fdd0152014-01-22 00:42:11 +01003655 ether_addr_copy(tt_roam_node->addr, client);
Antonio Quartullicc47f662011-04-27 14:27:57 +02003656
Sven Eckelmann807736f2012-07-15 22:26:51 +02003657 list_add(&tt_roam_node->list, &bat_priv->tt.roam_list);
Antonio Quartullicc47f662011-04-27 14:27:57 +02003658 ret = true;
3659 }
3660
3661unlock:
Sven Eckelmann807736f2012-07-15 22:26:51 +02003662 spin_unlock_bh(&bat_priv->tt.roam_list_lock);
Antonio Quartullicc47f662011-04-27 14:27:57 +02003663 return ret;
3664}
3665
Antonio Quartullic018ad32013-06-04 12:11:39 +02003666/**
3667 * batadv_send_roam_adv - send a roaming advertisement message
3668 * @bat_priv: the bat priv with all the soft interface information
3669 * @client: mac address of the roaming client
3670 * @vid: VLAN identifier
3671 * @orig_node: message destination
3672 *
3673 * Send a ROAMING_ADV message to the node which was previously serving this
3674 * client. This is done to inform the node that from now on all traffic destined
3675 * for this particular roamed client has to be forwarded to the sender of the
3676 * roaming message.
3677 */
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02003678static void batadv_send_roam_adv(struct batadv_priv *bat_priv, u8 *client,
Antonio Quartullic018ad32013-06-04 12:11:39 +02003679 unsigned short vid,
Sven Eckelmann56303d32012-06-05 22:31:31 +02003680 struct batadv_orig_node *orig_node)
Antonio Quartullicc47f662011-04-27 14:27:57 +02003681{
Sven Eckelmann56303d32012-06-05 22:31:31 +02003682 struct batadv_hard_iface *primary_if;
Marek Lindner122edaa2013-04-23 21:40:03 +08003683 struct batadv_tvlv_roam_adv tvlv_roam;
3684
3685 primary_if = batadv_primary_if_get_selected(bat_priv);
3686 if (!primary_if)
3687 goto out;
Antonio Quartullicc47f662011-04-27 14:27:57 +02003688
3689 /* before going on we have to check whether the client has
Sven Eckelmann9cfc7bd2012-05-12 02:09:43 +02003690 * already roamed to us too many times
3691 */
Sven Eckelmanna5130882012-05-16 20:23:16 +02003692 if (!batadv_tt_check_roam_count(bat_priv, client))
Antonio Quartullicc47f662011-04-27 14:27:57 +02003693 goto out;
3694
Sven Eckelmann39c75a52012-06-03 22:19:22 +02003695 batadv_dbg(BATADV_DBG_TT, bat_priv,
Antonio Quartulli16052782013-06-04 12:11:41 +02003696 "Sending ROAMING_ADV to %pM (client %pM, vid: %d)\n",
Sven Eckelmannf7a2bd62017-02-22 17:16:42 +01003697 orig_node->orig, client, batadv_print_vid(vid));
Antonio Quartullicc47f662011-04-27 14:27:57 +02003698
Sven Eckelmannd69909d2012-06-03 22:19:20 +02003699 batadv_inc_counter(bat_priv, BATADV_CNT_TT_ROAM_ADV_TX);
Martin Hundebøllf8214862012-04-20 17:02:45 +02003700
Marek Lindner122edaa2013-04-23 21:40:03 +08003701 memcpy(tvlv_roam.client, client, sizeof(tvlv_roam.client));
Antonio Quartullic018ad32013-06-04 12:11:39 +02003702 tvlv_roam.vid = htons(vid);
Marek Lindner122edaa2013-04-23 21:40:03 +08003703
3704 batadv_tvlv_unicast_send(bat_priv, primary_if->net_dev->dev_addr,
3705 orig_node->orig, BATADV_TVLV_ROAM, 1,
3706 &tvlv_roam, sizeof(tvlv_roam));
Antonio Quartullicc47f662011-04-27 14:27:57 +02003707
3708out:
Marek Lindner122edaa2013-04-23 21:40:03 +08003709 if (primary_if)
Sven Eckelmann82047ad2016-01-17 11:01:10 +01003710 batadv_hardif_put(primary_if);
Antonio Quartullia73105b2011-04-27 14:27:44 +02003711}
3712
Sven Eckelmanna5130882012-05-16 20:23:16 +02003713static void batadv_tt_purge(struct work_struct *work)
Antonio Quartullia73105b2011-04-27 14:27:44 +02003714{
Sven Eckelmann56303d32012-06-05 22:31:31 +02003715 struct delayed_work *delayed_work;
Sven Eckelmann807736f2012-07-15 22:26:51 +02003716 struct batadv_priv_tt *priv_tt;
Sven Eckelmann56303d32012-06-05 22:31:31 +02003717 struct batadv_priv *bat_priv;
3718
Geliang Tang4ba4bc02015-12-28 23:43:37 +08003719 delayed_work = to_delayed_work(work);
Sven Eckelmann807736f2012-07-15 22:26:51 +02003720 priv_tt = container_of(delayed_work, struct batadv_priv_tt, work);
3721 bat_priv = container_of(priv_tt, struct batadv_priv, tt);
Antonio Quartullia73105b2011-04-27 14:27:44 +02003722
Marek Lindnera19d3d82013-05-27 15:33:25 +08003723 batadv_tt_local_purge(bat_priv, BATADV_TT_LOCAL_TIMEOUT);
Antonio Quartulli30cfd022012-07-05 23:38:29 +02003724 batadv_tt_global_purge(bat_priv);
Sven Eckelmanna5130882012-05-16 20:23:16 +02003725 batadv_tt_req_purge(bat_priv);
3726 batadv_tt_roam_purge(bat_priv);
Antonio Quartullia73105b2011-04-27 14:27:44 +02003727
Antonio Quartulli72414442012-12-25 13:14:37 +01003728 queue_delayed_work(batadv_event_workqueue, &bat_priv->tt.work,
3729 msecs_to_jiffies(BATADV_TT_WORK_PERIOD));
Antonio Quartullia73105b2011-04-27 14:27:44 +02003730}
Antonio Quartullicc47f662011-04-27 14:27:57 +02003731
Sven Eckelmann56303d32012-06-05 22:31:31 +02003732void batadv_tt_free(struct batadv_priv *bat_priv)
Antonio Quartullicc47f662011-04-27 14:27:57 +02003733{
Marek Lindnere1bf0c12013-04-23 21:40:01 +08003734 batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_TT, 1);
3735 batadv_tvlv_handler_unregister(bat_priv, BATADV_TVLV_TT, 1);
3736
Sven Eckelmann807736f2012-07-15 22:26:51 +02003737 cancel_delayed_work_sync(&bat_priv->tt.work);
Antonio Quartullicc47f662011-04-27 14:27:57 +02003738
Sven Eckelmanna5130882012-05-16 20:23:16 +02003739 batadv_tt_local_table_free(bat_priv);
3740 batadv_tt_global_table_free(bat_priv);
3741 batadv_tt_req_list_free(bat_priv);
3742 batadv_tt_changes_list_free(bat_priv);
3743 batadv_tt_roam_list_free(bat_priv);
Antonio Quartullicc47f662011-04-27 14:27:57 +02003744
Sven Eckelmann807736f2012-07-15 22:26:51 +02003745 kfree(bat_priv->tt.last_changeset);
Antonio Quartullicc47f662011-04-27 14:27:57 +02003746}
Antonio Quartulli058d0e22011-07-07 01:40:58 +02003747
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003748/**
3749 * batadv_tt_local_set_flags - set or unset the specified flags on the local
3750 * table and possibly count them in the TT size
3751 * @bat_priv: the bat priv with all the soft interface information
3752 * @flags: the flag to switch
3753 * @enable: whether to set or unset the flag
3754 * @count: whether to increase the TT size by the number of changed entries
Sven Eckelmann9cfc7bd2012-05-12 02:09:43 +02003755 */
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02003756static void batadv_tt_local_set_flags(struct batadv_priv *bat_priv, u16 flags,
3757 bool enable, bool count)
Antonio Quartulli058d0e22011-07-07 01:40:58 +02003758{
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003759 struct batadv_hashtable *hash = bat_priv->tt.local_hash;
3760 struct batadv_tt_common_entry *tt_common_entry;
Antonio Quartulli058d0e22011-07-07 01:40:58 +02003761 struct hlist_head *head;
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02003762 u32 i;
Antonio Quartulli058d0e22011-07-07 01:40:58 +02003763
3764 if (!hash)
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003765 return;
Antonio Quartulli058d0e22011-07-07 01:40:58 +02003766
3767 for (i = 0; i < hash->size; i++) {
3768 head = &hash->table[i];
3769
3770 rcu_read_lock();
Sasha Levinb67bfe02013-02-27 17:06:00 -08003771 hlist_for_each_entry_rcu(tt_common_entry,
Antonio Quartulli058d0e22011-07-07 01:40:58 +02003772 head, hash_entry) {
Antonio Quartulli697f2532011-11-07 16:47:01 +01003773 if (enable) {
3774 if ((tt_common_entry->flags & flags) == flags)
3775 continue;
3776 tt_common_entry->flags |= flags;
3777 } else {
3778 if (!(tt_common_entry->flags & flags))
3779 continue;
3780 tt_common_entry->flags &= ~flags;
3781 }
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003782
3783 if (!count)
3784 continue;
3785
3786 batadv_tt_local_size_inc(bat_priv,
3787 tt_common_entry->vid);
Antonio Quartulli058d0e22011-07-07 01:40:58 +02003788 }
3789 rcu_read_unlock();
3790 }
Antonio Quartulli058d0e22011-07-07 01:40:58 +02003791}
3792
Sven Eckelmannacd34af2012-06-03 22:19:21 +02003793/* Purge out all the tt local entries marked with BATADV_TT_CLIENT_PENDING */
Sven Eckelmann56303d32012-06-05 22:31:31 +02003794static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv)
Antonio Quartulli058d0e22011-07-07 01:40:58 +02003795{
Sven Eckelmann807736f2012-07-15 22:26:51 +02003796 struct batadv_hashtable *hash = bat_priv->tt.local_hash;
Sven Eckelmann56303d32012-06-05 22:31:31 +02003797 struct batadv_tt_common_entry *tt_common;
3798 struct batadv_tt_local_entry *tt_local;
Sasha Levinb67bfe02013-02-27 17:06:00 -08003799 struct hlist_node *node_tmp;
Antonio Quartulli058d0e22011-07-07 01:40:58 +02003800 struct hlist_head *head;
3801 spinlock_t *list_lock; /* protects write access to the hash lists */
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02003802 u32 i;
Antonio Quartulli058d0e22011-07-07 01:40:58 +02003803
3804 if (!hash)
3805 return;
3806
3807 for (i = 0; i < hash->size; i++) {
3808 head = &hash->table[i];
3809 list_lock = &hash->list_locks[i];
3810
3811 spin_lock_bh(list_lock);
Sasha Levinb67bfe02013-02-27 17:06:00 -08003812 hlist_for_each_entry_safe(tt_common, node_tmp, head,
Sven Eckelmannacd34af2012-06-03 22:19:21 +02003813 hash_entry) {
3814 if (!(tt_common->flags & BATADV_TT_CLIENT_PENDING))
Antonio Quartulli058d0e22011-07-07 01:40:58 +02003815 continue;
3816
Sven Eckelmann39c75a52012-06-03 22:19:22 +02003817 batadv_dbg(BATADV_DBG_TT, bat_priv,
Antonio Quartulli16052782013-06-04 12:11:41 +02003818 "Deleting local tt entry (%pM, vid: %d): pending\n",
3819 tt_common->addr,
Sven Eckelmannf7a2bd62017-02-22 17:16:42 +01003820 batadv_print_vid(tt_common->vid));
Antonio Quartulli058d0e22011-07-07 01:40:58 +02003821
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003822 batadv_tt_local_size_dec(bat_priv, tt_common->vid);
Sasha Levinb67bfe02013-02-27 17:06:00 -08003823 hlist_del_rcu(&tt_common->hash_entry);
Sven Eckelmann56303d32012-06-05 22:31:31 +02003824 tt_local = container_of(tt_common,
3825 struct batadv_tt_local_entry,
3826 common);
Antonio Quartulli35df3b22014-05-08 17:13:15 +02003827
Sven Eckelmann95c0db92016-01-17 11:01:25 +01003828 batadv_tt_local_entry_put(tt_local);
Antonio Quartulli058d0e22011-07-07 01:40:58 +02003829 }
3830 spin_unlock_bh(list_lock);
3831 }
Antonio Quartulli058d0e22011-07-07 01:40:58 +02003832}
3833
Marek Lindnere1bf0c12013-04-23 21:40:01 +08003834/**
Marek Lindnera19d3d82013-05-27 15:33:25 +08003835 * batadv_tt_local_commit_changes_nolock - commit all pending local tt changes
3836 * which have been queued in the time since the last commit
Marek Lindnere1bf0c12013-04-23 21:40:01 +08003837 * @bat_priv: the bat priv with all the soft interface information
Marek Lindnera19d3d82013-05-27 15:33:25 +08003838 *
3839 * Caller must hold tt->commit_lock.
Marek Lindnere1bf0c12013-04-23 21:40:01 +08003840 */
Marek Lindnera19d3d82013-05-27 15:33:25 +08003841static void batadv_tt_local_commit_changes_nolock(struct batadv_priv *bat_priv)
Antonio Quartulli058d0e22011-07-07 01:40:58 +02003842{
Sven Eckelmann5274cd62015-06-21 14:45:15 +02003843 lockdep_assert_held(&bat_priv->tt.commit_lock);
3844
Marek Lindnere1bf0c12013-04-23 21:40:01 +08003845 if (atomic_read(&bat_priv->tt.local_changes) < 1) {
3846 if (!batadv_atomic_dec_not_zero(&bat_priv->tt.ogm_append_cnt))
3847 batadv_tt_tvlv_container_update(bat_priv);
Marek Lindnera19d3d82013-05-27 15:33:25 +08003848 return;
Marek Lindnere1bf0c12013-04-23 21:40:01 +08003849 }
Marek Lindnerbe9aa4c2012-05-07 04:22:05 +08003850
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003851 batadv_tt_local_set_flags(bat_priv, BATADV_TT_CLIENT_NEW, false, true);
Marek Lindnerbe9aa4c2012-05-07 04:22:05 +08003852
Sven Eckelmanna5130882012-05-16 20:23:16 +02003853 batadv_tt_local_purge_pending_clients(bat_priv);
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003854 batadv_tt_local_update_crc(bat_priv);
Antonio Quartulli058d0e22011-07-07 01:40:58 +02003855
3856 /* Increment the TTVN only once per OGM interval */
Sven Eckelmann807736f2012-07-15 22:26:51 +02003857 atomic_inc(&bat_priv->tt.vn);
Sven Eckelmann39c75a52012-06-03 22:19:22 +02003858 batadv_dbg(BATADV_DBG_TT, bat_priv,
Sven Eckelmann1eda58b2012-05-12 13:48:58 +02003859 "Local changes committed, updating to ttvn %u\n",
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02003860 (u8)atomic_read(&bat_priv->tt.vn));
Marek Lindnerbe9aa4c2012-05-07 04:22:05 +08003861
3862 /* reset the sending counter */
Sven Eckelmann807736f2012-07-15 22:26:51 +02003863 atomic_set(&bat_priv->tt.ogm_append_cnt, BATADV_TT_OGM_APPEND_MAX);
Marek Lindnere1bf0c12013-04-23 21:40:01 +08003864 batadv_tt_tvlv_container_update(bat_priv);
Marek Lindnera19d3d82013-05-27 15:33:25 +08003865}
Antonio Quartullia70a9aa2013-07-30 22:16:24 +02003866
Marek Lindnera19d3d82013-05-27 15:33:25 +08003867/**
3868 * batadv_tt_local_commit_changes - commit all pending local tt changes which
3869 * have been queued in the time since the last commit
3870 * @bat_priv: the bat priv with all the soft interface information
3871 */
3872void batadv_tt_local_commit_changes(struct batadv_priv *bat_priv)
3873{
3874 spin_lock_bh(&bat_priv->tt.commit_lock);
3875 batadv_tt_local_commit_changes_nolock(bat_priv);
Antonio Quartullia70a9aa2013-07-30 22:16:24 +02003876 spin_unlock_bh(&bat_priv->tt.commit_lock);
Antonio Quartulli058d0e22011-07-07 01:40:58 +02003877}
Antonio Quartulli59b699c2011-07-07 15:35:36 +02003878
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02003879bool batadv_is_ap_isolated(struct batadv_priv *bat_priv, u8 *src, u8 *dst,
3880 unsigned short vid)
Antonio Quartulli59b699c2011-07-07 15:35:36 +02003881{
Markus Elfring393b2992016-03-11 13:10:20 +01003882 struct batadv_tt_local_entry *tt_local_entry;
3883 struct batadv_tt_global_entry *tt_global_entry;
Antonio Quartullib8cbd812013-07-02 11:04:36 +02003884 struct batadv_softif_vlan *vlan;
Marek Lindner5870adc2012-06-20 17:16:05 +02003885 bool ret = false;
Antonio Quartulli59b699c2011-07-07 15:35:36 +02003886
Antonio Quartullib8cbd812013-07-02 11:04:36 +02003887 vlan = batadv_softif_vlan_get(bat_priv, vid);
Markus Elfringe087f342015-11-03 19:20:34 +01003888 if (!vlan)
3889 return false;
3890
3891 if (!atomic_read(&vlan->ap_isolation))
Markus Elfring393b2992016-03-11 13:10:20 +01003892 goto vlan_put;
Antonio Quartulli59b699c2011-07-07 15:35:36 +02003893
Antonio Quartullib8cbd812013-07-02 11:04:36 +02003894 tt_local_entry = batadv_tt_local_hash_find(bat_priv, dst, vid);
Antonio Quartulli59b699c2011-07-07 15:35:36 +02003895 if (!tt_local_entry)
Markus Elfring393b2992016-03-11 13:10:20 +01003896 goto vlan_put;
Antonio Quartulli59b699c2011-07-07 15:35:36 +02003897
Antonio Quartullib8cbd812013-07-02 11:04:36 +02003898 tt_global_entry = batadv_tt_global_hash_find(bat_priv, src, vid);
Antonio Quartulli59b699c2011-07-07 15:35:36 +02003899 if (!tt_global_entry)
Markus Elfring393b2992016-03-11 13:10:20 +01003900 goto local_entry_put;
Antonio Quartulli59b699c2011-07-07 15:35:36 +02003901
Markus Elfring393b2992016-03-11 13:10:20 +01003902 if (_batadv_is_ap_isolated(tt_local_entry, tt_global_entry))
3903 ret = true;
Antonio Quartulli59b699c2011-07-07 15:35:36 +02003904
Markus Elfring393b2992016-03-11 13:10:20 +01003905 batadv_tt_global_entry_put(tt_global_entry);
3906local_entry_put:
3907 batadv_tt_local_entry_put(tt_local_entry);
3908vlan_put:
Sven Eckelmann9c3bf082016-01-17 11:01:21 +01003909 batadv_softif_vlan_put(vlan);
Antonio Quartulli59b699c2011-07-07 15:35:36 +02003910 return ret;
3911}
Marek Lindnera943cac2011-07-30 13:10:18 +02003912
Marek Lindnere1bf0c12013-04-23 21:40:01 +08003913/**
3914 * batadv_tt_update_orig - update global translation table with new tt
3915 * information received via ogms
3916 * @bat_priv: the bat priv with all the soft interface information
Sven Eckelmanne51f0392015-09-06 21:38:51 +02003917 * @orig_node: the orig_node of the ogm
3918 * @tt_buff: pointer to the first tvlv VLAN entry
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003919 * @tt_num_vlan: number of tvlv VLAN entries
3920 * @tt_change: pointer to the first entry in the TT buffer
Marek Lindnere1bf0c12013-04-23 21:40:01 +08003921 * @tt_num_changes: number of tt changes inside the tt buffer
3922 * @ttvn: translation table version number of this changeset
Marek Lindnere1bf0c12013-04-23 21:40:01 +08003923 */
3924static void batadv_tt_update_orig(struct batadv_priv *bat_priv,
3925 struct batadv_orig_node *orig_node,
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02003926 const void *tt_buff, u16 tt_num_vlan,
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003927 struct batadv_tvlv_tt_change *tt_change,
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02003928 u16 tt_num_changes, u8 ttvn)
Marek Lindnera943cac2011-07-30 13:10:18 +02003929{
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02003930 u8 orig_ttvn = (u8)atomic_read(&orig_node->last_ttvn);
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003931 struct batadv_tvlv_tt_vlan_data *tt_vlan;
Marek Lindnera943cac2011-07-30 13:10:18 +02003932 bool full_table = true;
Linus Lüssinge17931d2014-02-15 17:47:50 +01003933 bool has_tt_init;
Marek Lindnera943cac2011-07-30 13:10:18 +02003934
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003935 tt_vlan = (struct batadv_tvlv_tt_vlan_data *)tt_buff;
Linus Lüssingac4eebd2015-06-16 17:10:24 +02003936 has_tt_init = test_bit(BATADV_ORIG_CAPA_HAS_TT,
3937 &orig_node->capa_initialized);
Linus Lüssinge17931d2014-02-15 17:47:50 +01003938
Antonio Quartulli17071572011-11-07 16:36:40 +01003939 /* orig table not initialised AND first diff is in the OGM OR the ttvn
Sven Eckelmann9cfc7bd2012-05-12 02:09:43 +02003940 * increased by one -> we can apply the attached changes
3941 */
Linus Lüssinge17931d2014-02-15 17:47:50 +01003942 if ((!has_tt_init && ttvn == 1) || ttvn - orig_ttvn == 1) {
Marek Lindnera943cac2011-07-30 13:10:18 +02003943 /* the OGM could not contain the changes due to their size or
Sven Eckelmann42d0b042012-06-03 22:19:17 +02003944 * because they have already been sent BATADV_TT_OGM_APPEND_MAX
3945 * times.
Sven Eckelmann9cfc7bd2012-05-12 02:09:43 +02003946 * In this case send a tt request
3947 */
Marek Lindnera943cac2011-07-30 13:10:18 +02003948 if (!tt_num_changes) {
3949 full_table = false;
3950 goto request_table;
3951 }
3952
Antonio Quartullia70a9aa2013-07-30 22:16:24 +02003953 spin_lock_bh(&orig_node->tt_lock);
3954
Sven Eckelmanna5130882012-05-16 20:23:16 +02003955 batadv_tt_update_changes(bat_priv, orig_node, tt_num_changes,
Sven Eckelmann96412692012-06-05 22:31:30 +02003956 ttvn, tt_change);
Marek Lindnera943cac2011-07-30 13:10:18 +02003957
3958 /* Even if we received the precomputed crc with the OGM, we
3959 * prefer to recompute it to spot any possible inconsistency
Sven Eckelmann9cfc7bd2012-05-12 02:09:43 +02003960 * in the global table
3961 */
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003962 batadv_tt_global_update_crc(bat_priv, orig_node);
Marek Lindnera943cac2011-07-30 13:10:18 +02003963
Antonio Quartullia70a9aa2013-07-30 22:16:24 +02003964 spin_unlock_bh(&orig_node->tt_lock);
3965
Marek Lindnera943cac2011-07-30 13:10:18 +02003966 /* The ttvn alone is not enough to guarantee consistency
3967 * because a single value could represent different states
3968 * (due to the wrap around). Thus a node has to check whether
3969 * the resulting table (after applying the changes) is still
3970 * consistent or not. E.g. a node could disconnect while its
3971 * ttvn is X and reconnect on ttvn = X + TTVN_MAX: in this case
3972 * checking the CRC value is mandatory to detect the
Sven Eckelmann9cfc7bd2012-05-12 02:09:43 +02003973 * inconsistency
3974 */
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003975 if (!batadv_tt_global_check_crc(orig_node, tt_vlan,
3976 tt_num_vlan))
Marek Lindnera943cac2011-07-30 13:10:18 +02003977 goto request_table;
Marek Lindnera943cac2011-07-30 13:10:18 +02003978 } else {
3979 /* if we missed more than one change or our tables are not
Sven Eckelmann9cfc7bd2012-05-12 02:09:43 +02003980 * in sync anymore -> request fresh tt data
3981 */
Linus Lüssinge17931d2014-02-15 17:47:50 +01003982 if (!has_tt_init || ttvn != orig_ttvn ||
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003983 !batadv_tt_global_check_crc(orig_node, tt_vlan,
3984 tt_num_vlan)) {
Marek Lindnera943cac2011-07-30 13:10:18 +02003985request_table:
Sven Eckelmann39c75a52012-06-03 22:19:22 +02003986 batadv_dbg(BATADV_DBG_TT, bat_priv,
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003987 "TT inconsistency for %pM. Need to retrieve the correct information (ttvn: %u last_ttvn: %u num_changes: %u)\n",
3988 orig_node->orig, ttvn, orig_ttvn,
3989 tt_num_changes);
Sven Eckelmanna5130882012-05-16 20:23:16 +02003990 batadv_send_tt_request(bat_priv, orig_node, ttvn,
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02003991 tt_vlan, tt_num_vlan,
3992 full_table);
Marek Lindnera943cac2011-07-30 13:10:18 +02003993 return;
3994 }
3995 }
3996}
Antonio Quartulli3275e7c2012-03-16 18:03:28 +01003997
Antonio Quartullic018ad32013-06-04 12:11:39 +02003998/**
3999 * batadv_tt_global_client_is_roaming - check if a client is marked as roaming
4000 * @bat_priv: the bat priv with all the soft interface information
4001 * @addr: the mac address of the client to check
4002 * @vid: VLAN identifier
4003 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +02004004 * Return: true if we know that the client has moved from its old originator
Antonio Quartullic018ad32013-06-04 12:11:39 +02004005 * to another one. This entry is still kept for consistency purposes and will be
4006 * deleted later by a DEL or because of timeout
Antonio Quartulli3275e7c2012-03-16 18:03:28 +01004007 */
Sven Eckelmann56303d32012-06-05 22:31:31 +02004008bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv,
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02004009 u8 *addr, unsigned short vid)
Antonio Quartulli3275e7c2012-03-16 18:03:28 +01004010{
Sven Eckelmann56303d32012-06-05 22:31:31 +02004011 struct batadv_tt_global_entry *tt_global_entry;
Antonio Quartulli3275e7c2012-03-16 18:03:28 +01004012 bool ret = false;
4013
Antonio Quartullic018ad32013-06-04 12:11:39 +02004014 tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr, vid);
Antonio Quartulli3275e7c2012-03-16 18:03:28 +01004015 if (!tt_global_entry)
4016 goto out;
4017
Antonio Quartullic1d07432013-01-15 22:17:19 +10004018 ret = tt_global_entry->common.flags & BATADV_TT_CLIENT_ROAM;
Sven Eckelmann5dafd8a2016-01-17 11:01:26 +01004019 batadv_tt_global_entry_put(tt_global_entry);
Antonio Quartulli3275e7c2012-03-16 18:03:28 +01004020out:
4021 return ret;
4022}
Antonio Quartulli30cfd022012-07-05 23:38:29 +02004023
Antonio Quartulli7c1fd912012-09-23 22:38:34 +02004024/**
4025 * batadv_tt_local_client_is_roaming - tells whether the client is roaming
4026 * @bat_priv: the bat priv with all the soft interface information
Antonio Quartullic018ad32013-06-04 12:11:39 +02004027 * @addr: the mac address of the local client to query
4028 * @vid: VLAN identifier
Antonio Quartulli7c1fd912012-09-23 22:38:34 +02004029 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +02004030 * Return: true if the local client is known to be roaming (it is not served by
Antonio Quartulli7c1fd912012-09-23 22:38:34 +02004031 * this node anymore) or not. If yes, the client is still present in the table
4032 * to keep the latter consistent with the node TTVN
4033 */
4034bool batadv_tt_local_client_is_roaming(struct batadv_priv *bat_priv,
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02004035 u8 *addr, unsigned short vid)
Antonio Quartulli7c1fd912012-09-23 22:38:34 +02004036{
4037 struct batadv_tt_local_entry *tt_local_entry;
4038 bool ret = false;
4039
Antonio Quartullic018ad32013-06-04 12:11:39 +02004040 tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr, vid);
Antonio Quartulli7c1fd912012-09-23 22:38:34 +02004041 if (!tt_local_entry)
4042 goto out;
4043
4044 ret = tt_local_entry->common.flags & BATADV_TT_CLIENT_ROAM;
Sven Eckelmann95c0db92016-01-17 11:01:25 +01004045 batadv_tt_local_entry_put(tt_local_entry);
Antonio Quartulli7c1fd912012-09-23 22:38:34 +02004046out:
4047 return ret;
Antonio Quartulli7c1fd912012-09-23 22:38:34 +02004048}
4049
Antonio Quartulli30cfd022012-07-05 23:38:29 +02004050bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv,
4051 struct batadv_orig_node *orig_node,
Antonio Quartullic018ad32013-06-04 12:11:39 +02004052 const unsigned char *addr,
Antonio Quartulli16052782013-06-04 12:11:41 +02004053 unsigned short vid)
Antonio Quartulli30cfd022012-07-05 23:38:29 +02004054{
Simon Wunderlich1227c9a2017-06-01 17:11:24 +02004055 /* ignore loop detect macs, they are not supposed to be in the tt local
4056 * data as well.
4057 */
4058 if (batadv_bla_is_loopdetect_mac(addr))
4059 return false;
4060
Antonio Quartulli16052782013-06-04 12:11:41 +02004061 if (!batadv_tt_global_add(bat_priv, orig_node, addr, vid,
Antonio Quartulli30cfd022012-07-05 23:38:29 +02004062 BATADV_TT_CLIENT_TEMP,
4063 atomic_read(&orig_node->last_ttvn)))
Simon Wunderlich75ae84a2017-06-01 17:11:26 +02004064 return false;
Antonio Quartulli30cfd022012-07-05 23:38:29 +02004065
4066 batadv_dbg(BATADV_DBG_TT, bat_priv,
Antonio Quartulli16052782013-06-04 12:11:41 +02004067 "Added temporary global client (addr: %pM, vid: %d, orig: %pM)\n",
Sven Eckelmannf7a2bd62017-02-22 17:16:42 +01004068 addr, batadv_print_vid(vid), orig_node->orig);
Simon Wunderlich75ae84a2017-06-01 17:11:26 +02004069
4070 return true;
Antonio Quartulli30cfd022012-07-05 23:38:29 +02004071}
Marek Lindnere1bf0c12013-04-23 21:40:01 +08004072
4073/**
Marek Lindnera19d3d82013-05-27 15:33:25 +08004074 * batadv_tt_local_resize_to_mtu - resize the local translation table fit the
4075 * maximum packet size that can be transported through the mesh
4076 * @soft_iface: netdev struct of the mesh interface
4077 *
4078 * Remove entries older than 'timeout' and half timeout if more entries need
4079 * to be removed.
4080 */
4081void batadv_tt_local_resize_to_mtu(struct net_device *soft_iface)
4082{
4083 struct batadv_priv *bat_priv = netdev_priv(soft_iface);
4084 int packet_size_max = atomic_read(&bat_priv->packet_size_max);
4085 int table_size, timeout = BATADV_TT_LOCAL_TIMEOUT / 2;
4086 bool reduced = false;
4087
4088 spin_lock_bh(&bat_priv->tt.commit_lock);
4089
4090 while (true) {
4091 table_size = batadv_tt_local_table_transmit_size(bat_priv);
4092 if (packet_size_max >= table_size)
4093 break;
4094
4095 batadv_tt_local_purge(bat_priv, timeout);
4096 batadv_tt_local_purge_pending_clients(bat_priv);
4097
4098 timeout /= 2;
4099 reduced = true;
4100 net_ratelimited_function(batadv_info, soft_iface,
4101 "Forced to purge local tt entries to fit new maximum fragment MTU (%i)\n",
4102 packet_size_max);
4103 }
4104
4105 /* commit these changes immediately, to avoid synchronization problem
4106 * with the TTVN
4107 */
4108 if (reduced)
4109 batadv_tt_local_commit_changes_nolock(bat_priv);
4110
4111 spin_unlock_bh(&bat_priv->tt.commit_lock);
4112}
4113
4114/**
Marek Lindnere1bf0c12013-04-23 21:40:01 +08004115 * batadv_tt_tvlv_ogm_handler_v1 - process incoming tt tvlv container
4116 * @bat_priv: the bat priv with all the soft interface information
4117 * @orig: the orig_node of the ogm
4118 * @flags: flags indicating the tvlv state (see batadv_tvlv_handler_flags)
4119 * @tvlv_value: tvlv buffer containing the gateway data
4120 * @tvlv_value_len: tvlv buffer length
4121 */
4122static void batadv_tt_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv,
4123 struct batadv_orig_node *orig,
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02004124 u8 flags, void *tvlv_value,
4125 u16 tvlv_value_len)
Marek Lindnere1bf0c12013-04-23 21:40:01 +08004126{
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02004127 struct batadv_tvlv_tt_vlan_data *tt_vlan;
4128 struct batadv_tvlv_tt_change *tt_change;
Marek Lindnere1bf0c12013-04-23 21:40:01 +08004129 struct batadv_tvlv_tt_data *tt_data;
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02004130 u16 num_entries, num_vlan;
Marek Lindnere1bf0c12013-04-23 21:40:01 +08004131
4132 if (tvlv_value_len < sizeof(*tt_data))
4133 return;
4134
4135 tt_data = (struct batadv_tvlv_tt_data *)tvlv_value;
4136 tvlv_value_len -= sizeof(*tt_data);
4137
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02004138 num_vlan = ntohs(tt_data->num_vlan);
4139
4140 if (tvlv_value_len < sizeof(*tt_vlan) * num_vlan)
4141 return;
4142
4143 tt_vlan = (struct batadv_tvlv_tt_vlan_data *)(tt_data + 1);
4144 tt_change = (struct batadv_tvlv_tt_change *)(tt_vlan + num_vlan);
4145 tvlv_value_len -= sizeof(*tt_vlan) * num_vlan;
4146
Antonio Quartulli298e6e62013-05-28 13:14:27 +02004147 num_entries = batadv_tt_entries(tvlv_value_len);
Marek Lindnere1bf0c12013-04-23 21:40:01 +08004148
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02004149 batadv_tt_update_orig(bat_priv, orig, tt_vlan, num_vlan, tt_change,
4150 num_entries, tt_data->ttvn);
Marek Lindnere1bf0c12013-04-23 21:40:01 +08004151}
4152
4153/**
Marek Lindner335fbe02013-04-23 21:40:02 +08004154 * batadv_tt_tvlv_unicast_handler_v1 - process incoming (unicast) tt tvlv
4155 * container
4156 * @bat_priv: the bat priv with all the soft interface information
4157 * @src: mac address of tt tvlv sender
4158 * @dst: mac address of tt tvlv recipient
4159 * @tvlv_value: tvlv buffer containing the tt data
4160 * @tvlv_value_len: tvlv buffer length
4161 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +02004162 * Return: NET_RX_DROP if the tt tvlv is to be re-routed, NET_RX_SUCCESS
Marek Lindner335fbe02013-04-23 21:40:02 +08004163 * otherwise.
4164 */
4165static int batadv_tt_tvlv_unicast_handler_v1(struct batadv_priv *bat_priv,
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02004166 u8 *src, u8 *dst,
Marek Lindner335fbe02013-04-23 21:40:02 +08004167 void *tvlv_value,
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02004168 u16 tvlv_value_len)
Marek Lindner335fbe02013-04-23 21:40:02 +08004169{
4170 struct batadv_tvlv_tt_data *tt_data;
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02004171 u16 tt_vlan_len, tt_num_entries;
Marek Lindner335fbe02013-04-23 21:40:02 +08004172 char tt_flag;
4173 bool ret;
4174
4175 if (tvlv_value_len < sizeof(*tt_data))
4176 return NET_RX_SUCCESS;
4177
4178 tt_data = (struct batadv_tvlv_tt_data *)tvlv_value;
4179 tvlv_value_len -= sizeof(*tt_data);
4180
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02004181 tt_vlan_len = sizeof(struct batadv_tvlv_tt_vlan_data);
4182 tt_vlan_len *= ntohs(tt_data->num_vlan);
4183
4184 if (tvlv_value_len < tt_vlan_len)
4185 return NET_RX_SUCCESS;
4186
4187 tvlv_value_len -= tt_vlan_len;
4188 tt_num_entries = batadv_tt_entries(tvlv_value_len);
Marek Lindner335fbe02013-04-23 21:40:02 +08004189
4190 switch (tt_data->flags & BATADV_TT_DATA_TYPE_MASK) {
4191 case BATADV_TT_REQUEST:
4192 batadv_inc_counter(bat_priv, BATADV_CNT_TT_REQUEST_RX);
4193
4194 /* If this node cannot provide a TT response the tt_request is
4195 * forwarded
4196 */
4197 ret = batadv_send_tt_response(bat_priv, tt_data, src, dst);
4198 if (!ret) {
4199 if (tt_data->flags & BATADV_TT_FULL_TABLE)
4200 tt_flag = 'F';
4201 else
4202 tt_flag = '.';
4203
4204 batadv_dbg(BATADV_DBG_TT, bat_priv,
4205 "Routing TT_REQUEST to %pM [%c]\n",
4206 dst, tt_flag);
4207 /* tvlv API will re-route the packet */
4208 return NET_RX_DROP;
4209 }
4210 break;
4211 case BATADV_TT_RESPONSE:
4212 batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_RX);
4213
4214 if (batadv_is_my_mac(bat_priv, dst)) {
4215 batadv_handle_tt_response(bat_priv, tt_data,
Antonio Quartulli7ea7b4a2013-07-30 22:16:25 +02004216 src, tt_num_entries);
Marek Lindner335fbe02013-04-23 21:40:02 +08004217 return NET_RX_SUCCESS;
4218 }
4219
4220 if (tt_data->flags & BATADV_TT_FULL_TABLE)
4221 tt_flag = 'F';
4222 else
4223 tt_flag = '.';
4224
4225 batadv_dbg(BATADV_DBG_TT, bat_priv,
4226 "Routing TT_RESPONSE to %pM [%c]\n", dst, tt_flag);
4227
4228 /* tvlv API will re-route the packet */
4229 return NET_RX_DROP;
4230 }
4231
4232 return NET_RX_SUCCESS;
4233}
4234
4235/**
Marek Lindner122edaa2013-04-23 21:40:03 +08004236 * batadv_roam_tvlv_unicast_handler_v1 - process incoming tt roam tvlv container
4237 * @bat_priv: the bat priv with all the soft interface information
4238 * @src: mac address of tt tvlv sender
4239 * @dst: mac address of tt tvlv recipient
4240 * @tvlv_value: tvlv buffer containing the tt data
4241 * @tvlv_value_len: tvlv buffer length
4242 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +02004243 * Return: NET_RX_DROP if the tt roam tvlv is to be re-routed, NET_RX_SUCCESS
Marek Lindner122edaa2013-04-23 21:40:03 +08004244 * otherwise.
4245 */
4246static int batadv_roam_tvlv_unicast_handler_v1(struct batadv_priv *bat_priv,
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02004247 u8 *src, u8 *dst,
Marek Lindner122edaa2013-04-23 21:40:03 +08004248 void *tvlv_value,
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02004249 u16 tvlv_value_len)
Marek Lindner122edaa2013-04-23 21:40:03 +08004250{
4251 struct batadv_tvlv_roam_adv *roaming_adv;
4252 struct batadv_orig_node *orig_node = NULL;
4253
4254 /* If this node is not the intended recipient of the
4255 * roaming advertisement the packet is forwarded
4256 * (the tvlv API will re-route the packet).
4257 */
4258 if (!batadv_is_my_mac(bat_priv, dst))
4259 return NET_RX_DROP;
4260
Marek Lindner122edaa2013-04-23 21:40:03 +08004261 if (tvlv_value_len < sizeof(*roaming_adv))
4262 goto out;
4263
4264 orig_node = batadv_orig_hash_find(bat_priv, src);
4265 if (!orig_node)
4266 goto out;
4267
4268 batadv_inc_counter(bat_priv, BATADV_CNT_TT_ROAM_ADV_RX);
4269 roaming_adv = (struct batadv_tvlv_roam_adv *)tvlv_value;
4270
4271 batadv_dbg(BATADV_DBG_TT, bat_priv,
4272 "Received ROAMING_ADV from %pM (client %pM)\n",
4273 src, roaming_adv->client);
4274
4275 batadv_tt_global_add(bat_priv, orig_node, roaming_adv->client,
Antonio Quartullic018ad32013-06-04 12:11:39 +02004276 ntohs(roaming_adv->vid), BATADV_TT_CLIENT_ROAM,
Marek Lindner122edaa2013-04-23 21:40:03 +08004277 atomic_read(&orig_node->last_ttvn) + 1);
4278
4279out:
4280 if (orig_node)
Sven Eckelmann5d967312016-01-17 11:01:09 +01004281 batadv_orig_node_put(orig_node);
Marek Lindner122edaa2013-04-23 21:40:03 +08004282 return NET_RX_SUCCESS;
4283}
4284
4285/**
Marek Lindnere1bf0c12013-04-23 21:40:01 +08004286 * batadv_tt_init - initialise the translation table internals
4287 * @bat_priv: the bat priv with all the soft interface information
4288 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +02004289 * Return: 0 on success or negative error number in case of failure.
Marek Lindnere1bf0c12013-04-23 21:40:01 +08004290 */
4291int batadv_tt_init(struct batadv_priv *bat_priv)
4292{
4293 int ret;
4294
Antonio Quartulli0eb015682013-10-13 02:50:20 +02004295 /* synchronized flags must be remote */
4296 BUILD_BUG_ON(!(BATADV_TT_SYNC_MASK & BATADV_TT_REMOTE_MASK));
4297
Marek Lindnere1bf0c12013-04-23 21:40:01 +08004298 ret = batadv_tt_local_init(bat_priv);
4299 if (ret < 0)
4300 return ret;
4301
4302 ret = batadv_tt_global_init(bat_priv);
4303 if (ret < 0)
4304 return ret;
4305
4306 batadv_tvlv_handler_register(bat_priv, batadv_tt_tvlv_ogm_handler_v1,
Marek Lindner335fbe02013-04-23 21:40:02 +08004307 batadv_tt_tvlv_unicast_handler_v1,
4308 BATADV_TVLV_TT, 1, BATADV_NO_FLAGS);
Marek Lindnere1bf0c12013-04-23 21:40:01 +08004309
Marek Lindner122edaa2013-04-23 21:40:03 +08004310 batadv_tvlv_handler_register(bat_priv, NULL,
4311 batadv_roam_tvlv_unicast_handler_v1,
4312 BATADV_TVLV_ROAM, 1, BATADV_NO_FLAGS);
4313
Marek Lindnere1bf0c12013-04-23 21:40:01 +08004314 INIT_DELAYED_WORK(&bat_priv->tt.work, batadv_tt_purge);
4315 queue_delayed_work(batadv_event_workqueue, &bat_priv->tt.work,
4316 msecs_to_jiffies(BATADV_TT_WORK_PERIOD));
4317
4318 return 1;
4319}
Antonio Quartulli42cb0be2013-11-16 12:03:52 +01004320
4321/**
4322 * batadv_tt_global_is_isolated - check if a client is marked as isolated
4323 * @bat_priv: the bat priv with all the soft interface information
4324 * @addr: the mac address of the client
4325 * @vid: the identifier of the VLAN where this client is connected
4326 *
Sven Eckelmann62fe7102015-09-15 19:00:48 +02004327 * Return: true if the client is marked with the TT_CLIENT_ISOLA flag, false
Antonio Quartulli42cb0be2013-11-16 12:03:52 +01004328 * otherwise
4329 */
4330bool batadv_tt_global_is_isolated(struct batadv_priv *bat_priv,
Sven Eckelmann6b5e9712015-05-26 18:34:26 +02004331 const u8 *addr, unsigned short vid)
Antonio Quartulli42cb0be2013-11-16 12:03:52 +01004332{
4333 struct batadv_tt_global_entry *tt;
4334 bool ret;
4335
4336 tt = batadv_tt_global_hash_find(bat_priv, addr, vid);
4337 if (!tt)
4338 return false;
4339
4340 ret = tt->common.flags & BATADV_TT_CLIENT_ISOLA;
4341
Sven Eckelmann5dafd8a2016-01-17 11:01:26 +01004342 batadv_tt_global_entry_put(tt);
Antonio Quartulli42cb0be2013-11-16 12:03:52 +01004343
4344 return ret;
4345}
Sven Eckelmann86452f82016-06-25 16:44:06 +02004346
4347/**
4348 * batadv_tt_cache_init - Initialize tt memory object cache
4349 *
4350 * Return: 0 on success or negative error number in case of failure.
4351 */
4352int __init batadv_tt_cache_init(void)
4353{
4354 size_t tl_size = sizeof(struct batadv_tt_local_entry);
4355 size_t tg_size = sizeof(struct batadv_tt_global_entry);
4356 size_t tt_orig_size = sizeof(struct batadv_tt_orig_list_entry);
4357 size_t tt_change_size = sizeof(struct batadv_tt_change_node);
4358 size_t tt_req_size = sizeof(struct batadv_tt_req_node);
4359 size_t tt_roam_size = sizeof(struct batadv_tt_roam_node);
4360
4361 batadv_tl_cache = kmem_cache_create("batadv_tl_cache", tl_size, 0,
4362 SLAB_HWCACHE_ALIGN, NULL);
4363 if (!batadv_tl_cache)
4364 return -ENOMEM;
4365
4366 batadv_tg_cache = kmem_cache_create("batadv_tg_cache", tg_size, 0,
4367 SLAB_HWCACHE_ALIGN, NULL);
4368 if (!batadv_tg_cache)
4369 goto err_tt_tl_destroy;
4370
4371 batadv_tt_orig_cache = kmem_cache_create("batadv_tt_orig_cache",
4372 tt_orig_size, 0,
4373 SLAB_HWCACHE_ALIGN, NULL);
4374 if (!batadv_tt_orig_cache)
4375 goto err_tt_tg_destroy;
4376
4377 batadv_tt_change_cache = kmem_cache_create("batadv_tt_change_cache",
4378 tt_change_size, 0,
4379 SLAB_HWCACHE_ALIGN, NULL);
4380 if (!batadv_tt_change_cache)
4381 goto err_tt_orig_destroy;
4382
4383 batadv_tt_req_cache = kmem_cache_create("batadv_tt_req_cache",
4384 tt_req_size, 0,
4385 SLAB_HWCACHE_ALIGN, NULL);
4386 if (!batadv_tt_req_cache)
4387 goto err_tt_change_destroy;
4388
4389 batadv_tt_roam_cache = kmem_cache_create("batadv_tt_roam_cache",
4390 tt_roam_size, 0,
4391 SLAB_HWCACHE_ALIGN, NULL);
4392 if (!batadv_tt_roam_cache)
4393 goto err_tt_req_destroy;
4394
4395 return 0;
4396
4397err_tt_req_destroy:
4398 kmem_cache_destroy(batadv_tt_req_cache);
4399 batadv_tt_req_cache = NULL;
4400err_tt_change_destroy:
4401 kmem_cache_destroy(batadv_tt_change_cache);
4402 batadv_tt_change_cache = NULL;
4403err_tt_orig_destroy:
4404 kmem_cache_destroy(batadv_tt_orig_cache);
4405 batadv_tt_orig_cache = NULL;
4406err_tt_tg_destroy:
4407 kmem_cache_destroy(batadv_tg_cache);
4408 batadv_tg_cache = NULL;
4409err_tt_tl_destroy:
4410 kmem_cache_destroy(batadv_tl_cache);
4411 batadv_tl_cache = NULL;
4412
4413 return -ENOMEM;
4414}
4415
4416/**
4417 * batadv_tt_cache_destroy - Destroy tt memory object cache
4418 */
4419void batadv_tt_cache_destroy(void)
4420{
4421 kmem_cache_destroy(batadv_tl_cache);
4422 kmem_cache_destroy(batadv_tg_cache);
4423 kmem_cache_destroy(batadv_tt_orig_cache);
4424 kmem_cache_destroy(batadv_tt_change_cache);
4425 kmem_cache_destroy(batadv_tt_req_cache);
4426 kmem_cache_destroy(batadv_tt_roam_cache);
4427}