gateway_client.c 17.0 KB
Newer Older
1
/*
2
 * Copyright (C) 2009-2012 B.A.T.M.A.N. contributors:
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 *
 * Marek Lindner
 *
 * 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"
23
#include "bat_sysfs.h"
24 25 26
#include "gateway_client.h"
#include "gateway_common.h"
#include "hard-interface.h"
27
#include "originator.h"
28
#include "translation-table.h"
29
#include "routing.h"
30 31 32 33 34
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/udp.h>
#include <linux/if_vlan.h>

35 36 37 38 39
/* This is the offset of the options field in a dhcp packet starting at
 * the beginning of the dhcp header */
#define DHCP_OPTIONS_OFFSET 240
#define DHCP_REQUEST 3

40
static void gw_node_free_ref(struct gw_node *gw_node)
41
{
42
	if (atomic_dec_and_test(&gw_node->refcount))
43
		kfree_rcu(gw_node, rcu);
44 45
}

46
static struct gw_node *gw_get_selected_gw_node(struct bat_priv *bat_priv)
47
{
48
	struct gw_node *gw_node;
49

50
	rcu_read_lock();
51 52
	gw_node = rcu_dereference(bat_priv->curr_gw);
	if (!gw_node)
53
		goto out;
54

55 56
	if (!atomic_inc_not_zero(&gw_node->refcount))
		gw_node = NULL;
57

58 59
out:
	rcu_read_unlock();
60
	return gw_node;
61 62
}

63
struct orig_node *gw_get_selected_orig(struct bat_priv *bat_priv)
64
{
65
	struct gw_node *gw_node;
66
	struct orig_node *orig_node = NULL;
67

68 69 70 71 72 73 74 75 76 77 78
	gw_node = gw_get_selected_gw_node(bat_priv);
	if (!gw_node)
		goto out;

	rcu_read_lock();
	orig_node = gw_node->orig_node;
	if (!orig_node)
		goto unlock;

	if (!atomic_inc_not_zero(&orig_node->refcount))
		orig_node = NULL;
79

80 81 82
unlock:
	rcu_read_unlock();
out:
83
	if (gw_node)
84
		gw_node_free_ref(gw_node);
85
	return orig_node;
86 87
}

88
static void gw_select(struct bat_priv *bat_priv, struct gw_node *new_gw_node)
89
{
90
	struct gw_node *curr_gw_node;
91

92 93
	spin_lock_bh(&bat_priv->gw_list_lock);

94 95
	if (new_gw_node && !atomic_inc_not_zero(&new_gw_node->refcount))
		new_gw_node = NULL;
96

97
	curr_gw_node = rcu_dereference_protected(bat_priv->curr_gw, 1);
98
	rcu_assign_pointer(bat_priv->curr_gw, new_gw_node);
99 100 101

	if (curr_gw_node)
		gw_node_free_ref(curr_gw_node);
102 103 104 105 106 107

	spin_unlock_bh(&bat_priv->gw_list_lock);
}

void gw_deselect(struct bat_priv *bat_priv)
{
108
	atomic_set(&bat_priv->gw_reselect, 1);
109 110
}

