translation-table.c 74.4 KB
Newer Older
1
/* Copyright (C) 2007-2012 B.A.T.M.A.N. contributors:
2
 *
3
 * Marek Lindner, Simon Wunderlich, Antonio Quartulli
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of version 2 of the GNU General Public
 * License as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA
 */

#include "main.h"
#include "translation-table.h"
#include "soft-interface.h"
23
#include "hard-interface.h"
24
#include "send.h"
25 26
#include "hash.h"
#include "originator.h"
27
#include "routing.h"
28
#include "bridge_loop_avoidance.h"
29

30 31
#include <linux/crc16.h>

32 33 34 35
/* hash class keys */
static struct lock_class_key batadv_tt_local_hash_lock_class_key;
static struct lock_class_key batadv_tt_global_hash_lock_class_key;

36 37
static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client,
				 struct batadv_orig_node *orig_node);
38 39
static void batadv_tt_purge(struct work_struct *work);
static void
40
batadv_tt_global_del_orig_list(struct batadv_tt_global_entry *tt_global_entry);
41 42 43 44
static void batadv_tt_global_del(struct batadv_priv *bat_priv,
				 struct batadv_orig_node *orig_node,
				 const unsigned char *addr,
				 const char *message, bool roaming);
45

46
/* returns 1 if they are the same mac addr */
47
static int batadv_compare_tt(const struct hlist_node *node, const void *data2)
48
{
49
	const void *data1 = container_of(node, struct batadv_tt_common_entry,
50
					 hash_entry);
51 52 53 54

	return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
}

55
static void batadv_tt_start_timer(struct batadv_priv *bat_priv)
56
{
57 58
	INIT_DELAYED_WORK(&bat_priv->tt.work, batadv_tt_purge);
	queue_delayed_work(batadv_event_workqueue, &bat_priv->tt.work,
59
			   msecs_to_jiffies(5000));
60 61
}

62
static struct batadv_tt_common_entry *
63
batadv_tt_hash_find(struct batadv_hashtable *hash, const void *data)
64 65 66
{
	struct hlist_head *head;
	struct hlist_node *node;
67 68
	struct batadv_tt_common_entry *tt_common_entry;
	struct batadv_tt_common_entry *tt_common_entry_tmp = NULL;
69
	uint32_t index;
70 71 72 73

	if (!hash)
		return NULL;

74
	index = batadv_choose_orig(data, hash->size);
75 76 77
	head = &hash->table[index];

	rcu_read_lock();
78
	hlist_for_each_entry_rcu(tt_common_entry, node, head, hash_entry) {
79
		if (!batadv_compare_eth(tt_common_entry, data))
80 81
			continue;

82
		if (!atomic_inc_not_zero(&tt_common_entry->refcount))
83 84
			continue;

85
		tt_common_entry_tmp = tt_common_entry;
86 87 88 89
		break;
	}
	rcu_read_unlock();

90
	return tt_common_entry_tmp;
91 92
}

93 94
static struct batadv_tt_local_entry *
batadv_tt_local_hash_find(struct batadv_priv *bat_priv, const void *data)
95
{
96 97
	struct batadv_tt_common_entry *tt_common_entry;
	struct batadv_tt_local_entry *tt_local_entry = NULL;
98

99
	tt_common_entry = batadv_tt_hash_find(bat_priv->tt.local_hash, data);
100 101
	if (tt_common_entry)
		tt_local_entry = container_of(tt_common_entry,
102 103
					      struct batadv_tt_local_entry,
					      common);
104 105
	return tt_local_entry;
}
106

107 108
static struct batadv_tt_global_entry *
batadv_tt_global_hash_find(struct batadv_priv *bat_priv, const void *data)
109
{
110 111
	struct batadv_tt_common_entry *tt_common_entry;
	struct batadv_tt_global_entry *tt_global_entry = NULL;
112

113
	tt_common_entry = batadv_tt_hash_find(bat_priv->tt.global_hash, data);
114 115
	if (tt_common_entry)
		tt_global_entry = container_of(tt_common_entry,
116 117
					       struct batadv_tt_global_entry,
					       common);
118
	return tt_global_entry;
119 120
}

121
static void
122
batadv_tt_local_entry_free_ref(struct batadv_tt_local_entry *tt_local_entry)
123
{
124 125
	if (atomic_dec_and_test(&tt_local_entry->common.refcount))
		kfree_rcu(tt_local_entry, common.rcu);
126 127
}

128
static void batadv_tt_global_entry_free_rcu(struct rcu_head *rcu)
129
{
130 131
	struct batadv_tt_common_entry *tt_common_entry;
	struct batadv_tt_global_entry *tt_global_entry;
132

133 134 135
	tt_common_entry = container_of(rcu, struct batadv_tt_common_entry, rcu);
	tt_global_entry = container_of(tt_common_entry,
				       struct batadv_tt_global_entry, common);
136 137 138 139

	kfree(tt_global_entry);
}

140
static void
141
batadv_tt_global_entry_free_ref(struct batadv_tt_global_entry *tt_global_entry)
142
{
143
	if (atomic_dec_and_test(&tt_global_entry->common.refcount)) {
144
		batadv_tt_global_del_orig_list(tt_global_entry);
145
		call_rcu(&tt_global_entry->common.rcu,
146
			 batadv_tt_global_entry_free_rcu);
147 148 149
	}
}

150
static void batadv_tt_orig_list_entry_free_rcu(struct rcu_head *rcu)
151
{
152
	struct batadv_tt_orig_list_entry *orig_entry;
153

154
	orig_entry = container_of(rcu, struct batadv_tt_orig_list_entry, rcu);
155
	batadv_orig_node_free_ref(orig_entry->orig_node);
156 157 158
	kfree(orig_entry);
}

159
static void
160
batadv_tt_orig_list_entry_free_ref(struct batadv_tt_orig_list_entry *orig_entry)
161
{
162 163
	if (!atomic_dec_and_test(&orig_entry->refcount))
		return;
164 165
	/* to avoid race conditions, immediately decrease the tt counter */
	atomic_dec(&orig_entry->orig_node->tt_size);
166
	call_rcu(&orig_entry->rcu, batadv_tt_orig_list_entry_free_rcu);
167 168
}

169
static void batadv_tt_local_event(struct batadv_priv *bat_priv,
170
				  const uint8_t *addr, uint8_t flags)
171
{
172
	struct batadv_tt_change_node *tt_change_node, *entry, *safe;
173 174
	bool event_removed = false;
	bool del_op_requested, del_op_entry;
175 176 177 178 179 180

	tt_change_node = kmalloc(sizeof(*tt_change_node), GFP_ATOMIC);

	if (!tt_change_node)
		return;

181
	tt_change_node->change.flags = flags;
182 183
	memcpy(tt_change_node->change.addr, addr, ETH_ALEN);

184
	del_op_requested = flags & BATADV_TT_CLIENT_DEL;
185 186

	/* check for ADD+DEL or DEL+ADD events */
187 188
	spin_lock_bh(&bat_priv->tt.changes_list_lock);
	list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list,
189 190 191 192 193 194 195 196 197 198 199
				 list) {
		if (!batadv_compare_eth(entry->change.addr, addr))
			continue;

		/* DEL+ADD in the same orig interval have no effect and can be
		 * removed to avoid silly behaviour on the receiver side. The
		 * other way around (ADD+DEL) can happen in case of roaming of
		 * a client still in the NEW state. Roaming of NEW clients is
		 * now possible due to automatically recognition of "temporary"
		 * clients
		 */
200
		del_op_entry = entry->change.flags & BATADV_TT_CLIENT_DEL;
201 202 203 204 205 206 207 208
		if (!del_op_requested && del_op_entry)
			goto del;
		if (del_op_requested && !del_op_entry)
			goto del;
		continue;
del:
		list_del(&entry->list);
		kfree(entry);
209
		kfree(tt_change_node);
210 211 212 213
		event_removed = true;
		goto unlock;
	}

214
	/* track the change in the OGMinterval list */
215
	list_add_tail(&tt_change_node->list, &bat_priv->tt.changes_list);
216 217

unlock:
218
	spin_unlock_bh(&bat_priv->tt.changes_list_lock);
219

220
	if (event_removed)
221
		atomic_dec(&bat_priv->tt.local_changes);
222
	else
223
		atomic_inc(&bat_priv->tt.local_changes);
224 225
}

226
int batadv_tt_len(int changes_num)
227
{
228
	return changes_num * sizeof(struct batadv_tt_change);
229 230
}

231
static int batadv_tt_local_init(struct batadv_priv *bat_priv)
232
{
233
	if (bat_priv->tt.local_hash)
234
		return 0;
235

236
	bat_priv->tt.local_hash = batadv_hash_new(1024);
237

238
	if (!bat_priv->tt.local_hash)
239
		return -ENOMEM;
240

241 242 243
	batadv_hash_set_lock_class(bat_priv->tt.local_hash,
				   &batadv_tt_local_hash_lock_class_key);

244
	return 0;
245 246
}

247 248 249 250 251 252 253 254 255 256 257 258 259
static void batadv_tt_global_free(struct batadv_priv *bat_priv,
				  struct batadv_tt_global_entry *tt_global,
				  const char *message)
{
	batadv_dbg(BATADV_DBG_TT, bat_priv,
		   "Deleting global tt entry %pM: %s\n",
		   tt_global->common.addr, message);

	batadv_hash_remove(bat_priv->tt.global_hash, batadv_compare_tt,
			   batadv_choose_orig, tt_global->common.addr);
	batadv_tt_global_entry_free_ref(tt_global);
}

260 261
void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
			 int ifindex)
262
{
263
	struct batadv_priv *bat_priv = netdev_priv(soft_iface);
264 265
	struct batadv_tt_local_entry *tt_local;
	struct batadv_tt_global_entry *tt_global;
266 267
	struct hlist_head *head;
	struct hlist_node *node;
268
	struct batadv_tt_orig_list_entry *orig_entry;
269
	int hash_added;
270
	bool roamed_back = false;
271

272
	tt_local = batadv_tt_local_hash_find(bat_priv, addr);
273
	tt_global = batadv_tt_global_hash_find(bat_priv, addr);
274

275 276
	if (tt_local) {
		tt_local->last_seen = jiffies;
277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301
		if (tt_local->common.flags & BATADV_TT_CLIENT_PENDING) {
			batadv_dbg(BATADV_DBG_TT, bat_priv,
				   "Re-adding pending client %pM\n", addr);
			/* whatever the reason why the PENDING flag was set,
			 * this is a client which was enqueued to be removed in
			 * this orig_interval. Since it popped up again, the
			 * flag can be reset like it was never enqueued
			 */
			tt_local->common.flags &= ~BATADV_TT_CLIENT_PENDING;
			goto add_event;
		}

		if (tt_local->common.flags & BATADV_TT_CLIENT_ROAM) {
			batadv_dbg(BATADV_DBG_TT, bat_priv,
				   "Roaming client %pM came back to its original location\n",
				   addr);
			/* the ROAM flag is set because this client roamed away
			 * and the node got a roaming_advertisement message. Now
			 * that the client popped up again at its original
			 * location such flag can be unset
			 */
			tt_local->common.flags &= ~BATADV_TT_CLIENT_ROAM;
			roamed_back = true;
		}
		goto check_roaming;
302 303
	}

304 305
	tt_local = kmalloc(sizeof(*tt_local), GFP_ATOMIC);
	if (!tt_local)
306
		goto out;
307

308
	batadv_dbg(BATADV_DBG_TT, bat_priv,
309
		   "Creating new local tt entry: %pM (ttvn: %d)\n", addr,
310
		   (uint8_t)atomic_read(&bat_priv->tt.vn));
311

312
	memcpy(tt_local->common.addr, addr, ETH_ALEN);
313 314 315 316 317
	/* The local entry has to be marked as NEW to avoid to send it in
	 * a full table response going out before the next ttvn increment
	 * (consistency check)
	 */
	tt_local->common.flags = BATADV_TT_CLIENT_NEW;
318
	if (batadv_is_wifi_iface(ifindex))
319 320 321 322
		tt_local->common.flags |= BATADV_TT_CLIENT_WIFI;
	atomic_set(&tt_local->common.refcount, 2);
	tt_local->last_seen = jiffies;
	tt_local->common.added_at = tt_local->last_seen;
323 324

	/* the batman interface mac address should never be purged */
325
	if (batadv_compare_eth(addr, soft_iface->dev_addr))
326
		tt_local->common.flags |= BATADV_TT_CLIENT_NOPURGE;
327

328
	hash_added = batadv_hash_add(bat_priv->tt.local_hash, batadv_compare_tt,
329 330
				     batadv_choose_orig, &tt_local->common,
				     &tt_local->common.hash_entry);
331 332 333

	if (unlikely(hash_added != 0)) {
		/* remove the reference for the hash */
334
		batadv_tt_local_entry_free_ref(tt_local);
335 336 337
		goto out;
	}

338
add_event:
339
	batadv_tt_local_event(bat_priv, addr, tt_local->common.flags);
340

341 342 343 344 345
check_roaming:
	/* Check whether it is a roaming, but don't do anything if the roaming
	 * process has already been handled
	 */
	if (tt_global && !(tt_global->common.flags & BATADV_TT_CLIENT_ROAM)) {
346
		/* These node are probably going to update their tt table */
347
		head = &tt_global->orig_list;
348 349
		rcu_read_lock();
		hlist_for_each_entry_rcu(orig_entry, node, head, list) {
350
			batadv_send_roam_adv(bat_priv, tt_global->common.addr,
351
					     orig_entry->orig_node);
352 353
		}
		rcu_read_unlock();
354 355 356 357 358 359 360 361 362 363 364
		if (roamed_back) {
			batadv_tt_global_free(bat_priv, tt_global,
					      "Roaming canceled");
			tt_global = NULL;
		} else {
			/* The global entry has to be marked as ROAMING and
			 * has to be kept for consistency purpose
			 */
			tt_global->common.flags |= BATADV_TT_CLIENT_ROAM;
			tt_global->roam_at = jiffies;
		}
365
	}
366

367
out:
368 369 370 371
	if (tt_local)
		batadv_tt_local_entry_free_ref(tt_local);
	if (tt_global)
		batadv_tt_global_entry_free_ref(tt_global);
372 373
}

