translation-table.c 74.3 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
static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client,
				 struct batadv_orig_node *orig_node);
34 35
static void batadv_tt_purge(struct work_struct *work);
static void
36
batadv_tt_global_del_orig_list(struct batadv_tt_global_entry *tt_global_entry);
37 38 39 40
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);
41

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

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

51
static void batadv_tt_start_timer(struct batadv_priv *bat_priv)
52
{
53 54
	INIT_DELAYED_WORK(&bat_priv->tt.work, batadv_tt_purge);
	queue_delayed_work(batadv_event_workqueue, &bat_priv->tt.work,
55
			   msecs_to_jiffies(5000));
56 57
}

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

	if (!hash)
		return NULL;

70
	index = batadv_choose_orig(data, hash->size);
71 72 73
	head = &hash->table[index];

	rcu_read_lock();
74
	hlist_for_each_entry_rcu(tt_common_entry, node, head, hash_entry) {
75
		if (!batadv_compare_eth(tt_common_entry, data))
76 77
			continue;

78
		if (!atomic_inc_not_zero(&tt_common_entry->refcount))
79 80
			continue;

81
		tt_common_entry_tmp = tt_common_entry;
82 83 84 85
		break;
	}
	rcu_read_unlock();

86
	return tt_common_entry_tmp;
87 88
}

89 90
static struct batadv_tt_local_entry *
batadv_tt_local_hash_find(struct batadv_priv *bat_priv, const void *data)
91
{
92 93
	struct batadv_tt_common_entry *tt_common_entry;
	struct batadv_tt_local_entry *tt_local_entry = NULL;
94

95
	tt_common_entry = batadv_tt_hash_find(bat_priv->tt.local_hash, data);
96 97
	if (tt_common_entry)
		tt_local_entry = container_of(tt_common_entry,
98 99
					      struct batadv_tt_local_entry,
					      common);
100 101
	return tt_local_entry;
}
102

103 104
static struct batadv_tt_global_entry *
batadv_tt_global_hash_find(struct batadv_priv *bat_priv, const void *data)
105
{
106 107
	struct batadv_tt_common_entry *tt_common_entry;
	struct batadv_tt_global_entry *tt_global_entry = NULL;
108

109
	tt_common_entry = batadv_tt_hash_find(bat_priv->tt.global_hash, data);
110 111
	if (tt_common_entry)
		tt_global_entry = container_of(tt_common_entry,
112 113
					       struct batadv_tt_global_entry,
					       common);
114
	return tt_global_entry;
115 116 117

}

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

125
static void batadv_tt_global_entry_free_rcu(struct rcu_head *rcu)
126
{
127 128
	struct batadv_tt_common_entry *tt_common_entry;
	struct batadv_tt_global_entry *tt_global_entry;
129

130 131 132
	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);
133 134 135 136

	kfree(tt_global_entry);
}

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

147
static void batadv_tt_orig_list_entry_free_rcu(struct rcu_head *rcu)
148
{
149
	struct batadv_tt_orig_list_entry *orig_entry;
150

151
	orig_entry = container_of(rcu, struct batadv_tt_orig_list_entry, rcu);
152
	batadv_orig_node_free_ref(orig_entry->orig_node);
153 154 155
	kfree(orig_entry);
}

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

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

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

	if (!tt_change_node)
		return;

178
	tt_change_node->change.flags = flags;
179 180
	memcpy(tt_change_node->change.addr, addr, ETH_ALEN);

181
	del_op_requested = flags & BATADV_TT_CLIENT_DEL;
182 183

	/* check for ADD+DEL or DEL+ADD events */
184 185
	spin_lock_bh(&bat_priv->tt.changes_list_lock);
	list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list,
186 187 188 189 190 191 192 193 194 195 196
				 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
		 */
197
		del_op_entry = entry->change.flags & BATADV_TT_CLIENT_DEL;
198 199 200 201 202 203 204 205
		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);
206
		kfree(tt_change_node);
207 208 209 210
		event_removed = true;
		goto unlock;
	}

211
	/* track the change in the OGMinterval list */
212
	list_add_tail(&tt_change_node->list, &bat_priv->tt.changes_list);
213 214

unlock:
215
	spin_unlock_bh(&bat_priv->tt.changes_list_lock);
216

217
	if (event_removed)
218
		atomic_dec(&bat_priv->tt.local_changes);
219
	else
220
		atomic_inc(&bat_priv->tt.local_changes);
221 222
}

223
int batadv_tt_len(int changes_num)
224
{
225
	return changes_num * sizeof(struct batadv_tt_change);
226 227
}

228
static int batadv_tt_local_init(struct batadv_priv *bat_priv)
229
{
230
	if (bat_priv->tt.local_hash)
231
		return 0;
232

233
	bat_priv->tt.local_hash = batadv_hash_new(1024);
234

235
	if (!bat_priv->tt.local_hash)
236
		return -ENOMEM;
237

238
	return 0;
239 240
}

241 242 243 244 245 246 247 248 249 250 251 252 253 254
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);

}

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

267
	tt_local = batadv_tt_local_hash_find(bat_priv, addr);
268
	tt_global = batadv_tt_global_hash_find(bat_priv, addr);
269

270 271
	if (tt_local) {
		tt_local->last_seen = jiffies;
272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296
		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;
297 298
	}

299 300
	tt_local = kmalloc(sizeof(*tt_local), GFP_ATOMIC);
	if (!tt_local)
301
		goto out;
302

303
	batadv_dbg(BATADV_DBG_TT, bat_priv,
304
		   "Creating new local tt entry: %pM (ttvn: %d)\n", addr,
305
		   (uint8_t)atomic_read(&bat_priv->tt.vn));
306

307 308
	memcpy(tt_local->common.addr, addr, ETH_ALEN);
	tt_local->common.flags = BATADV_NO_FLAGS;
309
	if (batadv_is_wifi_iface(ifindex))
310 311 312 313
		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;
314 315

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

319 320
	/* 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
321 322
	 * (consistency check)
	 */
323
	tt_local->common.flags |= BATADV_TT_CLIENT_NEW;
324

325
	hash_added = batadv_hash_add(bat_priv->tt.local_hash, batadv_compare_tt,
326 327
				     batadv_choose_orig, &tt_local->common,
				     &tt_local->common.hash_entry);
328 329 330

	if (unlikely(hash_added != 0)) {
		/* remove the reference for the hash */
331
		batadv_tt_local_entry_free_ref(tt_local);
332 333 334
		goto out;
	}

335
add_event:
336
	batadv_tt_local_event(bat_priv, addr, tt_local->common.flags);
337

338 339 340 341 342
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)) {
343
		/* These node are probably going to update their tt table */
344
		head = &tt_global->orig_list;
345 346
		rcu_read_lock();
		hlist_for_each_entry_rcu(orig_entry, node, head, list) {
347
			batadv_send_roam_adv(bat_priv, tt_global->common.addr,
348
					     orig_entry->orig_node);
349 350
		}
		rcu_read_unlock();
351 352 353 354 355 356 357 358 359 360 361
		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;
		}
362
	}
363

364
out:
365 366 367 368
	if (tt_local)
		batadv_tt_local_entry_free_ref(tt_local);
	if (tt_global)
		batadv_tt_global_entry_free_ref(tt_global);
369 370
}

371 372 373 374
static void batadv_tt_realloc_packet_buff(unsigned char **packet_buff,
					  int *packet_buff_len,
					  int min_packet_len,
					  int new_packet_len)
375 376 377 378 379 380 381 382 383 384 385 386 387 388
{
	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;
	}
}

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

397
	primary_if = batadv_primary_if_get_selected(bat_priv);
398 399

	req_len = min_packet_len;
400
	req_len += batadv_tt_len(atomic_read(&bat_priv->tt.local_changes));
401 402 403 404 405 406 407

	/* 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;

408 409
	batadv_tt_realloc_packet_buff(packet_buff, packet_buff_len,
				      min_packet_len, req_len);
410 411

	if (primary_if)
412
		batadv_hardif_free_ref(primary_if);
413 414
}

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

424 425
	batadv_tt_prepare_packet_buff(bat_priv, packet_buff,
				      packet_buff_len, min_packet_len);
426

427 428 429 430
	new_len = *packet_buff_len - min_packet_len;
	tt_buff = *packet_buff + min_packet_len;

	if (new_len > 0)
431
		tot_changes = new_len / batadv_tt_len(1);
432

433 434
	spin_lock_bh(&bat_priv->tt.changes_list_lock);
	atomic_set(&bat_priv->tt.local_changes, 0);
435

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

	/* Keep the buffer for possible tt_request */