111
static struct gw_node *gw_get_best_gw_node(struct bat_priv *bat_priv)
112
{
113
	struct neigh_node *router;
114 115
	struct hlist_node *node;
	struct gw_node *gw_node, *curr_gw = NULL;
116
	uint32_t max_gw_factor = 0, tmp_gw_factor = 0;
117
	uint8_t max_tq = 0;
118 119
	int down, up;

120
	rcu_read_lock();
121
	hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) {
122
		if (gw_node->deleted)
123 124
			continue;

125 126
		router = orig_node_get_router(gw_node->orig_node);
		if (!router)
127 128
			continue;

129 130 131
		if (!atomic_inc_not_zero(&gw_node->refcount))
			goto next;

132 133 134 135 136
		switch (atomic_read(&bat_priv->gw_sel_class)) {
		case 1: /* fast connection */
			gw_bandwidth_to_kbit(gw_node->orig_node->gw_flags,
					     &down, &up);

137
			tmp_gw_factor = (router->tq_avg * router->tq_avg *
138 139 140 141 142 143
					 down * 100 * 100) /
					 (TQ_LOCAL_WINDOW_SIZE *
					 TQ_LOCAL_WINDOW_SIZE * 64);

			if ((tmp_gw_factor > max_gw_factor) ||
			    ((tmp_gw_factor == max_gw_factor) &&
144 145 146 147 148 149
			     (router->tq_avg > max_tq))) {
				if (curr_gw)
					gw_node_free_ref(curr_gw);
				curr_gw = gw_node;
				atomic_inc(&curr_gw->refcount);
			}
150 151 152 153 154 155 156 157 158 159
			break;

		default: /**
			  * 2:  stable connection (use best statistic)
			  * 3:  fast-switch (use best statistic but change as
			  *     soon as a better gateway appears)
			  * XX: late-switch (use best statistic but change as
			  *     soon as a better gateway appears which has
			  *     $routing_class more tq points)
			  **/
160 161 162 163 164 165
			if (router->tq_avg > max_tq) {
				if (curr_gw)
					gw_node_free_ref(curr_gw);
				curr_gw = gw_node;
				atomic_inc(&curr_gw->refcount);
			}
166 167 168
			break;
		}

169 170
		if (router->tq_avg > max_tq)
			max_tq = router->tq_avg;
171 172 173

		if (tmp_gw_factor > max_gw_factor)
			max_gw_factor = tmp_gw_factor;
174

175 176 177
		gw_node_free_ref(gw_node);

next:
178
		neigh_node_free_ref(router);
179
	}
180
	rcu_read_unlock();
181

182 183
	return curr_gw;
}
184

185 186 187 188
void gw_election(struct bat_priv *bat_priv)
{
	struct gw_node *curr_gw = NULL, *next_gw = NULL;
	struct neigh_node *router = NULL;
189
	char gw_addr[18] = { '\0' };
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210

	/**
	 * The batman daemon checks here if we already passed a full originator
	 * cycle in order to make sure we don't choose the first gateway we
	 * hear about. This check is based on the daemon's uptime which we
	 * don't have.
	 **/
	if (atomic_read(&bat_priv->gw_mode) != GW_MODE_CLIENT)
		goto out;

	if (!atomic_dec_not_zero(&bat_priv->gw_reselect))
		goto out;

	curr_gw = gw_get_selected_gw_node(bat_priv);

	next_gw = gw_get_best_gw_node(bat_priv);

	if (curr_gw == next_gw)
		goto out;

	if (next_gw) {
211 212
		sprintf(gw_addr, "%pM", next_gw->orig_node->orig);

213 214 215 216 217
		router = orig_node_get_router(next_gw->orig_node);
		if (!router) {
			gw_deselect(bat_priv);
			goto out;
		}
218 219
	}

220 221 222
	if ((curr_gw) && (!next_gw)) {
		bat_dbg(DBG_BATMAN, bat_priv,
			"Removing selected gateway - no gateway in range\n");
223
		throw_uevent(bat_priv, UEV_GW, UEV_DEL, NULL);
224 225 226
	} else if ((!curr_gw) && (next_gw)) {
		bat_dbg(DBG_BATMAN, bat_priv,
			"Adding route to gateway %pM (gw_flags: %i, tq: %i)\n",
227
			next_gw->orig_node->orig, next_gw->orig_node->gw_flags,
228
			router->tq_avg);
229
		throw_uevent(bat_priv, UEV_GW, UEV_ADD, gw_addr);
230 231
	} else {
		bat_dbg(DBG_BATMAN, bat_priv,
232 233
			"Changing route to gateway %pM (gw_flags: %i, tq: %i)\n",
			next_gw->orig_node->orig, next_gw->orig_node->gw_flags,
234
			router->tq_avg);
235
		throw_uevent(bat_priv, UEV_GW, UEV_CHANGE, gw_addr);
236 237 238 239
	}

	gw_select(bat_priv, next_gw);

240 241 242
out:
	if (curr_gw)
		gw_node_free_ref(curr_gw);
243 244 245 246
	if (next_gw)
		gw_node_free_ref(next_gw);
	if (router)
		neigh_node_free_ref(router);
247 248 249 250
}