374 375 376 377
static void batadv_tt_realloc_packet_buff(unsigned char **packet_buff,
					  int *packet_buff_len,
					  int min_packet_len,
					  int new_packet_len)
378 379 380 381 382 383 384 385 386 387 388 389 390 391
{
	unsigned char *new_buff;

	new_buff = kmalloc(new_packet_len, GFP_ATOMIC);

	/* keep old buffer if kmalloc should fail */
	if (new_buff) {
		memcpy(new_buff, *packet_buff, min_packet_len);
		kfree(*packet_buff);
		*packet_buff = new_buff;
		*packet_buff_len = new_packet_len;
	}
}

392
static void batadv_tt_prepare_packet_buff(struct batadv_priv *bat_priv,
393 394 395
					  unsigned char **packet_buff,
					  int *packet_buff_len,
					  int min_packet_len)
396
{
397
	struct batadv_hard_iface *primary_if;
398 399
	int req_len;

400
	primary_if = batadv_primary_if_get_selected(bat_priv);
401 402

	req_len = min_packet_len;
403
	req_len += batadv_tt_len(atomic_read(&bat_priv->tt.local_changes));
404 405 406 407 408 409 410

	/* if we have too many changes for one packet don't send any
	 * and wait for the tt table request which will be fragmented
	 */
	if ((!primary_if) || (req_len > primary_if->soft_iface->mtu))
		req_len = min_packet_len;

411 412
	batadv_tt_realloc_packet_buff(packet_buff, packet_buff_len,
				      min_packet_len, req_len);
413 414

	if (primary_if)
415
		batadv_hardif_free_ref(primary_if);
416 417
}

418
static int batadv_tt_changes_fill_buff(struct batadv_priv *bat_priv,
419 420 421
				       unsigned char **packet_buff,
				       int *packet_buff_len,
				       int min_packet_len)
422
{
423
	struct batadv_tt_change_node *entry, *safe;
424 425 426
	int count = 0, tot_changes = 0, new_len;
	unsigned char *tt_buff;

427 428
	batadv_tt_prepare_packet_buff(bat_priv, packet_buff,
				      packet_buff_len, min_packet_len);
429

430 431 432 433
	new_len = *packet_buff_len - min_packet_len;
	tt_buff = *packet_buff + min_packet_len;

	if (new_len > 0)
434
		tot_changes = new_len / batadv_tt_len(1);
435

436 437
	spin_lock_bh(&bat_priv->tt.changes_list_lock);
	atomic_set(&bat_priv->tt.local_changes, 0);
438

439
	list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list,
440
				 list) {
441
		if (count < tot_changes) {
442
			memcpy(tt_buff + batadv_tt_len(count),
443
			       &entry->change, sizeof(struct batadv_tt_change));
444 445
			count++;
		}
446 447
		list_del(&entry->list);
		kfree(entry);
448
	}
449
	spin_unlock_bh(&bat_priv->tt.changes_list_lock);
450 451

	/* Keep the buffer for possible tt_request */
452 453 454 455
	spin_lock_bh(&bat_priv->tt.last_changeset_lock);
	kfree(bat_priv->tt.last_changeset);
	bat_priv->tt.last_changeset_len = 0;
	bat_priv->tt.last_changeset = NULL;
456 457 458
	/* check whether this new OGM has no changes due to size problems */
	if (new_len > 0) {
		/* if kmalloc() fails we will reply with the full table
459 460
		 * instead of providing the diff
		 */
461 462 463 464
		bat_priv->tt.last_changeset = kmalloc(new_len, GFP_ATOMIC);
		if (bat_priv->tt.last_changeset) {
			memcpy(bat_priv->tt.last_changeset, tt_buff, new_len);
			bat_priv->tt.last_changeset_len = new_len;
465 466
		}
	}
467
	spin_unlock_bh(&bat_priv->tt.last_changeset_lock);
468

469
	return count;
470 471
}

472
int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
473 474
{
	struct net_device *net_dev = (struct net_device *)seq->private;
475
	struct batadv_priv *bat_priv = netdev_priv(net_dev);
476
	struct batadv_hashtable *hash = bat_priv->tt.local_hash;
477
	struct batadv_tt_common_entry *tt_common_entry;
478
	struct batadv_tt_local_entry *tt_local;
479
	struct batadv_hard_iface *primary_if;
480
	struct hlist_node *node;
481
	struct hlist_head *head;
482
	uint32_t i;
483 484 485 486 487
	int last_seen_secs;
	int last_seen_msecs;
	unsigned long last_seen_jiffies;
	bool no_purge;
	uint16_t np_flag = BATADV_TT_CLIENT_NOPURGE;
488

489 490
	primary_if = batadv_seq_print_text_primary_if_get(seq);
	if (!primary_if)
491
		goto out;
492

493
	seq_printf(seq,
494 495 496
		   "Locally retrieved addresses (from %s) announced via TT (TTVN: %u CRC: %#.4x):\n",
		   net_dev->name, (uint8_t)atomic_read(&bat_priv->tt.vn),
		   bat_priv->tt.local_crc);
497 498
	seq_printf(seq, "       %-13s %-7s %-10s\n", "Client", "Flags",
		   "Last seen");
499 500 501 502

	for (i = 0; i < hash->size; i++) {
		head = &hash->table[i];

503
		rcu_read_lock();
504
		hlist_for_each_entry_rcu(tt_common_entry, node,
505
					 head, hash_entry) {
506 507 508 509 510 511 512 513 514 515 516
			tt_local = container_of(tt_common_entry,
						struct batadv_tt_local_entry,
						common);
			last_seen_jiffies = jiffies - tt_local->last_seen;
			last_seen_msecs = jiffies_to_msecs(last_seen_jiffies);
			last_seen_secs = last_seen_msecs / 1000;
			last_seen_msecs = last_seen_msecs % 1000;

			no_purge = tt_common_entry->flags & np_flag;

			seq_printf(seq, " * %pM [%c%c%c%c%c] %3u.%03u\n",
517 518
				   tt_common_entry->addr,
				   (tt_common_entry->flags &
519
				    BATADV_TT_CLIENT_ROAM ? 'R' : '.'),
520
				   no_purge ? 'P' : '.',
521
				   (tt_common_entry->flags &
522
				    BATADV_TT_CLIENT_NEW ? 'N' : '.'),
523
				   (tt_common_entry->flags &
524
				    BATADV_TT_CLIENT_PENDING ? 'X' : '.'),
525
				   (tt_common_entry->flags &
526 527 528
				    BATADV_TT_CLIENT_WIFI ? 'W' : '.'),
				   no_purge ? last_seen_secs : 0,
				   no_purge ? last_seen_msecs : 0);
529
		}
530
		rcu_read_unlock();
531
	}
532 533
out:
	if (primary_if)
534
		batadv_hardif_free_ref(primary_if);
535
	return 0;
536 537
}

538 539 540 541
static void
batadv_tt_local_set_pending(struct batadv_priv *bat_priv,
			    struct batadv_tt_local_entry *tt_local_entry,
			    uint16_t flags, const char *message)
542
{
543 544
	batadv_tt_local_event(bat_priv, tt_local_entry->common.addr,
			      tt_local_entry->common.flags | flags);
545

546 547
	/* The local client has to be marked as "pending to be removed" but has
	 * to be kept in the table in order to send it in a full table
548 549
	 * response issued before the net ttvn increment (consistency check)
	 */
550
	tt_local_entry->common.flags |= BATADV_TT_CLIENT_PENDING;
551

552
	batadv_dbg(BATADV_DBG_TT, bat_priv,
553 554
		   "Local tt entry (%pM) pending to be removed: %s\n",
		   tt_local_entry->common.addr, message);
555 556
}

557 558 559 560 561 562 563 564 565 566 567 568
/**
 * batadv_tt_local_remove - logically remove an entry from the local table
 * @bat_priv: the bat priv with all the soft interface information
 * @addr: the MAC address of the client to remove
 * @message: message to append to the log on deletion
 * @roaming: true if the deletion is due to a roaming event
 *
 * Returns the flags assigned to the local entry before being deleted
 */
uint16_t batadv_tt_local_remove(struct batadv_priv *bat_priv,
				const uint8_t *addr, const char *message,
				bool roaming)
569
{
570
	struct batadv_tt_local_entry *tt_local_entry;
571
	uint16_t flags, curr_flags = BATADV_NO_FLAGS;
572

573
	tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr);
574 575 576
	if (!tt_local_entry)
		goto out;

577 578
	curr_flags = tt_local_entry->common.flags;

579
	flags = BATADV_TT_CLIENT_DEL;
580 581 582 583
	/* if this global entry addition is due to a roaming, the node has to
	 * mark the local entry as "roamed" in order to correctly reroute
	 * packets later
	 */
584
	if (roaming) {
585
		flags |= BATADV_TT_CLIENT_ROAM;
586 587 588
		/* mark the local client as ROAMed */
		tt_local_entry->common.flags |= BATADV_TT_CLIENT_ROAM;
	}
589

590 591 592 593 594 595 596 597 598 599 600 601
	if (!(tt_local_entry->common.flags & BATADV_TT_CLIENT_NEW)) {
		batadv_tt_local_set_pending(bat_priv, tt_local_entry, flags,
					    message);
		goto out;
	}
	/* if this client has been added right now, it is possible to
	 * immediately purge it
	 */
	batadv_tt_local_event(bat_priv, tt_local_entry->common.addr,
			      curr_flags | BATADV_TT_CLIENT_DEL);
	hlist_del_rcu(&tt_local_entry->common.hash_entry);
	batadv_tt_local_entry_free_ref(tt_local_entry);
602

603 604
out:
	if (tt_local_entry)
605
		batadv_tt_local_entry_free_ref(tt_local_entry);
606 607

	return curr_flags;
608 609
}

610
static void batadv_tt_local_purge_list(struct batadv_priv *bat_priv,
611
				       struct hlist_head *head)
612
{
613 614
	struct batadv_tt_local_entry *tt_local_entry;
	struct batadv_tt_common_entry *tt_common_entry;
615
	struct hlist_node *node, *node_tmp;
616 617 618 619

	hlist_for_each_entry_safe(tt_common_entry, node, node_tmp, head,
				  hash_entry) {
		tt_local_entry = container_of(tt_common_entry,
620 621
					      struct batadv_tt_local_entry,
					      common);
622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637
		if (tt_local_entry->common.flags & BATADV_TT_CLIENT_NOPURGE)
			continue;

		/* entry already marked for deletion */
		if (tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING)
			continue;

		if (!batadv_has_timed_out(tt_local_entry->last_seen,
					  BATADV_TT_LOCAL_TIMEOUT))
			continue;

		batadv_tt_local_set_pending(bat_priv, tt_local_entry,
					    BATADV_TT_CLIENT_DEL, "timed out");
	}
}

638
static void batadv_tt_local_purge(struct batadv_priv *bat_priv)
639
{
640
	struct batadv_hashtable *hash = bat_priv->tt.local_hash;
641
	struct hlist_head *head;
642
	spinlock_t *list_lock; /* protects write access to the hash lists */
643
	uint32_t i;
644 645 646

	for (i = 0; i < hash->size; i++) {
		head = &hash->table[i];
647
		list_lock = &hash->list_locks[i];
648

649
		spin_lock_bh(list_lock);
650
		batadv_tt_local_purge_list(bat_priv, head);
651
		spin_unlock_bh(list_lock);
652 653 654
	}
}

655
static void batadv_tt_local_table_free(struct batadv_priv *bat_priv)
656
{
657
	struct batadv_hashtable *hash;
658
	spinlock_t *list_lock; /* protects write access to the hash lists */
659 660
	struct batadv_tt_common_entry *tt_common_entry;
	struct batadv_tt_local_entry *tt_local;
661 662
	struct hlist_node *node, *node_tmp;
	struct hlist_head *head;
663
	uint32_t i;
664

665
	if (!bat_priv->tt.local_hash)
666 667
		return;

668
	hash = bat_priv->tt.local_hash;
669 670 671 672 673 674

	for (i = 0; i < hash->size; i++) {
		head = &hash->table[i];
		list_lock = &hash->list_locks[i];

		spin_lock_bh(list_lock);
675
		hlist_for_each_entry_safe(tt_common_entry, node, node_tmp,
676 677
					  head, hash_entry) {
			hlist_del_rcu(node);
678 679 680 681
			tt_local = container_of(tt_common_entry,
						struct batadv_tt_local_entry,
						common);
			batadv_tt_local_entry_free_ref(tt_local);
682 683 684 685
		}
		spin_unlock_bh(list_lock);
	}

686
	batadv_hash_destroy(hash);
687

688
	bat_priv->tt.local_hash = NULL;
689 690
}