449 450 451 452
	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;
453 454 455
	/* 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
456 457
		 * instead of providing the diff
		 */
458 459 460 461
		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;
462 463
		}
	}
464
	spin_unlock_bh(&bat_priv->tt.last_changeset_lock);
465

466
	return count;
467 468
}

469
int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
470 471
{
	struct net_device *net_dev = (struct net_device *)seq->private;
472
	struct batadv_priv *bat_priv = netdev_priv(net_dev);
473
	struct batadv_hashtable *hash = bat_priv->tt.local_hash;
474 475
	struct batadv_tt_common_entry *tt_common_entry;
	struct batadv_hard_iface *primary_if;
476
	struct hlist_node *node;
477
	struct hlist_head *head;
478
	uint32_t i;
479

480 481
	primary_if = batadv_seq_print_text_primary_if_get(seq);
	if (!primary_if)
482
		goto out;
483

484 485
	seq_printf(seq,
		   "Locally retrieved addresses (from %s) announced via TT (TTVN: %u):\n",
486
		   net_dev->name, (uint8_t)atomic_read(&bat_priv->tt.vn));
487 488 489 490

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

491
		rcu_read_lock();
492
		hlist_for_each_entry_rcu(tt_common_entry, node,
493
					 head, hash_entry) {
494
			seq_printf(seq, " * %pM [%c%c%c%c%c]\n",
495 496
				   tt_common_entry->addr,
				   (tt_common_entry->flags &
497
				    BATADV_TT_CLIENT_ROAM ? 'R' : '.'),
498
				   (tt_common_entry->flags &
499
				    BATADV_TT_CLIENT_NOPURGE ? 'P' : '.'),
500
				   (tt_common_entry->flags &
501
				    BATADV_TT_CLIENT_NEW ? 'N' : '.'),
502
				   (tt_common_entry->flags &
503
				    BATADV_TT_CLIENT_PENDING ? 'X' : '.'),
504
				   (tt_common_entry->flags &
505
				    BATADV_TT_CLIENT_WIFI ? 'W' : '.'));
506
		}
507
		rcu_read_unlock();
508
	}
509 510
out:
	if (primary_if)
511
		batadv_hardif_free_ref(primary_if);
512
	return 0;
513 514
}

515 516 517 518
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)
519
{
520 521
	batadv_tt_local_event(bat_priv, tt_local_entry->common.addr,
			      tt_local_entry->common.flags | flags);
522

523 524
	/* 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
525 526
	 * response issued before the net ttvn increment (consistency check)
	 */
527
	tt_local_entry->common.flags |= BATADV_TT_CLIENT_PENDING;
528

529
	batadv_dbg(BATADV_DBG_TT, bat_priv,
530 531
		   "Local tt entry (%pM) pending to be removed: %s\n",
		   tt_local_entry->common.addr, message);
532 533
}

534 535 536 537 538 539 540 541 542 543 544 545
/**
 * 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)
546
{
547
	struct batadv_tt_local_entry *tt_local_entry;
548
	uint16_t flags, curr_flags = BATADV_NO_FLAGS;
549

550
	tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr);
551 552 553
	if (!tt_local_entry)
		goto out;

554 555
	curr_flags = tt_local_entry->common.flags;

556
	flags = BATADV_TT_CLIENT_DEL;
557 558 559 560
	/* 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
	 */
561
	if (roaming) {
562
		flags |= BATADV_TT_CLIENT_ROAM;
563 564 565
		/* mark the local client as ROAMed */
		tt_local_entry->common.flags |= BATADV_TT_CLIENT_ROAM;
	}
566

567 568 569 570 571 572 573 574 575 576 577 578
	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);
579

580 581
out:
	if (tt_local_entry)
582
		batadv_tt_local_entry_free_ref(tt_local_entry);
583 584

	return curr_flags;
585 586
}

587
static void batadv_tt_local_purge_list(struct batadv_priv *bat_priv,
588
				       struct hlist_head *head)
589
{
590 591
	struct batadv_tt_local_entry *tt_local_entry;
	struct batadv_tt_common_entry *tt_common_entry;
592
	struct hlist_node *node, *node_tmp;
593 594 595 596

	hlist_for_each_entry_safe(tt_common_entry, node, node_tmp, head,
				  hash_entry) {
		tt_local_entry = container_of(tt_common_entry,
597 598
					      struct batadv_tt_local_entry,
					      common);
599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614
		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");
	}
}

615
static void batadv_tt_local_purge(struct batadv_priv *bat_priv)
616
{
617
	struct batadv_hashtable *hash = bat_priv->tt.local_hash;
618
	struct hlist_head *head;
619
	spinlock_t *list_lock; /* protects write access to the hash lists */
620
	uint32_t i;
621 622 623

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

626
		spin_lock_bh(list_lock);
627
		batadv_tt_local_purge_list(bat_priv, head);
628
		spin_unlock_bh(list_lock);
629 630 631 632
	}

}

633
static void batadv_tt_local_table_free(struct batadv_priv *bat_priv)
634
{
635
	struct batadv_hashtable *hash;
636
	spinlock_t *list_lock; /* protects write access to the hash lists */
637 638
	struct batadv_tt_common_entry *tt_common_entry;
	struct batadv_tt_local_entry *tt_local;
639 640
	struct hlist_node *node, *node_tmp;
	struct hlist_head *head;
641
	uint32_t i;
642

643
	if (!bat_priv->tt.local_hash)
644 645
		return;

646
	hash = bat_priv->tt.local_hash;
647 648 649 650 651 652

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

		spin_lock_bh(list_lock);
653
		hlist_for_each_entry_safe(tt_common_entry, node, node_tmp,
654 655
					  head, hash_entry) {
			hlist_del_rcu(node);
656 657 658 659
			tt_local = container_of(tt_common_entry,
						struct batadv_tt_local_entry,
						common);
			batadv_tt_local_entry_free_ref(tt_local);
660 661 662 663
		}
		spin_unlock_bh(list_lock);
	}

664
	batadv_hash_destroy(hash);
665

666
	bat_priv->tt.local_hash = NULL;
667 668
}

669
static int batadv_tt_global_init(struct batadv_priv *bat_priv)
670
{
671
	if (bat_priv->tt.global_hash)
672
		return 0;
673

674
	bat_priv->tt.global_hash = batadv_hash_new(1024);
675

676
	if (!bat_priv->tt.global_hash)
677
		return -ENOMEM;
678

679
	return 0;
680 681
}

682
static void batadv_tt_changes_list_free(struct batadv_priv *bat_priv)
683
{
684
	struct batadv_tt_change_node *entry, *safe;
685

686
	spin_lock_bh(&bat_priv->tt.changes_list_lock);
687

688
	list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list,
689 690 691 692
				 list) {
		list_del(&entry->list);
		kfree(entry);
	}
693

694 695
	atomic_set(&bat_priv->tt.local_changes, 0);
	spin_unlock_bh(&bat_priv->tt.changes_list_lock);
696
}
697

698 699 700 701
/* 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
702
 */
703 704 705
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)
706
{
707
	struct batadv_tt_orig_list_entry *tmp_orig_entry, *orig_entry = NULL;
708 709 710 711 712 713
	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) {
714 715 716 717 718 719 720
		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;
721 722
	}
	rcu_read_unlock();
723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742

	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);
	}

743 744 745
	return found;
}

746
static void
747
batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global,
748
				struct batadv_orig_node *orig_node, int ttvn)
749
{
750
	struct batadv_tt_orig_list_entry *orig_entry;
751

752
	orig_entry = batadv_tt_global_orig_entry_find(tt_global, orig_node);
753 754 755 756 757
	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;
758
		goto out;
759
	}
760

761 762
	orig_entry = kzalloc(sizeof(*orig_entry), GFP_ATOMIC);
	if (!orig_entry)
763
		goto out;
764 765 766 767 768 769

	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;
770
	atomic_set(&orig_entry->refcount, 2);
771

772
	spin_lock_bh(&tt_global->list_lock);