void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node)
{
251
	struct orig_node *curr_gw_orig;
252
	struct neigh_node *router_gw = NULL, *router_orig = NULL;
253 254
	uint8_t gw_tq_avg, orig_tq_avg;

255
	curr_gw_orig = gw_get_selected_orig(bat_priv);
256 257
	if (!curr_gw_orig)
		goto deselect;
258

259 260 261
	router_gw = orig_node_get_router(curr_gw_orig);
	if (!router_gw)
		goto deselect;
262 263

	/* this node already is the gateway */
264
	if (curr_gw_orig == orig_node)
265
		goto out;
266

267 268 269
	router_orig = orig_node_get_router(orig_node);
	if (!router_orig)
		goto out;
270

271 272
	gw_tq_avg = router_gw->tq_avg;
	orig_tq_avg = router_orig->tq_avg;
273 274 275

	/* the TQ value has to be better */
	if (orig_tq_avg < gw_tq_avg)
276
		goto out;
277 278 279 280 281 282 283

	/**
	 * if the routing class is greater than 3 the value tells us how much
	 * greater the TQ value of the new gateway must be
	 **/
	if ((atomic_read(&bat_priv->gw_sel_class) > 3) &&
	    (orig_tq_avg - gw_tq_avg < atomic_read(&bat_priv->gw_sel_class)))
284
		goto out;
285 286

	bat_dbg(DBG_BATMAN, bat_priv,
287
		"Restarting gateway selection: better gateway found (tq curr: %i, tq new: %i)\n",
288 289 290 291
		gw_tq_avg, orig_tq_avg);

deselect:
	gw_deselect(bat_priv);
292
out:
293 294
	if (curr_gw_orig)
		orig_node_free_ref(curr_gw_orig);
295 296 297 298
	if (router_gw)
		neigh_node_free_ref(router_gw);
	if (router_orig)
		neigh_node_free_ref(router_orig);
299

300
	return;
301 302 303 304 305 306 307 308
}

static void gw_node_add(struct bat_priv *bat_priv,
			struct orig_node *orig_node, uint8_t new_gwflags)
{
	struct gw_node *gw_node;
	int down, up;

309
	gw_node = kzalloc(sizeof(*gw_node), GFP_ATOMIC);
310 311 312 313 314
	if (!gw_node)
		return;

	INIT_HLIST_NODE(&gw_node->list);
	gw_node->orig_node = orig_node;
315
	atomic_set(&gw_node->refcount, 1);
316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334

	spin_lock_bh(&bat_priv->gw_list_lock);
	hlist_add_head_rcu(&gw_node->list, &bat_priv->gw_list);
	spin_unlock_bh(&bat_priv->gw_list_lock);

	gw_bandwidth_to_kbit(new_gwflags, &down, &up);
	bat_dbg(DBG_BATMAN, bat_priv,
		"Found new gateway %pM -> gw_class: %i - %i%s/%i%s\n",
		orig_node->orig, new_gwflags,
		(down > 2048 ? down / 1024 : down),
		(down > 2048 ? "MBit" : "KBit"),
		(up > 2048 ? up / 1024 : up),
		(up > 2048 ? "MBit" : "KBit"));
}

void gw_node_update(struct bat_priv *bat_priv,
		    struct orig_node *orig_node, uint8_t new_gwflags)
{
	struct hlist_node *node;
335 336
	struct gw_node *gw_node, *curr_gw;

337 338 339 340 341 342
	/**
	 * Note: We don't need a NULL check here, since curr_gw never gets
	 * dereferenced. If curr_gw is NULL we also should not exit as we may
	 * have this gateway in our list (duplication check!) even though we
	 * have no currently selected gateway.
	 */
343
	curr_gw = gw_get_selected_gw_node(bat_priv);
344 345 346 347 348 349 350