691
static int batadv_tt_global_init(struct batadv_priv *bat_priv)
692
{
693
	if (bat_priv->tt.global_hash)
694
		return 0;
695

696
	bat_priv->tt.global_hash = batadv_hash_new(1024);
697

698
	if (!bat_priv->tt.global_hash)
699
		return -ENOMEM;
700

701 702 703
	batadv_hash_set_lock_class(bat_priv->tt.global_hash,
				   &batadv_tt_global_hash_lock_class_key);

704
	return 0;
705 706
}

707
static void batadv_tt_changes_list_free(struct batadv_priv *bat_priv)
708
{
709
	struct batadv_tt_change_node *entry, *safe;
710

711
	spin_lock_bh(&bat_priv->tt.changes_list_lock);
712

713
	list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list,
714 715 716 717
				 list) {
		list_del(&entry->list);
		kfree(entry);
	}
718

719 720
	atomic_set(&bat_priv->tt.local_changes, 0);
	spin_unlock_bh(&bat_priv->tt.changes_list_lock);
721
}
722

723 724 725 726
/* retrieves the orig_tt_list_entry belonging to orig_node from the
 * batadv_tt_global_entry list
 *
 * returns it with an increased refcounter, NULL if not found
727
 */
728 729 730
static struct batadv_tt_orig_list_entry *
batadv_tt_global_orig_entry_find(const struct batadv_tt_global_entry *entry,
				 const struct batadv_orig_node *orig_node)
731
{
732
	struct batadv_tt_orig_list_entry *tmp_orig_entry, *orig_entry = NULL;
733 734 735 736 737 738
	const struct hlist_head *head;
	struct hlist_node *node;

	rcu_read_lock();
	head = &entry->orig_list;
	hlist_for_each_entry_rcu(tmp_orig_entry, node, head, list) {
739 740 741 742 743 744 745
		if (tmp_orig_entry->orig_node != orig_node)
			continue;
		if (!atomic_inc_not_zero(&tmp_orig_entry->refcount))
			continue;

		orig_entry = tmp_orig_entry;
		break;
746 747
	}
	rcu_read_unlock();
748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767

	return orig_entry;
}

/* find out if an orig_node is already in the list of a tt_global_entry.
 * returns true if found, false otherwise
 */
static bool
batadv_tt_global_entry_has_orig(const struct batadv_tt_global_entry *entry,
				const struct batadv_orig_node *orig_node)
{
	struct batadv_tt_orig_list_entry *orig_entry;
	bool found = false;

	orig_entry = batadv_tt_global_orig_entry_find(entry, orig_node);
	if (orig_entry) {
		found = true;
		batadv_tt_orig_list_entry_free_ref(orig_entry);
	}

768 769 770
	return found;
}

771
static void
772
batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global,
773
				struct batadv_orig_node *orig_node, int ttvn)
774
{
775
	struct batadv_tt_orig_list_entry *orig_entry;
776

777
	orig_entry = batadv_tt_global_orig_entry_find(tt_global, orig_node);
778 779 780 781 782
	if (orig_entry) {
		/* refresh the ttvn: the current value could be a bogus one that
		 * was added during a "temporary client detection"
		 */
		orig_entry->ttvn = ttvn;
783
		goto out;
784
	}
785

786 787
	orig_entry = kzalloc(sizeof(*orig_entry), GFP_ATOMIC);
	if (!orig_entry)
788
		goto out;
789 790 791 792 793 794

	INIT_HLIST_NODE(&orig_entry->list);
	atomic_inc(&orig_node->refcount);
	atomic_inc(&orig_node->tt_size);
	orig_entry->orig_node = orig_node;
	orig_entry->ttvn = ttvn;
795
	atomic_set(&orig_entry->refcount, 2);
796

797
	spin_lock_bh(&tt_global->list_lock);
798
	hlist_add_head_rcu(&orig_entry->list,
799 800 801 802 803
			   &tt_global->orig_list);
	spin_unlock_bh(&tt_global->list_lock);
out:
	if (orig_entry)
		batadv_tt_orig_list_entry_free_ref(orig_entry);
804 805
}

806
/* caller must hold orig_node refcount */
807 808
int batadv_tt_global_add(struct batadv_priv *bat_priv,
			 struct batadv_orig_node *orig_node,
809 810
			 const unsigned char *tt_addr, uint8_t flags,
			 uint8_t ttvn)
811
{
812 813
	struct batadv_tt_global_entry *tt_global_entry;
	struct batadv_tt_local_entry *tt_local_entry;
814
	int ret = 0;
815
	int hash_added;
816
	struct batadv_tt_common_entry *common;
817
	uint16_t local_flags;
818

819
	tt_global_entry = batadv_tt_global_hash_find(bat_priv, tt_addr);
820 821 822 823 824 825 826 827 828
	tt_local_entry = batadv_tt_local_hash_find(bat_priv, tt_addr);

	/* if the node already has a local client for this entry, it has to wait
	 * for a roaming advertisement instead of manually messing up the global
	 * table
	 */
	if ((flags & BATADV_TT_CLIENT_TEMP) && tt_local_entry &&
	    !(tt_local_entry->common.flags & BATADV_TT_CLIENT_NEW))
		goto out;
829 830

	if (!tt_global_entry) {
831
		tt_global_entry = kzalloc(sizeof(*tt_global_entry), GFP_ATOMIC);
832
		if (!tt_global_entry)
833 834
			goto out;

835 836
		common = &tt_global_entry->common;
		memcpy(common->addr, tt_addr, ETH_ALEN);
837

838
		common->flags = flags;
839
		tt_global_entry->roam_at = 0;
840 841 842 843 844 845
		/* node must store current time in case of roaming. This is
		 * needed to purge this entry out on timeout (if nobody claims
		 * it)
		 */
		if (flags & BATADV_TT_CLIENT_ROAM)
			tt_global_entry->roam_at = jiffies;
846
		atomic_set(&common->refcount, 2);
847
		common->added_at = jiffies;
848 849 850

		INIT_HLIST_HEAD(&tt_global_entry->orig_list);
		spin_lock_init(&tt_global_entry->list_lock);
851

852
		hash_added = batadv_hash_add(bat_priv->tt.global_hash,
853 854 855
					     batadv_compare_tt,
					     batadv_choose_orig, common,
					     &common->hash_entry);
856 857 858

		if (unlikely(hash_added != 0)) {
			/* remove the reference for the hash */
859
			batadv_tt_global_entry_free_ref(tt_global_entry);
860 861
			goto out_remove;
		}
862
	} else {
863
		common = &tt_global_entry->common;
864 865
		/* If there is already a global entry, we can use this one for
		 * our processing.
866 867 868 869 870 871 872
		 * But if we are trying to add a temporary client then here are
		 * two options at this point:
		 * 1) the global client is not a temporary client: the global
		 *    client has to be left as it is, temporary information
		 *    should never override any already known client state
		 * 2) the global client is a temporary client: purge the
		 *    originator list and add the new one orig_entry
873
		 */
874 875 876 877 878 879 880 881 882
		if (flags & BATADV_TT_CLIENT_TEMP) {
			if (!(common->flags & BATADV_TT_CLIENT_TEMP))
				goto out;
			if (batadv_tt_global_entry_has_orig(tt_global_entry,
							    orig_node))
				goto out_remove;
			batadv_tt_global_del_orig_list(tt_global_entry);
			goto add_orig_entry;
		}
883 884 885 886

		/* if the client was temporary added before receiving the first
		 * OGM announcing it, we have to clear the TEMP flag
		 */
887
		common->flags &= ~BATADV_TT_CLIENT_TEMP;
888

889 890 891 892 893 894
		/* the change can carry possible "attribute" flags like the
		 * TT_CLIENT_WIFI, therefore they have to be copied in the
		 * client entry
		 */
		tt_global_entry->common.flags |= flags;

895 896
		/* If there is the BATADV_TT_CLIENT_ROAM flag set, there is only
		 * one originator left in the list and we previously received a
897 898 899 900 901
		 * delete + roaming change for this originator.
		 *
		 * We should first delete the old originator before adding the
		 * new one.
		 */
902
		if (common->flags & BATADV_TT_CLIENT_ROAM) {
903
			batadv_tt_global_del_orig_list(tt_global_entry);
904
			common->flags &= ~BATADV_TT_CLIENT_ROAM;
905
			tt_global_entry->roam_at = 0;
906 907
		}
	}
908
add_orig_entry:
909
	/* add the new orig_entry (if needed) or update it */
910
	batadv_tt_global_orig_entry_add(tt_global_entry, orig_node, ttvn);
911

912
	batadv_dbg(BATADV_DBG_TT, bat_priv,
913
		   "Creating new global tt entry: %pM (via %pM)\n",
914
		   common->addr, orig_node->orig);
915
	ret = 1;
916

917
out_remove:
918

919
	/* remove address from local hash if present */
920 921
	local_flags = batadv_tt_local_remove(bat_priv, tt_addr,
					     "global tt received",
922
					     !!(flags & BATADV_TT_CLIENT_ROAM));
923 924
	tt_global_entry->common.flags |= local_flags & BATADV_TT_CLIENT_WIFI;

925 926 927 928 929 930
	if (!(flags & BATADV_TT_CLIENT_ROAM))
		/* this is a normal global add. Therefore the client is not in a
		 * roaming state anymore.
		 */
		tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_ROAM;

931 932
out:
	if (tt_global_entry)
933
		batadv_tt_global_entry_free_ref(tt_global_entry);
934 935
	if (tt_local_entry)
		batadv_tt_local_entry_free_ref(tt_local_entry);
936
	return ret;
937 938
}

939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976
/* batadv_transtable_best_orig - Get best originator list entry from tt entry
 * @tt_global_entry: global translation table entry to be analyzed
 *
 * This functon assumes the caller holds rcu_read_lock().
 * Returns best originator list entry or NULL on errors.
 */
static struct batadv_tt_orig_list_entry *
batadv_transtable_best_orig(struct batadv_tt_global_entry *tt_global_entry)
{
	struct batadv_neigh_node *router = NULL;
	struct hlist_head *head;
	struct hlist_node *node;
	struct batadv_tt_orig_list_entry *orig_entry, *best_entry = NULL;
	int best_tq = 0;

	head = &tt_global_entry->orig_list;
	hlist_for_each_entry_rcu(orig_entry, node, head, list) {
		router = batadv_orig_node_get_router(orig_entry->orig_node);
		if (!router)
			continue;

		if (router->tq_avg > best_tq) {
			best_entry = orig_entry;
			best_tq = router->tq_avg;
		}

		batadv_neigh_node_free_ref(router);
	}

	return best_entry;
}

/* batadv_tt_global_print_entry - print all orig nodes who announce the address
 * for this global entry
 * @tt_global_entry: global translation table entry to be printed
 * @seq: debugfs table seq_file struct
 *
 * This functon assumes the caller holds rcu_read_lock().
977
 */
978
static void
979
batadv_tt_global_print_entry(struct batadv_tt_global_entry *tt_global_entry,
980
			     struct seq_file *seq)
981 982 983
{
	struct hlist_head *head;
	struct hlist_node *node;
984
	struct batadv_tt_orig_list_entry *orig_entry, *best_entry;
985
	struct batadv_tt_common_entry *tt_common_entry;
986 987 988 989
	uint16_t flags;
	uint8_t last_ttvn;

	tt_common_entry = &tt_global_entry->common;
990 991 992 993 994
	flags = tt_common_entry->flags;

	best_entry = batadv_transtable_best_orig(tt_global_entry);
	if (best_entry) {
		last_ttvn = atomic_read(&best_entry->orig_node->last_ttvn);
995 996
		seq_printf(seq,
			   " %c %pM  (%3u) via %pM     (%3u)   (%#.4x) [%c%c%c]\n",
997 998
			   '*', tt_global_entry->common.addr,
			   best_entry->ttvn, best_entry->orig_node->orig,
999
			   last_ttvn, best_entry->orig_node->tt_crc,
1000 1001 1002 1003
			   (flags & BATADV_TT_CLIENT_ROAM ? 'R' : '.'),
			   (flags & BATADV_TT_CLIENT_WIFI ? 'W' : '.'),
			   (flags & BATADV_TT_CLIENT_TEMP ? 'T' : '.'));
	}
1004 1005 1006 1007

	head = &tt_global_entry->orig_list;

	hlist_for_each_entry_rcu(orig_entry, node, head, list) {
1008 1009 1010
		if (best_entry == orig_entry)
			continue;

1011
		last_ttvn = atomic_read(&orig_entry->orig_node->last_ttvn);
1012 1013 1014 1015
		seq_printf(seq,	" %c %pM  (%3u) via %pM     (%3u)   [%c%c%c]\n",
			   '+', tt_global_entry->common.addr,
			   orig_entry->ttvn, orig_entry->orig_node->orig,
			   last_ttvn,
1016
			   (flags & BATADV_TT_CLIENT_ROAM ? 'R' : '.'),
1017 1018
			   (flags & BATADV_TT_CLIENT_WIFI ? 'W' : '.'),
			   (flags & BATADV_TT_CLIENT_TEMP ? 'T' : '.'));
1019 1020 1021
	}
}