773
	hlist_add_head_rcu(&orig_entry->list,
774 775 776 777 778
			   &tt_global->orig_list);
	spin_unlock_bh(&tt_global->list_lock);
out:
	if (orig_entry)
		batadv_tt_orig_list_entry_free_ref(orig_entry);
779 780
}

781
/* caller must hold orig_node refcount */
782 783
int batadv_tt_global_add(struct batadv_priv *bat_priv,
			 struct batadv_orig_node *orig_node,
784 785
			 const unsigned char *tt_addr, uint8_t flags,
			 uint8_t ttvn)
786
{
787 788
	struct batadv_tt_global_entry *tt_global_entry;
	struct batadv_tt_local_entry *tt_local_entry;
789
	int ret = 0;
790
	int hash_added;
791
	struct batadv_tt_common_entry *common;
792
	uint16_t local_flags;
793

794
	tt_global_entry = batadv_tt_global_hash_find(bat_priv, tt_addr);
795 796 797 798 799 800 801 802 803
	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;
804 805

	if (!tt_global_entry) {
806
		tt_global_entry = kzalloc(sizeof(*tt_global_entry), GFP_ATOMIC);
807
		if (!tt_global_entry)
808 809
			goto out;

810 811
		common = &tt_global_entry->common;
		memcpy(common->addr, tt_addr, ETH_ALEN);
812

813
		common->flags = flags;
814
		tt_global_entry->roam_at = 0;
815 816 817 818 819 820
		/* 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;
821
		atomic_set(&common->refcount, 2);
822
		common->added_at = jiffies;
823 824 825

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

827
		hash_added = batadv_hash_add(bat_priv->tt.global_hash,
828 829 830
					     batadv_compare_tt,
					     batadv_choose_orig, common,
					     &common->hash_entry);
831 832 833

		if (unlikely(hash_added != 0)) {
			/* remove the reference for the hash */
834
			batadv_tt_global_entry_free_ref(tt_global_entry);
835 836
			goto out_remove;
		}
837
	} else {
838
		common = &tt_global_entry->common;
839 840
		/* If there is already a global entry, we can use this one for
		 * our processing.
841 842 843 844 845 846 847
		 * 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
848
		 */
849 850 851 852 853 854 855 856 857
		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;
		}
858 859 860 861

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

864 865 866 867 868 869
		/* 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;

870 871
		/* If there is the BATADV_TT_CLIENT_ROAM flag set, there is only
		 * one originator left in the list and we previously received a
872 873 874 875 876
		 * delete + roaming change for this originator.
		 *
		 * We should first delete the old originator before adding the
		 * new one.
		 */
877
		if (common->flags & BATADV_TT_CLIENT_ROAM) {
878
			batadv_tt_global_del_orig_list(tt_global_entry);
879
			common->flags &= ~BATADV_TT_CLIENT_ROAM;
880
			tt_global_entry->roam_at = 0;
881 882
		}
	}
883
add_orig_entry:
884
	/* add the new orig_entry (if needed) or update it */
885
	batadv_tt_global_orig_entry_add(tt_global_entry, orig_node, ttvn);
886

887
	batadv_dbg(BATADV_DBG_TT, bat_priv,
888
		   "Creating new global tt entry: %pM (via %pM)\n",
889
		   common->addr, orig_node->orig);
890
	ret = 1;
891

892
out_remove:
893

894
	/* remove address from local hash if present */
895 896
	local_flags = batadv_tt_local_remove(bat_priv, tt_addr,
					     "global tt received",
897
					     !!(flags & BATADV_TT_CLIENT_ROAM));
898 899
	tt_global_entry->common.flags |= local_flags & BATADV_TT_CLIENT_WIFI;

900 901 902 903 904 905
	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;

906 907
out:
	if (tt_global_entry)
908
		batadv_tt_global_entry_free_ref(tt_global_entry);
909 910
	if (tt_local_entry)
		batadv_tt_local_entry_free_ref(tt_local_entry);
911
	return ret;
912 913
}

914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951
/* 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().
952
 */
953
static void
954
batadv_tt_global_print_entry(struct batadv_tt_global_entry *tt_global_entry,
955
			     struct seq_file *seq)
956 957 958
{
	struct hlist_head *head;
	struct hlist_node *node;
959
	struct batadv_tt_orig_list_entry *orig_entry, *best_entry;
960
	struct batadv_tt_common_entry *tt_common_entry;
961 962 963 964
	uint16_t flags;
	uint8_t last_ttvn;

	tt_common_entry = &tt_global_entry->common;
965 966 967 968 969 970 971 972 973 974 975 976 977
	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);
		seq_printf(seq,	" %c %pM  (%3u) via %pM     (%3u)   [%c%c%c]\n",
			   '*', tt_global_entry->common.addr,
			   best_entry->ttvn, best_entry->orig_node->orig,
			   last_ttvn,
			   (flags & BATADV_TT_CLIENT_ROAM ? 'R' : '.'),
			   (flags & BATADV_TT_CLIENT_WIFI ? 'W' : '.'),
			   (flags & BATADV_TT_CLIENT_TEMP ? 'T' : '.'));
	}
978 979 980 981

	head = &tt_global_entry->orig_list;

	hlist_for_each_entry_rcu(orig_entry, node, head, list) {
982 983 984
		if (best_entry == orig_entry)
			continue;

985
		last_ttvn = atomic_read(&orig_entry->orig_node->last_ttvn);
986 987 988 989
		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,
990
			   (flags & BATADV_TT_CLIENT_ROAM ? 'R' : '.'),
991 992
			   (flags & BATADV_TT_CLIENT_WIFI ? 'W' : '.'),
			   (flags & BATADV_TT_CLIENT_TEMP ? 'T' : '.'));
993 994 995
	}
}

996
int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset)
997 998
{
	struct net_device *net_dev = (struct net_device *)seq->private;
999
	struct batadv_priv *bat_priv = netdev_priv(net_dev);
1000
	struct batadv_hashtable *hash = bat_priv->tt.global_hash;
1001 1002 1003
	struct batadv_tt_common_entry *tt_common_entry;
	struct batadv_tt_global_entry *tt_global;
	struct batadv_hard_iface *primary_if;
1004
	struct hlist_node *node;
1005
	struct hlist_head *head;
1006
	uint32_t i;
1007

1008 1009
	primary_if = batadv_seq_print_text_primary_if_get(seq);
	if (!primary_if)
1010
		goto out;
1011

1012 1013
	seq_printf(seq,
		   "Globally announced TT entries received via the mesh %s\n",
1014
		   net_dev->name);
1015 1016
	seq_printf(seq, "       %-13s %s       %-15s %s %s\n",
		   "Client", "(TTVN)", "Originator", "(Curr TTVN)", "Flags");
1017 1018 1019 1020

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

1021
		rcu_read_lock();
1022
		hlist_for_each_entry_rcu(tt_common_entry, node,
1023
					 head, hash_entry) {
1024 1025 1026 1027
			tt_global = container_of(tt_common_entry,
						 struct batadv_tt_global_entry,
						 common);
			batadv_tt_global_print_entry(tt_global, seq);
1028
		}
1029
		rcu_read_unlock();
1030
	}
1031 1032
out:
	if (primary_if)
1033
		batadv_hardif_free_ref(primary_if);
1034
	return 0;
1035 1036
}

1037
/* deletes the orig list of a tt_global_entry */
1038
static void
1039
batadv_tt_global_del_orig_list(struct batadv_tt_global_entry *tt_global_entry)
1040
{
1041 1042
	struct hlist_head *head;
	struct hlist_node *node, *safe;
1043
	struct batadv_tt_orig_list_entry *orig_entry;
1044

1045 1046 1047 1048
	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);
1049
		batadv_tt_orig_list_entry_free_ref(orig_entry);
1050 1051
	}
	spin_unlock_bh(&tt_global_entry->list_lock);
1052

1053 1054
}

1055
static void
1056 1057 1058
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,
1059
				const char *message)
1060 1061 1062
{
	struct hlist_head *head;
	struct hlist_node *node, *safe;
1063
	struct batadv_tt_orig_list_entry *orig_entry;
1064 1065 1066 1067 1068

	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) {
1069
			batadv_dbg(BATADV_DBG_TT, bat_priv,
1070 1071 1072
				   "Deleting %pM from global tt entry %pM: %s\n",
				   orig_node->orig,
				   tt_global_entry->common.addr, message);
1073
			hlist_del_rcu(node);
1074
			batadv_tt_orig_list_entry_free_ref(orig_entry);
1075 1076 1077 1078 1079 1080
		}
	}
	spin_unlock_bh(&tt_global_entry->list_lock);
}