	rcu_read_lock();
	hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) {
		if (gw_node->orig_node != orig_node)
			continue;

		bat_dbg(DBG_BATMAN, bat_priv,
351
			"Gateway class of originator %pM changed from %i to %i\n",
352 353 354 355 356
			orig_node->orig, gw_node->orig_node->gw_flags,
			new_gwflags);

		gw_node->deleted = 0;

357
		if (new_gwflags == NO_FLAGS) {
358 359 360 361 362
			gw_node->deleted = jiffies;
			bat_dbg(DBG_BATMAN, bat_priv,
				"Gateway %pM removed from gateway list\n",
				orig_node->orig);

363 364
			if (gw_node == curr_gw)
				goto deselect;
365 366
		}

367
		goto unlock;
368 369
	}

370
	if (new_gwflags == NO_FLAGS)
371
		goto unlock;
372 373

	gw_node_add(bat_priv, orig_node, new_gwflags);
374 375 376 377 378 379
	goto unlock;

deselect:
	gw_deselect(bat_priv);
unlock:
	rcu_read_unlock();
380

381 382
	if (curr_gw)
		gw_node_free_ref(curr_gw);
383 384 385 386
}

void gw_node_delete(struct bat_priv *bat_priv, struct orig_node *orig_node)
{
387
	gw_node_update(bat_priv, orig_node, 0);
388 389 390 391
}

void gw_node_purge(struct bat_priv *bat_priv)
{
392
	struct gw_node *gw_node, *curr_gw;
393
	struct hlist_node *node, *node_tmp;
394
	unsigned long timeout = msecs_to_jiffies(2 * PURGE_TIMEOUT);
395
	int do_deselect = 0;
396 397

	curr_gw = gw_get_selected_gw_node(bat_priv);
398 399 400 401 402 403 404 405 406 407

	spin_lock_bh(&bat_priv->gw_list_lock);

	hlist_for_each_entry_safe(gw_node, node, node_tmp,
				  &bat_priv->gw_list, list) {
		if (((!gw_node->deleted) ||
		     (time_before(jiffies, gw_node->deleted + timeout))) &&
		    atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE)
			continue;

408 409
		if (curr_gw == gw_node)
			do_deselect = 1;
410 411

		hlist_del_rcu(&gw_node->list);
412
		gw_node_free_ref(gw_node);
413 414 415
	}

	spin_unlock_bh(&bat_priv->gw_list_lock);
416 417 418 419 420 421 422

	/* gw_deselect() needs to acquire the gw_list_lock */
	if (do_deselect)
		gw_deselect(bat_priv);

	if (curr_gw)
		gw_node_free_ref(curr_gw);
423 424
}

425 426 427
/**
 * fails if orig_node has no router
 */
428 429
static int _write_buffer_text(struct bat_priv *bat_priv, struct seq_file *seq,
			      const struct gw_node *gw_node)
430
{
431
	struct gw_node *curr_gw;
432 433
	struct neigh_node *router;
	int down, up, ret = -1;
434 435 436

	gw_bandwidth_to_kbit(gw_node->orig_node->gw_flags, &down, &up);

437 438 439
	router = orig_node_get_router(gw_node->orig_node);
	if (!router)
		goto out;
440

441
	curr_gw = gw_get_selected_gw_node(bat_priv);
442 443

	ret = seq_printf(seq, "%s %pM (%3i) %pM [%10s]: %3i - %i%s/%i%s\n",
444 445 446 447 448 449 450 451 452
			 (curr_gw == gw_node ? "=>" : "  "),
			 gw_node->orig_node->orig,
			 router->tq_avg, router->addr,
			 router->if_incoming->net_dev->name,
			 gw_node->orig_node->gw_flags,
			 (down > 2048 ? down / 1024 : down),
			 (down > 2048 ? "MBit" : "KBit"),
			 (up > 2048 ? up / 1024 : up),
			 (up > 2048 ? "MBit" : "KBit"));
453

454
	neigh_node_free_ref(router);
455 456
	if (curr_gw)
		gw_node_free_ref(curr_gw);
457
out:
458
	return ret;
459 460 461 462 463 464
}