1022
int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset)
1023 1024
{
	struct net_device *net_dev = (struct net_device *)seq->private;
1025
	struct batadv_priv *bat_priv = netdev_priv(net_dev);
1026
	struct batadv_hashtable *hash = bat_priv->tt.global_hash;
1027 1028 1029
	struct batadv_tt_common_entry *tt_common_entry;
	struct batadv_tt_global_entry *tt_global;
	struct batadv_hard_iface *primary_if;
1030
	struct hlist_node *node;
1031
	struct hlist_head *head;
1032
	uint32_t i;
1033

1034 1035
	primary_if = batadv_seq_print_text_primary_if_get(seq);
	if (!primary_if)
1036
		goto out;
1037

1038 1039
	seq_printf(seq,
		   "Globally announced TT entries received via the mesh %s\n",
1040
		   net_dev->name);
1041 1042 1043
	seq_printf(seq, "       %-13s %s       %-15s %s (%-6s) %s\n",
		   "Client", "(TTVN)", "Originator", "(Curr TTVN)", "CRC",
		   "Flags");
1044 1045 1046 1047

	for (i = 0; i < hash->size; i++) {
		head = &hash->table[i];

1048
		rcu_read_lock();
1049
		hlist_for_each_entry_rcu(tt_common_entry, node,
1050
					 head, hash_entry) {
1051 1052 1053 1054
			tt_global = container_of(tt_common_entry,
						 struct batadv_tt_global_entry,
						 common);
			batadv_tt_global_print_entry(tt_global, seq);
1055
		}
1056
		rcu_read_unlock();
1057
	}
1058 1059
out:
	if (primary_if)
1060
		batadv_hardif_free_ref(primary_if);
1061
	return 0;
1062 1063
}

1064
/* deletes the orig list of a tt_global_entry */
1065
static void
1066
batadv_tt_global_del_orig_list(struct batadv_tt_global_entry *tt_global_entry)
1067
{
1068 1069
	struct hlist_head *head;
	struct hlist_node *node, *safe;
1070
	struct batadv_tt_orig_list_entry *orig_entry;
1071

1072 1073 1074 1075
	spin_lock_bh(&tt_global_entry->list_lock);
	head = &tt_global_entry->orig_list;
	hlist_for_each_entry_safe(orig_entry, node, safe, head, list) {
		hlist_del_rcu(node);
1076
		batadv_tt_orig_list_entry_free_ref(orig_entry);
1077 1078 1079 1080
	}
	spin_unlock_bh(&tt_global_entry->list_lock);
}

1081
static void
1082 1083 1084
batadv_tt_global_del_orig_entry(struct batadv_priv *bat_priv,
				struct batadv_tt_global_entry *tt_global_entry,
				struct batadv_orig_node *orig_node,
1085
				const char *message)
1086 1087 1088
{
	struct hlist_head *head;
	struct hlist_node *node, *safe;
1089
	struct batadv_tt_orig_list_entry *orig_entry;
1090 1091 1092 1093 1094

	spin_lock_bh(&tt_global_entry->list_lock);
	head = &tt_global_entry->orig_list;
	hlist_for_each_entry_safe(orig_entry, node, safe, head, list) {
		if (orig_entry->orig_node == orig_node) {
1095
			batadv_dbg(BATADV_DBG_TT, bat_priv,
1096 1097 1098
				   "Deleting %pM from global tt entry %pM: %s\n",
				   orig_node->orig,
				   tt_global_entry->common.addr, message);
1099
			hlist_del_rcu(node);
1100
			batadv_tt_orig_list_entry_free_ref(orig_entry);
1101 1102 1103 1104 1105 1106
		}
	}
	spin_unlock_bh(&tt_global_entry->list_lock);
}

/* If the client is to be deleted, we check if it is the last origantor entry
1107 1108
 * within tt_global entry. If yes, we set the BATADV_TT_CLIENT_ROAM flag and the
 * timer, otherwise we simply remove the originator scheduled for deletion.
1109
 */
1110
static void
1111 1112 1113 1114
batadv_tt_global_del_roaming(struct batadv_priv *bat_priv,
			     struct batadv_tt_global_entry *tt_global_entry,
			     struct batadv_orig_node *orig_node,
			     const char *message)
1115 1116 1117 1118
{
	bool last_entry = true;
	struct hlist_head *head;
	struct hlist_node *node;
1119
	struct batadv_tt_orig_list_entry *orig_entry;
1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136

	/* no local entry exists, case 1:
	 * Check if this is the last one or if other entries exist.
	 */

	rcu_read_lock();
	head = &tt_global_entry->orig_list;
	hlist_for_each_entry_rcu(orig_entry, node, head, list) {
		if (orig_entry->orig_node != orig_node) {
			last_entry = false;
			break;
		}
	}
	rcu_read_unlock();

	if (last_entry) {
		/* its the last one, mark for roaming. */
1137
		tt_global_entry->common.flags |= BATADV_TT_CLIENT_ROAM;
1138 1139 1140 1141 1142
		tt_global_entry->roam_at = jiffies;
	} else
		/* there is another entry, we can simply delete this
		 * one and can still use the other one.
		 */
1143 1144
		batadv_tt_global_del_orig_entry(bat_priv, tt_global_entry,
						orig_node, message);
1145 1146 1147 1148
}



1149 1150
static void batadv_tt_global_del(struct batadv_priv *bat_priv,
				 struct batadv_orig_node *orig_node,
1151 1152
				 const unsigned char *addr,
				 const char *message, bool roaming)
1153
{
1154
	struct batadv_tt_global_entry *tt_global_entry;
1155
	struct batadv_tt_local_entry *local_entry = NULL;
1156

1157
	tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr);
1158
	if (!tt_global_entry)
1159
		goto out;
1160

1161
	if (!roaming) {
1162 1163
		batadv_tt_global_del_orig_entry(bat_priv, tt_global_entry,
						orig_node, message);
1164 1165

		if (hlist_empty(&tt_global_entry->orig_list))
1166 1167
			batadv_tt_global_free(bat_priv, tt_global_entry,
					      message);
1168 1169 1170

		goto out;
	}
1171 1172 1173

	/* if we are deleting a global entry due to a roam
	 * event, there are two possibilities:
1174 1175
	 * 1) the client roamed from node A to node B => if there
	 *    is only one originator left for this client, we mark
1176
	 *    it with BATADV_TT_CLIENT_ROAM, we start a timer and we
1177 1178
	 *    wait for node B to claim it. In case of timeout
	 *    the entry is purged.
1179 1180 1181
	 *
	 *    If there are other originators left, we directly delete
	 *    the originator.
1182
	 * 2) the client roamed to us => we can directly delete
1183 1184
	 *    the global entry, since it is useless now.
	 */
1185 1186 1187
	local_entry = batadv_tt_local_hash_find(bat_priv,
						tt_global_entry->common.addr);
	if (local_entry) {
1188
		/* local entry exists, case 2: client roamed to us. */
1189
		batadv_tt_global_del_orig_list(tt_global_entry);
1190
		batadv_tt_global_free(bat_priv, tt_global_entry, message);
1191 1192
	} else
		/* no local entry exists, case 1: check for roaming */
1193 1194
		batadv_tt_global_del_roaming(bat_priv, tt_global_entry,
					     orig_node, message);
1195 1196


1197
out:
1198
	if (tt_global_entry)
1199 1200 1201
		batadv_tt_global_entry_free_ref(tt_global_entry);
	if (local_entry)
		batadv_tt_local_entry_free_ref(local_entry);
1202 1203
}

1204 1205 1206
void batadv_tt_global_del_orig(struct batadv_priv *bat_priv,
			       struct batadv_orig_node *orig_node,
			       const char *message)
1207
{
1208 1209
	struct batadv_tt_global_entry *tt_global;
	struct batadv_tt_common_entry *tt_common_entry;
1210
	uint32_t i;
1211
	struct batadv_hashtable *hash = bat_priv->tt.global_hash;
1212 1213
	struct hlist_node *node, *safe;
	struct hlist_head *head;
1214
	spinlock_t *list_lock; /* protects write access to the hash lists */
1215

1216 1217 1218
	if (!hash)
		return;

1219 1220
	for (i = 0; i < hash->size; i++) {
		head = &hash->table[i];
1221
		list_lock = &hash->list_locks[i];
1222

1223
		spin_lock_bh(list_lock);
1224
		hlist_for_each_entry_safe(tt_common_entry, node, safe,
1225
					  head, hash_entry) {
1226 1227 1228
			tt_global = container_of(tt_common_entry,
						 struct batadv_tt_global_entry,
						 common);
1229

1230
			batadv_tt_global_del_orig_entry(bat_priv, tt_global,
1231
							orig_node, message);
1232

1233
			if (hlist_empty(&tt_global->orig_list)) {
1234
				batadv_dbg(BATADV_DBG_TT, bat_priv,
1235
					   "Deleting global tt entry %pM: %s\n",
1236
					   tt_global->common.addr, message);
1237
				hlist_del_rcu(node);
1238
				batadv_tt_global_entry_free_ref(tt_global);
1239
			}
1240
		}
1241
		spin_unlock_bh(list_lock);
1242
	}
1243
	orig_node->tt_initialised = false;
1244 1245
}

1246 1247
static bool batadv_tt_global_to_purge(struct batadv_tt_global_entry *tt_global,
				      char **msg)
1248
{
1249 1250 1251
	bool purge = false;
	unsigned long roam_timeout = BATADV_TT_CLIENT_ROAM_TIMEOUT;
	unsigned long temp_timeout = BATADV_TT_CLIENT_TEMP_TIMEOUT;
1252

1253 1254 1255 1256 1257
	if ((tt_global->common.flags & BATADV_TT_CLIENT_ROAM) &&
	    batadv_has_timed_out(tt_global->roam_at, roam_timeout)) {
		purge = true;
		*msg = "Roaming timeout\n";
	}
1258

1259 1260 1261 1262
	if ((tt_global->common.flags & BATADV_TT_CLIENT_TEMP) &&
	    batadv_has_timed_out(tt_global->common.added_at, temp_timeout)) {
		purge = true;
		*msg = "Temporary client timeout\n";
1263
	}
1264 1265

	return purge;
1266 1267
}

1268
static void batadv_tt_global_purge(struct batadv_priv *bat_priv)
1269
{
1270
	struct batadv_hashtable *hash = bat_priv->tt.global_hash;
1271
	struct hlist_head *head;
1272
	struct hlist_node *node, *node_tmp;
1273
	spinlock_t *list_lock; /* protects write access to the hash lists */
1274
	uint32_t i;
1275 1276 1277
	char *msg = NULL;
	struct batadv_tt_common_entry *tt_common;
	struct batadv_tt_global_entry *tt_global;
1278 1279 1280

	for (i = 0; i < hash->size; i++) {
		head = &hash->table[i];
1281
		list_lock = &hash->list_locks[i];
1282

1283
		spin_lock_bh(list_lock);
1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300
		hlist_for_each_entry_safe(tt_common, node, node_tmp, head,
					  hash_entry) {
			tt_global = container_of(tt_common,
						 struct batadv_tt_global_entry,
						 common);

			if (!batadv_tt_global_to_purge(tt_global, &msg))
				continue;

			batadv_dbg(BATADV_DBG_TT, bat_priv,
				   "Deleting global tt entry (%pM): %s\n",
				   tt_global->common.addr, msg);

			hlist_del_rcu(node);

			batadv_tt_global_entry_free_ref(tt_global);
		}
1301
		spin_unlock_bh(list_lock);
1302 1303 1304
	}
}

1305
static void batadv_tt_global_table_free(struct batadv_priv *bat_priv)
1306
{
1307
	struct batadv_hashtable *hash;
1308
	spinlock_t *list_lock; /* protects write access to the hash lists */
1309 1310
	struct batadv_tt_common_entry *tt_common_entry;
	struct batadv_tt_global_entry *tt_global;
1311 1312
	struct hlist_node *node, *node_tmp;
	struct hlist_head *head;
1313
	uint32_t i;
1314

1315
	if (!bat_priv->tt.global_hash)
1316 1317
		return;

1318
	hash = bat_priv->tt.global_hash;
1319 1320 1321 1322 1323 1324

	for (i = 0; i < hash->size; i++) {
		head = &hash->table[i];
		list_lock = &hash->list_locks[i];

		spin_lock_bh(list_lock);
1325
		hlist_for_each_entry_safe(tt_common_entry, node, node_tmp,
1326 1327
					  head, hash_entry) {
			hlist_del_rcu(node);
1328 1329 1330 1331
			tt_global = container_of(tt_common_entry,
						 struct batadv_tt_global_entry,
						 common);
			batadv_tt_global_entry_free_ref(tt_global);
1332 1333 1334 1335
		}
		spin_unlock_bh(list_lock);
	}

1336
	batadv_hash_destroy(hash);
1337

1338
	bat_priv->tt.global_hash = NULL;
1339 1340
}