/* If the client is to be deleted, we check if it is the last origantor entry
1081 1082
 * 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.
1083
 */
1084
static void
1085 1086 1087 1088
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)
1089 1090 1091 1092
{
	bool last_entry = true;
	struct hlist_head *head;
	struct hlist_node *node;
1093
	struct batadv_tt_orig_list_entry *orig_entry;
1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110

	/* 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. */
1111
		tt_global_entry->common.flags |= BATADV_TT_CLIENT_ROAM;
1112 1113 1114 1115 1116
		tt_global_entry->roam_at = jiffies;
	} else
		/* there is another entry, we can simply delete this
		 * one and can still use the other one.
		 */
1117 1118
		batadv_tt_global_del_orig_entry(bat_priv, tt_global_entry,
						orig_node, message);
1119 1120 1121 1122
}



1123 1124
static void batadv_tt_global_del(struct batadv_priv *bat_priv,
				 struct batadv_orig_node *orig_node,
1125 1126
				 const unsigned char *addr,
				 const char *message, bool roaming)
1127
{
1128
	struct batadv_tt_global_entry *tt_global_entry;
1129
	struct batadv_tt_local_entry *local_entry = NULL;
1130

1131
	tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr);
1132
	if (!tt_global_entry)
1133
		goto out;
1134

1135
	if (!roaming) {
1136 1137
		batadv_tt_global_del_orig_entry(bat_priv, tt_global_entry,
						orig_node, message);
1138 1139

		if (hlist_empty(&tt_global_entry->orig_list))
1140 1141
			batadv_tt_global_free(bat_priv, tt_global_entry,
					      message);
1142 1143 1144

		goto out;
	}
1145 1146 1147

	/* if we are deleting a global entry due to a roam
	 * event, there are two possibilities:
1148 1149
	 * 1) the client roamed from node A to node B => if there
	 *    is only one originator left for this client, we mark
1150
	 *    it with BATADV_TT_CLIENT_ROAM, we start a timer and we
1151 1152
	 *    wait for node B to claim it. In case of timeout
	 *    the entry is purged.
1153 1154 1155
	 *
	 *    If there are other originators left, we directly delete
	 *    the originator.
1156
	 * 2) the client roamed to us => we can directly delete
1157 1158
	 *    the global entry, since it is useless now.
	 */
1159 1160 1161
	local_entry = batadv_tt_local_hash_find(bat_priv,
						tt_global_entry->common.addr);
	if (local_entry) {
1162
		/* local entry exists, case 2: client roamed to us. */
1163
		batadv_tt_global_del_orig_list(tt_global_entry);
1164
		batadv_tt_global_free(bat_priv, tt_global_entry, message);
1165 1166
	} else
		/* no local entry exists, case 1: check for roaming */
1167 1168
		batadv_tt_global_del_roaming(bat_priv, tt_global_entry,
					     orig_node, message);
1169 1170


1171
out:
1172
	if (tt_global_entry)
1173 1174 1175
		batadv_tt_global_entry_free_ref(tt_global_entry);
	if (local_entry)
		batadv_tt_local_entry_free_ref(local_entry);
1176 1177
}

1178 1179 1180
void batadv_tt_global_del_orig(struct batadv_priv *bat_priv,
			       struct batadv_orig_node *orig_node,
			       const char *message)
1181
{
1182 1183
	struct batadv_tt_global_entry *tt_global;
	struct batadv_tt_common_entry *tt_common_entry;
1184
	uint32_t i;
1185
	struct batadv_hashtable *hash = bat_priv->tt.global_hash;
1186 1187
	struct hlist_node *node, *safe;
	struct hlist_head *head;
1188
	spinlock_t *list_lock; /* protects write access to the hash lists */
1189

1190 1191 1192
	if (!hash)
		return;

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

1197
		spin_lock_bh(list_lock);
1198
		hlist_for_each_entry_safe(tt_common_entry, node, safe,
1199
					  head, hash_entry) {
1200 1201 1202
			tt_global = container_of(tt_common_entry,
						 struct batadv_tt_global_entry,
						 common);
1203

1204
			batadv_tt_global_del_orig_entry(bat_priv, tt_global,
1205
							orig_node, message);
1206

1207
			if (hlist_empty(&tt_global->orig_list)) {
1208
				batadv_dbg(BATADV_DBG_TT, bat_priv,
1209
					   "Deleting global tt entry %pM: %s\n",
1210
					   tt_global->common.addr, message);
1211
				hlist_del_rcu(node);
1212
				batadv_tt_global_entry_free_ref(tt_global);
1213
			}
1214
		}
1215
		spin_unlock_bh(list_lock);
1216
	}
1217
	orig_node->tt_initialised = false;
1218 1219
}

1220 1221
static bool batadv_tt_global_to_purge(struct batadv_tt_global_entry *tt_global,
				      char **msg)
1222
{
1223 1224 1225
	bool purge = false;
	unsigned long roam_timeout = BATADV_TT_CLIENT_ROAM_TIMEOUT;
	unsigned long temp_timeout = BATADV_TT_CLIENT_TEMP_TIMEOUT;
1226

1227 1228 1229 1230 1231
	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";
	}
1232

1233 1234 1235 1236
	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";
1237
	}
1238 1239

	return purge;
1240 1241
}

1242
static void batadv_tt_global_purge(struct batadv_priv *bat_priv)
1243
{
1244
	struct batadv_hashtable *hash = bat_priv->tt.global_hash;
1245
	struct hlist_head *head;
1246
	struct hlist_node *node, *node_tmp;
1247
	spinlock_t *list_lock; /* protects write access to the hash lists */
1248
	uint32_t i;
1249 1250 1251
	char *msg = NULL;
	struct batadv_tt_common_entry *tt_common;
	struct batadv_tt_global_entry *tt_global;
1252 1253 1254

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

1257
		spin_lock_bh(list_lock);
1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274
		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);
		}
1275
		spin_unlock_bh(list_lock);
1276 1277 1278
	}
}

1279
static void batadv_tt_global_table_free(struct batadv_priv *bat_priv)
1280
{
1281
	struct batadv_hashtable *hash;
1282
	spinlock_t *list_lock; /* protects write access to the hash lists */
1283 1284
	struct batadv_tt_common_entry *tt_common_entry;
	struct batadv_tt_global_entry *tt_global;
1285 1286
	struct hlist_node *node, *node_tmp;
	struct hlist_head *head;
1287
	uint32_t i;
1288

1289
	if (!bat_priv->tt.global_hash)
1290 1291
		return;

1292
	hash = bat_priv->tt.global_hash;
1293 1294 1295 1296 1297 1298

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

		spin_lock_bh(list_lock);
1299
		hlist_for_each_entry_safe(tt_common_entry, node, node_tmp,
1300 1301
					  head, hash_entry) {
			hlist_del_rcu(node);
1302 1303 1304 1305
			tt_global = container_of(tt_common_entry,
						 struct batadv_tt_global_entry,
						 common);
			batadv_tt_global_entry_free_ref(tt_global);
1306 1307 1308 1309
		}
		spin_unlock_bh(list_lock);
	}

1310
	batadv_hash_destroy(hash);
1311

1312
	bat_priv->tt.global_hash = NULL;
1313 1314
}

1315 1316 1317
static bool
_batadv_is_ap_isolated(struct batadv_tt_local_entry *tt_local_entry,
		       struct batadv_tt_global_entry *tt_global_entry)
1318 1319 1320
{
	bool ret = false;

1321 1322
	if (tt_local_entry->common.flags & BATADV_TT_CLIENT_WIFI &&
	    tt_global_entry->common.flags & BATADV_TT_CLIENT_WIFI)
1323 1324 1325 1326 1327
		ret = true;

	return ret;
}

1328 1329 1330
struct batadv_orig_node *batadv_transtable_search(struct batadv_priv *bat_priv,
						  const uint8_t *src,
						  const uint8_t *addr)