int gw_client_seq_print_text(struct seq_file *seq, void *offset)
{
	struct net_device *net_dev = (struct net_device *)seq->private;
	struct bat_priv *bat_priv = netdev_priv(net_dev);
465
	struct hard_iface *primary_if;
466 467
	struct gw_node *gw_node;
	struct hlist_node *node;
468
	int gw_count = 0, ret = 0;
469

470 471
	primary_if = primary_if_get_selected(bat_priv);
	if (!primary_if) {
472 473
		ret = seq_printf(seq,
				 "BATMAN mesh %s disabled - please specify interfaces to enable it\n",
474 475
				 net_dev->name);
		goto out;
476 477
	}

478
	if (primary_if->if_status != IF_ACTIVE) {
479 480
		ret = seq_printf(seq,
				 "BATMAN mesh %s disabled - primary interface not active\n",
481 482
				 net_dev->name);
		goto out;
483 484
	}

485 486 487 488
	seq_printf(seq,
		   "      %-12s (%s/%i) %17s [%10s]: gw_class ... [B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%pM (%s)]\n",
		   "Gateway", "#", TQ_MAX_VALUE, "Nexthop", "outgoingIF",
		   SOURCE_VERSION, primary_if->net_dev->name,
489
		   primary_if->net_dev->dev_addr, net_dev->name);
490 491 492 493 494 495

	rcu_read_lock();
	hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) {
		if (gw_node->deleted)
			continue;

496 497
		/* fails if orig_node has no router */
		if (_write_buffer_text(bat_priv, seq, gw_node) < 0)
498 499 500 501 502 503 504 505 506
			continue;

		gw_count++;
	}
	rcu_read_unlock();

	if (gw_count == 0)
		seq_printf(seq, "No gateways in range ...\n");

507 508 509 510
out:
	if (primary_if)
		hardif_free_ref(primary_if);
	return ret;
511 512
}

513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530
static bool is_type_dhcprequest(struct sk_buff *skb, int header_len)
{
	int ret = false;
	unsigned char *p;
	int pkt_len;

	if (skb_linearize(skb) < 0)
		goto out;

	pkt_len = skb_headlen(skb);

	if (pkt_len < header_len + DHCP_OPTIONS_OFFSET + 1)
		goto out;

	p = skb->data + header_len + DHCP_OPTIONS_OFFSET;
	pkt_len -= header_len + DHCP_OPTIONS_OFFSET + 1;

	/* Access the dhcp option lists. Each entry is made up by:
531 532 533
	 * - octet 1: option type
	 * - octet 2: option data len (only if type != 255 and 0)
	 * - octet 3: option data */
534
	while (*p != 255 && !ret) {
535
		/* p now points to the first octet: option type */
536 537
		if (*p == 53) {
			/* type 53 is the message type option.
538
			 * Jump the len octet and go to the data octet */
539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560
			if (pkt_len < 2)
				goto out;
			p += 2;

			/* check if the message type is what we need */
			if (*p == DHCP_REQUEST)
				ret = true;
			break;
		} else if (*p == 0) {
			/* option type 0 (padding), just go forward */
			if (pkt_len < 1)
				goto out;
			pkt_len--;
			p++;
		} else {
			/* This is any other option. So we get the length... */
			if (pkt_len < 1)
				goto out;
			pkt_len--;
			p++;

			/* ...and then we jump over the data */
561
			if (pkt_len < 1 + (*p))
562
				goto out;
563 564
			pkt_len -= 1 + (*p);
			p += 1 + (*p);
565 566 567 568 569 570
		}
	}
out:
	return ret;
}

