diff options
-rw-r--r-- | networking/brctl.c | 218 |
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 @@ //usage: "\n delif BRIDGE IFACE Delete IFACE from BRIDGE" //usage: IF_FEATURE_BRCTL_FANCY( //usage: "\n stp BRIDGE 1/yes/on|0/no/off STP on/off" +//usage: "\n showstp BRIDGE Show stp info" //usage: "\n setageing BRIDGE SECONDS Set ageing time" //usage: "\n setfd BRIDGE SECONDS Set bridge forward delay" //usage: "\n sethello BRIDGE SECONDS Set hello time" @@ -65,7 +66,7 @@ //usage: ) // Not yet implemented: // hairpin BRIDGE IFACE on|off Hairpin on/off -// showstp BRIDGE Show stp info + #include "libbb.h" #include "common_bufsiz.h" @@ -146,8 +147,7 @@ static int show_bridge(const char *name, int need_hdr) if (need_hdr) puts("bridge name\tbridge id\t\tSTP enabled\tinterfaces"); - printf("%s\t\t", name); - printf("%s\t", filedata); + printf("%s\t\t%s\t", name, filedata); strcpy(sfx, "stp_state"); read_file(pathbuf); @@ -279,6 +279,212 @@ static void show_bridge_macs(const char *name) free(fdb); } + +static void show_bridge_timer(const char *msg) +{ + unsigned long long tvmsec = 10 * xstrtoull(filedata, 0); + unsigned tv_sec = tvmsec / 1000; + unsigned tv_msec = tvmsec % 1000; + printf("%s%4u.%.2u", msg, tv_sec, tv_msec / 10); +} + +static const char *show_bridge_state(unsigned state) +{ + /* See linux/if_bridge.h, BR_STATE_ constants */ + static const char state_names[] = + "disabled\0" //BR_STATE_DISABLED 0 + "listening\0" //BR_STATE_LISTENING 1 + "learning\0" //BR_STATE_LEARNING 2 + "forwarding\0" //BR_STATE_FORWARDING 3 + "blocking" //BR_STATE_BLOCKING 4 + ; + if (state < 5) + return nth_string(state_names, state); + return utoa(state); +} + +static void printf_xstrtou(const char *fmt) +{ + printf(fmt, xstrtou(filedata, 0)); +} + +static void show_bridge_port(const char *name) +{ + char pathbuf[IFNAMSIZ + sizeof("/brport/forward_delay_timer") + 32]; + char *sfx; + +#if IFNAMSIZ == 16 + sfx = pathbuf + sprintf(pathbuf, "%.16s/brport/", name); +#else + sfx = pathbuf + sprintf(pathbuf, "%.*s/brport/", (int)IFNAMSIZ, name); +#endif + + strcpy(sfx, "port_no"); + read_file(pathbuf); + printf("%s (%u)\n", name, xstrtou(filedata, 0)); + + strcpy(sfx + 5, "id"); // "port_id" + read_file(pathbuf); + printf_xstrtou(" port id\t\t%.4x"); + + strcpy(sfx, "state"); + read_file(pathbuf); + printf("\t\t\tstate\t\t%15s\n", show_bridge_state(xstrtou(filedata, 0))); + + strcpy(sfx, "designated_root"); + read_file(pathbuf); + printf(" designated root\t%s", filedata); + + strcpy(sfx, "path_cost"); + read_file(pathbuf); + printf_xstrtou("\tpath cost\t\t%4u\n"); + + strcpy(sfx, "designated_bridge"); + read_file(pathbuf); + printf(" designated bridge\t%s", filedata); + + strcpy(sfx, "message_age_timer"); + read_file(pathbuf); + show_bridge_timer("\tmessage age timer\t"); + + strcpy(sfx, "designated_port"); + read_file(pathbuf); + printf_xstrtou("\n designated port\t%.4x"); + + strcpy(sfx, "forward_delay_timer"); + read_file(pathbuf); + show_bridge_timer("\t\t\tforward delay timer\t"); + + strcpy(sfx, "designated_cost"); + read_file(pathbuf); + printf_xstrtou("\n designated cost\t%4u"); + + strcpy(sfx, "hold_timer"); + read_file(pathbuf); + show_bridge_timer("\t\t\thold timer\t\t"); + + printf("\n flags\t\t\t"); + + strcpy(sfx, "config_pending"); + read_file(pathbuf); + if (!LONE_CHAR(filedata, '0')) + printf("CONFIG_PENDING "); + + strcpy(sfx, "change_ack"); + read_file(pathbuf); + if (!LONE_CHAR(filedata, '0')) + printf("TOPOLOGY_CHANGE_ACK "); + + strcpy(sfx, "hairpin_mode"); + read_file(pathbuf); + if (!LONE_CHAR(filedata, '0')) + printf_xstrtou("\n hairpin mode\t\t%4u"); + + printf("\n\n"); +} + +static void show_bridge_ports(const char *name) +{ + DIR *ifaces; + struct dirent *ent; + char pathbuf[IFNAMSIZ + sizeof("/brif") + 8]; + +#if IFNAMSIZ == 16 + sprintf(pathbuf, "%.16s/brif", name); +#else + sprintf(pathbuf, "%.*s/brif", (int)IFNAMSIZ, name); +#endif + ifaces = opendir(pathbuf); + if (ifaces) { + while ((ent = readdir(ifaces)) != NULL) { + if (DOT_OR_DOTDOT(ent->d_name)) + continue; /* . or .. */ + show_bridge_port(ent->d_name); + } + closedir(ifaces); + } +} + +static void show_bridge_stp(const char *name) +{ + char pathbuf[IFNAMSIZ + sizeof("/bridge/topology_change_timer") + 32]; + char *sfx; + +#if IFNAMSIZ == 16 + sfx = pathbuf + sprintf(pathbuf, "%.16s/bridge/", name); +#else + sfx = pathbuf + sprintf(pathbuf, "%.*s/bridge/", (int)IFNAMSIZ, name); +#endif + + strcpy(sfx, "bridge_id"); + if (read_file(pathbuf) < 0) + bb_error_msg_and_die("bridge %s does not exist", name); + + printf("%s\n" + " bridge id\t\t%s", name, filedata); + + strcpy(sfx, "root_id"); + read_file(pathbuf); + printf("\n designated root\t%s", filedata); + + strcpy(sfx + 5, "port"); // "root_port" + read_file(pathbuf); + printf_xstrtou("\n root port\t\t%4u\t\t\t"); + + strcpy(sfx + 6, "ath_cost"); // "root_path_cost" + read_file(pathbuf); + printf_xstrtou("path cost\t\t%4u\n"); + + strcpy(sfx, "max_age"); + read_file(pathbuf); + show_bridge_timer(" max age\t\t"); + show_bridge_timer("\t\t\tbridge max age\t\t"); + + strcpy(sfx, "hello_time"); + read_file(pathbuf); + show_bridge_timer("\n hello time\t\t"); + show_bridge_timer("\t\t\tbridge hello time\t"); + + strcpy(sfx, "forward_delay"); + read_file(pathbuf); + show_bridge_timer("\n forward delay\t\t"); + show_bridge_timer("\t\t\tbridge forward delay\t"); + + strcpy(sfx, "ageing_time"); + read_file(pathbuf); + show_bridge_timer("\n ageing time\t\t"); + + strcpy(sfx, "hello_timer"); + read_file(pathbuf); + show_bridge_timer("\n hello timer\t\t"); + + strcpy(sfx, "tcn_timer"); + read_file(pathbuf); + show_bridge_timer("\t\t\ttcn timer\t\t"); + + strcpy(sfx, "topology_change_timer"); + read_file(pathbuf); + show_bridge_timer("\n topology change timer\t"); + + strcpy(sfx, "gc_timer"); + read_file(pathbuf); + show_bridge_timer("\t\t\tgc timer\t\t"); + + printf("\n flags\t\t\t"); + + strcpy(sfx, "topology_change"); + read_file(pathbuf); + if (!LONE_CHAR(filedata, '0')) + printf("TOPOLOGY_CHANGE "); + + strcpy(sfx, "topology_change_detected"); + read_file(pathbuf); + if (!LONE_CHAR(filedata, '0')) + printf("TOPOLOGY_CHANGE_DETECTED "); + printf("\n\n\n"); + + show_bridge_ports(name); +} #endif int brctl_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; @@ -288,6 +494,7 @@ int brctl_main(int argc UNUSED_PARAM, char **argv) "addbr\0" "delbr\0" "addif\0" "delif\0" IF_FEATURE_BRCTL_FANCY( "stp\0" + "showstp\0" "setageing\0" "setfd\0" "sethello\0" "setmaxage\0" "setpathcost\0" "setportprio\0" "setbridgeprio\0" @@ -297,6 +504,7 @@ int brctl_main(int argc UNUSED_PARAM, char **argv) enum { ARG_addbr = 0, ARG_delbr, ARG_addif, ARG_delif IF_FEATURE_BRCTL_FANCY(, ARG_stp, + ARG_showstp, ARG_setageing, ARG_setfd, ARG_sethello, ARG_setmaxage, ARG_setpathcost, ARG_setportprio, ARG_setbridgeprio, @@ -388,6 +596,10 @@ int brctl_main(int argc UNUSED_PARAM, char **argv) show_bridge_macs(br); return EXIT_SUCCESS; } + if (key == ARG_showstp) { + show_bridge_stp(br); + return EXIT_SUCCESS; + } if (!*argv) /* all but 'addbr/delbr' need at least two arguments */ bb_show_usage(); |