aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--networking/brctl.c218
1 files changed, 215 insertions, 3 deletions
diff --git a/networking/brctl.c b/networking/brctl.c
index ba5b6226f..e15710b5e 100644
--- a/networking/brctl.c
+++ b/networking/brctl.c
@@ -54,6 +54,7 @@
54//usage: "\n delif BRIDGE IFACE Delete IFACE from BRIDGE" 54//usage: "\n delif BRIDGE IFACE Delete IFACE from BRIDGE"
55//usage: IF_FEATURE_BRCTL_FANCY( 55//usage: IF_FEATURE_BRCTL_FANCY(
56//usage: "\n stp BRIDGE 1/yes/on|0/no/off STP on/off" 56//usage: "\n stp BRIDGE 1/yes/on|0/no/off STP on/off"
57//usage: "\n showstp BRIDGE Show stp info"
57//usage: "\n setageing BRIDGE SECONDS Set ageing time" 58//usage: "\n setageing BRIDGE SECONDS Set ageing time"
58//usage: "\n setfd BRIDGE SECONDS Set bridge forward delay" 59//usage: "\n setfd BRIDGE SECONDS Set bridge forward delay"
59//usage: "\n sethello BRIDGE SECONDS Set hello time" 60//usage: "\n sethello BRIDGE SECONDS Set hello time"
@@ -65,7 +66,7 @@
65//usage: ) 66//usage: )
66// Not yet implemented: 67// Not yet implemented:
67// hairpin BRIDGE IFACE on|off Hairpin on/off 68// hairpin BRIDGE IFACE on|off Hairpin on/off
68// showstp BRIDGE Show stp info 69
69 70
70#include "libbb.h" 71#include "libbb.h"
71#include "common_bufsiz.h" 72#include "common_bufsiz.h"
@@ -146,8 +147,7 @@ static int show_bridge(const char *name, int need_hdr)
146 147
147 if (need_hdr) 148 if (need_hdr)
148 puts("bridge name\tbridge id\t\tSTP enabled\tinterfaces"); 149 puts("bridge name\tbridge id\t\tSTP enabled\tinterfaces");
149 printf("%s\t\t", name); 150 printf("%s\t\t%s\t", name, filedata);
150 printf("%s\t", filedata);
151 151
152 strcpy(sfx, "stp_state"); 152 strcpy(sfx, "stp_state");
153 read_file(pathbuf); 153 read_file(pathbuf);
@@ -279,6 +279,212 @@ static void show_bridge_macs(const char *name)
279 279
280 free(fdb); 280 free(fdb);
281} 281}
282
283static void show_bridge_timer(const char *msg)
284{
285 unsigned long long tvmsec = 10 * xstrtoull(filedata, 0);
286 unsigned tv_sec = tvmsec / 1000;
287 unsigned tv_msec = tvmsec % 1000;
288 printf("%s%4u.%.2u", msg, tv_sec, tv_msec / 10);
289}
290
291static const char *show_bridge_state(unsigned state)
292{
293 /* See linux/if_bridge.h, BR_STATE_ constants */
294 static const char state_names[] =
295 "disabled\0" //BR_STATE_DISABLED 0
296 "listening\0" //BR_STATE_LISTENING 1
297 "learning\0" //BR_STATE_LEARNING 2
298 "forwarding\0" //BR_STATE_FORWARDING 3
299 "blocking" //BR_STATE_BLOCKING 4
300 ;
301 if (state < 5)
302 return nth_string(state_names, state);
303 return utoa(state);
304}
305
306static void printf_xstrtou(const char *fmt)
307{
308 printf(fmt, xstrtou(filedata, 0));
309}
310
311static void show_bridge_port(const char *name)
312{
313 char pathbuf[IFNAMSIZ + sizeof("/brport/forward_delay_timer") + 32];
314 char *sfx;
315
316#if IFNAMSIZ == 16
317 sfx = pathbuf + sprintf(pathbuf, "%.16s/brport/", name);
318#else
319 sfx = pathbuf + sprintf(pathbuf, "%.*s/brport/", (int)IFNAMSIZ, name);
320#endif
321
322 strcpy(sfx, "port_no");
323 read_file(pathbuf);
324 printf("%s (%u)\n", name, xstrtou(filedata, 0));
325
326 strcpy(sfx + 5, "id"); // "port_id"
327 read_file(pathbuf);
328 printf_xstrtou(" port id\t\t%.4x");
329
330 strcpy(sfx, "state");
331 read_file(pathbuf);
332 printf("\t\t\tstate\t\t%15s\n", show_bridge_state(xstrtou(filedata, 0)));
333
334 strcpy(sfx, "designated_root");
335 read_file(pathbuf);
336 printf(" designated root\t%s", filedata);
337
338 strcpy(sfx, "path_cost");
339 read_file(pathbuf);
340 printf_xstrtou("\tpath cost\t\t%4u\n");
341
342 strcpy(sfx, "designated_bridge");
343 read_file(pathbuf);
344 printf(" designated bridge\t%s", filedata);
345
346 strcpy(sfx, "message_age_timer");
347 read_file(pathbuf);
348 show_bridge_timer("\tmessage age timer\t");
349
350 strcpy(sfx, "designated_port");
351 read_file(pathbuf);
352 printf_xstrtou("\n designated port\t%.4x");
353
354 strcpy(sfx, "forward_delay_timer");
355 read_file(pathbuf);
356 show_bridge_timer("\t\t\tforward delay timer\t");
357
358 strcpy(sfx, "designated_cost");
359 read_file(pathbuf);
360 printf_xstrtou("\n designated cost\t%4u");
361
362 strcpy(sfx, "hold_timer");
363 read_file(pathbuf);
364 show_bridge_timer("\t\t\thold timer\t\t");
365
366 printf("\n flags\t\t\t");
367
368 strcpy(sfx, "config_pending");
369 read_file(pathbuf);
370 if (!LONE_CHAR(filedata, '0'))
371 printf("CONFIG_PENDING ");
372
373 strcpy(sfx, "change_ack");
374 read_file(pathbuf);
375 if (!LONE_CHAR(filedata, '0'))
376 printf("TOPOLOGY_CHANGE_ACK ");
377
378 strcpy(sfx, "hairpin_mode");
379 read_file(pathbuf);
380 if (!LONE_CHAR(filedata, '0'))
381 printf_xstrtou("\n hairpin mode\t\t%4u");
382
383 printf("\n\n");
384}
385
386static void show_bridge_ports(const char *name)
387{
388 DIR *ifaces;
389 struct dirent *ent;
390 char pathbuf[IFNAMSIZ + sizeof("/brif") + 8];
391
392#if IFNAMSIZ == 16
393 sprintf(pathbuf, "%.16s/brif", name);
394#else
395 sprintf(pathbuf, "%.*s/brif", (int)IFNAMSIZ, name);
396#endif
397 ifaces = opendir(pathbuf);
398 if (ifaces) {
399 while ((ent = readdir(ifaces)) != NULL) {
400 if (DOT_OR_DOTDOT(ent->d_name))
401 continue; /* . or .. */
402 show_bridge_port(ent->d_name);
403 }
404 closedir(ifaces);
405 }
406}
407
408static void show_bridge_stp(const char *name)
409{
410 char pathbuf[IFNAMSIZ + sizeof("/bridge/topology_change_timer") + 32];
411 char *sfx;
412
413#if IFNAMSIZ == 16
414 sfx = pathbuf + sprintf(pathbuf, "%.16s/bridge/", name);
415#else
416 sfx = pathbuf + sprintf(pathbuf, "%.*s/bridge/", (int)IFNAMSIZ, name);
417#endif
418
419 strcpy(sfx, "bridge_id");
420 if (read_file(pathbuf) < 0)
421 bb_error_msg_and_die("bridge %s does not exist", name);
422
423 printf("%s\n"
424 " bridge id\t\t%s", name, filedata);
425
426 strcpy(sfx, "root_id");
427 read_file(pathbuf);
428 printf("\n designated root\t%s", filedata);
429
430 strcpy(sfx + 5, "port"); // "root_port"
431 read_file(pathbuf);
432 printf_xstrtou("\n root port\t\t%4u\t\t\t");
433
434 strcpy(sfx + 6, "ath_cost"); // "root_path_cost"
435 read_file(pathbuf);
436 printf_xstrtou("path cost\t\t%4u\n");
437
438 strcpy(sfx, "max_age");
439 read_file(pathbuf);
440 show_bridge_timer(" max age\t\t");
441 show_bridge_timer("\t\t\tbridge max age\t\t");
442
443 strcpy(sfx, "hello_time");
444 read_file(pathbuf);
445 show_bridge_timer("\n hello time\t\t");
446 show_bridge_timer("\t\t\tbridge hello time\t");
447
448 strcpy(sfx, "forward_delay");
449 read_file(pathbuf);
450 show_bridge_timer("\n forward delay\t\t");
451 show_bridge_timer("\t\t\tbridge forward delay\t");
452
453 strcpy(sfx, "ageing_time");
454 read_file(pathbuf);
455 show_bridge_timer("\n ageing time\t\t");
456
457 strcpy(sfx, "hello_timer");
458 read_file(pathbuf);
459 show_bridge_timer("\n hello timer\t\t");
460
461 strcpy(sfx, "tcn_timer");
462 read_file(pathbuf);
463 show_bridge_timer("\t\t\ttcn timer\t\t");
464
465 strcpy(sfx, "topology_change_timer");
466 read_file(pathbuf);
467 show_bridge_timer("\n topology change timer\t");
468
469 strcpy(sfx, "gc_timer");
470 read_file(pathbuf);
471 show_bridge_timer("\t\t\tgc timer\t\t");
472
473 printf("\n flags\t\t\t");
474
475 strcpy(sfx, "topology_change");
476 read_file(pathbuf);
477 if (!LONE_CHAR(filedata, '0'))
478 printf("TOPOLOGY_CHANGE ");
479
480 strcpy(sfx, "topology_change_detected");
481 read_file(pathbuf);
482 if (!LONE_CHAR(filedata, '0'))
483 printf("TOPOLOGY_CHANGE_DETECTED ");
484 printf("\n\n\n");
485
486 show_bridge_ports(name);
487}
282#endif 488#endif
283 489
284int brctl_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 490int brctl_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
@@ -288,6 +494,7 @@ int brctl_main(int argc UNUSED_PARAM, char **argv)
288 "addbr\0" "delbr\0" "addif\0" "delif\0" 494 "addbr\0" "delbr\0" "addif\0" "delif\0"
289 IF_FEATURE_BRCTL_FANCY( 495 IF_FEATURE_BRCTL_FANCY(
290 "stp\0" 496 "stp\0"
497 "showstp\0"
291 "setageing\0" "setfd\0" "sethello\0" "setmaxage\0" 498 "setageing\0" "setfd\0" "sethello\0" "setmaxage\0"
292 "setpathcost\0" "setportprio\0" 499 "setpathcost\0" "setportprio\0"
293 "setbridgeprio\0" 500 "setbridgeprio\0"
@@ -297,6 +504,7 @@ int brctl_main(int argc UNUSED_PARAM, char **argv)
297 enum { ARG_addbr = 0, ARG_delbr, ARG_addif, ARG_delif 504 enum { ARG_addbr = 0, ARG_delbr, ARG_addif, ARG_delif
298 IF_FEATURE_BRCTL_FANCY(, 505 IF_FEATURE_BRCTL_FANCY(,
299 ARG_stp, 506 ARG_stp,
507 ARG_showstp,
300 ARG_setageing, ARG_setfd, ARG_sethello, ARG_setmaxage, 508 ARG_setageing, ARG_setfd, ARG_sethello, ARG_setmaxage,
301 ARG_setpathcost, ARG_setportprio, 509 ARG_setpathcost, ARG_setportprio,
302 ARG_setbridgeprio, 510 ARG_setbridgeprio,
@@ -388,6 +596,10 @@ int brctl_main(int argc UNUSED_PARAM, char **argv)
388 show_bridge_macs(br); 596 show_bridge_macs(br);
389 return EXIT_SUCCESS; 597 return EXIT_SUCCESS;
390 } 598 }
599 if (key == ARG_showstp) {
600 show_bridge_stp(br);
601 return EXIT_SUCCESS;
602 }
391 603
392 if (!*argv) /* all but 'addbr/delbr' need at least two arguments */ 604 if (!*argv) /* all but 'addbr/delbr' need at least two arguments */
393 bb_show_usage(); 605 bb_show_usage();