571
bool gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len)
572 573 574 575 576 577 578
{
	struct ethhdr *ethhdr;
	struct iphdr *iphdr;
	struct ipv6hdr *ipv6hdr;
	struct udphdr *udphdr;

	/* check for ethernet header */
579 580
	if (!pskb_may_pull(skb, *header_len + ETH_HLEN))
		return false;
581
	ethhdr = (struct ethhdr *)skb->data;
582
	*header_len += ETH_HLEN;
583 584 585

	/* check for initial vlan header */
	if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) {
586 587
		if (!pskb_may_pull(skb, *header_len + VLAN_HLEN))
			return false;
588
		ethhdr = (struct ethhdr *)(skb->data + VLAN_HLEN);
589
		*header_len += VLAN_HLEN;
590 591 592 593 594
	}

	/* check for ip header */
	switch (ntohs(ethhdr->h_proto)) {
	case ETH_P_IP:
595 596 597 598
		if (!pskb_may_pull(skb, *header_len + sizeof(*iphdr)))
			return false;
		iphdr = (struct iphdr *)(skb->data + *header_len);
		*header_len += iphdr->ihl * 4;
599 600 601

		/* check for udp header */
		if (iphdr->protocol != IPPROTO_UDP)
602
			return false;
603 604 605

		break;
	case ETH_P_IPV6:
606 607 608 609
		if (!pskb_may_pull(skb, *header_len + sizeof(*ipv6hdr)))
			return false;
		ipv6hdr = (struct ipv6hdr *)(skb->data + *header_len);
		*header_len += sizeof(*ipv6hdr);
610 611 612

		/* check for udp header */
		if (ipv6hdr->nexthdr != IPPROTO_UDP)
613
			return false;
614 615 616

		break;
	default:
617
		return false;
618 619
	}

620 621 622 623
	if (!pskb_may_pull(skb, *header_len + sizeof(*udphdr)))
		return false;
	udphdr = (struct udphdr *)(skb->data + *header_len);
	*header_len += sizeof(*udphdr);
624 625 626

	/* check for bootp port */
	if ((ntohs(ethhdr->h_proto) == ETH_P_IP) &&
627
	    (ntohs(udphdr->dest) != 67))
628
		return false;
629 630 631

	if ((ntohs(ethhdr->h_proto) == ETH_P_IPV6) &&
	    (ntohs(udphdr->dest) != 547))
632
		return false;
633

634 635
	return true;
}
636

637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689
bool gw_out_of_range(struct bat_priv *bat_priv,
		     struct sk_buff *skb, struct ethhdr *ethhdr)
{
	struct neigh_node *neigh_curr = NULL, *neigh_old = NULL;
	struct orig_node *orig_dst_node = NULL;
	struct gw_node *curr_gw = NULL;
	bool ret, out_of_range = false;
	unsigned int header_len = 0;
	uint8_t curr_tq_avg;

	ret = gw_is_dhcp_target(skb, &header_len);
	if (!ret)
		goto out;

	orig_dst_node = transtable_search(bat_priv, ethhdr->h_source,
					  ethhdr->h_dest);
	if (!orig_dst_node)
		goto out;

	if (!orig_dst_node->gw_flags)
		goto out;

	ret = is_type_dhcprequest(skb, header_len);
	if (!ret)
		goto out;

	switch (atomic_read(&bat_priv->gw_mode)) {
	case GW_MODE_SERVER:
		/* If we are a GW then we are our best GW. We can artificially
		 * set the tq towards ourself as the maximum value */
		curr_tq_avg = TQ_MAX_VALUE;
		break;
	case GW_MODE_CLIENT:
		curr_gw = gw_get_selected_gw_node(bat_priv);
		if (!curr_gw)
			goto out;

		/* packet is going to our gateway */
		if (curr_gw->orig_node == orig_dst_node)
			goto out;

		/* If the dhcp packet has been sent to a different gw,
		 * we have to evaluate whether the old gw is still
		 * reliable enough */
		neigh_curr = find_router(bat_priv, curr_gw->orig_node, NULL);
		if (!neigh_curr)
			goto out;

		curr_tq_avg = neigh_curr->tq_avg;
		break;
	case GW_MODE_OFF:
	default:
		goto out;
690
	}
691 692

	neigh_old = find_router(bat_priv, orig_dst_node, NULL);
693
	if (!neigh_old)
694 695 696 697 698 699 700 701 702 703
		goto out;

	if (curr_tq_avg - neigh_old->tq_avg > GW_THRESHOLD)
		out_of_range = true;

out:
	if (orig_dst_node)
		orig_node_free_ref(orig_dst_node);
	if (curr_gw)
		gw_node_free_ref(curr_gw);
704 705 706 707
	if (neigh_old)
		neigh_node_free_ref(neigh_old);
	if (neigh_curr)
		neigh_node_free_ref(neigh_curr);
708
	return out_of_range;
709
}