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 */ |