1341 1342 1343
static bool
_batadv_is_ap_isolated(struct batadv_tt_local_entry *tt_local_entry,
		       struct batadv_tt_global_entry *tt_global_entry)
1344 1345 1346
{
	bool ret = false;

1347 1348
	if (tt_local_entry->common.flags & BATADV_TT_CLIENT_WIFI &&
	    tt_global_entry->common.flags & BATADV_TT_CLIENT_WIFI)
1349 1350 1351 1352 1353
		ret = true;

	return ret;
}

1354 1355 1356
struct batadv_orig_node *batadv_transtable_search(struct batadv_priv *bat_priv,
						  const uint8_t *src,
						  const uint8_t *addr)
1357
{
1358 1359 1360
	struct batadv_tt_local_entry *tt_local_entry = NULL;
	struct batadv_tt_global_entry *tt_global_entry = NULL;
	struct batadv_orig_node *orig_node = NULL;
1361
	struct batadv_tt_orig_list_entry *best_entry;
1362

1363
	if (src && atomic_read(&bat_priv->ap_isolation)) {
1364
		tt_local_entry = batadv_tt_local_hash_find(bat_priv, src);
1365 1366
		if (!tt_local_entry ||
		    (tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING))
1367 1368
			goto out;
	}
1369

1370
	tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr);
1371
	if (!tt_global_entry)
1372
		goto out;
1373

1374
	/* check whether the clients should not communicate due to AP
1375 1376
	 * isolation
	 */
1377 1378
	if (tt_local_entry &&
	    _batadv_is_ap_isolated(tt_local_entry, tt_global_entry))
1379 1380
		goto out;

1381
	rcu_read_lock();
1382
	best_entry = batadv_transtable_best_orig(tt_global_entry);
1383
	/* found anything? */
1384 1385
	if (best_entry)
		orig_node = best_entry->orig_node;
1386 1387 1388
	if (orig_node && !atomic_inc_not_zero(&orig_node->refcount))
		orig_node = NULL;
	rcu_read_unlock();
1389

1390
out:
1391
	if (tt_global_entry)
1392
		batadv_tt_global_entry_free_ref(tt_global_entry);
1393
	if (tt_local_entry)
1394
		batadv_tt_local_entry_free_ref(tt_local_entry);
1395

1396
	return orig_node;
1397
}
1398 1399

/* Calculates the checksum of the local table of a given orig_node */
1400 1401
static uint16_t batadv_tt_global_crc(struct batadv_priv *bat_priv,
				     struct batadv_orig_node *orig_node)
1402 1403
{
	uint16_t total = 0, total_one;
1404
	struct batadv_hashtable *hash = bat_priv->tt.global_hash;
1405 1406
	struct batadv_tt_common_entry *tt_common;
	struct batadv_tt_global_entry *tt_global;
1407 1408
	struct hlist_node *node;
	struct hlist_head *head;
1409 1410
	uint32_t i;
	int j;
1411 1412 1413 1414 1415

	for (i = 0; i < hash->size; i++) {
		head = &hash->table[i];

		rcu_read_lock();
1416
		hlist_for_each_entry_rcu(tt_common, node, head, hash_entry) {
1417 1418 1419
			tt_global = container_of(tt_common,
						 struct batadv_tt_global_entry,
						 common);
1420 1421 1422 1423 1424
			/* Roaming clients are in the global table for
			 * consistency only. They don't have to be
			 * taken into account while computing the
			 * global crc
			 */
1425
			if (tt_common->flags & BATADV_TT_CLIENT_ROAM)
1426
				continue;
1427 1428 1429 1430 1431 1432
			/* Temporary clients have not been announced yet, so
			 * they have to be skipped while computing the global
			 * crc
			 */
			if (tt_common->flags & BATADV_TT_CLIENT_TEMP)
				continue;
1433 1434 1435 1436

			/* find out if this global entry is announced by this
			 * originator
			 */
1437
			if (!batadv_tt_global_entry_has_orig(tt_global,
1438
							     orig_node))
1439 1440 1441 1442 1443
				continue;

			total_one = 0;
			for (j = 0; j < ETH_ALEN; j++)
				total_one = crc16_byte(total_one,
1444
						       tt_common->addr[j]);
1445
			total ^= total_one;
1446 1447 1448 1449 1450 1451 1452 1453
		}
		rcu_read_unlock();
	}

	return total;
}

/* Calculates the checksum of the local table */
1454
static uint16_t batadv_tt_local_crc(struct batadv_priv *bat_priv)
1455 1456
{
	uint16_t total = 0, total_one;
1457
	struct batadv_hashtable *hash = bat_priv->tt.local_hash;
1458
	struct batadv_tt_common_entry *tt_common;
1459 1460
	struct hlist_node *node;
	struct hlist_head *head;
1461 1462
	uint32_t i;
	int j;
1463 1464 1465 1466 1467

	for (i = 0; i < hash->size; i++) {
		head = &hash->table[i];

		rcu_read_lock();
1468
		hlist_for_each_entry_rcu(tt_common, node, head, hash_entry) {
1469
			/* not yet committed clients have not to be taken into
1470 1471
			 * account while computing the CRC
			 */
1472
			if (tt_common->flags & BATADV_TT_CLIENT_NEW)
1473
				continue;
1474 1475 1476
			total_one = 0;
			for (j = 0; j < ETH_ALEN; j++)
				total_one = crc16_byte(total_one,
1477
						       tt_common->addr[j]);
1478 1479 1480 1481 1482 1483 1484 1485
			total ^= total_one;
		}
		rcu_read_unlock();
	}

	return total;
}

1486
static void batadv_tt_req_list_free(struct batadv_priv *bat_priv)
1487
{
1488
	struct batadv_tt_req_node *node, *safe;
1489

1490
	spin_lock_bh(&bat_priv->tt.req_list_lock);
1491

1492
	list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) {
1493 1494 1495 1496
		list_del(&node->list);
		kfree(node);
	}

1497
	spin_unlock_bh(&bat_priv->tt.req_list_lock);
1498 1499
}

1500 1501
static void batadv_tt_save_orig_buffer(struct batadv_priv *bat_priv,
				       struct batadv_orig_node *orig_node,
1502 1503
				       const unsigned char *tt_buff,
				       uint8_t tt_num_changes)
1504
{
1505
	uint16_t tt_buff_len = batadv_tt_len(tt_num_changes);
1506 1507

	/* Replace the old buffer only if I received something in the
1508 1509
	 * last OGM (the OGM could carry no changes)
	 */
1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522
	spin_lock_bh(&orig_node->tt_buff_lock);
	if (tt_buff_len > 0) {
		kfree(orig_node->tt_buff);
		orig_node->tt_buff_len = 0;
		orig_node->tt_buff = kmalloc(tt_buff_len, GFP_ATOMIC);
		if (orig_node->tt_buff) {
			memcpy(orig_node->tt_buff, tt_buff, tt_buff_len);
			orig_node->tt_buff_len = tt_buff_len;
		}
	}
	spin_unlock_bh(&orig_node->tt_buff_lock);
}

1523
static void batadv_tt_req_purge(struct batadv_priv *bat_priv)
1524
{
1525
	struct batadv_tt_req_node *node, *safe;
1526

1527 1528
	spin_lock_bh(&bat_priv->tt.req_list_lock);
	list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) {
1529 1530
		if (batadv_has_timed_out(node->issued_at,
					 BATADV_TT_REQUEST_TIMEOUT)) {
1531 1532 1533 1534
			list_del(&node->list);
			kfree(node);
		}
	}
1535
	spin_unlock_bh(&bat_priv->tt.req_list_lock);
1536 1537 1538
}

/* returns the pointer to the new tt_req_node struct if no request
1539 1540
 * has already been issued for this orig_node, NULL otherwise
 */
1541 1542 1543
static struct batadv_tt_req_node *
batadv_new_tt_req_node(struct batadv_priv *bat_priv,
		       struct batadv_orig_node *orig_node)
1544
{
1545
	struct batadv_tt_req_node *tt_req_node_tmp, *tt_req_node = NULL;
1546

1547 1548
	spin_lock_bh(&bat_priv->tt.req_list_lock);
	list_for_each_entry(tt_req_node_tmp, &bat_priv->tt.req_list, list) {
1549 1550
		if (batadv_compare_eth(tt_req_node_tmp, orig_node) &&
		    !batadv_has_timed_out(tt_req_node_tmp->issued_at,
1551
					  BATADV_TT_REQUEST_TIMEOUT))
1552 1553 1554 1555 1556 1557 1558 1559 1560 1561
			goto unlock;
	}

	tt_req_node = kmalloc(sizeof(*tt_req_node), GFP_ATOMIC);
	if (!tt_req_node)
		goto unlock;

	memcpy(tt_req_node->addr, orig_node->orig, ETH_ALEN);
	tt_req_node->issued_at = jiffies;

1562
	list_add(&tt_req_node->list, &bat_priv->tt.req_list);
1563
unlock:
1564
	spin_unlock_bh(&bat_priv->tt.req_list_lock);
1565 1566 1567
	return tt_req_node;
}

1568
/* data_ptr is useless here, but has to be kept to respect the prototype */
1569 1570
static int batadv_tt_local_valid_entry(const void *entry_ptr,
				       const void *data_ptr)
1571
{
1572
	const struct batadv_tt_common_entry *tt_common_entry = entry_ptr;
1573

1574
	if (tt_common_entry->flags & BATADV_TT_CLIENT_NEW)
1575 1576 1577 1578
		return 0;
	return 1;
}

1579 1580
static int batadv_tt_global_valid(const void *entry_ptr,
				  const void *data_ptr)
1581
{
1582 1583 1584
	const struct batadv_tt_common_entry *tt_common_entry = entry_ptr;
	const struct batadv_tt_global_entry *tt_global_entry;
	const struct batadv_orig_node *orig_node = data_ptr;
1585

1586 1587
	if (tt_common_entry->flags & BATADV_TT_CLIENT_ROAM ||
	    tt_common_entry->flags & BATADV_TT_CLIENT_TEMP)
1588 1589
		return 0;

1590 1591
	tt_global_entry = container_of(tt_common_entry,
				       struct batadv_tt_global_entry,
1592 1593
				       common);

1594
	return batadv_tt_global_entry_has_orig(tt_global_entry, orig_node);
1595 1596
}

1597 1598
static struct sk_buff *
batadv_tt_response_fill_table(uint16_t tt_len, uint8_t ttvn,
1599
			      struct batadv_hashtable *hash,
1600
			      struct batadv_hard_iface *primary_if,
1601 1602
			      int (*valid_cb)(const void *, const void *),
			      void *cb_data)
1603
{
1604
	struct batadv_tt_common_entry *tt_common_entry;
1605 1606
	struct batadv_tt_query_packet *tt_response;
	struct batadv_tt_change *tt_change;
1607 1608 1609 1610
	struct hlist_node *node;
	struct hlist_head *head;
	struct sk_buff *skb = NULL;
	uint16_t tt_tot, tt_count;
1611
	ssize_t tt_query_size = sizeof(struct batadv_tt_query_packet);
1612
	uint32_t i;
1613
	size_t len;
1614 1615 1616

	if (tt_query_size + tt_len > primary_if->soft_iface->mtu) {
		tt_len = primary_if->soft_iface->mtu - tt_query_size;
1617
		tt_len -= tt_len % sizeof(struct batadv_tt_change);
1618
	}
1619
	tt_tot = tt_len / sizeof(struct batadv_tt_change);
1620

1621
	len = tt_query_size + tt_len;
1622
	skb = dev_alloc_skb(len + ETH_HLEN + NET_IP_ALIGN);
1623 1624 1625
	if (!skb)
		goto out;

1626
	skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
1627
	tt_response = (struct batadv_tt_query_packet *)skb_put(skb, len);
1628 1629
	tt_response->ttvn = ttvn;

1630
	tt_change = (struct batadv_tt_change *)(skb->data + tt_query_size);
1631 1632 1633 1634 1635 1636
	tt_count = 0;

	rcu_read_lock();
	for (i = 0; i < hash->size; i++) {
		head = &hash->table[i];

1637
		hlist_for_each_entry_rcu(tt_common_entry, node,
1638 1639 1640 1641
					 head, hash_entry) {
			if (tt_count == tt_tot)
				break;

1642
			if ((valid_cb) && (!valid_cb(tt_common_entry, cb_data)))
1643 1644
				continue;

1645 1646
			memcpy(tt_change->addr, tt_common_entry->addr,
			       ETH_ALEN);
1647
			tt_change->flags = tt_common_entry->flags;
1648 1649 1650 1651 1652 1653 1654

			tt_count++;
			tt_change++;
		}
	}
	rcu_read_unlock();

1655
	/* store in the message the number of entries we have successfully
1656 1657
	 * copied
	 */
1658 1659
	tt_response->tt_data = htons(tt_count);

1660 1661 1662 1663
out:
	return skb;
}

1664 1665
static int batadv_send_tt_request(struct batadv_priv *bat_priv,
				  struct batadv_orig_node *dst_orig_node,
1666 1667
				  uint8_t ttvn, uint16_t tt_crc,
				  bool full_table)
