brctl: add support for showmacs command

function                                             old     new   delta
brctl_main                                           680     974    +294
packed_usage                                       33167   33187     +20
compare_fdbs                                           -      19     +19
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 2/0 up/down: 333/0)             Total: 333 bytes

Signed-off-by: Martin Lewis <martin.lewis.x84@gmail.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Martin Lewis 2019-09-15 18:04:49 +02:00 committed by Denys Vlasenko
parent 71b268c7d9
commit 6c1af283f7

View File

@ -61,10 +61,10 @@
//usage: "\n setbridgeprio BRIDGE PRIO Set bridge priority" //usage: "\n setbridgeprio BRIDGE PRIO Set bridge priority"
//usage: "\n setportprio BRIDGE IFACE PRIO Set port priority" //usage: "\n setportprio BRIDGE IFACE PRIO Set port priority"
//usage: "\n setpathcost BRIDGE IFACE COST Set path cost" //usage: "\n setpathcost BRIDGE IFACE COST Set path cost"
//usage: "\n showmacs BRIDGE List MAC addresses"
//usage: ) //usage: )
// Not yet implemented: // Not yet implemented:
// hairpin BRIDGE IFACE on|off Hairpin on/off // hairpin BRIDGE IFACE on|off Hairpin on/off
// showmacs BRIDGE List mac addrs
// showstp BRIDGE Show stp info // showstp BRIDGE Show stp info
#include "libbb.h" #include "libbb.h"
@ -196,6 +196,89 @@ static void write_uint(const char *name, const char *leaf, unsigned val)
bb_simple_perror_msg_and_die(name); bb_simple_perror_msg_and_die(name);
close(fd); 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 size_t read_bridge_forward_db(const char *name, struct fdb_entry **_fdb)
{
struct fdb_entry *fdb;
size_t nentries;
char *path;
int fd;
ssize_t cc;
path = concat_path_file(name, "brforward");
fd = open(path, O_RDONLY);
free(path);
if (fd < 0)
bb_error_msg_and_die("bridge %s does not exist", name);
fdb = NULL;
nentries = 0;
for (;;) {
fdb = xrealloc_vector(fdb, 4, nentries);
cc = full_read(fd, &fdb[nentries], sizeof(*fdb));
if (cc == 0) {
break;
}
if (cc != sizeof(*fdb)) {
bb_perror_msg_and_die("can't read bridge %s forward db", name);
}
++nentries;
}
close(fd);
qsort(fdb, nentries, sizeof(*fdb), compare_fdbs);
*_fdb = fdb;
return nentries;
}
static void show_bridge_macs(const char *name)
{
struct fdb_entry *fdb;
size_t nentries;
size_t i;
nentries = read_bridge_forward_db(name, &fdb);
printf("port no\tmac addr\t\tis local?\tageing timer\n");
for (i = 0; i < nentries; ++i) {
const struct fdb_entry *f = &fdb[i];
unsigned long tvmsec = 10UL * f->ageing_timer_value;
unsigned tv_sec = tvmsec / 1000;
unsigned tv_msec = tvmsec % 1000;
printf("%3u\t"
"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\t"
"%s\t\t"
"%4u.%.2u\n",
f->port_no,
f->mac_addr[0], f->mac_addr[1], f->mac_addr[2],
f->mac_addr[3], f->mac_addr[4], f->mac_addr[5],
(f->is_local ? "yes" : "no"),
tv_sec, tv_msec / 10
);
}
free(fdb);
}
#endif #endif
int brctl_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int brctl_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
@ -208,6 +291,7 @@ int brctl_main(int argc UNUSED_PARAM, char **argv)
"setageing\0" "setfd\0" "sethello\0" "setmaxage\0" "setageing\0" "setfd\0" "sethello\0" "setmaxage\0"
"setpathcost\0" "setportprio\0" "setpathcost\0" "setportprio\0"
"setbridgeprio\0" "setbridgeprio\0"
"showmacs\0"
) )
IF_FEATURE_BRCTL_SHOW("show\0"); IF_FEATURE_BRCTL_SHOW("show\0");
enum { ARG_addbr = 0, ARG_delbr, ARG_addif, ARG_delif enum { ARG_addbr = 0, ARG_delbr, ARG_addif, ARG_delif
@ -215,7 +299,8 @@ int brctl_main(int argc UNUSED_PARAM, char **argv)
ARG_stp, ARG_stp,
ARG_setageing, ARG_setfd, ARG_sethello, ARG_setmaxage, ARG_setageing, ARG_setfd, ARG_sethello, ARG_setmaxage,
ARG_setpathcost, ARG_setportprio, ARG_setpathcost, ARG_setportprio,
ARG_setbridgeprio ARG_setbridgeprio,
ARG_showmacs
) )
IF_FEATURE_BRCTL_SHOW(, ARG_show) IF_FEATURE_BRCTL_SHOW(, ARG_show)
}; };
@ -299,6 +384,11 @@ int brctl_main(int argc UNUSED_PARAM, char **argv)
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
if (key == ARG_showmacs) {
show_bridge_macs(br);
return EXIT_SUCCESS;
}
if (!*argv) /* all but 'addbr/delbr' need at least two arguments */ if (!*argv) /* all but 'addbr/delbr' need at least two arguments */
bb_show_usage(); bb_show_usage();
@ -365,23 +455,6 @@ int brctl_main(int argc UNUSED_PARAM, char **argv)
//goto done_next_argv; //goto done_next_argv;
return EXIT_SUCCESS; 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 #endif
/* always true: if (key == ARG_addif || key == ARG_delif) */ { /* always true: if (key == ARG_addif || key == ARG_delif) */ {
/* addif or delif */ /* addif or delif */