diff options
| author | Martin Lewis <martin.lewis.x84@gmail.com> | 2019-09-15 18:04:49 +0200 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2019-10-08 14:43:51 +0200 |
| commit | 6c1af283f73fb8640cd7273c2bf13eb102f80954 (patch) | |
| tree | 58d367bf3a3f63be48aa97e18ddb686c7c5f366e | |
| parent | 71b268c7d962a819f88050c2567dced975aa249e (diff) | |
| download | busybox-w32-6c1af283f73fb8640cd7273c2bf13eb102f80954.tar.gz busybox-w32-6c1af283f73fb8640cd7273c2bf13eb102f80954.tar.bz2 busybox-w32-6c1af283f73fb8640cd7273c2bf13eb102f80954.zip | |
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>
| -rw-r--r-- | networking/brctl.c | 111 |
1 files changed, 92 insertions, 19 deletions
diff --git a/networking/brctl.c b/networking/brctl.c index 586ca9b0c..ba5b6226f 100644 --- a/networking/brctl.c +++ b/networking/brctl.c | |||
| @@ -61,10 +61,10 @@ | |||
| 61 | //usage: "\n setbridgeprio BRIDGE PRIO Set bridge priority" | 61 | //usage: "\n setbridgeprio BRIDGE PRIO Set bridge priority" |
| 62 | //usage: "\n setportprio BRIDGE IFACE PRIO Set port priority" | 62 | //usage: "\n setportprio BRIDGE IFACE PRIO Set port priority" |
| 63 | //usage: "\n setpathcost BRIDGE IFACE COST Set path cost" | 63 | //usage: "\n setpathcost BRIDGE IFACE COST Set path cost" |
| 64 | //usage: "\n showmacs BRIDGE List MAC addresses" | ||
| 64 | //usage: ) | 65 | //usage: ) |
| 65 | // Not yet implemented: | 66 | // Not yet implemented: |
| 66 | // hairpin BRIDGE IFACE on|off Hairpin on/off | 67 | // hairpin BRIDGE IFACE on|off Hairpin on/off |
| 67 | // showmacs BRIDGE List mac addrs | ||
| 68 | // showstp BRIDGE Show stp info | 68 | // showstp BRIDGE Show stp info |
| 69 | 69 | ||
| 70 | #include "libbb.h" | 70 | #include "libbb.h" |
| @@ -196,6 +196,89 @@ static void write_uint(const char *name, const char *leaf, unsigned val) | |||
| 196 | bb_simple_perror_msg_and_die(name); | 196 | bb_simple_perror_msg_and_die(name); |
| 197 | close(fd); | 197 | close(fd); |
| 198 | } | 198 | } |
| 199 | |||
| 200 | struct fdb_entry { | ||
| 201 | uint8_t mac_addr[6]; | ||
| 202 | uint8_t port_no; | ||
| 203 | uint8_t is_local; | ||
| 204 | uint32_t ageing_timer_value; | ||
| 205 | uint8_t port_hi; | ||
| 206 | uint8_t pad0; | ||
| 207 | uint16_t unused; | ||
| 208 | }; | ||
| 209 | |||
| 210 | static int compare_fdbs(const void *_f0, const void *_f1) | ||
| 211 | { | ||
| 212 | const struct fdb_entry *f0 = _f0; | ||
| 213 | const struct fdb_entry *f1 = _f1; | ||
| 214 | |||
| 215 | return memcmp(f0->mac_addr, f1->mac_addr, 6); | ||
| 216 | } | ||
| 217 | |||
| 218 | static size_t read_bridge_forward_db(const char *name, struct fdb_entry **_fdb) | ||
| 219 | { | ||
| 220 | struct fdb_entry *fdb; | ||
| 221 | size_t nentries; | ||
| 222 | char *path; | ||
| 223 | int fd; | ||
| 224 | ssize_t cc; | ||
| 225 | |||
| 226 | path = concat_path_file(name, "brforward"); | ||
| 227 | fd = open(path, O_RDONLY); | ||
| 228 | free(path); | ||
| 229 | if (fd < 0) | ||
| 230 | bb_error_msg_and_die("bridge %s does not exist", name); | ||
| 231 | |||
| 232 | fdb = NULL; | ||
| 233 | nentries = 0; | ||
| 234 | for (;;) { | ||
| 235 | fdb = xrealloc_vector(fdb, 4, nentries); | ||
| 236 | cc = full_read(fd, &fdb[nentries], sizeof(*fdb)); | ||
| 237 | if (cc == 0) { | ||
| 238 | break; | ||
| 239 | } | ||
| 240 | if (cc != sizeof(*fdb)) { | ||
| 241 | bb_perror_msg_and_die("can't read bridge %s forward db", name); | ||
| 242 | } | ||
| 243 | ++nentries; | ||
| 244 | } | ||
| 245 | |||
| 246 | close(fd); | ||
| 247 | |||
| 248 | qsort(fdb, nentries, sizeof(*fdb), compare_fdbs); | ||
| 249 | |||
| 250 | *_fdb = fdb; | ||
| 251 | return nentries; | ||
| 252 | } | ||
| 253 | |||
| 254 | static void show_bridge_macs(const char *name) | ||
| 255 | { | ||
| 256 | struct fdb_entry *fdb; | ||
| 257 | size_t nentries; | ||
| 258 | size_t i; | ||
| 259 | |||
| 260 | nentries = read_bridge_forward_db(name, &fdb); | ||
| 261 | |||
| 262 | printf("port no\tmac addr\t\tis local?\tageing timer\n"); | ||
| 263 | for (i = 0; i < nentries; ++i) { | ||
| 264 | const struct fdb_entry *f = &fdb[i]; | ||
| 265 | unsigned long tvmsec = 10UL * f->ageing_timer_value; | ||
| 266 | unsigned tv_sec = tvmsec / 1000; | ||
| 267 | unsigned tv_msec = tvmsec % 1000; | ||
| 268 | printf("%3u\t" | ||
| 269 | "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\t" | ||
| 270 | "%s\t\t" | ||
| 271 | "%4u.%.2u\n", | ||
| 272 | f->port_no, | ||
| 273 | f->mac_addr[0], f->mac_addr[1], f->mac_addr[2], | ||
| 274 | f->mac_addr[3], f->mac_addr[4], f->mac_addr[5], | ||
| 275 | (f->is_local ? "yes" : "no"), | ||
| 276 | tv_sec, tv_msec / 10 | ||
| 277 | ); | ||
| 278 | } | ||
| 279 | |||
| 280 | free(fdb); | ||
| 281 | } | ||
| 199 | #endif | 282 | #endif |
| 200 | 283 | ||
| 201 | int brctl_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 284 | int brctl_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
| @@ -208,6 +291,7 @@ int brctl_main(int argc UNUSED_PARAM, char **argv) | |||
| 208 | "setageing\0" "setfd\0" "sethello\0" "setmaxage\0" | 291 | "setageing\0" "setfd\0" "sethello\0" "setmaxage\0" |
| 209 | "setpathcost\0" "setportprio\0" | 292 | "setpathcost\0" "setportprio\0" |
| 210 | "setbridgeprio\0" | 293 | "setbridgeprio\0" |
| 294 | "showmacs\0" | ||
| 211 | ) | 295 | ) |
| 212 | IF_FEATURE_BRCTL_SHOW("show\0"); | 296 | IF_FEATURE_BRCTL_SHOW("show\0"); |
| 213 | enum { ARG_addbr = 0, ARG_delbr, ARG_addif, ARG_delif | 297 | enum { ARG_addbr = 0, ARG_delbr, ARG_addif, ARG_delif |
| @@ -215,7 +299,8 @@ int brctl_main(int argc UNUSED_PARAM, char **argv) | |||
| 215 | ARG_stp, | 299 | ARG_stp, |
| 216 | ARG_setageing, ARG_setfd, ARG_sethello, ARG_setmaxage, | 300 | ARG_setageing, ARG_setfd, ARG_sethello, ARG_setmaxage, |
| 217 | ARG_setpathcost, ARG_setportprio, | 301 | ARG_setpathcost, ARG_setportprio, |
| 218 | ARG_setbridgeprio | 302 | ARG_setbridgeprio, |
| 303 | ARG_showmacs | ||
| 219 | ) | 304 | ) |
| 220 | IF_FEATURE_BRCTL_SHOW(, ARG_show) | 305 | IF_FEATURE_BRCTL_SHOW(, ARG_show) |
| 221 | }; | 306 | }; |
| @@ -299,6 +384,11 @@ int brctl_main(int argc UNUSED_PARAM, char **argv) | |||
| 299 | return EXIT_SUCCESS; | 384 | return EXIT_SUCCESS; |
| 300 | } | 385 | } |
| 301 | 386 | ||
| 387 | if (key == ARG_showmacs) { | ||
| 388 | show_bridge_macs(br); | ||
| 389 | return EXIT_SUCCESS; | ||
| 390 | } | ||
| 391 | |||
| 302 | if (!*argv) /* all but 'addbr/delbr' need at least two arguments */ | 392 | if (!*argv) /* all but 'addbr/delbr' need at least two arguments */ |
| 303 | bb_show_usage(); | 393 | bb_show_usage(); |
| 304 | 394 | ||
| @@ -365,23 +455,6 @@ int brctl_main(int argc UNUSED_PARAM, char **argv) | |||
| 365 | //goto done_next_argv; | 455 | //goto done_next_argv; |
| 366 | return EXIT_SUCCESS; | 456 | return EXIT_SUCCESS; |
| 367 | } | 457 | } |
| 368 | |||
| 369 | /* TODO: "showmacs BR" | ||
| 370 | * port no\tmac addr\t\tis local?\tageing timer | ||
| 371 | * <sp><sp>1\txx:xx:xx:xx:xx:xx\tno\t\t<sp><sp><sp>1.31 | ||
| 372 | * port no mac addr is local? ageing timer | ||
| 373 | * 1 xx:xx:xx:xx:xx:xx no 1.31 | ||
| 374 | * Read fixed-sized records from /sys/class/net/BR/brforward: | ||
| 375 | * struct __fdb_entry { | ||
| 376 | * uint8_t mac_addr[ETH_ALEN]; | ||
| 377 | * uint8_t port_no; //lsb | ||
| 378 | * uint8_t is_local; | ||
| 379 | * uint32_t ageing_timer_value; | ||
| 380 | * uint8_t port_hi; | ||
| 381 | * uint8_t pad0; | ||
| 382 | * uint16_t unused; | ||
| 383 | * }; | ||
| 384 | */ | ||
| 385 | #endif | 458 | #endif |
| 386 | /* always true: if (key == ARG_addif || key == ARG_delif) */ { | 459 | /* always true: if (key == ARG_addif || key == ARG_delif) */ { |
| 387 | /* addif or delif */ | 460 | /* addif or delif */ |
