aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv/gateway_client.c
diff options
context:
space:
mode:
authorMarek Lindner <lindner_marek@yahoo.de>2013-04-23 09:39:58 -0400
committerAntonio Quartulli <antonio@meshcoding.com>2013-10-09 15:22:27 -0400
commit414254e342a0d58144de40c3da777521ebaeeb07 (patch)
treea292367d064dd72f4b7a095382e11a9974d685af /net/batman-adv/gateway_client.c
parentef26157747d42254453f6b3ac2bd8bd3c53339c3 (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>
Diffstat (limited to 'net/batman-adv/gateway_client.c')
-rw-r--r--net/batman-adv/gateway_client.c187
1 files changed, 121 insertions, 66 deletions
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 */
340static void batadv_gw_node_add(struct batadv_priv *bat_priv, 350static 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
369void 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 */
387static struct batadv_gw_node *
388batadv_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 */
419void 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
413deselect: 457 /* Note: We don't need a NULL check here, since curr_gw never
414 batadv_gw_deselect(bat_priv); 458 * gets dereferenced.
415unlock: 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
465out:
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
422void batadv_gw_node_delete(struct batadv_priv *bat_priv, 472void 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
428void batadv_gw_node_purge(struct batadv_priv *bat_priv) 483void 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)