1668 1669
{
	struct sk_buff *skb = NULL;
1670
	struct batadv_tt_query_packet *tt_request;
1671 1672
	struct batadv_hard_iface *primary_if;
	struct batadv_tt_req_node *tt_req_node = NULL;
1673
	int ret = 1;
1674
	size_t tt_req_len;
1675

1676
	primary_if = batadv_primary_if_get_selected(bat_priv);
1677 1678 1679 1680
	if (!primary_if)
		goto out;

	/* The new tt_req will be issued only if I'm not waiting for a
1681 1682
	 * reply from the same orig_node yet
	 */
1683
	tt_req_node = batadv_new_tt_req_node(bat_priv, dst_orig_node);
1684 1685 1686
	if (!tt_req_node)
		goto out;

1687
	skb = dev_alloc_skb(sizeof(*tt_request) + ETH_HLEN + NET_IP_ALIGN);
1688 1689 1690
	if (!skb)
		goto out;

1691
	skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
1692

1693 1694
	tt_req_len = sizeof(*tt_request);
	tt_request = (struct batadv_tt_query_packet *)skb_put(skb, tt_req_len);
1695

1696
	tt_request->header.packet_type = BATADV_TT_QUERY;
1697
	tt_request->header.version = BATADV_COMPAT_VERSION;
1698 1699
	memcpy(tt_request->src, primary_if->net_dev->dev_addr, ETH_ALEN);
	memcpy(tt_request->dst, dst_orig_node->orig, ETH_ALEN);
1700
	tt_request->header.ttl = BATADV_TTL;
1701
	tt_request->ttvn = ttvn;
1702
	tt_request->tt_data = htons(tt_crc);
1703
	tt_request->flags = BATADV_TT_REQUEST;
1704 1705

	if (full_table)
1706
		tt_request->flags |= BATADV_TT_FULL_TABLE;
1707

1708 1709
	batadv_dbg(BATADV_DBG_TT, bat_priv, "Sending TT_REQUEST to %pM [%c]\n",
		   dst_orig_node->orig, (full_table ? 'F' : '.'));
1710

1711
	batadv_inc_counter(bat_priv, BATADV_CNT_TT_REQUEST_TX);
1712

1713 1714
	if (batadv_send_skb_to_orig(skb, dst_orig_node, NULL))
		ret = 0;
1715 1716 1717

out:
	if (primary_if)
1718
		batadv_hardif_free_ref(primary_if);
1719 1720 1721
	if (ret)
		kfree_skb(skb);
	if (ret && tt_req_node) {
1722
		spin_lock_bh(&bat_priv->tt.req_list_lock);
1723
		list_del(&tt_req_node->list);
1724
		spin_unlock_bh(&bat_priv->tt.req_list_lock);
1725 1726 1727 1728 1729
		kfree(tt_req_node);
	}
	return ret;
}

1730
static bool
1731
batadv_send_other_tt_response(struct batadv_priv *bat_priv,
1732
			      struct batadv_tt_query_packet *tt_request)
1733
{
1734
	struct batadv_orig_node *req_dst_orig_node;
1735 1736
	struct batadv_orig_node *res_dst_orig_node = NULL;
	struct batadv_hard_iface *primary_if = NULL;
1737 1738 1739 1740 1741 1742
	uint8_t orig_ttvn, req_ttvn, ttvn;
	int ret = false;
	unsigned char *tt_buff;
	bool full_table;
	uint16_t tt_len, tt_tot;
	struct sk_buff *skb = NULL;
1743
	struct batadv_tt_query_packet *tt_response;
1744
	uint8_t *packet_pos;
1745
	size_t len;
1746

1747
	batadv_dbg(BATADV_DBG_TT, bat_priv,
1748 1749
		   "Received TT_REQUEST from %pM for ttvn: %u (%pM) [%c]\n",
		   tt_request->src, tt_request->ttvn, tt_request->dst,
1750
		   (tt_request->flags & BATADV_TT_FULL_TABLE ? 'F' : '.'));
1751 1752

	/* Let's get the orig node of the REAL destination */
1753
	req_dst_orig_node = batadv_orig_hash_find(bat_priv, tt_request->dst);
1754 1755 1756
	if (!req_dst_orig_node)
		goto out;

1757
	res_dst_orig_node = batadv_orig_hash_find(bat_priv, tt_request->src);
1758 1759 1760
	if (!res_dst_orig_node)
		goto out;

1761
	primary_if = batadv_primary_if_get_selected(bat_priv);
1762 1763 1764 1765 1766 1767
	if (!primary_if)
		goto out;

	orig_ttvn = (uint8_t)atomic_read(&req_dst_orig_node->last_ttvn);
	req_ttvn = tt_request->ttvn;

1768
	/* I don't have the requested data */
1769
	if (orig_ttvn != req_ttvn ||
1770
	    tt_request->tt_data != htons(req_dst_orig_node->tt_crc))
1771 1772
		goto out;

1773
	/* If the full table has been explicitly requested */
1774
	if (tt_request->flags & BATADV_TT_FULL_TABLE ||
1775 1776 1777 1778 1779 1780
	    !req_dst_orig_node->tt_buff)
		full_table = true;
	else
		full_table = false;

	/* In this version, fragmentation is not implemented, then
1781 1782
	 * I'll send only one packet with as much TT entries as I can
	 */
1783 1784 1785
	if (!full_table) {
		spin_lock_bh(&req_dst_orig_node->tt_buff_lock);
		tt_len = req_dst_orig_node->tt_buff_len;
1786
		tt_tot = tt_len / sizeof(struct batadv_tt_change);
1787

1788
		len = sizeof(*tt_response) + tt_len;
1789
		skb = dev_alloc_skb(len + ETH_HLEN + NET_IP_ALIGN);
1790 1791 1792
		if (!skb)
			goto unlock;

1793
		skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
1794 1795
		packet_pos = skb_put(skb, len);
		tt_response = (struct batadv_tt_query_packet *)packet_pos;
1796 1797 1798
		tt_response->ttvn = req_ttvn;
		tt_response->tt_data = htons(tt_tot);

1799
		tt_buff = skb->data + sizeof(*tt_response);
1800 1801 1802 1803 1804 1805
		/* Copy the last orig_node's OGM buffer */
		memcpy(tt_buff, req_dst_orig_node->tt_buff,
		       req_dst_orig_node->tt_buff_len);

		spin_unlock_bh(&req_dst_orig_node->tt_buff_lock);
	} else {
1806 1807
		tt_len = (uint16_t)atomic_read(&req_dst_orig_node->tt_size);
		tt_len *= sizeof(struct batadv_tt_change);
1808 1809
		ttvn = (uint8_t)atomic_read(&req_dst_orig_node->last_ttvn);

1810
		skb = batadv_tt_response_fill_table(tt_len, ttvn,
1811
						    bat_priv->tt.global_hash,
1812 1813 1814
						    primary_if,
						    batadv_tt_global_valid,
						    req_dst_orig_node);
1815 1816 1817
		if (!skb)
			goto out;

1818
		tt_response = (struct batadv_tt_query_packet *)skb->data;
1819 1820
	}

1821
	tt_response->header.packet_type = BATADV_TT_QUERY;
1822
	tt_response->header.version = BATADV_COMPAT_VERSION;
1823
	tt_response->header.ttl = BATADV_TTL;
1824 1825
	memcpy(tt_response->src, req_dst_orig_node->orig, ETH_ALEN);
	memcpy(tt_response->dst, tt_request->src, ETH_ALEN);
1826
	tt_response->flags = BATADV_TT_RESPONSE;
1827 1828

	if (full_table)
1829
		tt_response->flags |= BATADV_TT_FULL_TABLE;
1830

1831
	batadv_dbg(BATADV_DBG_TT, bat_priv,
1832 1833
		   "Sending TT_RESPONSE %pM for %pM (ttvn: %u)\n",
		   res_dst_orig_node->orig, req_dst_orig_node->orig, req_ttvn);
1834

1835
	batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX);
1836

1837 1838
	if (batadv_send_skb_to_orig(skb, res_dst_orig_node, NULL))
		ret = true;
1839 1840 1841 1842 1843 1844 1845
	goto out;

unlock:
	spin_unlock_bh(&req_dst_orig_node->tt_buff_lock);

out:
	if (res_dst_orig_node)
1846
		batadv_orig_node_free_ref(res_dst_orig_node);
1847
	if (req_dst_orig_node)
1848
		batadv_orig_node_free_ref(req_dst_orig_node);
1849
	if (primary_if)
1850
		batadv_hardif_free_ref(primary_if);
1851 1852 1853 1854
	if (!ret)
		kfree_skb(skb);
	return ret;
}
1855 1856

static bool
1857
batadv_send_my_tt_response(struct batadv_priv *bat_priv,
1858
			   struct batadv_tt_query_packet *tt_request)
1859
{
1860
	struct batadv_orig_node *orig_node;
1861
	struct batadv_hard_iface *primary_if = NULL;
1862 1863 1864 1865 1866 1867
	uint8_t my_ttvn, req_ttvn, ttvn;
	int ret = false;
	unsigned char *tt_buff;
	bool full_table;
	uint16_t tt_len, tt_tot;
	struct sk_buff *skb = NULL;
1868
	struct batadv_tt_query_packet *tt_response;
1869
	uint8_t *packet_pos;
1870
	size_t len;
1871

1872
	batadv_dbg(BATADV_DBG_TT, bat_priv,
1873 1874
		   "Received TT_REQUEST from %pM for ttvn: %u (me) [%c]\n",
		   tt_request->src, tt_request->ttvn,
1875
		   (tt_request->flags & BATADV_TT_FULL_TABLE ? 'F' : '.'));
1876 1877


1878
	my_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn);
1879 1880
	req_ttvn = tt_request->ttvn;

1881
	orig_node = batadv_orig_hash_find(bat_priv, tt_request->src);
1882 1883 1884
	if (!orig_node)
		goto out;

1885
	primary_if = batadv_primary_if_get_selected(bat_priv);
1886 1887 1888 1889
	if (!primary_if)
		goto out;

	/* If the full table has been explicitly requested or the gap
1890 1891
	 * is too big send the whole local translation table
	 */
1892
	if (tt_request->flags & BATADV_TT_FULL_TABLE || my_ttvn != req_ttvn ||
1893
	    !bat_priv->tt.last_changeset)
1894 1895 1896 1897 1898
		full_table = true;
	else
		full_table = false;

	/* In this version, fragmentation is not implemented, then
1899 1900
	 * I'll send only one packet with as much TT entries as I can
	 */
1901
	if (!full_table) {
1902 1903
		spin_lock_bh(&bat_priv->tt.last_changeset_lock);
		tt_len = bat_priv->tt.last_changeset_len;
1904
		tt_tot = tt_len / sizeof(struct batadv_tt_change);
1905

1906
		len = sizeof(*tt_response) + tt_len;
1907
		skb = dev_alloc_skb(len + ETH_HLEN + NET_IP_ALIGN);
1908 1909 1910
		if (!skb)
			goto unlock;

1911
		skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
1912 1913
		packet_pos = skb_put(skb, len);
		tt_response = (struct batadv_tt_query_packet *)packet_pos;
1914 1915 1916
		tt_response->ttvn = req_ttvn;
		tt_response->tt_data = htons(tt_tot);

1917
		tt_buff = skb->data + sizeof(*tt_response);
1918 1919 1920
		memcpy(tt_buff, bat_priv->tt.last_changeset,
		       bat_priv->tt.last_changeset_len);
		spin_unlock_bh(&bat_priv->tt.last_changeset_lock);
1921
	} else {
1922
		tt_len = (uint16_t)atomic_read(&bat_priv->tt.local_entry_num);
1923
		tt_len *= sizeof(struct batadv_tt_change);
1924
		ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn);
1925

1926
		skb = batadv_tt_response_fill_table(tt_len, ttvn,
1927
						    bat_priv->tt.local_hash,
1928 1929 1930
						    primary_if,
						    batadv_tt_local_valid_entry,
						    NULL);
1931 1932 1933
		if (!skb)
			goto out;

1934
		tt_response = (struct batadv_tt_query_packet *)skb->data;
1935 1936
	}

1937
	tt_response->header.packet_type = BATADV_TT_QUERY;
1938
	tt_response->header.version = BATADV_COMPAT_VERSION;
1939
	tt_response->header.ttl = BATADV_TTL;
1940 1941
	memcpy(tt_response->src, primary_if->net_dev->dev_addr, ETH_ALEN);
	memcpy(tt_response->dst, tt_request->src, ETH_ALEN);
1942
	tt_response->flags = BATADV_TT_RESPONSE;
1943 1944

	if (full_table)
1945
		tt_response->flags |= BATADV_TT_FULL_TABLE;
1946

1947
	batadv_dbg(BATADV_DBG_TT, bat_priv,
1948 1949
		   "Sending TT_RESPONSE to %pM [%c]\n",
		   orig_node->orig,
1950
		   (tt_response->flags & BATADV_TT_FULL_TABLE ? 'F' : '.'));
1951

1952
	batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX);
1953

1954 1955
	if (batadv_send_skb_to_orig(skb, orig_node, NULL))
		ret = true;
