brctl: add support for showstp command
function old new delta brctl_main 974 2339 +1365 show_bridge_timer - 93 +93 static.state_names - 48 +48 printf_xstrtou - 26 +26 packed_usage 33243 33253 +10 show_bridge 333 323 -10 ------------------------------------------------------------------------------ (add/remove: 3/0 grow/shrink: 2/1 up/down: 1542/-10) Total: 1532 bytes text data bss dec hex filename 999868 551 5612 1006031 f59cf busybox_old 1002309 551 5612 1008472 f6358 busybox_unstripped Signed-off-by: Martin Lewis <martin.lewis.x84@gmail.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
		
				
					committed by
					
						
						Denys Vlasenko
					
				
			
			
				
	
			
			
			
						parent
						
							42f454b13b
						
					
				
				
					commit
					6dcf563633
				
			@@ -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();
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user