diff options
author | Marek Lindner <lindner_marek@yahoo.de> | 2013-04-23 09:39:58 -0400 |
---|---|---|
committer | Antonio Quartulli <antonio@meshcoding.com> | 2013-10-09 15:22:27 -0400 |
commit | 414254e342a0d58144de40c3da777521ebaeeb07 (patch) | |
tree | a292367d064dd72f4b7a095382e11a9974d685af | |
parent | ef26157747d42254453f6b3ac2bd8bd3c53339c3 (diff) |
batman-adv: tvlv - gateway download/upload bandwidth container
Prior to this patch batman-adv read the advertised uplink bandwidth
from userspace and compressed this information into a single byte
called "gateway class".
Now the download & upload bandwidth information is sent as-is. No
userspace change is necessary since the sysfs API always allowed
to specify a bandwidth.
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
Signed-off-by: Spyros Gasteratos <morfeas3000@gmail.com>
Signed-off-by: Antonio Quartulli <antonio@meshcoding.com>
-rw-r--r-- | net/batman-adv/bat_iv_ogm.c | 23 | ||||
-rw-r--r-- | net/batman-adv/gateway_client.c | 187 | ||||
-rw-r--r-- | net/batman-adv/gateway_client.h | 2 | ||||
-rw-r--r-- | net/batman-adv/gateway_common.c | 230 | ||||
-rw-r--r-- | net/batman-adv/gateway_common.h | 14 | ||||
-rw-r--r-- | net/batman-adv/main.c | 5 | ||||
-rw-r--r-- | net/batman-adv/originator.c | 4 | ||||
-rw-r--r-- | net/batman-adv/packet.h | 21 | ||||
-rw-r--r-- | net/batman-adv/soft-interface.c | 3 | ||||
-rw-r--r-- | net/batman-adv/sysfs.c | 17 | ||||
-rw-r--r-- | net/batman-adv/types.h | 12 |
11 files changed, 327 insertions, 191 deletions
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index f7dd7e51fff4..f0f02d1a10d7 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c | |||
@@ -135,6 +135,7 @@ static int batadv_iv_ogm_iface_enable(struct batadv_hard_iface *hard_iface) | |||
135 | batadv_ogm_packet->header.version = BATADV_COMPAT_VERSION; | 135 | batadv_ogm_packet->header.version = BATADV_COMPAT_VERSION; |
136 | batadv_ogm_packet->header.ttl = 2; | 136 | batadv_ogm_packet->header.ttl = 2; |
137 | batadv_ogm_packet->flags = BATADV_NO_FLAGS; | 137 | batadv_ogm_packet->flags = BATADV_NO_FLAGS; |
138 | batadv_ogm_packet->reserved = 0; | ||
138 | batadv_ogm_packet->tq = BATADV_TQ_MAX_VALUE; | 139 | batadv_ogm_packet->tq = BATADV_TQ_MAX_VALUE; |
139 | batadv_ogm_packet->tt_num_changes = 0; | 140 | batadv_ogm_packet->tt_num_changes = 0; |
140 | batadv_ogm_packet->ttvn = 0; | 141 | batadv_ogm_packet->ttvn = 0; |
@@ -690,7 +691,6 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface) | |||
690 | int *ogm_buff_len = &hard_iface->bat_iv.ogm_buff_len; | 691 | int *ogm_buff_len = &hard_iface->bat_iv.ogm_buff_len; |
691 | int vis_server, tt_num_changes = 0; | 692 | int vis_server, tt_num_changes = 0; |
692 | uint32_t seqno; | 693 | uint32_t seqno; |
693 | uint8_t bandwidth; | ||
694 | uint16_t tvlv_len = 0; | 694 | uint16_t tvlv_len = 0; |
695 | 695 | ||
696 | vis_server = atomic_read(&bat_priv->vis_mode); | 696 | vis_server = atomic_read(&bat_priv->vis_mode); |
@@ -719,14 +719,6 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface) | |||
719 | else | 719 | else |
720 | batadv_ogm_packet->flags &= ~BATADV_VIS_SERVER; | 720 | batadv_ogm_packet->flags &= ~BATADV_VIS_SERVER; |
721 | 721 | ||
722 | if (hard_iface == primary_if && | ||
723 | atomic_read(&bat_priv->gw_mode) == BATADV_GW_MODE_SERVER) { | ||
724 | bandwidth = (uint8_t)atomic_read(&bat_priv->gw_bandwidth); | ||
725 | batadv_ogm_packet->gw_flags = bandwidth; | ||
726 | } else { | ||
727 | batadv_ogm_packet->gw_flags = BATADV_NO_FLAGS; | ||
728 | } | ||
729 | |||
730 | batadv_iv_ogm_slide_own_bcast_window(hard_iface); | 722 | batadv_iv_ogm_slide_own_bcast_window(hard_iface); |
731 | batadv_iv_ogm_queue_add(bat_priv, hard_iface->bat_iv.ogm_buff, | 723 | batadv_iv_ogm_queue_add(bat_priv, hard_iface->bat_iv.ogm_buff, |
732 | hard_iface->bat_iv.ogm_buff_len, hard_iface, 1, | 724 | hard_iface->bat_iv.ogm_buff_len, hard_iface, 1, |
@@ -861,19 +853,6 @@ update_tt: | |||
861 | batadv_ogm_packet->tt_num_changes, | 853 | batadv_ogm_packet->tt_num_changes, |
862 | batadv_ogm_packet->ttvn, | 854 | batadv_ogm_packet->ttvn, |
863 | ntohs(batadv_ogm_packet->tt_crc)); | 855 | ntohs(batadv_ogm_packet->tt_crc)); |
864 | |||
865 | if (orig_node->gw_flags != batadv_ogm_packet->gw_flags) | ||
866 | batadv_gw_node_update(bat_priv, orig_node, | ||
867 | batadv_ogm_packet->gw_flags); | ||
868 | |||
869 | orig_node->gw_flags = batadv_ogm_packet->gw_flags; | ||
870 | |||
871 | /* restart gateway selection if fast or late switching was enabled */ | ||
872 | if ((orig_node->gw_flags) && | ||
873 | (atomic_read(&bat_priv->gw_mode) == BATADV_GW_MODE_CLIENT) && | ||
874 | (atomic_read(&bat_priv->gw_sel_class) > 2)) | ||
875 | batadv_gw_check_election(bat_priv, orig_node); | ||
876 | |||
877 | goto out; | 856 | goto out; |
878 | 857 | ||
879 | unlock: | 858 | unlock: |
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index 1ce4b8763ef2..1bce63aa5f5f 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c | |||
@@ -118,7 +118,6 @@ batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv) | |||
118 | uint32_t max_gw_factor = 0, tmp_gw_factor = 0; | 118 | uint32_t max_gw_factor = 0, tmp_gw_factor = 0; |
119 | uint32_t gw_divisor; | 119 | uint32_t gw_divisor; |
120 | uint8_t max_tq = 0; | 120 | uint8_t max_tq = 0; |
121 | int down, up; | ||
122 | uint8_t tq_avg; | 121 | uint8_t tq_avg; |
123 | struct batadv_orig_node *orig_node; | 122 | struct batadv_orig_node *orig_node; |
124 | 123 | ||
@@ -142,10 +141,9 @@ batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv) | |||
142 | 141 | ||
143 | switch (atomic_read(&bat_priv->gw_sel_class)) { | 142 | switch (atomic_read(&bat_priv->gw_sel_class)) { |
144 | case 1: /* fast connection */ | 143 | case 1: /* fast connection */ |
145 | batadv_gw_bandwidth_to_kbit(orig_node->gw_flags, | 144 | tmp_gw_factor = tq_avg * tq_avg; |
146 | &down, &up); | 145 | tmp_gw_factor *= gw_node->bandwidth_down; |
147 | 146 | tmp_gw_factor *= 100 * 100; | |
148 | tmp_gw_factor = tq_avg * tq_avg * down * 100 * 100; | ||
149 | tmp_gw_factor /= gw_divisor; | 147 | tmp_gw_factor /= gw_divisor; |
150 | 148 | ||
151 | if ((tmp_gw_factor > max_gw_factor) || | 149 | if ((tmp_gw_factor > max_gw_factor) || |
@@ -258,16 +256,22 @@ void batadv_gw_election(struct batadv_priv *bat_priv) | |||
258 | NULL); | 256 | NULL); |
259 | } else if ((!curr_gw) && (next_gw)) { | 257 | } else if ((!curr_gw) && (next_gw)) { |
260 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | 258 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, |
261 | "Adding route to gateway %pM (gw_flags: %i, tq: %i)\n", | 259 | "Adding route to gateway %pM (bandwidth: %u.%u/%u.%u MBit, tq: %i)\n", |
262 | next_gw->orig_node->orig, | 260 | next_gw->orig_node->orig, |
263 | next_gw->orig_node->gw_flags, router->tq_avg); | 261 | next_gw->bandwidth_down / 10, |
262 | next_gw->bandwidth_down % 10, | ||
263 | next_gw->bandwidth_up / 10, | ||
264 | next_gw->bandwidth_up % 10, router->tq_avg); | ||
264 | batadv_throw_uevent(bat_priv, BATADV_UEV_GW, BATADV_UEV_ADD, | 265 | batadv_throw_uevent(bat_priv, BATADV_UEV_GW, BATADV_UEV_ADD, |
265 | gw_addr); | 266 | gw_addr); |
266 | } else { | 267 | } else { |
267 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | 268 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, |
268 | "Changing route to gateway %pM (gw_flags: %i, tq: %i)\n", | 269 | "Changing route to gateway %pM (bandwidth: %u.%u/%u.%u MBit, tq: %i)\n", |
269 | next_gw->orig_node->orig, | 270 | next_gw->orig_node->orig, |
270 | next_gw->orig_node->gw_flags, router->tq_avg); | 271 | next_gw->bandwidth_down / 10, |
272 | next_gw->bandwidth_down % 10, | ||
273 | next_gw->bandwidth_up / 10, | ||
274 | next_gw->bandwidth_up % 10, router->tq_avg); | ||
271 | batadv_throw_uevent(bat_priv, BATADV_UEV_GW, BATADV_UEV_CHANGE, | 275 | batadv_throw_uevent(bat_priv, BATADV_UEV_GW, BATADV_UEV_CHANGE, |
272 | gw_addr); | 276 | gw_addr); |
273 | } | 277 | } |
@@ -337,12 +341,20 @@ out: | |||
337 | return; | 341 | return; |
338 | } | 342 | } |
339 | 343 | ||
344 | /** | ||
345 | * batadv_gw_node_add - add gateway node to list of available gateways | ||
346 | * @bat_priv: the bat priv with all the soft interface information | ||
347 | * @orig_node: originator announcing gateway capabilities | ||
348 | * @gateway: announced bandwidth information | ||
349 | */ | ||
340 | static void batadv_gw_node_add(struct batadv_priv *bat_priv, | 350 | static void batadv_gw_node_add(struct batadv_priv *bat_priv, |
341 | struct batadv_orig_node *orig_node, | 351 | struct batadv_orig_node *orig_node, |
342 | uint8_t new_gwflags) | 352 | struct batadv_tvlv_gateway_data *gateway) |
343 | { | 353 | { |
344 | struct batadv_gw_node *gw_node; | 354 | struct batadv_gw_node *gw_node; |
345 | int down, up; | 355 | |
356 | if (gateway->bandwidth_down == 0) | ||
357 | return; | ||
346 | 358 | ||
347 | gw_node = kzalloc(sizeof(*gw_node), GFP_ATOMIC); | 359 | gw_node = kzalloc(sizeof(*gw_node), GFP_ATOMIC); |
348 | if (!gw_node) | 360 | if (!gw_node) |
@@ -356,73 +368,116 @@ static void batadv_gw_node_add(struct batadv_priv *bat_priv, | |||
356 | hlist_add_head_rcu(&gw_node->list, &bat_priv->gw.list); | 368 | hlist_add_head_rcu(&gw_node->list, &bat_priv->gw.list); |
357 | spin_unlock_bh(&bat_priv->gw.list_lock); | 369 | spin_unlock_bh(&bat_priv->gw.list_lock); |
358 | 370 | ||
359 | batadv_gw_bandwidth_to_kbit(new_gwflags, &down, &up); | ||
360 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | 371 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, |
361 | "Found new gateway %pM -> gw_class: %i - %i%s/%i%s\n", | 372 | "Found new gateway %pM -> gw bandwidth: %u.%u/%u.%u MBit\n", |
362 | orig_node->orig, new_gwflags, | 373 | orig_node->orig, |
363 | (down > 2048 ? down / 1024 : down), | 374 | ntohl(gateway->bandwidth_down) / 10, |
364 | (down > 2048 ? "MBit" : "KBit"), | 375 | ntohl(gateway->bandwidth_down) % 10, |
365 | (up > 2048 ? up / 1024 : up), | 376 | ntohl(gateway->bandwidth_up) / 10, |
366 | (up > 2048 ? "MBit" : "KBit")); | 377 | ntohl(gateway->bandwidth_up) % 10); |
367 | } | 378 | } |
368 | 379 | ||
369 | void batadv_gw_node_update(struct batadv_priv *bat_priv, | 380 | /** |
370 | struct batadv_orig_node *orig_node, | 381 | * batadv_gw_node_get - retrieve gateway node from list of available gateways |
371 | uint8_t new_gwflags) | 382 | * @bat_priv: the bat priv with all the soft interface information |
383 | * @orig_node: originator announcing gateway capabilities | ||
384 | * | ||
385 | * Returns gateway node if found or NULL otherwise. | ||
386 | */ | ||
387 | static struct batadv_gw_node * | ||
388 | batadv_gw_node_get(struct batadv_priv *bat_priv, | ||
389 | struct batadv_orig_node *orig_node) | ||
372 | { | 390 | { |
373 | struct batadv_gw_node *gw_node, *curr_gw; | 391 | struct batadv_gw_node *gw_node_tmp, *gw_node = NULL; |
374 | |||
375 | /* Note: We don't need a NULL check here, since curr_gw never gets | ||
376 | * dereferenced. If curr_gw is NULL we also should not exit as we may | ||
377 | * have this gateway in our list (duplication check!) even though we | ||
378 | * have no currently selected gateway. | ||
379 | */ | ||
380 | curr_gw = batadv_gw_get_selected_gw_node(bat_priv); | ||
381 | 392 | ||
382 | rcu_read_lock(); | 393 | rcu_read_lock(); |
383 | hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.list, list) { | 394 | hlist_for_each_entry_rcu(gw_node_tmp, &bat_priv->gw.list, list) { |
384 | if (gw_node->orig_node != orig_node) | 395 | if (gw_node_tmp->orig_node != orig_node) |
385 | continue; | 396 | continue; |
386 | 397 | ||
387 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | 398 | if (gw_node_tmp->deleted) |
388 | "Gateway class of originator %pM changed from %i to %i\n", | 399 | continue; |
389 | orig_node->orig, gw_node->orig_node->gw_flags, | ||
390 | new_gwflags); | ||
391 | 400 | ||
392 | gw_node->deleted = 0; | 401 | if (!atomic_inc_not_zero(&gw_node_tmp->refcount)) |
402 | continue; | ||
393 | 403 | ||
394 | if (new_gwflags == BATADV_NO_FLAGS) { | 404 | gw_node = gw_node_tmp; |
395 | gw_node->deleted = jiffies; | 405 | break; |
396 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | 406 | } |
397 | "Gateway %pM removed from gateway list\n", | 407 | rcu_read_unlock(); |
398 | orig_node->orig); | ||
399 | 408 | ||
400 | if (gw_node == curr_gw) | 409 | return gw_node; |
401 | goto deselect; | 410 | } |
402 | } | ||
403 | 411 | ||
404 | goto unlock; | 412 | /** |
413 | * batadv_gw_node_update - update list of available gateways with changed | ||
414 | * bandwidth information | ||
415 | * @bat_priv: the bat priv with all the soft interface information | ||
416 | * @orig_node: originator announcing gateway capabilities | ||
417 | * @gateway: announced bandwidth information | ||
418 | */ | ||
419 | void batadv_gw_node_update(struct batadv_priv *bat_priv, | ||
420 | struct batadv_orig_node *orig_node, | ||
421 | struct batadv_tvlv_gateway_data *gateway) | ||
422 | { | ||
423 | struct batadv_gw_node *gw_node, *curr_gw = NULL; | ||
424 | |||
425 | gw_node = batadv_gw_node_get(bat_priv, orig_node); | ||
426 | if (!gw_node) { | ||
427 | batadv_gw_node_add(bat_priv, orig_node, gateway); | ||
428 | goto out; | ||
405 | } | 429 | } |
406 | 430 | ||
407 | if (new_gwflags == BATADV_NO_FLAGS) | 431 | if ((gw_node->bandwidth_down == ntohl(gateway->bandwidth_down)) && |
408 | goto unlock; | 432 | (gw_node->bandwidth_up == ntohl(gateway->bandwidth_up))) |
433 | goto out; | ||
409 | 434 | ||
410 | batadv_gw_node_add(bat_priv, orig_node, new_gwflags); | 435 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, |
411 | goto unlock; | 436 | "Gateway bandwidth of originator %pM changed from %u.%u/%u.%u MBit to %u.%u/%u.%u MBit\n", |
437 | orig_node->orig, | ||
438 | gw_node->bandwidth_down / 10, | ||
439 | gw_node->bandwidth_down % 10, | ||
440 | gw_node->bandwidth_up / 10, | ||
441 | gw_node->bandwidth_up % 10, | ||
442 | ntohl(gateway->bandwidth_down) / 10, | ||
443 | ntohl(gateway->bandwidth_down) % 10, | ||
444 | ntohl(gateway->bandwidth_up) / 10, | ||
445 | ntohl(gateway->bandwidth_up) % 10); | ||
446 | |||
447 | gw_node->bandwidth_down = ntohl(gateway->bandwidth_down); | ||
448 | gw_node->bandwidth_up = ntohl(gateway->bandwidth_up); | ||
449 | |||
450 | gw_node->deleted = 0; | ||
451 | if (ntohl(gateway->bandwidth_down) == 0) { | ||
452 | gw_node->deleted = jiffies; | ||
453 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | ||
454 | "Gateway %pM removed from gateway list\n", | ||
455 | orig_node->orig); | ||
412 | 456 | ||
413 | deselect: | 457 | /* Note: We don't need a NULL check here, since curr_gw never |
414 | batadv_gw_deselect(bat_priv); | 458 | * gets dereferenced. |
415 | unlock: | 459 | */ |
416 | rcu_read_unlock(); | 460 | curr_gw = batadv_gw_get_selected_gw_node(bat_priv); |
461 | if (gw_node == curr_gw) | ||
462 | batadv_gw_deselect(bat_priv); | ||
463 | } | ||
417 | 464 | ||
465 | out: | ||
418 | if (curr_gw) | 466 | if (curr_gw) |
419 | batadv_gw_node_free_ref(curr_gw); | 467 | batadv_gw_node_free_ref(curr_gw); |
468 | if (gw_node) | ||
469 | batadv_gw_node_free_ref(gw_node); | ||
420 | } | 470 | } |
421 | 471 | ||
422 | void batadv_gw_node_delete(struct batadv_priv *bat_priv, | 472 | void batadv_gw_node_delete(struct batadv_priv *bat_priv, |
423 | struct batadv_orig_node *orig_node) | 473 | struct batadv_orig_node *orig_node) |
424 | { | 474 | { |
425 | batadv_gw_node_update(bat_priv, orig_node, 0); | 475 | struct batadv_tvlv_gateway_data gateway; |
476 | |||
477 | gateway.bandwidth_down = 0; | ||
478 | gateway.bandwidth_up = 0; | ||
479 | |||
480 | batadv_gw_node_update(bat_priv, orig_node, &gateway); | ||
426 | } | 481 | } |
427 | 482 | ||
428 | void batadv_gw_node_purge(struct batadv_priv *bat_priv) | 483 | void batadv_gw_node_purge(struct batadv_priv *bat_priv) |
@@ -467,9 +522,7 @@ static int batadv_write_buffer_text(struct batadv_priv *bat_priv, | |||
467 | { | 522 | { |
468 | struct batadv_gw_node *curr_gw; | 523 | struct batadv_gw_node *curr_gw; |
469 | struct batadv_neigh_node *router; | 524 | struct batadv_neigh_node *router; |
470 | int down, up, ret = -1; | 525 | int ret = -1; |
471 | |||
472 | batadv_gw_bandwidth_to_kbit(gw_node->orig_node->gw_flags, &down, &up); | ||
473 | 526 | ||
474 | router = batadv_orig_node_get_router(gw_node->orig_node); | 527 | router = batadv_orig_node_get_router(gw_node->orig_node); |
475 | if (!router) | 528 | if (!router) |
@@ -477,16 +530,15 @@ static int batadv_write_buffer_text(struct batadv_priv *bat_priv, | |||
477 | 530 | ||
478 | curr_gw = batadv_gw_get_selected_gw_node(bat_priv); | 531 | curr_gw = batadv_gw_get_selected_gw_node(bat_priv); |
479 | 532 | ||
480 | ret = seq_printf(seq, "%s %pM (%3i) %pM [%10s]: %3i - %i%s/%i%s\n", | 533 | ret = seq_printf(seq, "%s %pM (%3i) %pM [%10s]: %u.%u/%u.%u MBit\n", |
481 | (curr_gw == gw_node ? "=>" : " "), | 534 | (curr_gw == gw_node ? "=>" : " "), |
482 | gw_node->orig_node->orig, | 535 | gw_node->orig_node->orig, |
483 | router->tq_avg, router->addr, | 536 | router->tq_avg, router->addr, |
484 | router->if_incoming->net_dev->name, | 537 | router->if_incoming->net_dev->name, |
485 | gw_node->orig_node->gw_flags, | 538 | gw_node->bandwidth_down / 10, |
486 | (down > 2048 ? down / 1024 : down), | 539 | gw_node->bandwidth_down % 10, |
487 | (down > 2048 ? "MBit" : "KBit"), | 540 | gw_node->bandwidth_up / 10, |
488 | (up > 2048 ? up / 1024 : up), | 541 | gw_node->bandwidth_up % 10); |
489 | (up > 2048 ? "MBit" : "KBit")); | ||
490 | 542 | ||
491 | batadv_neigh_node_free_ref(router); | 543 | batadv_neigh_node_free_ref(router); |
492 | if (curr_gw) | 544 | if (curr_gw) |
@@ -508,7 +560,7 @@ int batadv_gw_client_seq_print_text(struct seq_file *seq, void *offset) | |||
508 | goto out; | 560 | goto out; |
509 | 561 | ||
510 | seq_printf(seq, | 562 | seq_printf(seq, |
511 | " %-12s (%s/%i) %17s [%10s]: gw_class ... [B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%pM (%s)]\n", | 563 | " %-12s (%s/%i) %17s [%10s]: advertised uplink bandwidth ... [B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%pM (%s)]\n", |
512 | "Gateway", "#", BATADV_TQ_MAX_VALUE, "Nexthop", "outgoingIF", | 564 | "Gateway", "#", BATADV_TQ_MAX_VALUE, "Nexthop", "outgoingIF", |
513 | BATADV_SOURCE_VERSION, primary_if->net_dev->name, | 565 | BATADV_SOURCE_VERSION, primary_if->net_dev->name, |
514 | primary_if->net_dev->dev_addr, net_dev->name); | 566 | primary_if->net_dev->dev_addr, net_dev->name); |
@@ -675,7 +727,7 @@ bool batadv_gw_out_of_range(struct batadv_priv *bat_priv, | |||
675 | { | 727 | { |
676 | struct batadv_neigh_node *neigh_curr = NULL, *neigh_old = NULL; | 728 | struct batadv_neigh_node *neigh_curr = NULL, *neigh_old = NULL; |
677 | struct batadv_orig_node *orig_dst_node = NULL; | 729 | struct batadv_orig_node *orig_dst_node = NULL; |
678 | struct batadv_gw_node *curr_gw = NULL; | 730 | struct batadv_gw_node *gw_node = NULL, *curr_gw = NULL; |
679 | struct ethhdr *ethhdr; | 731 | struct ethhdr *ethhdr; |
680 | bool ret, out_of_range = false; | 732 | bool ret, out_of_range = false; |
681 | unsigned int header_len = 0; | 733 | unsigned int header_len = 0; |
@@ -691,7 +743,8 @@ bool batadv_gw_out_of_range(struct batadv_priv *bat_priv, | |||
691 | if (!orig_dst_node) | 743 | if (!orig_dst_node) |
692 | goto out; | 744 | goto out; |
693 | 745 | ||
694 | if (!orig_dst_node->gw_flags) | 746 | gw_node = batadv_gw_node_get(bat_priv, orig_dst_node); |
747 | if (!gw_node->bandwidth_down == 0) | ||
695 | goto out; | 748 | goto out; |
696 | 749 | ||
697 | ret = batadv_is_type_dhcprequest(skb, header_len); | 750 | ret = batadv_is_type_dhcprequest(skb, header_len); |
@@ -742,6 +795,8 @@ out: | |||
742 | batadv_orig_node_free_ref(orig_dst_node); | 795 | batadv_orig_node_free_ref(orig_dst_node); |
743 | if (curr_gw) | 796 | if (curr_gw) |
744 | batadv_gw_node_free_ref(curr_gw); | 797 | batadv_gw_node_free_ref(curr_gw); |
798 | if (gw_node) | ||
799 | batadv_gw_node_free_ref(gw_node); | ||
745 | if (neigh_old) | 800 | if (neigh_old) |
746 | batadv_neigh_node_free_ref(neigh_old); | 801 | batadv_neigh_node_free_ref(neigh_old); |
747 | if (neigh_curr) | 802 | if (neigh_curr) |
diff --git a/net/batman-adv/gateway_client.h b/net/batman-adv/gateway_client.h index ceef4ebe8bcd..d95c2d23195e 100644 --- a/net/batman-adv/gateway_client.h +++ b/net/batman-adv/gateway_client.h | |||
@@ -29,7 +29,7 @@ void batadv_gw_check_election(struct batadv_priv *bat_priv, | |||
29 | struct batadv_orig_node *orig_node); | 29 | struct batadv_orig_node *orig_node); |
30 | void batadv_gw_node_update(struct batadv_priv *bat_priv, | 30 | void batadv_gw_node_update(struct batadv_priv *bat_priv, |
31 | struct batadv_orig_node *orig_node, | 31 | struct batadv_orig_node *orig_node, |
32 | uint8_t new_gwflags); | 32 | struct batadv_tvlv_gateway_data *gateway); |
33 | void batadv_gw_node_delete(struct batadv_priv *bat_priv, | 33 | void batadv_gw_node_delete(struct batadv_priv *bat_priv, |
34 | struct batadv_orig_node *orig_node); | 34 | struct batadv_orig_node *orig_node); |
35 | void batadv_gw_node_purge(struct batadv_priv *bat_priv); | 35 | void batadv_gw_node_purge(struct batadv_priv *bat_priv); |
diff --git a/net/batman-adv/gateway_common.c b/net/batman-adv/gateway_common.c index 84bb2b18d711..b211b0f9cb78 100644 --- a/net/batman-adv/gateway_common.c +++ b/net/batman-adv/gateway_common.c | |||
@@ -21,64 +21,23 @@ | |||
21 | #include "gateway_common.h" | 21 | #include "gateway_common.h" |
22 | #include "gateway_client.h" | 22 | #include "gateway_client.h" |
23 | 23 | ||
24 | /* calculates the gateway class from kbit */ | 24 | /** |
25 | static void batadv_kbit_to_gw_bandwidth(int down, int up, long *gw_srv_class) | 25 | * batadv_parse_gw_bandwidth - parse supplied string buffer to extract download |
26 | { | 26 | * and upload bandwidth information |
27 | int mdown = 0, tdown, tup, difference; | 27 | * @net_dev: the soft interface net device |
28 | uint8_t sbit, part; | 28 | * @buff: string buffer to parse |
29 | 29 | * @down: pointer holding the returned download bandwidth information | |
30 | *gw_srv_class = 0; | 30 | * @up: pointer holding the returned upload bandwidth information |
31 | difference = 0x0FFFFFFF; | 31 | * |
32 | 32 | * Returns false on parse error and true otherwise. | |
33 | /* test all downspeeds */ | 33 | */ |
34 | for (sbit = 0; sbit < 2; sbit++) { | ||
35 | for (part = 0; part < 16; part++) { | ||
36 | tdown = 32 * (sbit + 2) * (1 << part); | ||
37 | |||
38 | if (abs(tdown - down) < difference) { | ||
39 | *gw_srv_class = (sbit << 7) + (part << 3); | ||
40 | difference = abs(tdown - down); | ||
41 | mdown = tdown; | ||
42 | } | ||
43 | } | ||
44 | } | ||
45 | |||
46 | /* test all upspeeds */ | ||
47 | difference = 0x0FFFFFFF; | ||
48 | |||
49 | for (part = 0; part < 8; part++) { | ||
50 | tup = ((part + 1) * (mdown)) / 8; | ||
51 | |||
52 | if (abs(tup - up) < difference) { | ||
53 | *gw_srv_class = (*gw_srv_class & 0xF8) | part; | ||
54 | difference = abs(tup - up); | ||
55 | } | ||
56 | } | ||
57 | } | ||
58 | |||
59 | /* returns the up and downspeeds in kbit, calculated from the class */ | ||
60 | void batadv_gw_bandwidth_to_kbit(uint8_t gw_srv_class, int *down, int *up) | ||
61 | { | ||
62 | int sbit = (gw_srv_class & 0x80) >> 7; | ||
63 | int dpart = (gw_srv_class & 0x78) >> 3; | ||
64 | int upart = (gw_srv_class & 0x07); | ||
65 | |||
66 | if (!gw_srv_class) { | ||
67 | *down = 0; | ||
68 | *up = 0; | ||
69 | return; | ||
70 | } | ||
71 | |||
72 | *down = 32 * (sbit + 2) * (1 << dpart); | ||
73 | *up = ((upart + 1) * (*down)) / 8; | ||
74 | } | ||
75 | |||
76 | static bool batadv_parse_gw_bandwidth(struct net_device *net_dev, char *buff, | 34 | static bool batadv_parse_gw_bandwidth(struct net_device *net_dev, char *buff, |
77 | int *up, int *down) | 35 | uint32_t *down, uint32_t *up) |
78 | { | 36 | { |
79 | int ret, multi = 1; | 37 | enum batadv_bandwidth_units bw_unit_type = BATADV_BW_UNIT_KBIT; |
80 | char *slash_ptr, *tmp_ptr; | 38 | char *slash_ptr, *tmp_ptr; |
81 | long ldown, lup; | 39 | long ldown, lup; |
40 | int ret; | ||
82 | 41 | ||
83 | slash_ptr = strchr(buff, '/'); | 42 | slash_ptr = strchr(buff, '/'); |
84 | if (slash_ptr) | 43 | if (slash_ptr) |
@@ -88,10 +47,10 @@ static bool batadv_parse_gw_bandwidth(struct net_device *net_dev, char *buff, | |||
88 | tmp_ptr = buff + strlen(buff) - 4; | 47 | tmp_ptr = buff + strlen(buff) - 4; |
89 | 48 | ||
90 | if (strnicmp(tmp_ptr, "mbit", 4) == 0) | 49 | if (strnicmp(tmp_ptr, "mbit", 4) == 0) |
91 | multi = 1024; | 50 | bw_unit_type = BATADV_BW_UNIT_MBIT; |
92 | 51 | ||
93 | if ((strnicmp(tmp_ptr, "kbit", 4) == 0) || | 52 | if ((strnicmp(tmp_ptr, "kbit", 4) == 0) || |
94 | (multi > 1)) | 53 | (bw_unit_type == BATADV_BW_UNIT_MBIT)) |
95 | *tmp_ptr = '\0'; | 54 | *tmp_ptr = '\0'; |
96 | } | 55 | } |
97 | 56 | ||
@@ -103,20 +62,28 @@ static bool batadv_parse_gw_bandwidth(struct net_device *net_dev, char *buff, | |||
103 | return false; | 62 | return false; |
104 | } | 63 | } |
105 | 64 | ||
106 | *down = ldown * multi; | 65 | switch (bw_unit_type) { |
66 | case BATADV_BW_UNIT_MBIT: | ||
67 | *down = ldown * 10; | ||
68 | break; | ||
69 | case BATADV_BW_UNIT_KBIT: | ||
70 | default: | ||
71 | *down = ldown / 100; | ||
72 | break; | ||
73 | } | ||
107 | 74 | ||
108 | /* we also got some upload info */ | 75 | /* we also got some upload info */ |
109 | if (slash_ptr) { | 76 | if (slash_ptr) { |
110 | multi = 1; | 77 | bw_unit_type = BATADV_BW_UNIT_KBIT; |
111 | 78 | ||
112 | if (strlen(slash_ptr + 1) > 4) { | 79 | if (strlen(slash_ptr + 1) > 4) { |
113 | tmp_ptr = slash_ptr + 1 - 4 + strlen(slash_ptr + 1); | 80 | tmp_ptr = slash_ptr + 1 - 4 + strlen(slash_ptr + 1); |
114 | 81 | ||
115 | if (strnicmp(tmp_ptr, "mbit", 4) == 0) | 82 | if (strnicmp(tmp_ptr, "mbit", 4) == 0) |
116 | multi = 1024; | 83 | bw_unit_type = BATADV_BW_UNIT_MBIT; |
117 | 84 | ||
118 | if ((strnicmp(tmp_ptr, "kbit", 4) == 0) || | 85 | if ((strnicmp(tmp_ptr, "kbit", 4) == 0) || |
119 | (multi > 1)) | 86 | (bw_unit_type == BATADV_BW_UNIT_MBIT)) |
120 | *tmp_ptr = '\0'; | 87 | *tmp_ptr = '\0'; |
121 | } | 88 | } |
122 | 89 | ||
@@ -128,52 +95,149 @@ static bool batadv_parse_gw_bandwidth(struct net_device *net_dev, char *buff, | |||
128 | return false; | 95 | return false; |
129 | } | 96 | } |
130 | 97 | ||
131 | *up = lup * multi; | 98 | switch (bw_unit_type) { |
99 | case BATADV_BW_UNIT_MBIT: | ||
100 | *up = lup * 10; | ||
101 | break; | ||
102 | case BATADV_BW_UNIT_KBIT: | ||
103 | default: | ||
104 | *up = lup / 100; | ||
105 | break; | ||
106 | } | ||
132 | } | 107 | } |
133 | 108 | ||
134 | return true; | 109 | return true; |
135 | } | 110 | } |
136 | 111 | ||
112 | /** | ||
113 | * batadv_gw_tvlv_container_update - update the gw tvlv container after gateway | ||
114 | * setting change | ||
115 | * @bat_priv: the bat priv with all the soft interface information | ||
116 | */ | ||
117 | void batadv_gw_tvlv_container_update(struct batadv_priv *bat_priv) | ||
118 | { | ||
119 | struct batadv_tvlv_gateway_data gw; | ||
120 | uint32_t down, up; | ||
121 | char gw_mode; | ||
122 | |||
123 | gw_mode = atomic_read(&bat_priv->gw_mode); | ||
124 | |||
125 | switch (gw_mode) { | ||
126 | case BATADV_GW_MODE_OFF: | ||
127 | case BATADV_GW_MODE_CLIENT: | ||
128 | batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_GW, 1); | ||
129 | break; | ||
130 | case BATADV_GW_MODE_SERVER: | ||
131 | down = atomic_read(&bat_priv->gw.bandwidth_down); | ||
132 | up = atomic_read(&bat_priv->gw.bandwidth_up); | ||
133 | gw.bandwidth_down = htonl(down); | ||
134 | gw.bandwidth_up = htonl(up); | ||
135 | batadv_tvlv_container_register(bat_priv, BATADV_TVLV_GW, 1, | ||
136 | &gw, sizeof(gw)); | ||
137 | break; | ||
138 | } | ||
139 | } | ||
140 | |||
137 | ssize_t batadv_gw_bandwidth_set(struct net_device *net_dev, char *buff, | 141 | ssize_t batadv_gw_bandwidth_set(struct net_device *net_dev, char *buff, |
138 | size_t count) | 142 | size_t count) |
139 | { | 143 | { |
140 | struct batadv_priv *bat_priv = netdev_priv(net_dev); | 144 | struct batadv_priv *bat_priv = netdev_priv(net_dev); |
141 | long gw_bandwidth_tmp = 0; | 145 | uint32_t down_curr, up_curr, down_new = 0, up_new = 0; |
142 | int up = 0, down = 0; | ||
143 | bool ret; | 146 | bool ret; |
144 | 147 | ||
145 | ret = batadv_parse_gw_bandwidth(net_dev, buff, &up, &down); | 148 | down_curr = (unsigned int)atomic_read(&bat_priv->gw.bandwidth_down); |
149 | up_curr = (unsigned int)atomic_read(&bat_priv->gw.bandwidth_up); | ||
150 | |||
151 | ret = batadv_parse_gw_bandwidth(net_dev, buff, &down_new, &up_new); | ||
146 | if (!ret) | 152 | if (!ret) |
147 | goto end; | 153 | goto end; |
148 | 154 | ||
149 | if ((!down) || (down < 256)) | 155 | if (!down_new) |
150 | down = 2000; | 156 | down_new = 1; |
151 | |||
152 | if (!up) | ||
153 | up = down / 5; | ||
154 | 157 | ||
155 | batadv_kbit_to_gw_bandwidth(down, up, &gw_bandwidth_tmp); | 158 | if (!up_new) |
159 | up_new = down_new / 5; | ||
156 | 160 | ||
157 | /* the gw bandwidth we guessed above might not match the given | 161 | if (!up_new) |
158 | * speeds, hence we need to calculate it back to show the number | 162 | up_new = 1; |
159 | * that is going to be propagated | ||
160 | */ | ||
161 | batadv_gw_bandwidth_to_kbit((uint8_t)gw_bandwidth_tmp, &down, &up); | ||
162 | 163 | ||
163 | if (atomic_read(&bat_priv->gw_bandwidth) == gw_bandwidth_tmp) | 164 | if ((down_curr == down_new) && (up_curr == up_new)) |
164 | return count; | 165 | return count; |
165 | 166 | ||
166 | batadv_gw_deselect(bat_priv); | 167 | batadv_gw_deselect(bat_priv); |
167 | batadv_info(net_dev, | 168 | batadv_info(net_dev, |
168 | "Changing gateway bandwidth from: '%i' to: '%ld' (propagating: %d%s/%d%s)\n", | 169 | "Changing gateway bandwidth from: '%u.%u/%u.%u MBit' to: '%u.%u/%u.%u MBit'\n", |
169 | atomic_read(&bat_priv->gw_bandwidth), gw_bandwidth_tmp, | 170 | down_curr / 10, down_curr % 10, up_curr / 10, up_curr % 10, |
170 | (down > 2048 ? down / 1024 : down), | 171 | down_new / 10, down_new % 10, up_new / 10, up_new % 10); |
171 | (down > 2048 ? "MBit" : "KBit"), | ||
172 | (up > 2048 ? up / 1024 : up), | ||
173 | (up > 2048 ? "MBit" : "KBit")); | ||
174 | 172 | ||
175 | atomic_set(&bat_priv->gw_bandwidth, gw_bandwidth_tmp); | 173 | atomic_set(&bat_priv->gw.bandwidth_down, down_new); |
174 | atomic_set(&bat_priv->gw.bandwidth_up, up_new); | ||
175 | batadv_gw_tvlv_container_update(bat_priv); | ||
176 | 176 | ||
177 | end: | 177 | end: |
178 | return count; | 178 | return count; |
179 | } | 179 | } |
180 | |||
181 | /** | ||
182 | * batadv_gw_tvlv_ogm_handler_v1 - process incoming gateway tvlv container | ||
183 | * @bat_priv: the bat priv with all the soft interface information | ||
184 | * @orig: the orig_node of the ogm | ||
185 | * @flags: flags indicating the tvlv state (see batadv_tvlv_handler_flags) | ||
186 | * @tvlv_value: tvlv buffer containing the gateway data | ||
187 | * @tvlv_value_len: tvlv buffer length | ||
188 | */ | ||
189 | static void batadv_gw_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv, | ||
190 | struct batadv_orig_node *orig, | ||
191 | uint8_t flags, | ||
192 | void *tvlv_value, | ||
193 | uint16_t tvlv_value_len) | ||
194 | { | ||
195 | struct batadv_tvlv_gateway_data gateway, *gateway_ptr; | ||
196 | |||
197 | /* only fetch the tvlv value if the handler wasn't called via the | ||
198 | * CIFNOTFND flag and if there is data to fetch | ||
199 | */ | ||
200 | if ((flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND) || | ||
201 | (tvlv_value_len < sizeof(gateway))) { | ||
202 | gateway.bandwidth_down = 0; | ||
203 | gateway.bandwidth_up = 0; | ||
204 | } else { | ||
205 | gateway_ptr = tvlv_value; | ||
206 | gateway.bandwidth_down = gateway_ptr->bandwidth_down; | ||
207 | gateway.bandwidth_up = gateway_ptr->bandwidth_up; | ||
208 | if ((gateway.bandwidth_down == 0) || | ||
209 | (gateway.bandwidth_up == 0)) { | ||
210 | gateway.bandwidth_down = 0; | ||
211 | gateway.bandwidth_up = 0; | ||
212 | } | ||
213 | } | ||
214 | |||
215 | batadv_gw_node_update(bat_priv, orig, &gateway); | ||
216 | |||
217 | /* restart gateway selection if fast or late switching was enabled */ | ||
218 | if ((gateway.bandwidth_down != 0) && | ||
219 | (atomic_read(&bat_priv->gw_mode) == BATADV_GW_MODE_CLIENT) && | ||
220 | (atomic_read(&bat_priv->gw_sel_class) > 2)) | ||
221 | batadv_gw_check_election(bat_priv, orig); | ||
222 | } | ||
223 | |||
224 | /** | ||
225 | * batadv_gw_init - initialise the gateway handling internals | ||
226 | * @bat_priv: the bat priv with all the soft interface information | ||
227 | */ | ||
228 | void batadv_gw_init(struct batadv_priv *bat_priv) | ||
229 | { | ||
230 | batadv_tvlv_handler_register(bat_priv, batadv_gw_tvlv_ogm_handler_v1, | ||
231 | NULL, BATADV_TVLV_GW, 1, | ||
232 | BATADV_TVLV_HANDLER_OGM_CIFNOTFND); | ||
233 | } | ||
234 | |||
235 | /** | ||
236 | * batadv_gw_free - free the gateway handling internals | ||
237 | * @bat_priv: the bat priv with all the soft interface information | ||
238 | */ | ||
239 | void batadv_gw_free(struct batadv_priv *bat_priv) | ||
240 | { | ||
241 | batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_GW, 1); | ||
242 | batadv_tvlv_handler_unregister(bat_priv, BATADV_TVLV_GW, 1); | ||
243 | } | ||
diff --git a/net/batman-adv/gateway_common.h b/net/batman-adv/gateway_common.h index 509b2bf8c2f4..56384a4cd18c 100644 --- a/net/batman-adv/gateway_common.h +++ b/net/batman-adv/gateway_common.h | |||
@@ -26,12 +26,24 @@ enum batadv_gw_modes { | |||
26 | BATADV_GW_MODE_SERVER, | 26 | BATADV_GW_MODE_SERVER, |
27 | }; | 27 | }; |
28 | 28 | ||
29 | /** | ||
30 | * enum batadv_bandwidth_units - bandwidth unit types | ||
31 | * @BATADV_BW_UNIT_KBIT: unit type kbit | ||
32 | * @BATADV_BW_UNIT_MBIT: unit type mbit | ||
33 | */ | ||
34 | enum batadv_bandwidth_units { | ||
35 | BATADV_BW_UNIT_KBIT, | ||
36 | BATADV_BW_UNIT_MBIT, | ||
37 | }; | ||
38 | |||
29 | #define BATADV_GW_MODE_OFF_NAME "off" | 39 | #define BATADV_GW_MODE_OFF_NAME "off" |
30 | #define BATADV_GW_MODE_CLIENT_NAME "client" | 40 | #define BATADV_GW_MODE_CLIENT_NAME "client" |
31 | #define BATADV_GW_MODE_SERVER_NAME "server" | 41 | #define BATADV_GW_MODE_SERVER_NAME "server" |
32 | 42 | ||
33 | void batadv_gw_bandwidth_to_kbit(uint8_t gw_class, int *down, int *up); | ||
34 | ssize_t batadv_gw_bandwidth_set(struct net_device *net_dev, char *buff, | 43 | ssize_t batadv_gw_bandwidth_set(struct net_device *net_dev, char *buff, |
35 | size_t count); | 44 | size_t count); |
45 | void batadv_gw_tvlv_container_update(struct batadv_priv *bat_priv); | ||
46 | void batadv_gw_init(struct batadv_priv *bat_priv); | ||
47 | void batadv_gw_free(struct batadv_priv *bat_priv); | ||
36 | 48 | ||
37 | #endif /* _NET_BATMAN_ADV_GATEWAY_COMMON_H_ */ | 49 | #endif /* _NET_BATMAN_ADV_GATEWAY_COMMON_H_ */ |
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c index e2de68a5b0c6..cb9a446baba8 100644 --- a/net/batman-adv/main.c +++ b/net/batman-adv/main.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include "bridge_loop_avoidance.h" | 37 | #include "bridge_loop_avoidance.h" |
38 | #include "distributed-arp-table.h" | 38 | #include "distributed-arp-table.h" |
39 | #include "unicast.h" | 39 | #include "unicast.h" |
40 | #include "gateway_common.h" | ||
40 | #include "vis.h" | 41 | #include "vis.h" |
41 | #include "hash.h" | 42 | #include "hash.h" |
42 | #include "bat_algo.h" | 43 | #include "bat_algo.h" |
@@ -152,6 +153,8 @@ int batadv_mesh_init(struct net_device *soft_iface) | |||
152 | if (ret < 0) | 153 | if (ret < 0) |
153 | goto err; | 154 | goto err; |
154 | 155 | ||
156 | batadv_gw_init(bat_priv); | ||
157 | |||
155 | atomic_set(&bat_priv->gw.reselect, 0); | 158 | atomic_set(&bat_priv->gw.reselect, 0); |
156 | atomic_set(&bat_priv->mesh_state, BATADV_MESH_ACTIVE); | 159 | atomic_set(&bat_priv->mesh_state, BATADV_MESH_ACTIVE); |
157 | 160 | ||
@@ -190,6 +193,8 @@ void batadv_mesh_free(struct net_device *soft_iface) | |||
190 | */ | 193 | */ |
191 | batadv_originator_free(bat_priv); | 194 | batadv_originator_free(bat_priv); |
192 | 195 | ||
196 | batadv_gw_free(bat_priv); | ||
197 | |||
193 | free_percpu(bat_priv->bat_counters); | 198 | free_percpu(bat_priv->bat_counters); |
194 | bat_priv->bat_counters = NULL; | 199 | bat_priv->bat_counters = NULL; |
195 | 200 | ||
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index f50553a7de62..5d53d2f38377 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c | |||
@@ -388,9 +388,7 @@ static void _batadv_purge_orig(struct batadv_priv *bat_priv) | |||
388 | hlist_for_each_entry_safe(orig_node, node_tmp, | 388 | hlist_for_each_entry_safe(orig_node, node_tmp, |
389 | head, hash_entry) { | 389 | head, hash_entry) { |
390 | if (batadv_purge_orig_node(bat_priv, orig_node)) { | 390 | if (batadv_purge_orig_node(bat_priv, orig_node)) { |
391 | if (orig_node->gw_flags) | 391 | batadv_gw_node_delete(bat_priv, orig_node); |
392 | batadv_gw_node_delete(bat_priv, | ||
393 | orig_node); | ||
394 | hlist_del_rcu(&orig_node->hash_entry); | 392 | hlist_del_rcu(&orig_node->hash_entry); |
395 | batadv_orig_node_free_ref(orig_node); | 393 | batadv_orig_node_free_ref(orig_node); |
396 | continue; | 394 | continue; |
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h index b5c21c418a5f..6d0b3a73cee7 100644 --- a/net/batman-adv/packet.h +++ b/net/batman-adv/packet.h | |||
@@ -118,6 +118,14 @@ enum batadv_bla_claimframe { | |||
118 | BATADV_CLAIM_TYPE_REQUEST = 0x03, | 118 | BATADV_CLAIM_TYPE_REQUEST = 0x03, |
119 | }; | 119 | }; |
120 | 120 | ||
121 | /** | ||
122 | * enum batadv_tvlv_type - tvlv type definitions | ||
123 | * @BATADV_TVLV_GW: gateway tvlv | ||
124 | */ | ||
125 | enum batadv_tvlv_type { | ||
126 | BATADV_TVLV_GW = 0x01, | ||
127 | }; | ||
128 | |||
121 | /* the destination hardware field in the ARP frame is used to | 129 | /* the destination hardware field in the ARP frame is used to |
122 | * transport the claim type and the group id | 130 | * transport the claim type and the group id |
123 | */ | 131 | */ |
@@ -147,7 +155,7 @@ struct batadv_ogm_packet { | |||
147 | __be32 seqno; | 155 | __be32 seqno; |
148 | uint8_t orig[ETH_ALEN]; | 156 | uint8_t orig[ETH_ALEN]; |
149 | uint8_t prev_sender[ETH_ALEN]; | 157 | uint8_t prev_sender[ETH_ALEN]; |
150 | uint8_t gw_flags; /* flags related to gateway class */ | 158 | uint8_t reserved; |
151 | uint8_t tq; | 159 | uint8_t tq; |
152 | uint8_t tt_num_changes; | 160 | uint8_t tt_num_changes; |
153 | uint8_t ttvn; /* translation table version number */ | 161 | uint8_t ttvn; /* translation table version number */ |
@@ -352,4 +360,15 @@ struct batadv_tvlv_hdr { | |||
352 | __be16 len; | 360 | __be16 len; |
353 | }; | 361 | }; |
354 | 362 | ||
363 | /** | ||
364 | * struct batadv_tvlv_gateway_data - gateway data propagated through gw tvlv | ||
365 | * container | ||
366 | * @bandwidth_down: advertised uplink download bandwidth | ||
367 | * @bandwidth_up: advertised uplink upload bandwidth | ||
368 | */ | ||
369 | struct batadv_tvlv_gateway_data { | ||
370 | __be32 bandwidth_down; | ||
371 | __be32 bandwidth_up; | ||
372 | }; | ||
373 | |||
355 | #endif /* _NET_BATMAN_ADV_PACKET_H_ */ | 374 | #endif /* _NET_BATMAN_ADV_PACKET_H_ */ |
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 813db4e64602..84623a955d52 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c | |||
@@ -472,7 +472,8 @@ static int batadv_softif_init_late(struct net_device *dev) | |||
472 | atomic_set(&bat_priv->vis_mode, BATADV_VIS_TYPE_CLIENT_UPDATE); | 472 | atomic_set(&bat_priv->vis_mode, BATADV_VIS_TYPE_CLIENT_UPDATE); |
473 | atomic_set(&bat_priv->gw_mode, BATADV_GW_MODE_OFF); | 473 | atomic_set(&bat_priv->gw_mode, BATADV_GW_MODE_OFF); |
474 | atomic_set(&bat_priv->gw_sel_class, 20); | 474 | atomic_set(&bat_priv->gw_sel_class, 20); |
475 | atomic_set(&bat_priv->gw_bandwidth, 41); | 475 | atomic_set(&bat_priv->gw.bandwidth_down, 100); |
476 | atomic_set(&bat_priv->gw.bandwidth_up, 20); | ||
476 | atomic_set(&bat_priv->orig_interval, 1000); | 477 | atomic_set(&bat_priv->orig_interval, 1000); |
477 | atomic_set(&bat_priv->hop_penalty, 30); | 478 | atomic_set(&bat_priv->hop_penalty, 30); |
478 | #ifdef CONFIG_BATMAN_ADV_DEBUG | 479 | #ifdef CONFIG_BATMAN_ADV_DEBUG |
diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c index 4114b961bc2c..68793f53f182 100644 --- a/net/batman-adv/sysfs.c +++ b/net/batman-adv/sysfs.c | |||
@@ -390,6 +390,7 @@ static ssize_t batadv_store_gw_mode(struct kobject *kobj, | |||
390 | */ | 390 | */ |
391 | batadv_gw_check_client_stop(bat_priv); | 391 | batadv_gw_check_client_stop(bat_priv); |
392 | atomic_set(&bat_priv->gw_mode, (unsigned int)gw_mode_tmp); | 392 | atomic_set(&bat_priv->gw_mode, (unsigned int)gw_mode_tmp); |
393 | batadv_gw_tvlv_container_update(bat_priv); | ||
393 | return count; | 394 | return count; |
394 | } | 395 | } |
395 | 396 | ||
@@ -397,15 +398,13 @@ static ssize_t batadv_show_gw_bwidth(struct kobject *kobj, | |||
397 | struct attribute *attr, char *buff) | 398 | struct attribute *attr, char *buff) |
398 | { | 399 | { |
399 | struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj); | 400 | struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj); |
400 | int down, up; | 401 | uint32_t down, up; |
401 | int gw_bandwidth = atomic_read(&bat_priv->gw_bandwidth); | 402 | |
402 | 403 | down = atomic_read(&bat_priv->gw.bandwidth_down); | |
403 | batadv_gw_bandwidth_to_kbit(gw_bandwidth, &down, &up); | 404 | up = atomic_read(&bat_priv->gw.bandwidth_up); |
404 | return sprintf(buff, "%i%s/%i%s\n", | 405 | |
405 | (down > 2048 ? down / 1024 : down), | 406 | return sprintf(buff, "%u.%u/%u.%u MBit\n", down / 10, |
406 | (down > 2048 ? "MBit" : "KBit"), | 407 | down % 10, up / 10, up % 10); |
407 | (up > 2048 ? up / 1024 : up), | ||
408 | (up > 2048 ? "MBit" : "KBit")); | ||
409 | } | 408 | } |
410 | 409 | ||
411 | static ssize_t batadv_store_gw_bwidth(struct kobject *kobj, | 410 | static ssize_t batadv_store_gw_bwidth(struct kobject *kobj, |
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 4bdea16bc70c..b22a04391f6c 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h | |||
@@ -99,7 +99,6 @@ struct batadv_hard_iface { | |||
99 | * @last_seen: time when last packet from this node was received | 99 | * @last_seen: time when last packet from this node was received |
100 | * @bcast_seqno_reset: time when the broadcast seqno window was reset | 100 | * @bcast_seqno_reset: time when the broadcast seqno window was reset |
101 | * @batman_seqno_reset: time when the batman seqno window was reset | 101 | * @batman_seqno_reset: time when the batman seqno window was reset |
102 | * @gw_flags: flags related to gateway class | ||
103 | * @flags: for now only VIS_SERVER flag | 102 | * @flags: for now only VIS_SERVER flag |
104 | * @last_ttvn: last seen translation table version number | 103 | * @last_ttvn: last seen translation table version number |
105 | * @tt_crc: CRC of the translation table | 104 | * @tt_crc: CRC of the translation table |
@@ -147,7 +146,6 @@ struct batadv_orig_node { | |||
147 | unsigned long last_seen; | 146 | unsigned long last_seen; |
148 | unsigned long bcast_seqno_reset; | 147 | unsigned long bcast_seqno_reset; |
149 | unsigned long batman_seqno_reset; | 148 | unsigned long batman_seqno_reset; |
150 | uint8_t gw_flags; | ||
151 | uint8_t flags; | 149 | uint8_t flags; |
152 | atomic_t last_ttvn; | 150 | atomic_t last_ttvn; |
153 | uint16_t tt_crc; | 151 | uint16_t tt_crc; |
@@ -189,6 +187,8 @@ struct batadv_orig_node { | |||
189 | * struct batadv_gw_node - structure for orig nodes announcing gw capabilities | 187 | * struct batadv_gw_node - structure for orig nodes announcing gw capabilities |
190 | * @list: list node for batadv_priv_gw::list | 188 | * @list: list node for batadv_priv_gw::list |
191 | * @orig_node: pointer to corresponding orig node | 189 | * @orig_node: pointer to corresponding orig node |
190 | * @bandwidth_down: advertised uplink download bandwidth | ||
191 | * @bandwidth_up: advertised uplink upload bandwidth | ||
192 | * @deleted: this struct is scheduled for deletion | 192 | * @deleted: this struct is scheduled for deletion |
193 | * @refcount: number of contexts the object is used | 193 | * @refcount: number of contexts the object is used |
194 | * @rcu: struct used for freeing in an RCU-safe manner | 194 | * @rcu: struct used for freeing in an RCU-safe manner |
@@ -196,6 +196,8 @@ struct batadv_orig_node { | |||
196 | struct batadv_gw_node { | 196 | struct batadv_gw_node { |
197 | struct hlist_node list; | 197 | struct hlist_node list; |
198 | struct batadv_orig_node *orig_node; | 198 | struct batadv_orig_node *orig_node; |
199 | uint32_t bandwidth_down; | ||
200 | uint32_t bandwidth_up; | ||
199 | unsigned long deleted; | 201 | unsigned long deleted; |
200 | atomic_t refcount; | 202 | atomic_t refcount; |
201 | struct rcu_head rcu; | 203 | struct rcu_head rcu; |
@@ -420,12 +422,16 @@ struct batadv_priv_debug_log { | |||
420 | * @list: list of available gateway nodes | 422 | * @list: list of available gateway nodes |
421 | * @list_lock: lock protecting gw_list & curr_gw | 423 | * @list_lock: lock protecting gw_list & curr_gw |
422 | * @curr_gw: pointer to currently selected gateway node | 424 | * @curr_gw: pointer to currently selected gateway node |
425 | * @bandwidth_down: advertised uplink download bandwidth (if gw_mode server) | ||
426 | * @bandwidth_up: advertised uplink upload bandwidth (if gw_mode server) | ||
423 | * @reselect: bool indicating a gateway re-selection is in progress | 427 | * @reselect: bool indicating a gateway re-selection is in progress |
424 | */ | 428 | */ |
425 | struct batadv_priv_gw { | 429 | struct batadv_priv_gw { |
426 | struct hlist_head list; | 430 | struct hlist_head list; |
427 | spinlock_t list_lock; /* protects gw_list & curr_gw */ | 431 | spinlock_t list_lock; /* protects gw_list & curr_gw */ |
428 | struct batadv_gw_node __rcu *curr_gw; /* rcu protected pointer */ | 432 | struct batadv_gw_node __rcu *curr_gw; /* rcu protected pointer */ |
433 | atomic_t bandwidth_down; | ||
434 | atomic_t bandwidth_up; | ||
429 | atomic_t reselect; | 435 | atomic_t reselect; |
430 | }; | 436 | }; |
431 | 437 | ||
@@ -521,7 +527,6 @@ struct batadv_priv_nc { | |||
521 | * @vis_mode: vis operation: client or server (see batadv_vis_packettype) | 527 | * @vis_mode: vis operation: client or server (see batadv_vis_packettype) |
522 | * @gw_mode: gateway operation: off, client or server (see batadv_gw_modes) | 528 | * @gw_mode: gateway operation: off, client or server (see batadv_gw_modes) |
523 | * @gw_sel_class: gateway selection class (applies if gw_mode client) | 529 | * @gw_sel_class: gateway selection class (applies if gw_mode client) |
524 | * @gw_bandwidth: gateway announced bandwidth (applies if gw_mode server) | ||
525 | * @orig_interval: OGM broadcast interval in milliseconds | 530 | * @orig_interval: OGM broadcast interval in milliseconds |
526 | * @hop_penalty: penalty which will be applied to an OGM's tq-field on every hop | 531 | * @hop_penalty: penalty which will be applied to an OGM's tq-field on every hop |
527 | * @log_level: configured log level (see batadv_dbg_level) | 532 | * @log_level: configured log level (see batadv_dbg_level) |
@@ -569,7 +574,6 @@ struct batadv_priv { | |||
569 | atomic_t vis_mode; | 574 | atomic_t vis_mode; |
570 | atomic_t gw_mode; | 575 | atomic_t gw_mode; |
571 | atomic_t gw_sel_class; | 576 | atomic_t gw_sel_class; |
572 | atomic_t gw_bandwidth; | ||
573 | atomic_t orig_interval; | 577 | atomic_t orig_interval; |
574 | atomic_t hop_penalty; | 578 | atomic_t hop_penalty; |
575 | #ifdef CONFIG_BATMAN_ADV_DEBUG | 579 | #ifdef CONFIG_BATMAN_ADV_DEBUG |