1331
{
1332 1333 1334
	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;
1335
	struct batadv_tt_orig_list_entry *best_entry;
1336

1337
	if (src && atomic_read(&bat_priv->ap_isolation)) {
1338
		tt_local_entry = batadv_tt_local_hash_find(bat_priv, src);
1339 1340
		if (!tt_local_entry ||
		    (tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING))
1341 1342
			goto out;
	}
1343

1344
	tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr);
1345
	if (!tt_global_entry)
1346
		goto out;
1347

1348
	/* check whether the clients should not communicate due to AP
1349 1350
	 * isolation
	 */
1351 1352
	if (tt_local_entry &&
	    _batadv_is_ap_isolated(tt_local_entry, tt_global_entry))
1353 1354
		goto out;

1355
	rcu_read_lock();
1356
	best_entry = batadv_transtable_best_orig(tt_global_entry);
1357
	/* found anything? */
1358 1359
	if (best_entry)
		orig_node = best_entry->orig_node;
1360 1361 1362
	if (orig_node && !atomic_inc_not_zero(&orig_node->refcount))
		orig_node = NULL;
	rcu_read_unlock();
1363

1364
out:
1365
	if (tt_global_entry)
1366
		batadv_tt_global_entry_free_ref(tt_global_entry);
1367
	if (tt_local_entry)
1368
		batadv_tt_local_entry_free_ref(tt_local_entry);
1369

1370
	return orig_node;
1371
}
1372 1373

/* Calculates the checksum of the local table of a given orig_node */
1374 1375
static uint16_t batadv_tt_global_crc(struct batadv_priv *bat_priv,
				     struct batadv_orig_node *orig_node)
1376 1377
{
	uint16_t total = 0, total_one;
1378
	struct batadv_hashtable *hash = bat_priv->tt.global_hash;
1379 1380
	struct batadv_tt_common_entry *tt_common;
	struct batadv_tt_global_entry *tt_global;
1381 1382
	struct hlist_node *node;
	struct hlist_head *head;
1383 1384
	uint32_t i;
	int j;
1385 1386 1387 1388 1389

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

		rcu_read_lock();
1390
		hlist_for_each_entry_rcu(tt_common, node, head, hash_entry) {
1391 1392 1393
			tt_global = container_of(tt_common,
						 struct batadv_tt_global_entry,
						 common);
1394 1395 1396 1397 1398
			/* Roaming clients are in the global table for
			 * consistency only. They don't have to be
			 * taken into account while computing the
			 * global crc
			 */
1399
			if (tt_common->flags & BATADV_TT_CLIENT_ROAM)
1400
				continue;
1401 1402 1403 1404 1405 1406
			/* 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;
1407 1408 1409 1410

			/* find out if this global entry is announced by this
			 * originator
			 */
1411
			if (!batadv_tt_global_entry_has_orig(tt_global,
1412
							     orig_node))
1413 1414 1415 1416 1417
				continue;

			total_one = 0;
			for (j = 0; j < ETH_ALEN; j++)
				total_one = crc16_byte(total_one,
1418
						       tt_common->addr[j]);
1419
			total ^= total_one;
1420 1421 1422 1423 1424 1425 1426 1427
		}
		rcu_read_unlock();
	}

	return total;
}

/* Calculates the checksum of the local table */
1428
static uint16_t batadv_tt_local_crc(struct batadv_priv *bat_priv)
1429 1430
{
	uint16_t total = 0, total_one;
1431
	struct batadv_hashtable *hash = bat_priv->tt.local_hash;
1432
	struct batadv_tt_common_entry *tt_common;
1433 1434
	struct hlist_node *node;
	struct hlist_head *head;
1435 1436
	uint32_t i;
	int j;
1437 1438 1439 1440 1441

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

		rcu_read_lock();
1442
		hlist_for_each_entry_rcu(tt_common, node, head, hash_entry) {
1443
			/* not yet committed clients have not to be taken into
1444 1445
			 * account while computing the CRC
			 */
1446
			if (tt_common->flags & BATADV_TT_CLIENT_NEW)
1447
				continue;
1448 1449 1450
			total_one = 0;
			for (j = 0; j < ETH_ALEN; j++)
				total_one = crc16_byte(total_one,
1451
						       tt_common->addr[j]);
1452 1453 1454 1455 1456 1457 1458 1459
			total ^= total_one;
		}
		rcu_read_unlock();
	}

	return total;
}

1460
static void batadv_tt_req_list_free(struct batadv_priv *bat_priv)
1461
{
1462
	struct batadv_tt_req_node *node, *safe;
1463

1464
	spin_lock_bh(&bat_priv->tt.req_list_lock);
1465

1466
	list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) {
1467 1468 1469 1470
		list_del(&node->list);
		kfree(node);
	}

1471
	spin_unlock_bh(&bat_priv->tt.req_list_lock);
1472 1473
}

1474 1475
static void batadv_tt_save_orig_buffer(struct batadv_priv *bat_priv,
				       struct batadv_orig_node *orig_node,
1476 1477
				       const unsigned char *tt_buff,
				       uint8_t tt_num_changes)
1478
{
1479
	uint16_t tt_buff_len = batadv_tt_len(tt_num_changes);
1480 1481

	/* Replace the old buffer only if I received something in the
1482 1483
	 * last OGM (the OGM could carry no changes)
	 */
1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496
	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);
}

1497
static void batadv_tt_req_purge(struct batadv_priv *bat_priv)
1498
{
1499
	struct batadv_tt_req_node *node, *safe;
1500

1501 1502
	spin_lock_bh(&bat_priv->tt.req_list_lock);
	list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) {
1503 1504
		if (batadv_has_timed_out(node->issued_at,
					 BATADV_TT_REQUEST_TIMEOUT)) {
1505 1506 1507 1508
			list_del(&node->list);
			kfree(node);
		}
	}
1509
	spin_unlock_bh(&bat_priv->tt.req_list_lock);
1510 1511 1512
}

/* returns the pointer to the new tt_req_node struct if no request
1513 1514
 * has already been issued for this orig_node, NULL otherwise
 */
1515 1516 1517
static struct batadv_tt_req_node *
batadv_new_tt_req_node(struct batadv_priv *bat_priv,
		       struct batadv_orig_node *orig_node)