1956 1957 1958
	goto out;

unlock:
1959
	spin_unlock_bh(&bat_priv->tt.last_changeset_lock);
1960 1961
out:
	if (orig_node)
1962
		batadv_orig_node_free_ref(orig_node);
1963
	if (primary_if)
1964
		batadv_hardif_free_ref(primary_if);
1965 1966 1967 1968 1969 1970
	if (!ret)
		kfree_skb(skb);
	/* This packet was for me, so it doesn't need to be re-routed */
	return true;
}

1971
bool batadv_send_tt_response(struct batadv_priv *bat_priv,
1972
			     struct batadv_tt_query_packet *tt_request)
1973
{
1974
	if (batadv_is_my_mac(tt_request->dst)) {
1975
		/* don't answer backbone gws! */
1976
		if (batadv_bla_is_backbone_gw_orig(bat_priv, tt_request->src))
1977 1978
			return true;

1979
		return batadv_send_my_tt_response(bat_priv, tt_request);
1980
	} else {
1981
		return batadv_send_other_tt_response(bat_priv, tt_request);
1982
	}
1983 1984
}

1985 1986
static void _batadv_tt_update_changes(struct batadv_priv *bat_priv,
				      struct batadv_orig_node *orig_node,
1987
				      struct batadv_tt_change *tt_change,
1988
				      uint16_t tt_num_changes, uint8_t ttvn)
1989 1990
{
	int i;
1991
	int roams;
1992 1993

	for (i = 0; i < tt_num_changes; i++) {
1994 1995
		if ((tt_change + i)->flags & BATADV_TT_CLIENT_DEL) {
			roams = (tt_change + i)->flags & BATADV_TT_CLIENT_ROAM;
1996 1997
			batadv_tt_global_del(bat_priv, orig_node,
					     (tt_change + i)->addr,
1998 1999
					     "tt removed by changes",
					     roams);
2000 2001
		} else {
			if (!batadv_tt_global_add(bat_priv, orig_node,
2002 2003
						  (tt_change + i)->addr,
						  (tt_change + i)->flags, ttvn))
2004 2005 2006 2007 2008 2009 2010
				/* In case of problem while storing a
				 * global_entry, we stop the updating
				 * procedure without committing the
				 * ttvn change. This will avoid to send
				 * corrupted data on tt_request
				 */
				return;
2011
		}
2012
	}
2013
	orig_node->tt_initialised = true;
2014 2015
}

2016
static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv,
2017
				  struct batadv_tt_query_packet *tt_response)
2018
{
2019
	struct batadv_orig_node *orig_node;
2020

2021
	orig_node = batadv_orig_hash_find(bat_priv, tt_response->src);
2022 2023 2024 2025
	if (!orig_node)
		goto out;

	/* Purge the old table first.. */
2026
	batadv_tt_global_del_orig(bat_priv, orig_node, "Received full table");
2027

2028
	_batadv_tt_update_changes(bat_priv, orig_node,
2029
				  (struct batadv_tt_change *)(tt_response + 1),
2030 2031
				  ntohs(tt_response->tt_data),
				  tt_response->ttvn);
2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042

	spin_lock_bh(&orig_node->tt_buff_lock);
	kfree(orig_node->tt_buff);
	orig_node->tt_buff_len = 0;
	orig_node->tt_buff = NULL;
	spin_unlock_bh(&orig_node->tt_buff_lock);

	atomic_set(&orig_node->last_ttvn, tt_response->ttvn);

out:
	if (orig_node)
2043
		batadv_orig_node_free_ref(orig_node);
2044 2045
}

2046 2047
static void batadv_tt_update_changes(struct batadv_priv *bat_priv,
				     struct batadv_orig_node *orig_node,
2048
				     uint16_t tt_num_changes, uint8_t ttvn,
2049
				     struct batadv_tt_change *tt_change)
2050
{
2051 2052
	_batadv_tt_update_changes(bat_priv, orig_node, tt_change,
				  tt_num_changes, ttvn);
2053

2054 2055
	batadv_tt_save_orig_buffer(bat_priv, orig_node,
				   (unsigned char *)tt_change, tt_num_changes);
2056 2057 2058
	atomic_set(&orig_node->last_ttvn, ttvn);
}

2059
bool batadv_is_my_client(struct batadv_priv *bat_priv, const uint8_t *addr)
2060
{
2061
	struct batadv_tt_local_entry *tt_local_entry;
2062
	bool ret = false;
2063

2064
	tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr);
2065 2066
	if (!tt_local_entry)
		goto out;
2067
	/* Check if the client has been logically deleted (but is kept for
2068 2069
	 * consistency purpose)
	 */
2070 2071
	if ((tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING) ||
	    (tt_local_entry->common.flags & BATADV_TT_CLIENT_ROAM))
2072
		goto out;
2073 2074
	ret = true;
out:
2075
	if (tt_local_entry)
2076
		batadv_tt_local_entry_free_ref(tt_local_entry);
2077
	return ret;
2078 2079
}

2080
void batadv_handle_tt_response(struct batadv_priv *bat_priv,
2081
			       struct batadv_tt_query_packet *tt_response)
2082
{
2083 2084
	struct batadv_tt_req_node *node, *safe;
	struct batadv_orig_node *orig_node = NULL;
2085
	struct batadv_tt_change *tt_change;
2086

2087
	batadv_dbg(BATADV_DBG_TT, bat_priv,
2088 2089 2090
		   "Received TT_RESPONSE from %pM for ttvn %d t_size: %d [%c]\n",
		   tt_response->src, tt_response->ttvn,
		   ntohs(tt_response->tt_data),
2091
		   (tt_response->flags & BATADV_TT_FULL_TABLE ? 'F' : '.'));
2092

2093
	/* we should have never asked a backbone gw */
2094
	if (batadv_bla_is_backbone_gw_orig(bat_priv, tt_response->src))
2095 2096
		goto out;

2097
	orig_node = batadv_orig_hash_find(bat_priv, tt_response->src);
2098 2099 2100
	if (!orig_node)
		goto out;

2101
	if (tt_response->flags & BATADV_TT_FULL_TABLE) {
2102
		batadv_tt_fill_gtable(bat_priv, tt_response);
2103 2104
	} else {
		tt_change = (struct batadv_tt_change *)(tt_response + 1);
2105 2106
		batadv_tt_update_changes(bat_priv, orig_node,
					 ntohs(tt_response->tt_data),
2107 2108
					 tt_response->ttvn, tt_change);
	}
2109 2110

	/* Delete the tt_req_node from pending tt_requests list */
2111 2112
	spin_lock_bh(&bat_priv->tt.req_list_lock);
	list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) {
2113
		if (!batadv_compare_eth(node->addr, tt_response->src))
2114 2115 2116 2117
			continue;
		list_del(&node->list);
		kfree(node);
	}
2118
	spin_unlock_bh(&bat_priv->tt.req_list_lock);
2119 2120

	/* Recalculate the CRC for this orig_node and store it */
2121
	orig_node->tt_crc = batadv_tt_global_crc(bat_priv, orig_node);
2122 2123
out:
	if (orig_node)
2124
		batadv_orig_node_free_ref(orig_node);
2125 2126
}

2127
int batadv_tt_init(struct batadv_priv *bat_priv)
2128
{
2129
	int ret;
2130

2131
	ret = batadv_tt_local_init(bat_priv);
2132 2133 2134
	if (ret < 0)
		return ret;

2135
	ret = batadv_tt_global_init(bat_priv);
2136 2137
	if (ret < 0)
		return ret;
2138

2139
	batadv_tt_start_timer(bat_priv);
2140 2141 2142 2143

	return 1;
}

2144
static void batadv_tt_roam_list_free(struct batadv_priv *bat_priv)
2145
{
2146
	struct batadv_tt_roam_node *node, *safe;
2147

2148
	spin_lock_bh(&bat_priv->tt.roam_list_lock);
2149

2150
	list_for_each_entry_safe(node, safe, &bat_priv->tt.roam_list, list) {
2151 2152 2153 2154
		list_del(&node->list);
		kfree(node);
	}

2155
	spin_unlock_bh(&bat_priv->tt.roam_list_lock);
2156 2157
}

2158
static void batadv_tt_roam_purge(struct batadv_priv *bat_priv)
2159
{
2160
	struct batadv_tt_roam_node *node, *safe;
2161

2162 2163
	spin_lock_bh(&bat_priv->tt.roam_list_lock);
	list_for_each_entry_safe(node, safe, &bat_priv->tt.roam_list, list) {
2164 2165
		if (!batadv_has_timed_out(node->first_time,
					  BATADV_ROAMING_MAX_TIME))
2166 2167 2168 2169 2170
			continue;

		list_del(&node->list);
		kfree(node);
	}
2171
	spin_unlock_bh(&bat_priv->tt.roam_list_lock);
2172 2173 2174 2175 2176 2177
}

/* This function checks whether the client already reached the
 * maximum number of possible roaming phases. In this case the ROAMING_ADV
 * will not be sent.
 *
2178 2179
 * returns true if the ROAMING_ADV can be sent, false otherwise
 */
2180
static bool batadv_tt_check_roam_count(struct batadv_priv *bat_priv,
2181
				       uint8_t *client)
2182
{
2183
	struct batadv_tt_roam_node *tt_roam_node;
2184 2185
	bool ret = false;

2186
	spin_lock_bh(&bat_priv->tt.roam_list_lock);
2187
	/* The new tt_req will be issued only if I'm not waiting for a
2188 2189
	 * reply from the same orig_node yet
	 */
2190
	list_for_each_entry(tt_roam_node, &bat_priv->tt.roam_list, list) {
2191
		if (!batadv_compare_eth(tt_roam_node->addr, client))
2192 2193
			continue;

2194
		if (batadv_has_timed_out(tt_roam_node->first_time,
2195
					 BATADV_ROAMING_MAX_TIME))
2196 2197
			continue;

2198
		if (!batadv_atomic_dec_not_zero(&tt_roam_node->counter))
2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210
			/* Sorry, you roamed too many times! */
			goto unlock;
		ret = true;
		break;
	}

	if (!ret) {
		tt_roam_node = kmalloc(sizeof(*tt_roam_node), GFP_ATOMIC);
		if (!tt_roam_node)
			goto unlock;

		tt_roam_node->first_time = jiffies;
2211 2212
		atomic_set(&tt_roam_node->counter,
			   BATADV_ROAMING_MAX_COUNT - 1);
2213 2214
		memcpy(tt_roam_node->addr, client, ETH_ALEN);

2215
		list_add(&tt_roam_node->list, &bat_priv->tt.roam_list);
2216 2217 2218 2219
		ret = true;
	}

unlock:
2220
	spin_unlock_bh(&bat_priv->tt.roam_list_lock);
2221 2222 2223
	return ret;
}

2224 2225
static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client,
				 struct batadv_orig_node *orig_node)
2226 2227
{
	struct sk_buff *skb = NULL;
2228
	struct batadv_roam_adv_packet *roam_adv_packet;
2229
	int ret = 1;
2230
	struct batadv_hard_iface *primary_if;
2231
	size_t len = sizeof(*roam_adv_packet);
2232 2233

	/* before going on we have to check whether the client has
2234 2235
	 * already roamed to us too many times
	 */
2236
	if (!batadv_tt_check_roam_count(bat_priv, client))
2237 2238
		goto out;

2239
	skb = dev_alloc_skb(sizeof(*roam_adv_packet) + ETH_HLEN + NET_IP_ALIGN);
2240 2241 2242
	if (!skb)
		goto out;

2243
	skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
2244

2245
	roam_adv_packet = (struct batadv_roam_adv_packet *)skb_put(skb, len);
2246

2247
	roam_adv_packet->header.packet_type = BATADV_ROAM_ADV;
2248
	roam_adv_packet->header.version = BATADV_COMPAT_VERSION;
2249
	roam_adv_packet->header.ttl = BATADV_TTL;
2250
	roam_adv_packet->reserved = 0;
2251
	primary_if = batadv_primary_if_get_selected(bat_priv);
2252 2253 2254
	if (!primary_if)
		goto out;
	memcpy(roam_adv_packet->src, primary_if->net_dev->dev_addr, ETH_ALEN);
2255
	batadv_hardif_free_ref(primary_if);
2256 2257 2258
	memcpy(roam_adv_packet->dst, orig_node->orig, ETH_ALEN);
	memcpy(roam_adv_packet->client, client, ETH_ALEN);

2259
	batadv_dbg(BATADV_DBG_TT, bat_priv,
2260 2261
		   "Sending ROAMING_ADV to %pM (client %pM)\n",
		   orig_node->orig, client);
2262

2263
	batadv_inc_counter(bat_priv, BATADV_CNT_TT_ROAM_ADV_TX);
2264

2265 2266
	if (batadv_send_skb_to_orig(skb, orig_node, NULL))
		ret = 0;
2267 2268

out:
2269
	if (ret && skb)
2270 2271
		kfree_skb(skb);
	return;
2272 2273
}

