2 * iplink_bridge.c Bridge device support
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
9 * Authors: Jiri Pirko <jiri@resnulli.us>
15 #include <netinet/in.h>
16 #include <netinet/ether.h>
17 #include <linux/if_link.h>
18 #include <linux/if_bridge.h>
23 #include "ip_common.h"
25 static unsigned int xstats_print_attr
;
26 static int filter_index
;
28 static void print_explain(FILE *f
)
31 "Usage: ... bridge [ fdb_flush ]\n"
32 " [ forward_delay FORWARD_DELAY ]\n"
33 " [ hello_time HELLO_TIME ]\n"
34 " [ max_age MAX_AGE ]\n"
35 " [ ageing_time AGEING_TIME ]\n"
36 " [ stp_state STP_STATE ]\n"
37 " [ priority PRIORITY ]\n"
38 " [ group_fwd_mask MASK ]\n"
39 " [ group_address ADDRESS ]\n"
40 " [ vlan_filtering VLAN_FILTERING ]\n"
41 " [ vlan_protocol VLAN_PROTOCOL ]\n"
42 " [ vlan_default_pvid VLAN_DEFAULT_PVID ]\n"
43 " [ vlan_stats_enabled VLAN_STATS_ENABLED ]\n"
44 " [ mcast_snooping MULTICAST_SNOOPING ]\n"
45 " [ mcast_router MULTICAST_ROUTER ]\n"
46 " [ mcast_query_use_ifaddr MCAST_QUERY_USE_IFADDR ]\n"
47 " [ mcast_querier MULTICAST_QUERIER ]\n"
48 " [ mcast_hash_elasticity HASH_ELASTICITY ]\n"
49 " [ mcast_hash_max HASH_MAX ]\n"
50 " [ mcast_last_member_count LAST_MEMBER_COUNT ]\n"
51 " [ mcast_startup_query_count STARTUP_QUERY_COUNT ]\n"
52 " [ mcast_last_member_interval LAST_MEMBER_INTERVAL ]\n"
53 " [ mcast_membership_interval MEMBERSHIP_INTERVAL ]\n"
54 " [ mcast_querier_interval QUERIER_INTERVAL ]\n"
55 " [ mcast_query_interval QUERY_INTERVAL ]\n"
56 " [ mcast_query_response_interval QUERY_RESPONSE_INTERVAL ]\n"
57 " [ mcast_startup_query_interval STARTUP_QUERY_INTERVAL ]\n"
58 " [ mcast_stats_enabled MCAST_STATS_ENABLED ]\n"
59 " [ mcast_igmp_version IGMP_VERSION ]\n"
60 " [ mcast_mld_version MLD_VERSION ]\n"
61 " [ nf_call_iptables NF_CALL_IPTABLES ]\n"
62 " [ nf_call_ip6tables NF_CALL_IP6TABLES ]\n"
63 " [ nf_call_arptables NF_CALL_ARPTABLES ]\n"
65 "Where: VLAN_PROTOCOL := { 802.1Q | 802.1ad }\n"
69 static void explain(void)
71 print_explain(stderr
);
74 void br_dump_bridge_id(const struct ifla_bridge_id
*id
, char *buf
, size_t len
)
78 ether_ntoa_r((const struct ether_addr
*)id
->addr
, eaddr
);
79 snprintf(buf
, len
, "%.2x%.2x.%s", id
->prio
[0], id
->prio
[1], eaddr
);
82 static int bridge_parse_opt(struct link_util
*lu
, int argc
, char **argv
,
88 if (matches(*argv
, "forward_delay") == 0) {
90 if (get_u32(&val
, *argv
, 0))
91 invarg("invalid forward_delay", *argv
);
93 addattr32(n
, 1024, IFLA_BR_FORWARD_DELAY
, val
);
94 } else if (matches(*argv
, "hello_time") == 0) {
96 if (get_u32(&val
, *argv
, 0))
97 invarg("invalid hello_time", *argv
);
99 addattr32(n
, 1024, IFLA_BR_HELLO_TIME
, val
);
100 } else if (matches(*argv
, "max_age") == 0) {
102 if (get_u32(&val
, *argv
, 0))
103 invarg("invalid max_age", *argv
);
105 addattr32(n
, 1024, IFLA_BR_MAX_AGE
, val
);
106 } else if (matches(*argv
, "ageing_time") == 0) {
108 if (get_u32(&val
, *argv
, 0))
109 invarg("invalid ageing_time", *argv
);
111 addattr32(n
, 1024, IFLA_BR_AGEING_TIME
, val
);
112 } else if (matches(*argv
, "stp_state") == 0) {
114 if (get_u32(&val
, *argv
, 0))
115 invarg("invalid stp_state", *argv
);
117 addattr32(n
, 1024, IFLA_BR_STP_STATE
, val
);
118 } else if (matches(*argv
, "priority") == 0) {
122 if (get_u16(&prio
, *argv
, 0))
123 invarg("invalid priority", *argv
);
125 addattr16(n
, 1024, IFLA_BR_PRIORITY
, prio
);
126 } else if (matches(*argv
, "vlan_filtering") == 0) {
130 if (get_u8(&vlan_filter
, *argv
, 0))
131 invarg("invalid vlan_filtering", *argv
);
133 addattr8(n
, 1024, IFLA_BR_VLAN_FILTERING
, vlan_filter
);
134 } else if (matches(*argv
, "vlan_protocol") == 0) {
138 if (ll_proto_a2n(&vlan_proto
, *argv
))
139 invarg("invalid vlan_protocol", *argv
);
141 addattr16(n
, 1024, IFLA_BR_VLAN_PROTOCOL
, vlan_proto
);
142 } else if (matches(*argv
, "group_fwd_mask") == 0) {
146 if (get_u16(&fwd_mask
, *argv
, 0))
147 invarg("invalid group_fwd_mask", *argv
);
149 addattr16(n
, 1024, IFLA_BR_GROUP_FWD_MASK
, fwd_mask
);
150 } else if (matches(*argv
, "group_address") == 0) {
155 len
= ll_addr_a2n(llabuf
, sizeof(llabuf
), *argv
);
158 addattr_l(n
, 1024, IFLA_BR_GROUP_ADDR
, llabuf
, len
);
159 } else if (matches(*argv
, "fdb_flush") == 0) {
160 addattr(n
, 1024, IFLA_BR_FDB_FLUSH
);
161 } else if (matches(*argv
, "vlan_default_pvid") == 0) {
165 if (get_u16(&default_pvid
, *argv
, 0))
166 invarg("invalid vlan_default_pvid", *argv
);
168 addattr16(n
, 1024, IFLA_BR_VLAN_DEFAULT_PVID
,
170 } else if (matches(*argv
, "vlan_stats_enabled") == 0) {
171 __u8 vlan_stats_enabled
;
174 if (get_u8(&vlan_stats_enabled
, *argv
, 0))
175 invarg("invalid vlan_stats_enabled", *argv
);
176 addattr8(n
, 1024, IFLA_BR_VLAN_STATS_ENABLED
,
178 } else if (matches(*argv
, "mcast_router") == 0) {
182 if (get_u8(&mcast_router
, *argv
, 0))
183 invarg("invalid mcast_router", *argv
);
185 addattr8(n
, 1024, IFLA_BR_MCAST_ROUTER
, mcast_router
);
186 } else if (matches(*argv
, "mcast_snooping") == 0) {
190 if (get_u8(&mcast_snoop
, *argv
, 0))
191 invarg("invalid mcast_snooping", *argv
);
193 addattr8(n
, 1024, IFLA_BR_MCAST_SNOOPING
, mcast_snoop
);
194 } else if (matches(*argv
, "mcast_query_use_ifaddr") == 0) {
198 if (get_u8(&mcast_qui
, *argv
, 0))
199 invarg("invalid mcast_query_use_ifaddr",
202 addattr8(n
, 1024, IFLA_BR_MCAST_QUERY_USE_IFADDR
,
204 } else if (matches(*argv
, "mcast_querier") == 0) {
208 if (get_u8(&mcast_querier
, *argv
, 0))
209 invarg("invalid mcast_querier", *argv
);
211 addattr8(n
, 1024, IFLA_BR_MCAST_QUERIER
, mcast_querier
);
212 } else if (matches(*argv
, "mcast_hash_elasticity") == 0) {
216 if (get_u32(&mcast_hash_el
, *argv
, 0))
217 invarg("invalid mcast_hash_elasticity",
220 addattr32(n
, 1024, IFLA_BR_MCAST_HASH_ELASTICITY
,
222 } else if (matches(*argv
, "mcast_hash_max") == 0) {
223 __u32 mcast_hash_max
;
226 if (get_u32(&mcast_hash_max
, *argv
, 0))
227 invarg("invalid mcast_hash_max", *argv
);
229 addattr32(n
, 1024, IFLA_BR_MCAST_HASH_MAX
,
231 } else if (matches(*argv
, "mcast_last_member_count") == 0) {
235 if (get_u32(&mcast_lmc
, *argv
, 0))
236 invarg("invalid mcast_last_member_count",
239 addattr32(n
, 1024, IFLA_BR_MCAST_LAST_MEMBER_CNT
,
241 } else if (matches(*argv
, "mcast_startup_query_count") == 0) {
245 if (get_u32(&mcast_sqc
, *argv
, 0))
246 invarg("invalid mcast_startup_query_count",
249 addattr32(n
, 1024, IFLA_BR_MCAST_STARTUP_QUERY_CNT
,
251 } else if (matches(*argv
, "mcast_last_member_interval") == 0) {
252 __u64 mcast_last_member_intvl
;
255 if (get_u64(&mcast_last_member_intvl
, *argv
, 0))
256 invarg("invalid mcast_last_member_interval",
259 addattr64(n
, 1024, IFLA_BR_MCAST_LAST_MEMBER_INTVL
,
260 mcast_last_member_intvl
);
261 } else if (matches(*argv
, "mcast_membership_interval") == 0) {
262 __u64 mcast_membership_intvl
;
265 if (get_u64(&mcast_membership_intvl
, *argv
, 0))
266 invarg("invalid mcast_membership_interval",
269 addattr64(n
, 1024, IFLA_BR_MCAST_MEMBERSHIP_INTVL
,
270 mcast_membership_intvl
);
271 } else if (matches(*argv
, "mcast_querier_interval") == 0) {
272 __u64 mcast_querier_intvl
;
275 if (get_u64(&mcast_querier_intvl
, *argv
, 0))
276 invarg("invalid mcast_querier_interval",
279 addattr64(n
, 1024, IFLA_BR_MCAST_QUERIER_INTVL
,
280 mcast_querier_intvl
);
281 } else if (matches(*argv
, "mcast_query_interval") == 0) {
282 __u64 mcast_query_intvl
;
285 if (get_u64(&mcast_query_intvl
, *argv
, 0))
286 invarg("invalid mcast_query_interval",
289 addattr64(n
, 1024, IFLA_BR_MCAST_QUERY_INTVL
,
291 } else if (!matches(*argv
, "mcast_query_response_interval")) {
292 __u64 mcast_query_resp_intvl
;
295 if (get_u64(&mcast_query_resp_intvl
, *argv
, 0))
296 invarg("invalid mcast_query_response_interval",
299 addattr64(n
, 1024, IFLA_BR_MCAST_QUERY_RESPONSE_INTVL
,
300 mcast_query_resp_intvl
);
301 } else if (!matches(*argv
, "mcast_startup_query_interval")) {
302 __u64 mcast_startup_query_intvl
;
305 if (get_u64(&mcast_startup_query_intvl
, *argv
, 0))
306 invarg("invalid mcast_startup_query_interval",
309 addattr64(n
, 1024, IFLA_BR_MCAST_STARTUP_QUERY_INTVL
,
310 mcast_startup_query_intvl
);
311 } else if (matches(*argv
, "mcast_stats_enabled") == 0) {
312 __u8 mcast_stats_enabled
;
315 if (get_u8(&mcast_stats_enabled
, *argv
, 0))
316 invarg("invalid mcast_stats_enabled", *argv
);
317 addattr8(n
, 1024, IFLA_BR_MCAST_STATS_ENABLED
,
318 mcast_stats_enabled
);
319 } else if (matches(*argv
, "mcast_igmp_version") == 0) {
323 if (get_u8(&igmp_version
, *argv
, 0))
324 invarg("invalid mcast_igmp_version", *argv
);
325 addattr8(n
, 1024, IFLA_BR_MCAST_IGMP_VERSION
,
327 } else if (matches(*argv
, "mcast_mld_version") == 0) {
331 if (get_u8(&mld_version
, *argv
, 0))
332 invarg("invalid mcast_mld_version", *argv
);
333 addattr8(n
, 1024, IFLA_BR_MCAST_MLD_VERSION
,
335 } else if (matches(*argv
, "nf_call_iptables") == 0) {
339 if (get_u8(&nf_call_ipt
, *argv
, 0))
340 invarg("invalid nf_call_iptables", *argv
);
342 addattr8(n
, 1024, IFLA_BR_NF_CALL_IPTABLES
,
344 } else if (matches(*argv
, "nf_call_ip6tables") == 0) {
348 if (get_u8(&nf_call_ip6t
, *argv
, 0))
349 invarg("invalid nf_call_ip6tables", *argv
);
351 addattr8(n
, 1024, IFLA_BR_NF_CALL_IP6TABLES
,
353 } else if (matches(*argv
, "nf_call_arptables") == 0) {
357 if (get_u8(&nf_call_arpt
, *argv
, 0))
358 invarg("invalid nf_call_arptables", *argv
);
360 addattr8(n
, 1024, IFLA_BR_NF_CALL_ARPTABLES
,
362 } else if (matches(*argv
, "help") == 0) {
366 fprintf(stderr
, "bridge: unknown command \"%s\"?\n", *argv
);
376 static void _bridge_print_timer(FILE *f
,
378 struct rtattr
*timer
)
382 __jiffies_to_tv(&tv
, rta_getattr_u64(timer
));
383 if (is_json_context()) {
384 json_writer_t
*jw
= get_json_writer();
386 jsonw_name(jw
, attr
);
387 jsonw_printf(jw
, "%i.%.2i",
389 (int)tv
.tv_usec
/ 10000);
391 fprintf(f
, "%s %4i.%.2i ", attr
, (int)tv
.tv_sec
,
392 (int)tv
.tv_usec
/ 10000);
396 static void bridge_print_opt(struct link_util
*lu
, FILE *f
, struct rtattr
*tb
[])
401 if (tb
[IFLA_BR_FORWARD_DELAY
])
402 print_uint(PRINT_ANY
,
405 rta_getattr_u32(tb
[IFLA_BR_FORWARD_DELAY
]));
407 if (tb
[IFLA_BR_HELLO_TIME
])
408 print_uint(PRINT_ANY
,
411 rta_getattr_u32(tb
[IFLA_BR_HELLO_TIME
]));
413 if (tb
[IFLA_BR_MAX_AGE
])
414 print_uint(PRINT_ANY
,
417 rta_getattr_u32(tb
[IFLA_BR_MAX_AGE
]));
419 if (tb
[IFLA_BR_AGEING_TIME
])
420 print_uint(PRINT_ANY
,
423 rta_getattr_u32(tb
[IFLA_BR_AGEING_TIME
]));
425 if (tb
[IFLA_BR_STP_STATE
])
426 print_uint(PRINT_ANY
,
429 rta_getattr_u32(tb
[IFLA_BR_STP_STATE
]));
431 if (tb
[IFLA_BR_PRIORITY
])
432 print_uint(PRINT_ANY
,
435 rta_getattr_u16(tb
[IFLA_BR_PRIORITY
]));
437 if (tb
[IFLA_BR_VLAN_FILTERING
])
438 print_uint(PRINT_ANY
,
440 "vlan_filtering %u ",
441 rta_getattr_u8(tb
[IFLA_BR_VLAN_FILTERING
]));
443 if (tb
[IFLA_BR_VLAN_PROTOCOL
]) {
446 print_string(PRINT_ANY
,
449 ll_proto_n2a(rta_getattr_u16(tb
[IFLA_BR_VLAN_PROTOCOL
]),
453 if (tb
[IFLA_BR_BRIDGE_ID
]) {
456 br_dump_bridge_id(RTA_DATA(tb
[IFLA_BR_BRIDGE_ID
]), bridge_id
,
458 print_string(PRINT_ANY
,
464 if (tb
[IFLA_BR_ROOT_ID
]) {
467 br_dump_bridge_id(RTA_DATA(tb
[IFLA_BR_BRIDGE_ID
]), root_id
,
469 print_string(PRINT_ANY
,
471 "designated_root %s ",
475 if (tb
[IFLA_BR_ROOT_PORT
])
476 print_uint(PRINT_ANY
,
479 rta_getattr_u16(tb
[IFLA_BR_ROOT_PORT
]));
481 if (tb
[IFLA_BR_ROOT_PATH_COST
])
482 print_uint(PRINT_ANY
,
484 "root_path_cost %u ",
485 rta_getattr_u32(tb
[IFLA_BR_ROOT_PATH_COST
]));
487 if (tb
[IFLA_BR_TOPOLOGY_CHANGE
])
488 print_uint(PRINT_ANY
,
490 "topology_change %u ",
491 rta_getattr_u8(tb
[IFLA_BR_TOPOLOGY_CHANGE
]));
493 if (tb
[IFLA_BR_TOPOLOGY_CHANGE_DETECTED
])
494 print_uint(PRINT_ANY
,
495 "topology_change_detected",
496 "topology_change_detected %u ",
497 rta_getattr_u8(tb
[IFLA_BR_TOPOLOGY_CHANGE_DETECTED
]));
499 if (tb
[IFLA_BR_HELLO_TIMER
])
500 _bridge_print_timer(f
, "hello_timer", tb
[IFLA_BR_HELLO_TIMER
]);
502 if (tb
[IFLA_BR_TCN_TIMER
])
503 _bridge_print_timer(f
, "tcn_timer", tb
[IFLA_BR_TCN_TIMER
]);
505 if (tb
[IFLA_BR_TOPOLOGY_CHANGE_TIMER
])
506 _bridge_print_timer(f
, "topology_change_timer",
507 tb
[IFLA_BR_TOPOLOGY_CHANGE_TIMER
]);
509 if (tb
[IFLA_BR_GC_TIMER
])
510 _bridge_print_timer(f
, "gc_timer", tb
[IFLA_BR_GC_TIMER
]);
512 if (tb
[IFLA_BR_VLAN_DEFAULT_PVID
])
513 print_uint(PRINT_ANY
,
515 "vlan_default_pvid %u ",
516 rta_getattr_u16(tb
[IFLA_BR_VLAN_DEFAULT_PVID
]));
518 if (tb
[IFLA_BR_VLAN_STATS_ENABLED
])
519 print_uint(PRINT_ANY
,
520 "vlan_stats_enabled",
521 "vlan_stats_enabled %u ",
522 rta_getattr_u8(tb
[IFLA_BR_VLAN_STATS_ENABLED
]));
524 if (tb
[IFLA_BR_GROUP_FWD_MASK
])
525 print_0xhex(PRINT_ANY
,
527 "group_fwd_mask %#x ",
528 rta_getattr_u16(tb
[IFLA_BR_GROUP_FWD_MASK
]));
530 if (tb
[IFLA_BR_GROUP_ADDR
]) {
533 print_string(PRINT_ANY
,
536 ll_addr_n2a(RTA_DATA(tb
[IFLA_BR_GROUP_ADDR
]),
537 RTA_PAYLOAD(tb
[IFLA_BR_GROUP_ADDR
]),
538 1 /*ARPHDR_ETHER*/, mac
, sizeof(mac
)));
541 if (tb
[IFLA_BR_MCAST_SNOOPING
])
542 print_uint(PRINT_ANY
,
544 "mcast_snooping %u ",
545 rta_getattr_u8(tb
[IFLA_BR_MCAST_SNOOPING
]));
547 if (tb
[IFLA_BR_MCAST_ROUTER
])
548 print_uint(PRINT_ANY
,
551 rta_getattr_u8(tb
[IFLA_BR_MCAST_ROUTER
]));
553 if (tb
[IFLA_BR_MCAST_QUERY_USE_IFADDR
])
554 print_uint(PRINT_ANY
,
555 "mcast_query_use_ifaddr",
556 "mcast_query_use_ifaddr %u ",
557 rta_getattr_u8(tb
[IFLA_BR_MCAST_QUERY_USE_IFADDR
]));
559 if (tb
[IFLA_BR_MCAST_QUERIER
])
560 print_uint(PRINT_ANY
,
563 rta_getattr_u8(tb
[IFLA_BR_MCAST_QUERIER
]));
565 if (tb
[IFLA_BR_MCAST_HASH_ELASTICITY
])
566 print_uint(PRINT_ANY
,
567 "mcast_hash_elasticity",
568 "mcast_hash_elasticity %u ",
569 rta_getattr_u32(tb
[IFLA_BR_MCAST_HASH_ELASTICITY
]));
571 if (tb
[IFLA_BR_MCAST_HASH_MAX
])
572 print_uint(PRINT_ANY
,
574 "mcast_hash_max %u ",
575 rta_getattr_u32(tb
[IFLA_BR_MCAST_HASH_MAX
]));
577 if (tb
[IFLA_BR_MCAST_LAST_MEMBER_CNT
])
578 print_uint(PRINT_ANY
,
579 "mcast_last_member_cnt",
580 "mcast_last_member_count %u ",
581 rta_getattr_u32(tb
[IFLA_BR_MCAST_LAST_MEMBER_CNT
]));
583 if (tb
[IFLA_BR_MCAST_STARTUP_QUERY_CNT
])
584 print_uint(PRINT_ANY
,
585 "mcast_startup_query_cnt",
586 "mcast_startup_query_count %u ",
587 rta_getattr_u32(tb
[IFLA_BR_MCAST_STARTUP_QUERY_CNT
]));
589 if (tb
[IFLA_BR_MCAST_LAST_MEMBER_INTVL
])
590 print_lluint(PRINT_ANY
,
591 "mcast_last_member_intvl",
592 "mcast_last_member_interval %llu ",
593 rta_getattr_u64(tb
[IFLA_BR_MCAST_LAST_MEMBER_INTVL
]));
595 if (tb
[IFLA_BR_MCAST_MEMBERSHIP_INTVL
])
596 print_lluint(PRINT_ANY
,
597 "mcast_membership_intvl",
598 "mcast_membership_interval %llu ",
599 rta_getattr_u64(tb
[IFLA_BR_MCAST_MEMBERSHIP_INTVL
]));
601 if (tb
[IFLA_BR_MCAST_QUERIER_INTVL
])
602 print_lluint(PRINT_ANY
,
603 "mcast_querier_intvl",
604 "mcast_querier_interval %llu ",
605 rta_getattr_u64(tb
[IFLA_BR_MCAST_QUERIER_INTVL
]));
607 if (tb
[IFLA_BR_MCAST_QUERY_INTVL
])
608 print_lluint(PRINT_ANY
,
610 "mcast_query_interval %llu ",
611 rta_getattr_u64(tb
[IFLA_BR_MCAST_QUERY_INTVL
]));
613 if (tb
[IFLA_BR_MCAST_QUERY_RESPONSE_INTVL
])
614 print_lluint(PRINT_ANY
,
615 "mcast_query_response_intvl",
616 "mcast_query_response_interval %llu ",
617 rta_getattr_u64(tb
[IFLA_BR_MCAST_QUERY_RESPONSE_INTVL
]));
619 if (tb
[IFLA_BR_MCAST_STARTUP_QUERY_INTVL
])
620 print_lluint(PRINT_ANY
,
621 "mcast_startup_query_intvl",
622 "mcast_startup_query_interval %llu ",
623 rta_getattr_u64(tb
[IFLA_BR_MCAST_STARTUP_QUERY_INTVL
]));
625 if (tb
[IFLA_BR_MCAST_STATS_ENABLED
])
626 print_uint(PRINT_ANY
,
627 "mcast_stats_enabled",
628 "mcast_stats_enabled %u ",
629 rta_getattr_u8(tb
[IFLA_BR_MCAST_STATS_ENABLED
]));
631 if (tb
[IFLA_BR_MCAST_IGMP_VERSION
])
632 print_uint(PRINT_ANY
,
633 "mcast_igmp_version",
634 "mcast_igmp_version %u ",
635 rta_getattr_u8(tb
[IFLA_BR_MCAST_IGMP_VERSION
]));
637 if (tb
[IFLA_BR_MCAST_MLD_VERSION
])
638 print_uint(PRINT_ANY
,
640 "mcast_mld_version %u ",
641 rta_getattr_u8(tb
[IFLA_BR_MCAST_MLD_VERSION
]));
643 if (tb
[IFLA_BR_NF_CALL_IPTABLES
])
644 print_uint(PRINT_ANY
,
646 "nf_call_iptables %u ",
647 rta_getattr_u8(tb
[IFLA_BR_NF_CALL_IPTABLES
]));
649 if (tb
[IFLA_BR_NF_CALL_IP6TABLES
])
650 print_uint(PRINT_ANY
,
652 "nf_call_ip6tables %u ",
653 rta_getattr_u8(tb
[IFLA_BR_NF_CALL_IP6TABLES
]));
655 if (tb
[IFLA_BR_NF_CALL_ARPTABLES
])
656 print_uint(PRINT_ANY
,
658 "nf_call_arptables %u ",
659 rta_getattr_u8(tb
[IFLA_BR_NF_CALL_ARPTABLES
]));
662 static void bridge_print_help(struct link_util
*lu
, int argc
, char **argv
,
668 static void bridge_print_xstats_help(struct link_util
*lu
, FILE *f
)
670 fprintf(f
, "Usage: ... %s [ igmp ] [ dev DEVICE ]\n", lu
->id
);
673 static void bridge_print_stats_attr(FILE *f
, struct rtattr
*attr
, int ifindex
)
675 struct rtattr
*brtb
[LINK_XSTATS_TYPE_MAX
+1];
676 struct br_mcast_stats
*mstats
;
677 struct rtattr
*i
, *list
;
678 const char *ifname
= "";
681 parse_rtattr(brtb
, LINK_XSTATS_TYPE_MAX
, RTA_DATA(attr
),
683 if (!brtb
[LINK_XSTATS_TYPE_BRIDGE
])
686 list
= brtb
[LINK_XSTATS_TYPE_BRIDGE
];
687 rem
= RTA_PAYLOAD(list
);
688 for (i
= RTA_DATA(list
); RTA_OK(i
, rem
); i
= RTA_NEXT(i
, rem
)) {
689 if (xstats_print_attr
&& i
->rta_type
!= xstats_print_attr
)
691 switch (i
->rta_type
) {
692 case BRIDGE_XSTATS_MCAST
:
693 mstats
= RTA_DATA(i
);
694 ifname
= ll_index_to_name(ifindex
);
695 fprintf(f
, "%-16s\n", ifname
);
696 fprintf(f
, "%-16s IGMP queries:\n", "");
697 fprintf(f
, "%-16s RX: v1 %llu v2 %llu v3 %llu\n",
699 mstats
->igmp_v1queries
[BR_MCAST_DIR_RX
],
700 mstats
->igmp_v2queries
[BR_MCAST_DIR_RX
],
701 mstats
->igmp_v3queries
[BR_MCAST_DIR_RX
]);
702 fprintf(f
, "%-16s TX: v1 %llu v2 %llu v3 %llu\n",
704 mstats
->igmp_v1queries
[BR_MCAST_DIR_TX
],
705 mstats
->igmp_v2queries
[BR_MCAST_DIR_TX
],
706 mstats
->igmp_v3queries
[BR_MCAST_DIR_TX
]);
708 fprintf(f
, "%-16s IGMP reports:\n", "");
709 fprintf(f
, "%-16s RX: v1 %llu v2 %llu v3 %llu\n",
711 mstats
->igmp_v1reports
[BR_MCAST_DIR_RX
],
712 mstats
->igmp_v2reports
[BR_MCAST_DIR_RX
],
713 mstats
->igmp_v3reports
[BR_MCAST_DIR_RX
]);
714 fprintf(f
, "%-16s TX: v1 %llu v2 %llu v3 %llu\n",
716 mstats
->igmp_v1reports
[BR_MCAST_DIR_TX
],
717 mstats
->igmp_v2reports
[BR_MCAST_DIR_TX
],
718 mstats
->igmp_v3reports
[BR_MCAST_DIR_TX
]);
720 fprintf(f
, "%-16s IGMP leaves: RX: %llu TX: %llu\n",
722 mstats
->igmp_leaves
[BR_MCAST_DIR_RX
],
723 mstats
->igmp_leaves
[BR_MCAST_DIR_TX
]);
725 fprintf(f
, "%-16s IGMP parse errors: %llu\n",
726 "", mstats
->igmp_parse_errors
);
728 fprintf(f
, "%-16s MLD queries:\n", "");
729 fprintf(f
, "%-16s RX: v1 %llu v2 %llu\n",
731 mstats
->mld_v1queries
[BR_MCAST_DIR_RX
],
732 mstats
->mld_v2queries
[BR_MCAST_DIR_RX
]);
733 fprintf(f
, "%-16s TX: v1 %llu v2 %llu\n",
735 mstats
->mld_v1queries
[BR_MCAST_DIR_TX
],
736 mstats
->mld_v2queries
[BR_MCAST_DIR_TX
]);
738 fprintf(f
, "%-16s MLD reports:\n", "");
739 fprintf(f
, "%-16s RX: v1 %llu v2 %llu\n",
741 mstats
->mld_v1reports
[BR_MCAST_DIR_RX
],
742 mstats
->mld_v2reports
[BR_MCAST_DIR_RX
]);
743 fprintf(f
, "%-16s TX: v1 %llu v2 %llu\n",
745 mstats
->mld_v1reports
[BR_MCAST_DIR_TX
],
746 mstats
->mld_v2reports
[BR_MCAST_DIR_TX
]);
748 fprintf(f
, "%-16s MLD leaves: RX: %llu TX: %llu\n",
750 mstats
->mld_leaves
[BR_MCAST_DIR_RX
],
751 mstats
->mld_leaves
[BR_MCAST_DIR_TX
]);
753 fprintf(f
, "%-16s MLD parse errors: %llu\n",
754 "", mstats
->mld_parse_errors
);
760 int bridge_print_xstats(struct nlmsghdr
*n
, void *arg
)
762 struct if_stats_msg
*ifsm
= NLMSG_DATA(n
);
763 struct rtattr
*tb
[IFLA_STATS_MAX
+1];
764 int len
= n
->nlmsg_len
;
767 len
-= NLMSG_LENGTH(sizeof(*ifsm
));
769 fprintf(stderr
, "BUG: wrong nlmsg len %d\n", len
);
772 if (filter_index
&& filter_index
!= ifsm
->ifindex
)
775 parse_rtattr(tb
, IFLA_STATS_MAX
, IFLA_STATS_RTA(ifsm
), len
);
776 if (tb
[IFLA_STATS_LINK_XSTATS
])
777 bridge_print_stats_attr(fp
, tb
[IFLA_STATS_LINK_XSTATS
],
780 if (tb
[IFLA_STATS_LINK_XSTATS_SLAVE
])
781 bridge_print_stats_attr(fp
, tb
[IFLA_STATS_LINK_XSTATS_SLAVE
],
787 int bridge_parse_xstats(struct link_util
*lu
, int argc
, char **argv
)
790 if (strcmp(*argv
, "igmp") == 0 || strcmp(*argv
, "mcast") == 0) {
791 xstats_print_attr
= BRIDGE_XSTATS_MCAST
;
792 } else if (strcmp(*argv
, "dev") == 0) {
794 filter_index
= ll_name_to_index(*argv
);
797 } else if (strcmp(*argv
, "help") == 0) {
798 bridge_print_xstats_help(lu
, stdout
);
801 invarg("unknown attribute", *argv
);
809 struct link_util bridge_link_util
= {
811 .maxattr
= IFLA_BR_MAX
,
812 .parse_opt
= bridge_parse_opt
,
813 .print_opt
= bridge_print_opt
,
814 .print_help
= bridge_print_help
,
815 .parse_ifla_xstats
= bridge_parse_xstats
,
816 .print_ifla_xstats
= bridge_print_xstats
,