1518
{
1519
	struct batadv_tt_req_node *tt_req_node_tmp, *tt_req_node = NULL;
1520

1521 1522
	spin_lock_bh(&bat_priv->tt.req_list_lock);
	list_for_each_entry(tt_req_node_tmp, &bat_priv->tt.req_list, list) {
1523 1524
		if (batadv_compare_eth(tt_req_node_tmp, orig_node) &&
		    !batadv_has_timed_out(tt_req_node_tmp->issued_at,
1525
					  BATADV_TT_REQUEST_TIMEOUT))
1526 1527 1528 1529 1530 1531 1532 1533 1534 1535
			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;

1536
	list_add(&tt_req_node->list, &bat_priv->tt.req_list);
1537
unlock:
1538
	spin_unlock_bh(&bat_priv->tt.req_list_lock);
1539 1540 1541
	return tt_req_node;
}

1542
/* data_ptr is useless here, but has to be kept to respect the prototype */
1543 1544
static int batadv_tt_local_valid_entry(const void *entry_ptr,
				       const void *data_ptr)
1545
{
1546
	const struct batadv_tt_common_entry *tt_common_entry = entry_ptr;
1547

1548
	if (tt_common_entry->flags & BATADV_TT_CLIENT_NEW)
1549 1550 1551 1552
		return 0;
	return 1;
}

1553 1554
static int batadv_tt_global_valid(const void *entry_ptr,
				  const void *data_ptr)
1555
{
1556 1557 1558
	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;
1559

1560 1561
	if (tt_common_entry->flags & BATADV_TT_CLIENT_ROAM ||
	    tt_common_entry->flags & BATADV_TT_CLIENT_TEMP)
1562 1563
		return 0;

1564 1565
	tt_global_entry = container_of(tt_common_entry,
				       struct batadv_tt_global_entry,
1566 1567
				       common);

1568
	return batadv_tt_global_entry_has_orig(tt_global_entry, orig_node);
1569 1570
}

1571 1572
static struct sk_buff *
batadv_tt_response_fill_table(uint16_t tt_len, uint8_t ttvn,
1573
			      struct batadv_hashtable *hash,
1574
			      struct batadv_hard_iface *primary_if,
1575 1576
			      int (*valid_cb)(const void *, const void *),
			      void *cb_data)
1577
{
1578
	struct batadv_tt_common_entry *tt_common_entry;
1579 1580
	struct batadv_tt_query_packet *tt_response;
	struct batadv_tt_change *tt_change;
1581 1582 1583 1584
	struct hlist_node *node;
	struct hlist_head *head;
	struct sk_buff *skb = NULL;
	uint16_t tt_tot, tt_count;
1585
	ssize_t tt_query_size = sizeof(struct batadv_tt_query_packet);
1586
	uint32_t i;
1587
	size_t len;
1588 1589 1590

	if (tt_query_size + tt_len > primary_if->soft_iface->mtu) {
		tt_len = primary_if->soft_iface->mtu - tt_query_size;
1591
		tt_len -= tt_len % sizeof(struct batadv_tt_change);
1592
	}
1593
	tt_tot = tt_len / sizeof(struct batadv_tt_change);
1594

1595
	len = tt_query_size + tt_len;
1596
	skb = dev_alloc_skb(len + ETH_HLEN + NET_IP_ALIGN);
1597 1598 1599
	if (!skb)
		goto out;

1600
	skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
1601
	tt_response = (struct batadv_tt_query_packet *)skb_put(skb, len);
1602 1603
	tt_response->ttvn = ttvn;

1604
	tt_change = (struct batadv_tt_change *)(skb->data + tt_query_size);
1605 1606 1607 1608 1609 1610
	tt_count = 0;

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

1611
		hlist_for_each_entry_rcu(tt_common_entry, node,
1612 1613 1614 1615
					 head, hash_entry) {
			if (tt_count == tt_tot)
				break;

1616
			if ((valid_cb) && (!valid_cb(tt_common_entry, cb_data)))
1617 1618
				continue;

1619 1620
			memcpy(tt_change->addr, tt_common_entry->addr,
			       ETH_ALEN);
1621
			tt_change->flags = tt_common_entry->flags;
1622 1623 1624 1625 1626 1627 1628

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

1629
	/* store in the message the number of entries we have successfully
1630 1631
	 * copied
	 */
1632 1633
	tt_response->tt_data = htons(tt_count);

1634 1635 1636 1637
out:
	return skb;
}

1638 1639
static int batadv_send_tt_request(struct batadv_priv *bat_priv,
				  struct batadv_orig_node *dst_orig_node,
1640 1641
				  uint8_t ttvn, uint16_t tt_crc,
				  bool full_table)
1642 1643
{
	struct sk_buff *skb = NULL;
1644
	struct batadv_tt_query_packet *tt_request;
1645 1646 1647
	struct batadv_neigh_node *neigh_node = NULL;
	struct batadv_hard_iface *primary_if;
	struct batadv_tt_req_node *tt_req_node = NULL;
1648
	int ret = 1;
1649
	size_t tt_req_len;
1650

1651
	primary_if = batadv_primary_if_get_selected(bat_priv);
1652 1653 1654 1655
	if (!primary_if)
		goto out;

	/* The new tt_req will be issued only if I'm not waiting for a
1656 1657
	 * reply from the same orig_node yet
	 */
1658
	tt_req_node = batadv_new_tt_req_node(bat_priv, dst_orig_node);
1659 1660 1661
	if (!tt_req_node)
		goto out;

1662
	skb = dev_alloc_skb(sizeof(*tt_request) + ETH_HLEN + NET_IP_ALIGN);
1663 1664 1665
	if (!skb)
		goto out;

1666
	skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
1667

1668 1669
	tt_req_len = sizeof(*tt_request);
	tt_request = (struct batadv_tt_query_packet *)skb_put(skb, tt_req_len);
1670

1671
	tt_request->header.packet_type = BATADV_TT_QUERY;
1672
	tt_request->header.version = BATADV_COMPAT_VERSION;
1673 1674
	memcpy(tt_request->src, primary_if->net_dev->dev_addr, ETH_ALEN);
	memcpy(tt_request->dst, dst_orig_node->orig, ETH_ALEN);
1675
	tt_request->header.ttl = BATADV_TTL;
1676
	tt_request->ttvn = ttvn;
1677
	tt_request->tt_data = htons(tt_crc);
1678
	tt_request->flags = BATADV_TT_REQUEST;
1679 1680

	if (full_table)
1681
		tt_request->flags |= BATADV_TT_FULL_TABLE;
1682

1683
	neigh_node = batadv_orig_node_get_router(dst_orig_node);
1684 1685 1686
	if (!neigh_node)
		goto out;

1687
	batadv_dbg(BATADV_DBG_TT, bat_priv,
1688 1689 1690
		   "Sending TT_REQUEST to %pM via %pM [%c]\n",
		   dst_orig_node->orig, neigh_node->addr,
		   (full_table ? 'F' : '.'));
1691

1692
	batadv_inc_counter(bat_priv, BATADV_CNT_TT_REQUEST_TX);
1693

1694
	batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
1695 1696 1697 1698
	ret = 0;

out:
	if (neigh_node)
1699
		batadv_neigh_node_free_ref(neigh_node);
1700
	if (primary_if)
1701
		batadv_hardif_free_ref(primary_if);
1702 1703 1704
	if (ret)
		kfree_skb(skb);
	if (ret && tt_req_node) {
1705
		spin_lock_bh(&bat_priv->tt.req_list_lock);
1706
		list_del(&tt_req_node->list);
1707
		spin_unlock_bh(&bat_priv->tt.req_list_lock);
1708 1709 1710 1711 1712
		kfree(tt_req_node);
	}
	return ret;
}

1713
static bool
1714
batadv_send_other_tt_response(struct batadv_priv *bat_priv,
1715
			      struct batadv_tt_query_packet *tt_request)
1716
{
1717
	struct batadv_orig_node *req_dst_orig_node;
1718 1719 1720
	struct batadv_orig_node *res_dst_orig_node = NULL;
	struct batadv_neigh_node *neigh_node = NULL;
	struct batadv_hard_iface *primary_if = NULL;
1721 1722 1723 1724 1725 1726
	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;
1727
	struct batadv_tt_query_packet *tt_response;
1728
	uint8_t *packet_pos;
1729
	size_t len;
1730

1731
	batadv_dbg(BATADV_DBG_TT, bat_priv,
1732 1733
		   "Received TT_REQUEST from %pM for ttvn: %u (%pM) [%c]\n",
		   tt_request->src, tt_request->ttvn, tt_request->dst,
1734
		   (tt_request->flags & BATADV_TT_FULL_TABLE ? 'F' : '.'));
1735 1736

	/* Let's get the orig node of the REAL destination */
1737
	req_dst_orig_node = batadv_orig_hash_find(bat_priv, tt_request->dst);
1738 1739 1740
	if (!req_dst_orig_node)
		goto out;

1741
	res_dst_orig_node = batadv_orig_hash_find(bat_priv, tt_request->src);
1742 1743 1744
	if (!res_dst_orig_node)
		goto out;

1745
	neigh_node = batadv_orig_node_get_router(res_dst_orig_node);
1746 1747 1748
	if (!neigh_node)
		goto out;

1749
	primary_if = batadv_primary_if_get_selected(bat_priv);
1750 1751 1752 1753 1754 1755
	if (!primary_if)
		goto out;

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

1756
	/* I don't have the requested data */
1757
	if (orig_ttvn != req_ttvn ||
1758
	    tt_request->tt_data != htons(req_dst_orig_node->tt_crc))
1759 1760
		goto out;

1761
	/* If the full table has been explicitly requested */
1762
	if (tt_request->flags & BATADV_TT_FULL_TABLE ||
1763 1764 1765 1766 1767 1768
	    !req_dst_orig_node->tt_buff)
		full_table = true;
	else
		full_table = false;

	/* In this version, fragmentation is not implemented, then
1769 1770
	 * I'll send only one packet with as much TT entries as I can
	 */
1771 1772 1773
	if (!full_table) {
		spin_lock_bh(&req_dst_orig_node->tt_buff_lock);
		tt_len = req_dst_orig_node->tt_buff_len;
1774
		tt_tot = tt_len / sizeof(struct batadv_tt_change);
1775

1776
		len = sizeof(*tt_response) + tt_len;
1777
		skb = dev_alloc_skb(len + ETH_HLEN + NET_IP_ALIGN);
1778 1779 1780
		if (!skb)
			goto unlock;

1781
		skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
1782 1783
		packet_pos = skb_put(skb, len);
		tt_response = (struct batadv_tt_query_packet *)packet_pos;
1784 1785 1786
		tt_response->ttvn = req_ttvn;
		tt_response->tt_data = htons(tt_tot);

1787
		tt_buff = skb->data + sizeof(*tt_response);
1788 1789 1790 1791 1792 1793
		/* 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 {
1794 1795
		tt_len = (uint16_t)atomic_read(&req_dst_orig_node->tt_size);
		tt_len *= sizeof(struct batadv_tt_change);
1796 1797
		ttvn = (uint8_t)atomic_read(&req_dst_orig_node->last_ttvn);

1798
		skb = batadv_tt_response_fill_table(tt_len, ttvn,
1799
						    bat_priv->tt.global_hash,
1800 1801 1802
						    primary_if,
						    batadv_tt_global_valid,
						    req_dst_orig_node);
1803 1804 1805
		if (!skb)
			goto out;

1806
		tt_response = (struct batadv_tt_query_packet *)skb->data;
1807 1808
	}

1809
	tt_response->header.packet_type = BATADV_TT_QUERY;
1810
	tt_response->header.version = BATADV_COMPAT_VERSION;
1811
	tt_response->header.ttl = BATADV_TTL;
1812 1813
	memcpy(tt_response->src, req_dst_orig_node->orig, ETH_ALEN);
	memcpy(tt_response->dst, tt_request->src, ETH_ALEN);
1814
	tt_response->flags = BATADV_TT_RESPONSE;
1815 1816

	if (full_table)
1817
		tt_response->flags |= BATADV_TT_FULL_TABLE;
1818

1819
	batadv_dbg(BATADV_DBG_TT, bat_priv,
1820 1821 1822
		   "Sending TT_RESPONSE %pM via %pM for %pM (ttvn: %u)\n",
		   res_dst_orig_node->orig, neigh_node->addr,
		   req_dst_orig_node->orig, req_ttvn);
1823

1824
	batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX);
1825

1826
	batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
1827 1828 1829 1830 1831 1832 1833 1834
	ret = true;
	goto out;

unlock:
	spin_unlock_bh(&req_dst_orig_node->tt_buff_lock);

out:
	if (res_dst_orig_node)
1835
		batadv_orig_node_free_ref(res_dst_orig_node);
1836
	if (req_dst_orig_node)
1837
		batadv_orig_node_free_ref(req_dst_orig_node);
1838
	if (neigh_node)
1839
		batadv_neigh_node_free_ref(neigh_node);
1840
	if (primary_if)
1841
		batadv_hardif_free_ref(primary_if);
1842 1843 1844 1845 1846
	if (!ret)
		kfree_skb(skb);
	return ret;

}
1847 1848

static bool
1849
batadv_send_my_tt_response(struct batadv_priv *bat_priv,
1850
			   struct batadv_tt_query_packet *tt_request)
1851
{
1852
	struct batadv_orig_node *orig_node;
1853 1854
	struct batadv_neigh_node *neigh_node = NULL;
	struct batadv_hard_iface *primary_if = NULL;
1855 1856 1857 1858 1859 1860
	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;
1861
	struct batadv_tt_query_packet *tt_response;
1862
	uint8_t *packet_pos;
1863
	size_t len;
1864

1865
	batadv_dbg(BATADV_DBG_TT, bat_priv,
1866 1867
		   "Received TT_REQUEST from %pM for ttvn: %u (me) [%c]\n",
		   tt_request->src, tt_request->ttvn,
1868
		   (tt_request->flags & BATADV_TT_FULL_TABLE ? 'F' : '.'));
1869 1870


1871
	my_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn);
1872 1873
	req_ttvn = tt_request->ttvn;

1874
	orig_node = batadv_orig_hash_find(bat_priv, tt_request->src);
1875 1876 1877
	if (!orig_node)
		goto out;

1878
	neigh_node = batadv_orig_node_get_router(orig_node);
1879 1880 1881
	if (!neigh_node)
		goto out;

1882
	primary_if = batadv_primary_if_get_selected(bat_priv);
1883 1884 1885 1886
	if (!primary_if)
		goto out;

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

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

1903
		len = sizeof(*tt_response) + tt_len;
1904
		skb = dev_alloc_skb(len + ETH_HLEN + NET_IP_ALIGN);
1905 1906 1907
		if (!skb)
			goto unlock;

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

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

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

1931
		tt_response = (struct batadv_tt_query_packet *)skb->data;
1932 1933
	}

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

	if (full_table)
1942
		tt_response->flags |= BATADV_TT_FULL_TABLE;
1943

1944
	batadv_dbg(BATADV_DBG_TT, bat_priv,
1945 1946
		   "Sending TT_RESPONSE to %pM via %pM [%c]\n",
		   orig_node->orig, neigh_node->addr,
1947
		   (tt_response->flags & BATADV_TT_FULL_TABLE ? 'F' : '.'));
1948

1949
	batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX);
1950

1951
	batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
1952 1953 1954 1955
	ret = true;
	goto out;

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

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

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

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

	for (i = 0; i < tt_num_changes; i++) {
1993 1994
		if ((tt_change + i)->flags & BATADV_TT_CLIENT_DEL) {
			roams = (tt_change + i)->flags & BATADV_TT_CLIENT_ROAM;
1995 1996
			batadv_tt_global_del(bat_priv, orig_node,
					     (tt_change + i)->addr,
1997 1998
					     "tt removed by changes",
					     roams);
1999 2000
		} else {
			if (!batadv_tt_global_add(bat_priv, orig_node,
2001 2002
						  (tt_change + i)->addr,
						  (tt_change + i)->flags, ttvn))
2003 2004 2005 2006 2007 2008 2009
				/* 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;
2010
		}
2011
	}
2012
	orig_node->tt_initialised = true;
2013 2014
}

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

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

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

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

	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)
2042
		batadv_orig_node_free_ref(orig_node);
2043 2044
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2138
	batadv_tt_start_timer(bat_priv);
2139 2140 2141 2142

	return 1;
}

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

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

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

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

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

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

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

/* 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.
 *
2177 2178
 * returns true if the ROAMING_ADV can be sent, false otherwise
 */
2179
static bool batadv_tt_check_roam_count(struct batadv_priv *bat_priv,
2180
				       uint8_t *client)
2181
{
2182
	struct batadv_tt_roam_node *tt_roam_node;
2183 2184
	bool ret = false;

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

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

2197
		if (!batadv_atomic_dec_not_zero(&tt_roam_node->counter))
2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209
			/* 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;
2210 2211
		atomic_set(&tt_roam_node->counter,
			   BATADV_ROAMING_MAX_COUNT - 1);
2212 2213
		memcpy(tt_roam_node->addr, client, ETH_ALEN);

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

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

2223 2224
static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client,
				 struct batadv_orig_node *orig_node)
2225
{
2226
	struct batadv_neigh_node *neigh_node = NULL;
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
	neigh_node = batadv_orig_node_get_router(orig_node);
2260 2261 2262
	if (!neigh_node)
		goto out;

2263
	batadv_dbg(BATADV_DBG_TT, bat_priv,
2264 2265
		   "Sending ROAMING_ADV to %pM (client %pM) via %pM\n",
		   orig_node->orig, client, neigh_node->addr);
2266

2267
	batadv_inc_counter(bat_priv, BATADV_CNT_TT_ROAM_ADV_TX);
2268

2269
	batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
2270 2271 2272 2273
	ret = 0;

out:
	if (neigh_node)
2274
		batadv_neigh_node_free_ref(neigh_node);
2275 2276 2277
	if (ret)
		kfree_skb(skb);
	return;
2278 2279
}

2280
static void batadv_tt_purge(struct work_struct *work)
2281
{
2282
	struct delayed_work *delayed_work;
2283
	struct batadv_priv_tt *priv_tt;
2284 2285 2286
	struct batadv_priv *bat_priv;

	delayed_work = container_of(work, struct delayed_work, work);
2287 2288
	priv_tt = container_of(delayed_work, struct batadv_priv_tt, work);
	bat_priv = container_of(priv_tt, struct batadv_priv, tt);
2289

2290
	batadv_tt_local_purge(bat_priv);
2291
	batadv_tt_global_purge(bat_priv);
2292 2293
	batadv_tt_req_purge(bat_priv);
	batadv_tt_roam_purge(bat_priv);
2294

2295
	batadv_tt_start_timer(bat_priv);
2296
}
2297

2298
void batadv_tt_free(struct batadv_priv *bat_priv)
2299
{
2300
	cancel_delayed_work_sync(&bat_priv->tt.work);
2301

2302 2303 2304 2305 2306
	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);
2307

2308
	kfree(bat_priv->tt.last_changeset);
2309
}
2310

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

	if (!hash)
2324
		goto out;
2325 2326 2327 2328 2329

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

		rcu_read_lock();
2330
		hlist_for_each_entry_rcu(tt_common_entry, node,
2331
					 head, hash_entry) {
2332 2333 2334 2335 2336 2337 2338 2339 2340 2341
			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++;
2342 2343 2344
		}
		rcu_read_unlock();
	}
2345 2346
out:
	return changed_num;
2347 2348
}

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

	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);
2368 2369 2370
		hlist_for_each_entry_safe(tt_common, node, node_tmp, head,
					  hash_entry) {
			if (!(tt_common->flags & BATADV_TT_CLIENT_PENDING))
2371 2372
				continue;

2373
			batadv_dbg(BATADV_DBG_TT, bat_priv,
2374
				   "Deleting local tt entry (%pM): pending\n",
2375
				   tt_common->addr);
2376

2377
			atomic_dec(&bat_priv->tt.local_entry_num);
2378
			hlist_del_rcu(node);
2379 2380 2381 2382
			tt_local = container_of(tt_common,
						struct batadv_tt_local_entry,
						common);
			batadv_tt_local_entry_free_ref(tt_local);
2383 2384 2385 2386 2387 2388
		}
		spin_unlock_bh(list_lock);
	}

}

2389
static int batadv_tt_commit_changes(struct batadv_priv *bat_priv,
2390 2391
				    unsigned char **packet_buff,
				    int *packet_buff_len, int packet_min_len)
2392
{
2393 2394
	uint16_t changed_num = 0;

2395
	if (atomic_read(&bat_priv->tt.local_changes) < 1)
2396 2397
		return -ENOENT;

2398
	changed_num = batadv_tt_set_flags(bat_priv->tt.local_hash,
2399
					  BATADV_TT_CLIENT_NEW, false);
2400 2401

	/* all reset entries have to be counted as local entries */
2402
	atomic_add(changed_num, &bat_priv->tt.local_entry_num);
2403
	batadv_tt_local_purge_pending_clients(bat_priv);
2404
	bat_priv->tt.local_crc = batadv_tt_local_crc(bat_priv);
2405 2406

	/* Increment the TTVN only once per OGM interval */
2407
	atomic_inc(&bat_priv->tt.vn);
2408
	batadv_dbg(BATADV_DBG_TT, bat_priv,
2409
		   "Local changes committed, updating to ttvn %u\n",
2410
		   (uint8_t)atomic_read(&bat_priv->tt.vn));
2411 2412

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

2415 2416
	return batadv_tt_changes_fill_buff(bat_priv, packet_buff,
					   packet_buff_len, packet_min_len);
2417 2418 2419
}

/* when calling this function (hard_iface == primary_if) has to be true */
2420
int batadv_tt_append_diff(struct batadv_priv *bat_priv,
2421 2422 2423 2424 2425 2426
			  unsigned char **packet_buff, int *packet_buff_len,
			  int packet_min_len)
{
	int tt_num_changes;

	/* if at least one change happened */
2427 2428 2429
	tt_num_changes = batadv_tt_commit_changes(bat_priv, packet_buff,
						  packet_buff_len,
						  packet_min_len);
2430 2431 2432

	/* if the changes have been sent often enough */
	if ((tt_num_changes < 0) &&
2433
	    (!batadv_atomic_dec_not_zero(&bat_priv->tt.ogm_append_cnt))) {
2434 2435
		batadv_tt_realloc_packet_buff(packet_buff, packet_buff_len,
					      packet_min_len, packet_min_len);
2436 2437 2438 2439
		tt_num_changes = 0;
	}

	return tt_num_changes;
2440
}
2441

2442
bool batadv_is_ap_isolated(struct batadv_priv *bat_priv, uint8_t *src,
2443
			   uint8_t *dst)
2444
{
2445 2446
	struct batadv_tt_local_entry *tt_local_entry = NULL;
	struct batadv_tt_global_entry *tt_global_entry = NULL;
2447
	bool ret = false;
2448 2449

	if (!atomic_read(&bat_priv->ap_isolation))
2450
		goto out;
2451

2452
	tt_local_entry = batadv_tt_local_hash_find(bat_priv, dst);
2453 2454 2455
	if (!tt_local_entry)
		goto out;

2456
	tt_global_entry = batadv_tt_global_hash_find(bat_priv, src);
2457 2458 2459
	if (!tt_global_entry)
		goto out;

2460
	if (!_batadv_is_ap_isolated(tt_local_entry, tt_global_entry))
2461 2462
		goto out;

2463
	ret = true;
2464 2465 2466

out:
	if (tt_global_entry)
2467
		batadv_tt_global_entry_free_ref(tt_global_entry);
2468
	if (tt_local_entry)
2469
		batadv_tt_local_entry_free_ref(tt_local_entry);
2470 2471
	return ret;
}
2472

2473 2474
void batadv_tt_update_orig(struct batadv_priv *bat_priv,
			   struct batadv_orig_node *orig_node,
2475 2476
			   const unsigned char *tt_buff, uint8_t tt_num_changes,
			   uint8_t ttvn, uint16_t tt_crc)
2477 2478 2479
{
	uint8_t orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
	bool full_table = true;
2480
	struct batadv_tt_change *tt_change;
2481

2482
	/* don't care about a backbone gateways updates. */
2483
	if (batadv_bla_is_backbone_gw_orig(bat_priv, orig_node->orig))
2484 2485
		return;

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

2501
		tt_change = (struct batadv_tt_change *)tt_buff;
2502
		batadv_tt_update_changes(bat_priv, orig_node, tt_num_changes,
2503
					 ttvn, tt_change);
2504 2505 2506

		/* Even if we received the precomputed crc with the OGM, we
		 * prefer to recompute it to spot any possible inconsistency
2507 2508
		 * in the global table
		 */
2509
		orig_node->tt_crc = batadv_tt_global_crc(bat_priv, orig_node);
2510 2511 2512 2513 2514 2515 2516 2517

		/* 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
2518 2519
		 * inconsistency
		 */
2520 2521 2522 2523
		if (orig_node->tt_crc != tt_crc)
			goto request_table;
	} else {
		/* if we missed more than one change or our tables are not
2524 2525
		 * in sync anymore -> request fresh tt data
		 */
2526 2527
		if (!orig_node->tt_initialised || ttvn != orig_ttvn ||
		    orig_node->tt_crc != tt_crc) {
2528
request_table:
2529
			batadv_dbg(BATADV_DBG_TT, bat_priv,
2530 2531 2532
				   "TT inconsistency for %pM. Need to retrieve the correct information (ttvn: %u last_ttvn: %u crc: %u last_crc: %u num_changes: %u)\n",
				   orig_node->orig, ttvn, orig_ttvn, tt_crc,
				   orig_node->tt_crc, tt_num_changes);
2533 2534
			batadv_send_tt_request(bat_priv, orig_node, ttvn,
					       tt_crc, full_table);
2535 2536 2537 2538
			return;
		}
	}
}
2539 2540 2541 2542 2543

/* 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
 */
2544
bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv,
2545
					uint8_t *addr)
2546
{
2547
	struct batadv_tt_global_entry *tt_global_entry;
2548 2549
	bool ret = false;

2550
	tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr);
2551 2552 2553
	if (!tt_global_entry)
		goto out;

2554
	ret = !!(tt_global_entry->common.flags & BATADV_TT_CLIENT_ROAM);
2555
	batadv_tt_global_entry_free_ref(tt_global_entry);
2556 2557 2558
out:
	return ret;
}
2559

2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585
/**
 * 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;

}

2586 2587 2588 2589 2590 2591
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;

2592 2593 2594 2595 2596 2597 2598
	/* 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;

2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610
	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;
}