2274
static void batadv_tt_purge(struct work_struct *work)
2275
{
2276
	struct delayed_work *delayed_work;
2277
	struct batadv_priv_tt *priv_tt;
2278 2279 2280
	struct batadv_priv *bat_priv;

	delayed_work = container_of(work, struct delayed_work, work);
2281 2282
	priv_tt = container_of(delayed_work, struct batadv_priv_tt, work);
	bat_priv = container_of(priv_tt, struct batadv_priv, tt);
2283

2284
	batadv_tt_local_purge(bat_priv);
2285
	batadv_tt_global_purge(bat_priv);
2286 2287
	batadv_tt_req_purge(bat_priv);
	batadv_tt_roam_purge(bat_priv);
2288

2289
	batadv_tt_start_timer(bat_priv);
2290
}
2291

2292
void batadv_tt_free(struct batadv_priv *bat_priv)
2293
{
2294
	cancel_delayed_work_sync(&bat_priv->tt.work);
2295

2296 2297 2298 2299 2300
	batadv_tt_local_table_free(bat_priv);
	batadv_tt_global_table_free(bat_priv);
	batadv_tt_req_list_free(bat_priv);
	batadv_tt_changes_list_free(bat_priv);
	batadv_tt_roam_list_free(bat_priv);
2301

2302
	kfree(bat_priv->tt.last_changeset);
2303
}
2304

2305
/* This function will enable or disable the specified flags for all the entries
2306 2307
 * in the given hash table and returns the number of modified entries
 */
2308 2309
static uint16_t batadv_tt_set_flags(struct batadv_hashtable *hash,
				    uint16_t flags, bool enable)
2310
{
2311
	uint32_t i;
2312
	uint16_t changed_num = 0;
2313 2314
	struct hlist_head *head;
	struct hlist_node *node;
2315
	struct batadv_tt_common_entry *tt_common_entry;
2316 2317

	if (!hash)
2318
		goto out;
2319 2320 2321 2322 2323

	for (i = 0; i < hash->size; i++) {
		head = &hash->table[i];

		rcu_read_lock();
2324
		hlist_for_each_entry_rcu(tt_common_entry, node,
2325
					 head, hash_entry) {
2326 2327 2328 2329 2330 2331 2332 2333 2334 2335
			if (enable) {
				if ((tt_common_entry->flags & flags) == flags)
					continue;
				tt_common_entry->flags |= flags;
			} else {
				if (!(tt_common_entry->flags & flags))
					continue;
				tt_common_entry->flags &= ~flags;
			}
			changed_num++;
2336 2337 2338
		}
		rcu_read_unlock();
	}
2339 2340
out:
	return changed_num;
2341 2342
}

2343
/* Purge out all the tt local entries marked with BATADV_TT_CLIENT_PENDING */
2344
static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv)
2345
{
2346
	struct batadv_hashtable *hash = bat_priv->tt.local_hash;
2347 2348
	struct batadv_tt_common_entry *tt_common;
	struct batadv_tt_local_entry *tt_local;
2349 2350 2351
	struct hlist_node *node, *node_tmp;
	struct hlist_head *head;
	spinlock_t *list_lock; /* protects write access to the hash lists */
2352
	uint32_t i;
2353 2354 2355 2356 2357 2358 2359 2360 2361

	if (!hash)
		return;

	for (i = 0; i < hash->size; i++) {
		head = &hash->table[i];
		list_lock = &hash->list_locks[i];

		spin_lock_bh(list_lock);
2362 2363 2364
		hlist_for_each_entry_safe(tt_common, node, node_tmp, head,
					  hash_entry) {
			if (!(tt_common->flags & BATADV_TT_CLIENT_PENDING))
2365 2366
				continue;

2367
			batadv_dbg(BATADV_DBG_TT, bat_priv,
2368
				   "Deleting local tt entry (%pM): pending\n",
2369
				   tt_common->addr);
2370

2371
			atomic_dec(&bat_priv->tt.local_entry_num);
2372
			hlist_del_rcu(node);
2373 2374 2375 2376
			tt_local = container_of(tt_common,
						struct batadv_tt_local_entry,
						common);
			batadv_tt_local_entry_free_ref(tt_local);
2377 2378 2379 2380 2381
		}
		spin_unlock_bh(list_lock);
	}
}

2382
static int batadv_tt_commit_changes(struct batadv_priv *bat_priv,
2383 2384
				    unsigned char **packet_buff,
				    int *packet_buff_len, int packet_min_len)
2385
{
2386 2387
	uint16_t changed_num = 0;

2388
	if (atomic_read(&bat_priv->tt.local_changes) < 1)
2389 2390
		return -ENOENT;

2391
	changed_num = batadv_tt_set_flags(bat_priv->tt.local_hash,
2392
					  BATADV_TT_CLIENT_NEW, false);
2393 2394

	/* all reset entries have to be counted as local entries */
2395
	atomic_add(changed_num, &bat_priv->tt.local_entry_num);
2396
	batadv_tt_local_purge_pending_clients(bat_priv);
2397
	bat_priv->tt.local_crc = batadv_tt_local_crc(bat_priv);
2398 2399

	/* Increment the TTVN only once per OGM interval */
2400
	atomic_inc(&bat_priv->tt.vn);
2401
	batadv_dbg(BATADV_DBG_TT, bat_priv,
2402
		   "Local changes committed, updating to ttvn %u\n",
2403
		   (uint8_t)atomic_read(&bat_priv->tt.vn));
2404 2405

	/* reset the sending counter */
2406
	atomic_set(&bat_priv->tt.ogm_append_cnt, BATADV_TT_OGM_APPEND_MAX);
2407

2408 2409
	return batadv_tt_changes_fill_buff(bat_priv, packet_buff,
					   packet_buff_len, packet_min_len);
2410 2411 2412
}

/* when calling this function (hard_iface == primary_if) has to be true */
2413
int batadv_tt_append_diff(struct batadv_priv *bat_priv,
2414 2415 2416 2417 2418 2419
			  unsigned char **packet_buff, int *packet_buff_len,
			  int packet_min_len)
{
	int tt_num_changes;

	/* if at least one change happened */
2420 2421 2422
	tt_num_changes = batadv_tt_commit_changes(bat_priv, packet_buff,
						  packet_buff_len,
						  packet_min_len);
2423 2424 2425

	/* if the changes have been sent often enough */
	if ((tt_num_changes < 0) &&
2426
	    (!batadv_atomic_dec_not_zero(&bat_priv->tt.ogm_append_cnt))) {
2427 2428
		batadv_tt_realloc_packet_buff(packet_buff, packet_buff_len,
					      packet_min_len, packet_min_len);
2429 2430 2431 2432
		tt_num_changes = 0;
	}

	return tt_num_changes;
2433
}
2434

2435
bool batadv_is_ap_isolated(struct batadv_priv *bat_priv, uint8_t *src,
2436
			   uint8_t *dst)
2437
{
2438 2439
	struct batadv_tt_local_entry *tt_local_entry = NULL;
	struct batadv_tt_global_entry *tt_global_entry = NULL;
2440
	bool ret = false;
2441 2442

	if (!atomic_read(&bat_priv->ap_isolation))
2443
		goto out;
2444

2445
	tt_local_entry = batadv_tt_local_hash_find(bat_priv, dst);
2446 2447 2448
	if (!tt_local_entry)
		goto out;

2449
	tt_global_entry = batadv_tt_global_hash_find(bat_priv, src);
2450 2451 2452
	if (!tt_global_entry)
		goto out;

2453
	if (!_batadv_is_ap_isolated(tt_local_entry, tt_global_entry))
2454 2455
		goto out;

2456
	ret = true;
2457 2458 2459

out:
	if (tt_global_entry)
2460
		batadv_tt_global_entry_free_ref(tt_global_entry);
2461
	if (tt_local_entry)
2462
		batadv_tt_local_entry_free_ref(tt_local_entry);
2463 2464
	return ret;
}
2465

2466 2467
void batadv_tt_update_orig(struct batadv_priv *bat_priv,
			   struct batadv_orig_node *orig_node,
2468 2469
			   const unsigned char *tt_buff, uint8_t tt_num_changes,
			   uint8_t ttvn, uint16_t tt_crc)
2470 2471 2472
{
	uint8_t orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
	bool full_table = true;
2473
	struct batadv_tt_change *tt_change;
2474

2475
	/* don't care about a backbone gateways updates. */
2476
	if (batadv_bla_is_backbone_gw_orig(bat_priv, orig_node->orig))
2477 2478
		return;

2479
	/* orig table not initialised AND first diff is in the OGM OR the ttvn
2480 2481
	 * increased by one -> we can apply the attached changes
	 */
2482 2483
	if ((!orig_node->tt_initialised && ttvn == 1) ||
	    ttvn - orig_ttvn == 1) {
2484
		/* the OGM could not contain the changes due to their size or
2485 2486
		 * because they have already been sent BATADV_TT_OGM_APPEND_MAX
		 * times.
2487 2488
		 * In this case send a tt request
		 */
2489 2490 2491 2492 2493
		if (!tt_num_changes) {
			full_table = false;
			goto request_table;
		}

2494
		tt_change = (struct batadv_tt_change *)tt_buff;
2495
		batadv_tt_update_changes(bat_priv, orig_node, tt_num_changes,
2496
					 ttvn, tt_change);
2497 2498 2499

		/* Even if we received the precomputed crc with the OGM, we
		 * prefer to recompute it to spot any possible inconsistency
2500 2501
		 * in the global table
		 */
2502
		orig_node->tt_crc = batadv_tt_global_crc(bat_priv, orig_node);
2503 2504 2505 2506 2507 2508 2509 2510

		/* The ttvn alone is not enough to guarantee consistency
		 * because a single value could represent different states
		 * (due to the wrap around). Thus a node has to check whether
		 * the resulting table (after applying the changes) is still
		 * consistent or not. E.g. a node could disconnect while its
		 * ttvn is X and reconnect on ttvn = X + TTVN_MAX: in this case
		 * checking the CRC value is mandatory to detect the
2511 2512
		 * inconsistency
		 */
2513 2514 2515 2516
		if (orig_node->tt_crc != tt_crc)
			goto request_table;
	} else {
		/* if we missed more than one change or our tables are not
2517 2518
		 * in sync anymore -> request fresh tt data
		 */
2519 2520
		if (!orig_node->tt_initialised || ttvn != orig_ttvn ||
		    orig_node->tt_crc != tt_crc) {
2521
request_table:
2522
			batadv_dbg(BATADV_DBG_TT, bat_priv,
2523
				   "TT inconsistency for %pM. Need to retrieve the correct information (ttvn: %u last_ttvn: %u crc: %#.4x last_crc: %#.4x num_changes: %u)\n",
2524 2525
				   orig_node->orig, ttvn, orig_ttvn, tt_crc,
				   orig_node->tt_crc, tt_num_changes);
2526 2527
			batadv_send_tt_request(bat_priv, orig_node, ttvn,
					       tt_crc, full_table);
2528 2529 2530 2531
			return;
		}
	}
}
2532 2533 2534 2535 2536

/* returns true whether we know that the client has moved from its old
 * originator to another one. This entry is kept is still kept for consistency
 * purposes
 */
2537
bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv,
2538
					uint8_t *addr)
2539
{
2540
	struct batadv_tt_global_entry *tt_global_entry;
2541 2542
	bool ret = false;

2543
	tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr);
2544 2545 2546
	if (!tt_global_entry)
		goto out;

2547
	ret = !!(tt_global_entry->common.flags & BATADV_TT_CLIENT_ROAM);
2548
	batadv_tt_global_entry_free_ref(tt_global_entry);
2549 2550 2551
out:
	return ret;
}
2552

2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577
/**
 * batadv_tt_local_client_is_roaming - tells whether the client is roaming
 * @bat_priv: the bat priv with all the soft interface information
 * @addr: the MAC address of the local client to query
 *
 * Returns true if the local client is known to be roaming (it is not served by
 * this node anymore) or not. If yes, the client is still present in the table
 * to keep the latter consistent with the node TTVN
 */
bool batadv_tt_local_client_is_roaming(struct batadv_priv *bat_priv,
				       uint8_t *addr)
{
	struct batadv_tt_local_entry *tt_local_entry;
	bool ret = false;

	tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr);
	if (!tt_local_entry)
		goto out;

	ret = tt_local_entry->common.flags & BATADV_TT_CLIENT_ROAM;
	batadv_tt_local_entry_free_ref(tt_local_entry);
out:
	return ret;
}

2578 2579 2580 2581 2582 2583
bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv,
					  struct batadv_orig_node *orig_node,
					  const unsigned char *addr)
{
	bool ret = false;

2584 2585 2586 2587 2588 2589 2590
	/* if the originator is a backbone node (meaning it belongs to the same
	 * LAN of this node) the temporary client must not be added because to
	 * reach such destination the node must use the LAN instead of the mesh
	 */
	if (batadv_bla_is_backbone_gw_orig(bat_priv, orig_node->orig))
		goto out;

2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602
	if (!batadv_tt_global_add(bat_priv, orig_node, addr,
				  BATADV_TT_CLIENT_TEMP,
				  atomic_read(&orig_node->last_ttvn)))
		goto out;

	batadv_dbg(BATADV_DBG_TT, bat_priv,
		   "Added temporary global client (addr: %pM orig: %pM)\n",
		   addr, orig_node->orig);
	ret = true;
out:
	return ret;
}