[PATCH] brctl: Added support for showmacs command
Martin Lewis
martin.lewis.x84 at gmail.com
Sun Sep 15 16:04:49 UTC 2019
Signed-off-by: Martin Lewis <martin.lewis.x84 at gmail.com>
---
networking/brctl.c | 119 ++++++++++++++++++++++++++++++++++++++++++++---------
1 file changed, 100 insertions(+), 19 deletions(-)
diff --git a/networking/brctl.c b/networking/brctl.c
index 586ca9b..35771a5 100644
--- a/networking/brctl.c
+++ b/networking/brctl.c
@@ -61,10 +61,10 @@
//usage: "\n setbridgeprio BRIDGE PRIO Set bridge priority"
//usage: "\n setportprio BRIDGE IFACE PRIO Set port priority"
//usage: "\n setpathcost BRIDGE IFACE COST Set path cost"
+//usage: "\n showmacs BRIDGE List mac addrs"
//usage: )
// Not yet implemented:
// hairpin BRIDGE IFACE on|off Hairpin on/off
-// showmacs BRIDGE List mac addrs
// showstp BRIDGE Show stp info
#include "libbb.h"
@@ -196,6 +196,94 @@ static void write_uint(const char *name, const char *leaf, unsigned val)
bb_simple_perror_msg_and_die(name);
close(fd);
}
+
+struct __fdb_entry {
+ uint8_t mac_addr[6];
+ uint8_t port_no;
+ uint8_t is_local;
+ uint32_t ageing_timer_value;
+ uint8_t port_hi;
+ uint8_t pad0;
+ uint16_t unused;
+};
+
+static int compare_fdbs(const void *_f0, const void *_f1)
+{
+ const struct __fdb_entry *f0 = _f0;
+ const struct __fdb_entry *f1 = _f1;
+
+ return memcmp(f0->mac_addr, f1->mac_addr, 6);
+}
+
+static int read_bridge_forward_db(const char *name, struct __fdb_entry **_fdb, size_t *_nentries)
+{
+ struct __fdb_entry *fdb = NULL;
+ size_t nentries = 0;
+
+ char *path;
+ int fd;
+ ssize_t cc;
+
+ path = concat_path_file(name, "/brforward");
+ fd = open(path, O_RDONLY);
+ free(path);
+ if (fd < 0)
+ return -1;
+
+ for (;;) {
+ fdb = xrealloc(fdb, (nentries + 1) * sizeof(*fdb));
+ cc = full_read(fd, &fdb[nentries], sizeof(*fdb));
+ if (cc < 0) {
+ bb_perror_msg_and_die("can't read bridge %s forward db", name);
+ }
+ if (cc == 0) {
+ break;
+ }
+ ++nentries;
+ }
+
+ close(fd);
+
+ qsort(fdb, nentries, sizeof(*fdb), compare_fdbs);
+
+ *_fdb = fdb;
+ *_nentries = nentries;
+ return 0;
+}
+
+static inline void show_bridge_timer(uint32_t ageing_timer)
+{
+ unsigned long long tvusec = 10000ULL * ageing_timer;
+ unsigned int tv_sec = tvusec / 1000000;
+ unsigned int tv_usec = tvusec - (1000000 * tv_sec);
+
+ printf("%4u.%.2u", tv_sec, tv_usec / 10000);
+}
+
+static int show_bridge_macs(const char *name)
+{
+ struct __fdb_entry *fdb;
+ size_t nentries;
+ size_t i;
+
+ if (read_bridge_forward_db(name, &fdb, &nentries) < 0)
+ return -1;
+
+ printf("port no\tmac addr\t\tis local?\tageing timer\n");
+ for (i = 0; i < nentries; ++i) {
+ const struct __fdb_entry *f = &fdb[i];
+ printf("%3u\t", f->port_no);
+ printf("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\t",
+ f->mac_addr[0], f->mac_addr[1], f->mac_addr[2],
+ f->mac_addr[3], f->mac_addr[4], f->mac_addr[5]);
+ printf("%s\t\t", f->is_local ? "yes" : "no");
+ show_bridge_timer(f->ageing_timer_value);
+ printf("\n");
+ }
+
+ free(fdb);
+ return 0;
+}
#endif
int brctl_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
@@ -208,6 +296,7 @@ int brctl_main(int argc UNUSED_PARAM, char **argv)
"setageing\0" "setfd\0" "sethello\0" "setmaxage\0"
"setpathcost\0" "setportprio\0"
"setbridgeprio\0"
+ "showmacs\0"
)
IF_FEATURE_BRCTL_SHOW("show\0");
enum { ARG_addbr = 0, ARG_delbr, ARG_addif, ARG_delif
@@ -215,7 +304,8 @@ int brctl_main(int argc UNUSED_PARAM, char **argv)
ARG_stp,
ARG_setageing, ARG_setfd, ARG_sethello, ARG_setmaxage,
ARG_setpathcost, ARG_setportprio,
- ARG_setbridgeprio
+ ARG_setbridgeprio,
+ ARG_showmacs
)
IF_FEATURE_BRCTL_SHOW(, ARG_show)
};
@@ -299,6 +389,14 @@ int brctl_main(int argc UNUSED_PARAM, char **argv)
return EXIT_SUCCESS;
}
+ if (key == ARG_showmacs) {
+ if (show_bridge_macs(br) < 0) {
+ bb_error_msg("bridge %s does not exist", br);
+ return EXIT_FAILURE;
+ }
+ return EXIT_SUCCESS;
+ }
+
if (!*argv) /* all but 'addbr/delbr' need at least two arguments */
bb_show_usage();
@@ -365,23 +463,6 @@ int brctl_main(int argc UNUSED_PARAM, char **argv)
//goto done_next_argv;
return EXIT_SUCCESS;
}
-
-/* TODO: "showmacs BR"
- * port no\tmac addr\t\tis local?\tageing timer
- * <sp><sp>1\txx:xx:xx:xx:xx:xx\tno\t\t<sp><sp><sp>1.31
- * port no mac addr is local? ageing timer
- * 1 xx:xx:xx:xx:xx:xx no 1.31
- * Read fixed-sized records from /sys/class/net/BR/brforward:
- * struct __fdb_entry {
- * uint8_t mac_addr[ETH_ALEN];
- * uint8_t port_no; //lsb
- * uint8_t is_local;
- * uint32_t ageing_timer_value;
- * uint8_t port_hi;
- * uint8_t pad0;
- * uint16_t unused;
- * };
- */
#endif
/* always true: if (key == ARG_addif || key == ARG_delif) */ {
/* addif or delif */
--
1.9.1
More information about the busybox
mailing list