]> git.proxmox.com Git - mirror_iproute2.git/blame - ip/iplink_bridge.c
ip-xfrm: Fix help messages
[mirror_iproute2.git] / ip / iplink_bridge.c
CommitLineData
28d84b42
JP
1/*
2 * iplink_bridge.c Bridge device support
3 *
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.
8 *
9 * Authors: Jiri Pirko <jiri@resnulli.us>
10 */
11
12#include <stdio.h>
13#include <stdlib.h>
14#include <string.h>
60ec0ecf 15#include <netinet/in.h>
98447086 16#include <netinet/ether.h>
28d84b42 17#include <linux/if_link.h>
60ec0ecf 18#include <linux/if_bridge.h>
60ec0ecf 19#include <net/if.h>
28d84b42 20
1eea5c46 21#include "rt_names.h"
28d84b42
JP
22#include "utils.h"
23#include "ip_common.h"
24
60ec0ecf
NA
25static unsigned int xstats_print_attr;
26static int filter_index;
27
43367ef7 28static void print_explain(FILE *f)
28d84b42 29{
43367ef7 30 fprintf(f,
f3372d62 31 "Usage: ... bridge [ fdb_flush ]\n"
8589eb4e
MC
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 " [ vlan_stats_per_port VLAN_STATS_PER_PORT ]\n"
45 " [ mcast_snooping MULTICAST_SNOOPING ]\n"
46 " [ mcast_router MULTICAST_ROUTER ]\n"
47 " [ mcast_query_use_ifaddr MCAST_QUERY_USE_IFADDR ]\n"
48 " [ mcast_querier MULTICAST_QUERIER ]\n"
49 " [ mcast_hash_elasticity HASH_ELASTICITY ]\n"
50 " [ mcast_hash_max HASH_MAX ]\n"
51 " [ mcast_last_member_count LAST_MEMBER_COUNT ]\n"
52 " [ mcast_startup_query_count STARTUP_QUERY_COUNT ]\n"
53 " [ mcast_last_member_interval LAST_MEMBER_INTERVAL ]\n"
54 " [ mcast_membership_interval MEMBERSHIP_INTERVAL ]\n"
55 " [ mcast_querier_interval QUERIER_INTERVAL ]\n"
56 " [ mcast_query_interval QUERY_INTERVAL ]\n"
57 " [ mcast_query_response_interval QUERY_RESPONSE_INTERVAL ]\n"
58 " [ mcast_startup_query_interval STARTUP_QUERY_INTERVAL ]\n"
59 " [ mcast_stats_enabled MCAST_STATS_ENABLED ]\n"
60 " [ mcast_igmp_version IGMP_VERSION ]\n"
61 " [ mcast_mld_version MLD_VERSION ]\n"
62 " [ nf_call_iptables NF_CALL_IPTABLES ]\n"
63 " [ nf_call_ip6tables NF_CALL_IP6TABLES ]\n"
64 " [ nf_call_arptables NF_CALL_ARPTABLES ]\n"
1eea5c46
TM
65 "\n"
66 "Where: VLAN_PROTOCOL := { 802.1Q | 802.1ad }\n"
28d84b42
JP
67 );
68}
69
43367ef7
ZS
70static void explain(void)
71{
72 print_explain(stderr);
73}
74
3069539f 75void br_dump_bridge_id(const struct ifla_bridge_id *id, char *buf, size_t len)
70dfb0b8
NA
76{
77 char eaddr[32];
78
79 ether_ntoa_r((const struct ether_addr *)id->addr, eaddr);
80 snprintf(buf, len, "%.2x%.2x.%s", id->prio[0], id->prio[1], eaddr);
81}
82
28d84b42
JP
83static int bridge_parse_opt(struct link_util *lu, int argc, char **argv,
84 struct nlmsghdr *n)
85{
86 __u32 val;
87
88 while (argc > 0) {
89 if (matches(*argv, "forward_delay") == 0) {
90 NEXT_ARG();
6a9ce30e 91 if (get_u32(&val, *argv, 0))
28d84b42 92 invarg("invalid forward_delay", *argv);
6a9ce30e 93
28d84b42
JP
94 addattr32(n, 1024, IFLA_BR_FORWARD_DELAY, val);
95 } else if (matches(*argv, "hello_time") == 0) {
96 NEXT_ARG();
6a9ce30e 97 if (get_u32(&val, *argv, 0))
28d84b42 98 invarg("invalid hello_time", *argv);
6a9ce30e 99
28d84b42
JP
100 addattr32(n, 1024, IFLA_BR_HELLO_TIME, val);
101 } else if (matches(*argv, "max_age") == 0) {
102 NEXT_ARG();
6a9ce30e 103 if (get_u32(&val, *argv, 0))
28d84b42 104 invarg("invalid max_age", *argv);
6a9ce30e 105
28d84b42 106 addattr32(n, 1024, IFLA_BR_MAX_AGE, val);
6c99fb60
NA
107 } else if (matches(*argv, "ageing_time") == 0) {
108 NEXT_ARG();
6a9ce30e 109 if (get_u32(&val, *argv, 0))
6c99fb60 110 invarg("invalid ageing_time", *argv);
6a9ce30e 111
6c99fb60 112 addattr32(n, 1024, IFLA_BR_AGEING_TIME, val);
dab04962
NA
113 } else if (matches(*argv, "stp_state") == 0) {
114 NEXT_ARG();
6a9ce30e 115 if (get_u32(&val, *argv, 0))
dab04962 116 invarg("invalid stp_state", *argv);
6a9ce30e 117
dab04962 118 addattr32(n, 1024, IFLA_BR_STP_STATE, val);
b0197a04
NA
119 } else if (matches(*argv, "priority") == 0) {
120 __u16 prio;
121
122 NEXT_ARG();
6a9ce30e 123 if (get_u16(&prio, *argv, 0))
b0197a04 124 invarg("invalid priority", *argv);
6a9ce30e 125
b0197a04 126 addattr16(n, 1024, IFLA_BR_PRIORITY, prio);
e4d456f0
NA
127 } else if (matches(*argv, "vlan_filtering") == 0) {
128 __u8 vlan_filter;
129
130 NEXT_ARG();
8a4cd394 131 if (get_u8(&vlan_filter, *argv, 0))
e4d456f0 132 invarg("invalid vlan_filtering", *argv);
8a4cd394 133
e4d456f0 134 addattr8(n, 1024, IFLA_BR_VLAN_FILTERING, vlan_filter);
1eea5c46
TM
135 } else if (matches(*argv, "vlan_protocol") == 0) {
136 __u16 vlan_proto;
137
138 NEXT_ARG();
8a4cd394 139 if (ll_proto_a2n(&vlan_proto, *argv))
1eea5c46 140 invarg("invalid vlan_protocol", *argv);
8a4cd394 141
1eea5c46 142 addattr16(n, 1024, IFLA_BR_VLAN_PROTOCOL, vlan_proto);
8caaf33b
NA
143 } else if (matches(*argv, "group_fwd_mask") == 0) {
144 __u16 fwd_mask;
145
146 NEXT_ARG();
147 if (get_u16(&fwd_mask, *argv, 0))
148 invarg("invalid group_fwd_mask", *argv);
149
150 addattr16(n, 1024, IFLA_BR_GROUP_FWD_MASK, fwd_mask);
0a61aa39
NA
151 } else if (matches(*argv, "group_address") == 0) {
152 char llabuf[32];
153 int len;
154
155 NEXT_ARG();
156 len = ll_addr_a2n(llabuf, sizeof(llabuf), *argv);
157 if (len < 0)
158 return -1;
159 addattr_l(n, 1024, IFLA_BR_GROUP_ADDR, llabuf, len);
f3372d62
HL
160 } else if (matches(*argv, "fdb_flush") == 0) {
161 addattr(n, 1024, IFLA_BR_FDB_FLUSH);
719832af
NA
162 } else if (matches(*argv, "vlan_default_pvid") == 0) {
163 __u16 default_pvid;
164
165 NEXT_ARG();
166 if (get_u16(&default_pvid, *argv, 0))
167 invarg("invalid vlan_default_pvid", *argv);
168
169 addattr16(n, 1024, IFLA_BR_VLAN_DEFAULT_PVID,
170 default_pvid);
7d93b567
HL
171 } else if (matches(*argv, "vlan_stats_enabled") == 0) {
172 __u8 vlan_stats_enabled;
173
174 NEXT_ARG();
175 if (get_u8(&vlan_stats_enabled, *argv, 0))
176 invarg("invalid vlan_stats_enabled", *argv);
177 addattr8(n, 1024, IFLA_BR_VLAN_STATS_ENABLED,
178 vlan_stats_enabled);
90306a14
NA
179 } else if (matches(*argv, "vlan_stats_per_port") == 0) {
180 __u8 vlan_stats_per_port;
181
182 NEXT_ARG();
183 if (get_u8(&vlan_stats_per_port, *argv, 0))
184 invarg("invalid vlan_stats_per_port", *argv);
185 addattr8(n, 1024, IFLA_BR_VLAN_STATS_PER_PORT,
186 vlan_stats_per_port);
963d137c
NA
187 } else if (matches(*argv, "mcast_router") == 0) {
188 __u8 mcast_router;
189
190 NEXT_ARG();
191 if (get_u8(&mcast_router, *argv, 0))
192 invarg("invalid mcast_router", *argv);
193
194 addattr8(n, 1024, IFLA_BR_MCAST_ROUTER, mcast_router);
7ddd2d94
NA
195 } else if (matches(*argv, "mcast_snooping") == 0) {
196 __u8 mcast_snoop;
197
198 NEXT_ARG();
199 if (get_u8(&mcast_snoop, *argv, 0))
200 invarg("invalid mcast_snooping", *argv);
201
202 addattr8(n, 1024, IFLA_BR_MCAST_SNOOPING, mcast_snoop);
449843d1
NA
203 } else if (matches(*argv, "mcast_query_use_ifaddr") == 0) {
204 __u8 mcast_qui;
205
206 NEXT_ARG();
207 if (get_u8(&mcast_qui, *argv, 0))
208 invarg("invalid mcast_query_use_ifaddr",
209 *argv);
210
211 addattr8(n, 1024, IFLA_BR_MCAST_QUERY_USE_IFADDR,
212 mcast_qui);
0778b741
NA
213 } else if (matches(*argv, "mcast_querier") == 0) {
214 __u8 mcast_querier;
215
216 NEXT_ARG();
217 if (get_u8(&mcast_querier, *argv, 0))
218 invarg("invalid mcast_querier", *argv);
219
220 addattr8(n, 1024, IFLA_BR_MCAST_QUERIER, mcast_querier);
92c0ef70
NA
221 } else if (matches(*argv, "mcast_hash_elasticity") == 0) {
222 __u32 mcast_hash_el;
223
224 NEXT_ARG();
225 if (get_u32(&mcast_hash_el, *argv, 0))
226 invarg("invalid mcast_hash_elasticity",
227 *argv);
228
229 addattr32(n, 1024, IFLA_BR_MCAST_HASH_ELASTICITY,
230 mcast_hash_el);
8b9eb7cd
NA
231 } else if (matches(*argv, "mcast_hash_max") == 0) {
232 __u32 mcast_hash_max;
233
234 NEXT_ARG();
235 if (get_u32(&mcast_hash_max, *argv, 0))
236 invarg("invalid mcast_hash_max", *argv);
237
238 addattr32(n, 1024, IFLA_BR_MCAST_HASH_MAX,
239 mcast_hash_max);
fb44cadb
NA
240 } else if (matches(*argv, "mcast_last_member_count") == 0) {
241 __u32 mcast_lmc;
242
243 NEXT_ARG();
244 if (get_u32(&mcast_lmc, *argv, 0))
245 invarg("invalid mcast_last_member_count",
246 *argv);
247
248 addattr32(n, 1024, IFLA_BR_MCAST_LAST_MEMBER_CNT,
249 mcast_lmc);
ceb64866
NA
250 } else if (matches(*argv, "mcast_startup_query_count") == 0) {
251 __u32 mcast_sqc;
252
253 NEXT_ARG();
254 if (get_u32(&mcast_sqc, *argv, 0))
255 invarg("invalid mcast_startup_query_count",
256 *argv);
257
258 addattr32(n, 1024, IFLA_BR_MCAST_STARTUP_QUERY_CNT,
259 mcast_sqc);
10082a25
NA
260 } else if (matches(*argv, "mcast_last_member_interval") == 0) {
261 __u64 mcast_last_member_intvl;
262
263 NEXT_ARG();
264 if (get_u64(&mcast_last_member_intvl, *argv, 0))
265 invarg("invalid mcast_last_member_interval",
266 *argv);
267
268 addattr64(n, 1024, IFLA_BR_MCAST_LAST_MEMBER_INTVL,
269 mcast_last_member_intvl);
7f3d5592
NA
270 } else if (matches(*argv, "mcast_membership_interval") == 0) {
271 __u64 mcast_membership_intvl;
272
273 NEXT_ARG();
8a4cd394 274 if (get_u64(&mcast_membership_intvl, *argv, 0))
7f3d5592
NA
275 invarg("invalid mcast_membership_interval",
276 *argv);
8a4cd394 277
7f3d5592
NA
278 addattr64(n, 1024, IFLA_BR_MCAST_MEMBERSHIP_INTVL,
279 mcast_membership_intvl);
1f2244b8
NA
280 } else if (matches(*argv, "mcast_querier_interval") == 0) {
281 __u64 mcast_querier_intvl;
282
283 NEXT_ARG();
8a4cd394 284 if (get_u64(&mcast_querier_intvl, *argv, 0))
1f2244b8
NA
285 invarg("invalid mcast_querier_interval",
286 *argv);
8a4cd394 287
1f2244b8
NA
288 addattr64(n, 1024, IFLA_BR_MCAST_QUERIER_INTVL,
289 mcast_querier_intvl);
5a32388f
NA
290 } else if (matches(*argv, "mcast_query_interval") == 0) {
291 __u64 mcast_query_intvl;
292
293 NEXT_ARG();
8a4cd394 294 if (get_u64(&mcast_query_intvl, *argv, 0))
5a32388f
NA
295 invarg("invalid mcast_query_interval",
296 *argv);
8a4cd394 297
5a32388f
NA
298 addattr64(n, 1024, IFLA_BR_MCAST_QUERY_INTVL,
299 mcast_query_intvl);
483df11c
NA
300 } else if (!matches(*argv, "mcast_query_response_interval")) {
301 __u64 mcast_query_resp_intvl;
302
303 NEXT_ARG();
8a4cd394 304 if (get_u64(&mcast_query_resp_intvl, *argv, 0))
483df11c
NA
305 invarg("invalid mcast_query_response_interval",
306 *argv);
8a4cd394 307
483df11c
NA
308 addattr64(n, 1024, IFLA_BR_MCAST_QUERY_RESPONSE_INTVL,
309 mcast_query_resp_intvl);
178b1806
NA
310 } else if (!matches(*argv, "mcast_startup_query_interval")) {
311 __u64 mcast_startup_query_intvl;
312
313 NEXT_ARG();
8a4cd394 314 if (get_u64(&mcast_startup_query_intvl, *argv, 0))
178b1806
NA
315 invarg("invalid mcast_startup_query_interval",
316 *argv);
8a4cd394 317
178b1806
NA
318 addattr64(n, 1024, IFLA_BR_MCAST_STARTUP_QUERY_INTVL,
319 mcast_startup_query_intvl);
6ddad009
HL
320 } else if (matches(*argv, "mcast_stats_enabled") == 0) {
321 __u8 mcast_stats_enabled;
322
323 NEXT_ARG();
324 if (get_u8(&mcast_stats_enabled, *argv, 0))
325 invarg("invalid mcast_stats_enabled", *argv);
326 addattr8(n, 1024, IFLA_BR_MCAST_STATS_ENABLED,
327 mcast_stats_enabled);
19756950
HL
328 } else if (matches(*argv, "mcast_igmp_version") == 0) {
329 __u8 igmp_version;
330
331 NEXT_ARG();
332 if (get_u8(&igmp_version, *argv, 0))
333 invarg("invalid mcast_igmp_version", *argv);
334 addattr8(n, 1024, IFLA_BR_MCAST_IGMP_VERSION,
335 igmp_version);
c3f1e3c4
HL
336 } else if (matches(*argv, "mcast_mld_version") == 0) {
337 __u8 mld_version;
338
339 NEXT_ARG();
340 if (get_u8(&mld_version, *argv, 0))
341 invarg("invalid mcast_mld_version", *argv);
342 addattr8(n, 1024, IFLA_BR_MCAST_MLD_VERSION,
343 mld_version);
861c5dae
NA
344 } else if (matches(*argv, "nf_call_iptables") == 0) {
345 __u8 nf_call_ipt;
346
347 NEXT_ARG();
8a4cd394 348 if (get_u8(&nf_call_ipt, *argv, 0))
861c5dae 349 invarg("invalid nf_call_iptables", *argv);
8a4cd394 350
861c5dae
NA
351 addattr8(n, 1024, IFLA_BR_NF_CALL_IPTABLES,
352 nf_call_ipt);
353 } else if (matches(*argv, "nf_call_ip6tables") == 0) {
354 __u8 nf_call_ip6t;
355
356 NEXT_ARG();
8a4cd394 357 if (get_u8(&nf_call_ip6t, *argv, 0))
861c5dae 358 invarg("invalid nf_call_ip6tables", *argv);
8a4cd394 359
861c5dae
NA
360 addattr8(n, 1024, IFLA_BR_NF_CALL_IP6TABLES,
361 nf_call_ip6t);
362 } else if (matches(*argv, "nf_call_arptables") == 0) {
363 __u8 nf_call_arpt;
364
365 NEXT_ARG();
8a4cd394 366 if (get_u8(&nf_call_arpt, *argv, 0))
861c5dae 367 invarg("invalid nf_call_arptables", *argv);
8a4cd394 368
861c5dae
NA
369 addattr8(n, 1024, IFLA_BR_NF_CALL_ARPTABLES,
370 nf_call_arpt);
28d84b42
JP
371 } else if (matches(*argv, "help") == 0) {
372 explain();
373 return -1;
374 } else {
375 fprintf(stderr, "bridge: unknown command \"%s\"?\n", *argv);
376 explain();
377 return -1;
378 }
379 argc--, argv++;
380 }
381
382 return 0;
383}
384
20aeecfb
JF
385static void _bridge_print_timer(FILE *f,
386 const char *attr,
387 struct rtattr *timer)
388{
389 struct timeval tv;
390
391 __jiffies_to_tv(&tv, rta_getattr_u64(timer));
392 if (is_json_context()) {
393 json_writer_t *jw = get_json_writer();
394
395 jsonw_name(jw, attr);
396 jsonw_printf(jw, "%i.%.2i",
397 (int)tv.tv_sec,
398 (int)tv.tv_usec / 10000);
399 } else {
400 fprintf(f, "%s %4i.%.2i ", attr, (int)tv.tv_sec,
401 (int)tv.tv_usec / 10000);
402 }
403}
404
28d84b42
JP
405static void bridge_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
406{
407 if (!tb)
408 return;
409
410 if (tb[IFLA_BR_FORWARD_DELAY])
20aeecfb
JF
411 print_uint(PRINT_ANY,
412 "forward_delay",
413 "forward_delay %u ",
414 rta_getattr_u32(tb[IFLA_BR_FORWARD_DELAY]));
28d84b42
JP
415
416 if (tb[IFLA_BR_HELLO_TIME])
20aeecfb
JF
417 print_uint(PRINT_ANY,
418 "hello_time",
419 "hello_time %u ",
420 rta_getattr_u32(tb[IFLA_BR_HELLO_TIME]));
28d84b42
JP
421
422 if (tb[IFLA_BR_MAX_AGE])
20aeecfb
JF
423 print_uint(PRINT_ANY,
424 "max_age",
425 "max_age %u ",
426 rta_getattr_u32(tb[IFLA_BR_MAX_AGE]));
fdba0515
NA
427
428 if (tb[IFLA_BR_AGEING_TIME])
20aeecfb
JF
429 print_uint(PRINT_ANY,
430 "ageing_time",
431 "ageing_time %u ",
432 rta_getattr_u32(tb[IFLA_BR_AGEING_TIME]));
fdba0515
NA
433
434 if (tb[IFLA_BR_STP_STATE])
20aeecfb
JF
435 print_uint(PRINT_ANY,
436 "stp_state",
437 "stp_state %u ",
438 rta_getattr_u32(tb[IFLA_BR_STP_STATE]));
fdba0515
NA
439
440 if (tb[IFLA_BR_PRIORITY])
20aeecfb
JF
441 print_uint(PRINT_ANY,
442 "priority",
443 "priority %u ",
444 rta_getattr_u16(tb[IFLA_BR_PRIORITY]));
e4d456f0
NA
445
446 if (tb[IFLA_BR_VLAN_FILTERING])
20aeecfb
JF
447 print_uint(PRINT_ANY,
448 "vlan_filtering",
449 "vlan_filtering %u ",
450 rta_getattr_u8(tb[IFLA_BR_VLAN_FILTERING]));
1eea5c46
TM
451
452 if (tb[IFLA_BR_VLAN_PROTOCOL]) {
453 SPRINT_BUF(b1);
454
20aeecfb
JF
455 print_string(PRINT_ANY,
456 "vlan_protocol",
457 "vlan_protocol %s ",
458 ll_proto_n2a(rta_getattr_u16(tb[IFLA_BR_VLAN_PROTOCOL]),
459 b1, sizeof(b1)));
1eea5c46 460 }
70dfb0b8
NA
461
462 if (tb[IFLA_BR_BRIDGE_ID]) {
463 char bridge_id[32];
464
465 br_dump_bridge_id(RTA_DATA(tb[IFLA_BR_BRIDGE_ID]), bridge_id,
466 sizeof(bridge_id));
20aeecfb
JF
467 print_string(PRINT_ANY,
468 "bridge_id",
469 "bridge_id %s ",
470 bridge_id);
70dfb0b8
NA
471 }
472
473 if (tb[IFLA_BR_ROOT_ID]) {
474 char root_id[32];
475
476 br_dump_bridge_id(RTA_DATA(tb[IFLA_BR_BRIDGE_ID]), root_id,
477 sizeof(root_id));
20aeecfb
JF
478 print_string(PRINT_ANY,
479 "root_id",
480 "designated_root %s ",
481 root_id);
70dfb0b8 482 }
4e3bbc66
NA
483
484 if (tb[IFLA_BR_ROOT_PORT])
20aeecfb
JF
485 print_uint(PRINT_ANY,
486 "root_port",
487 "root_port %u ",
488 rta_getattr_u16(tb[IFLA_BR_ROOT_PORT]));
4e3bbc66
NA
489
490 if (tb[IFLA_BR_ROOT_PATH_COST])
20aeecfb
JF
491 print_uint(PRINT_ANY,
492 "root_path_cost",
493 "root_path_cost %u ",
494 rta_getattr_u32(tb[IFLA_BR_ROOT_PATH_COST]));
4e3bbc66
NA
495
496 if (tb[IFLA_BR_TOPOLOGY_CHANGE])
20aeecfb
JF
497 print_uint(PRINT_ANY,
498 "topology_change",
499 "topology_change %u ",
500 rta_getattr_u8(tb[IFLA_BR_TOPOLOGY_CHANGE]));
4e3bbc66
NA
501
502 if (tb[IFLA_BR_TOPOLOGY_CHANGE_DETECTED])
20aeecfb
JF
503 print_uint(PRINT_ANY,
504 "topology_change_detected",
505 "topology_change_detected %u ",
506 rta_getattr_u8(tb[IFLA_BR_TOPOLOGY_CHANGE_DETECTED]));
8c0f7a16 507
20aeecfb
JF
508 if (tb[IFLA_BR_HELLO_TIMER])
509 _bridge_print_timer(f, "hello_timer", tb[IFLA_BR_HELLO_TIMER]);
8c0f7a16 510
20aeecfb
JF
511 if (tb[IFLA_BR_TCN_TIMER])
512 _bridge_print_timer(f, "tcn_timer", tb[IFLA_BR_TCN_TIMER]);
8c0f7a16 513
20aeecfb
JF
514 if (tb[IFLA_BR_TOPOLOGY_CHANGE_TIMER])
515 _bridge_print_timer(f, "topology_change_timer",
516 tb[IFLA_BR_TOPOLOGY_CHANGE_TIMER]);
8c0f7a16 517
20aeecfb
JF
518 if (tb[IFLA_BR_GC_TIMER])
519 _bridge_print_timer(f, "gc_timer", tb[IFLA_BR_GC_TIMER]);
8caaf33b 520
719832af 521 if (tb[IFLA_BR_VLAN_DEFAULT_PVID])
20aeecfb
JF
522 print_uint(PRINT_ANY,
523 "vlan_default_pvid",
524 "vlan_default_pvid %u ",
525 rta_getattr_u16(tb[IFLA_BR_VLAN_DEFAULT_PVID]));
719832af 526
7d93b567 527 if (tb[IFLA_BR_VLAN_STATS_ENABLED])
20aeecfb
JF
528 print_uint(PRINT_ANY,
529 "vlan_stats_enabled",
530 "vlan_stats_enabled %u ",
531 rta_getattr_u8(tb[IFLA_BR_VLAN_STATS_ENABLED]));
7d93b567 532
90306a14
NA
533 if (tb[IFLA_BR_VLAN_STATS_PER_PORT])
534 print_uint(PRINT_ANY,
535 "vlan_stats_per_port",
536 "vlan_stats_per_port %u ",
537 rta_getattr_u8(tb[IFLA_BR_VLAN_STATS_PER_PORT]));
538
8caaf33b 539 if (tb[IFLA_BR_GROUP_FWD_MASK])
20aeecfb
JF
540 print_0xhex(PRINT_ANY,
541 "group_fwd_mask",
90c5c969 542 "group_fwd_mask %#llx ",
20aeecfb 543 rta_getattr_u16(tb[IFLA_BR_GROUP_FWD_MASK]));
0a61aa39
NA
544
545 if (tb[IFLA_BR_GROUP_ADDR]) {
546 SPRINT_BUF(mac);
547
20aeecfb
JF
548 print_string(PRINT_ANY,
549 "group_addr",
550 "group_address %s ",
551 ll_addr_n2a(RTA_DATA(tb[IFLA_BR_GROUP_ADDR]),
552 RTA_PAYLOAD(tb[IFLA_BR_GROUP_ADDR]),
553 1 /*ARPHDR_ETHER*/, mac, sizeof(mac)));
0a61aa39 554 }
963d137c 555
7ddd2d94 556 if (tb[IFLA_BR_MCAST_SNOOPING])
20aeecfb
JF
557 print_uint(PRINT_ANY,
558 "mcast_snooping",
559 "mcast_snooping %u ",
560 rta_getattr_u8(tb[IFLA_BR_MCAST_SNOOPING]));
7ddd2d94 561
963d137c 562 if (tb[IFLA_BR_MCAST_ROUTER])
20aeecfb
JF
563 print_uint(PRINT_ANY,
564 "mcast_router",
565 "mcast_router %u ",
566 rta_getattr_u8(tb[IFLA_BR_MCAST_ROUTER]));
449843d1
NA
567
568 if (tb[IFLA_BR_MCAST_QUERY_USE_IFADDR])
20aeecfb
JF
569 print_uint(PRINT_ANY,
570 "mcast_query_use_ifaddr",
571 "mcast_query_use_ifaddr %u ",
572 rta_getattr_u8(tb[IFLA_BR_MCAST_QUERY_USE_IFADDR]));
0778b741
NA
573
574 if (tb[IFLA_BR_MCAST_QUERIER])
20aeecfb
JF
575 print_uint(PRINT_ANY,
576 "mcast_querier",
577 "mcast_querier %u ",
578 rta_getattr_u8(tb[IFLA_BR_MCAST_QUERIER]));
92c0ef70
NA
579
580 if (tb[IFLA_BR_MCAST_HASH_ELASTICITY])
20aeecfb
JF
581 print_uint(PRINT_ANY,
582 "mcast_hash_elasticity",
583 "mcast_hash_elasticity %u ",
584 rta_getattr_u32(tb[IFLA_BR_MCAST_HASH_ELASTICITY]));
8b9eb7cd
NA
585
586 if (tb[IFLA_BR_MCAST_HASH_MAX])
20aeecfb
JF
587 print_uint(PRINT_ANY,
588 "mcast_hash_max",
589 "mcast_hash_max %u ",
590 rta_getattr_u32(tb[IFLA_BR_MCAST_HASH_MAX]));
fb44cadb
NA
591
592 if (tb[IFLA_BR_MCAST_LAST_MEMBER_CNT])
20aeecfb
JF
593 print_uint(PRINT_ANY,
594 "mcast_last_member_cnt",
595 "mcast_last_member_count %u ",
596 rta_getattr_u32(tb[IFLA_BR_MCAST_LAST_MEMBER_CNT]));
ceb64866
NA
597
598 if (tb[IFLA_BR_MCAST_STARTUP_QUERY_CNT])
20aeecfb
JF
599 print_uint(PRINT_ANY,
600 "mcast_startup_query_cnt",
601 "mcast_startup_query_count %u ",
602 rta_getattr_u32(tb[IFLA_BR_MCAST_STARTUP_QUERY_CNT]));
10082a25
NA
603
604 if (tb[IFLA_BR_MCAST_LAST_MEMBER_INTVL])
20aeecfb
JF
605 print_lluint(PRINT_ANY,
606 "mcast_last_member_intvl",
607 "mcast_last_member_interval %llu ",
608 rta_getattr_u64(tb[IFLA_BR_MCAST_LAST_MEMBER_INTVL]));
7f3d5592
NA
609
610 if (tb[IFLA_BR_MCAST_MEMBERSHIP_INTVL])
20aeecfb
JF
611 print_lluint(PRINT_ANY,
612 "mcast_membership_intvl",
613 "mcast_membership_interval %llu ",
614 rta_getattr_u64(tb[IFLA_BR_MCAST_MEMBERSHIP_INTVL]));
1f2244b8
NA
615
616 if (tb[IFLA_BR_MCAST_QUERIER_INTVL])
20aeecfb
JF
617 print_lluint(PRINT_ANY,
618 "mcast_querier_intvl",
619 "mcast_querier_interval %llu ",
620 rta_getattr_u64(tb[IFLA_BR_MCAST_QUERIER_INTVL]));
5a32388f
NA
621
622 if (tb[IFLA_BR_MCAST_QUERY_INTVL])
20aeecfb
JF
623 print_lluint(PRINT_ANY,
624 "mcast_query_intvl",
625 "mcast_query_interval %llu ",
626 rta_getattr_u64(tb[IFLA_BR_MCAST_QUERY_INTVL]));
483df11c
NA
627
628 if (tb[IFLA_BR_MCAST_QUERY_RESPONSE_INTVL])
20aeecfb
JF
629 print_lluint(PRINT_ANY,
630 "mcast_query_response_intvl",
631 "mcast_query_response_interval %llu ",
632 rta_getattr_u64(tb[IFLA_BR_MCAST_QUERY_RESPONSE_INTVL]));
178b1806
NA
633
634 if (tb[IFLA_BR_MCAST_STARTUP_QUERY_INTVL])
20aeecfb
JF
635 print_lluint(PRINT_ANY,
636 "mcast_startup_query_intvl",
637 "mcast_startup_query_interval %llu ",
638 rta_getattr_u64(tb[IFLA_BR_MCAST_STARTUP_QUERY_INTVL]));
861c5dae 639
6ddad009 640 if (tb[IFLA_BR_MCAST_STATS_ENABLED])
20aeecfb
JF
641 print_uint(PRINT_ANY,
642 "mcast_stats_enabled",
643 "mcast_stats_enabled %u ",
644 rta_getattr_u8(tb[IFLA_BR_MCAST_STATS_ENABLED]));
6ddad009 645
19756950 646 if (tb[IFLA_BR_MCAST_IGMP_VERSION])
20aeecfb
JF
647 print_uint(PRINT_ANY,
648 "mcast_igmp_version",
649 "mcast_igmp_version %u ",
650 rta_getattr_u8(tb[IFLA_BR_MCAST_IGMP_VERSION]));
19756950 651
c3f1e3c4 652 if (tb[IFLA_BR_MCAST_MLD_VERSION])
20aeecfb
JF
653 print_uint(PRINT_ANY,
654 "mcast_mld_version",
655 "mcast_mld_version %u ",
656 rta_getattr_u8(tb[IFLA_BR_MCAST_MLD_VERSION]));
c3f1e3c4 657
861c5dae 658 if (tb[IFLA_BR_NF_CALL_IPTABLES])
20aeecfb
JF
659 print_uint(PRINT_ANY,
660 "nf_call_iptables",
661 "nf_call_iptables %u ",
662 rta_getattr_u8(tb[IFLA_BR_NF_CALL_IPTABLES]));
861c5dae
NA
663
664 if (tb[IFLA_BR_NF_CALL_IP6TABLES])
20aeecfb
JF
665 print_uint(PRINT_ANY,
666 "nf_call_ip6tables",
667 "nf_call_ip6tables %u ",
668 rta_getattr_u8(tb[IFLA_BR_NF_CALL_IP6TABLES]));
861c5dae
NA
669
670 if (tb[IFLA_BR_NF_CALL_ARPTABLES])
20aeecfb
JF
671 print_uint(PRINT_ANY,
672 "nf_call_arptables",
673 "nf_call_arptables %u ",
674 rta_getattr_u8(tb[IFLA_BR_NF_CALL_ARPTABLES]));
28d84b42
JP
675}
676
43367ef7 677static void bridge_print_help(struct link_util *lu, int argc, char **argv,
20aeecfb 678 FILE *f)
43367ef7
ZS
679{
680 print_explain(f);
681}
682
60ec0ecf
NA
683static void bridge_print_xstats_help(struct link_util *lu, FILE *f)
684{
685 fprintf(f, "Usage: ... %s [ igmp ] [ dev DEVICE ]\n", lu->id);
686}
687
a9bc23a7 688static void bridge_print_stats_attr(struct rtattr *attr, int ifindex)
60ec0ecf
NA
689{
690 struct rtattr *brtb[LINK_XSTATS_TYPE_MAX+1];
0dcf36db 691 struct bridge_stp_xstats *sstats;
60ec0ecf
NA
692 struct br_mcast_stats *mstats;
693 struct rtattr *i, *list;
694 const char *ifname = "";
695 int rem;
696
697 parse_rtattr(brtb, LINK_XSTATS_TYPE_MAX, RTA_DATA(attr),
698 RTA_PAYLOAD(attr));
699 if (!brtb[LINK_XSTATS_TYPE_BRIDGE])
700 return;
701
702 list = brtb[LINK_XSTATS_TYPE_BRIDGE];
703 rem = RTA_PAYLOAD(list);
a9bc23a7
NA
704 open_json_object(NULL);
705 ifname = ll_index_to_name(ifindex);
706 print_string(PRINT_ANY, "ifname", "%-16s\n", ifname);
60ec0ecf
NA
707 for (i = RTA_DATA(list); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) {
708 if (xstats_print_attr && i->rta_type != xstats_print_attr)
709 continue;
710 switch (i->rta_type) {
711 case BRIDGE_XSTATS_MCAST:
712 mstats = RTA_DATA(i);
a9bc23a7
NA
713 open_json_object("multicast");
714 open_json_object("igmp_queries");
715 print_string(PRINT_FP, NULL,
716 "%-16s IGMP queries:\n", "");
717 print_string(PRINT_FP, NULL, "%-16s ", "");
718 print_u64(PRINT_ANY, "rx_v1", "RX: v1 %llu ",
719 mstats->igmp_v1queries[BR_MCAST_DIR_RX]);
720 print_u64(PRINT_ANY, "rx_v2", "v2 %llu ",
721 mstats->igmp_v2queries[BR_MCAST_DIR_RX]);
722 print_u64(PRINT_ANY, "rx_v3", "v3 %llu\n",
723 mstats->igmp_v3queries[BR_MCAST_DIR_RX]);
724 print_string(PRINT_FP, NULL, "%-16s ", "");
725 print_u64(PRINT_ANY, "tx_v1", "TX: v1 %llu ",
726 mstats->igmp_v1queries[BR_MCAST_DIR_TX]);
727 print_u64(PRINT_ANY, "tx_v2", "v2 %llu ",
728 mstats->igmp_v2queries[BR_MCAST_DIR_TX]);
729 print_u64(PRINT_ANY, "tx_v3", "v3 %llu\n",
730 mstats->igmp_v3queries[BR_MCAST_DIR_TX]);
731 close_json_object();
732
733 open_json_object("igmp_reports");
734 print_string(PRINT_FP, NULL,
735 "%-16s IGMP reports:\n", "");
736 print_string(PRINT_FP, NULL, "%-16s ", "");
737 print_u64(PRINT_ANY, "rx_v1", "RX: v1 %llu ",
738 mstats->igmp_v1reports[BR_MCAST_DIR_RX]);
739 print_u64(PRINT_ANY, "rx_v2", "v2 %llu ",
740 mstats->igmp_v2reports[BR_MCAST_DIR_RX]);
741 print_u64(PRINT_ANY, "rx_v3", "v3 %llu\n",
742 mstats->igmp_v3reports[BR_MCAST_DIR_RX]);
743 print_string(PRINT_FP, NULL, "%-16s ", "");
744 print_u64(PRINT_ANY, "tx_v1", "TX: v1 %llu ",
745 mstats->igmp_v1reports[BR_MCAST_DIR_TX]);
746 print_u64(PRINT_ANY, "tx_v2", "v2 %llu",
747 mstats->igmp_v2reports[BR_MCAST_DIR_TX]);
748 print_u64(PRINT_ANY, "tx_v3", "v3 %llu\n",
749 mstats->igmp_v3reports[BR_MCAST_DIR_TX]);
750 close_json_object();
751
752 open_json_object("igmp_leaves");
753 print_string(PRINT_FP, NULL,
754 "%-16s IGMP leaves: ", "");
755 print_u64(PRINT_ANY, "rx", "RX: %llu ",
756 mstats->igmp_leaves[BR_MCAST_DIR_RX]);
757 print_u64(PRINT_ANY, "tx", "TX: %llu\n",
758 mstats->igmp_leaves[BR_MCAST_DIR_TX]);
759 close_json_object();
760
761 print_string(PRINT_FP, NULL,
762 "%-16s IGMP parse errors: ", "");
763 print_u64(PRINT_ANY, "igmp_parse_errors", "%llu\n",
764 mstats->igmp_parse_errors);
765
766 open_json_object("mld_queries");
767 print_string(PRINT_FP, NULL,
768 "%-16s MLD queries:\n", "");
769 print_string(PRINT_FP, NULL, "%-16s ", "");
770 print_u64(PRINT_ANY, "rx_v1", "RX: v1 %llu ",
771 mstats->mld_v1queries[BR_MCAST_DIR_RX]);
772 print_u64(PRINT_ANY, "rx_v2", "v2 %llu\n",
773 mstats->mld_v2queries[BR_MCAST_DIR_RX]);
774 print_string(PRINT_FP, NULL, "%-16s ", "");
775 print_u64(PRINT_ANY, "tx_v1", "TX: v1 %llu ",
776 mstats->mld_v1queries[BR_MCAST_DIR_TX]);
777 print_u64(PRINT_ANY, "tx_v2", "v2 %llu\n",
778 mstats->mld_v2queries[BR_MCAST_DIR_TX]);
779 close_json_object();
780
781 open_json_object("mld_reports");
782 print_string(PRINT_FP, NULL,
783 "%-16s MLD reports:\n", "");
784 print_string(PRINT_FP, NULL, "%-16s ", "");
785 print_u64(PRINT_ANY, "rx_v1", "RX: v1 %llu ",
786 mstats->mld_v1reports[BR_MCAST_DIR_RX]);
787 print_u64(PRINT_ANY, "rx_v2", "v2 %llu\n",
788 mstats->mld_v2reports[BR_MCAST_DIR_RX]);
789 print_string(PRINT_FP, NULL, "%-16s ", "");
790 print_u64(PRINT_ANY, "tx_v1", "TX: v1 %llu ",
791 mstats->mld_v1reports[BR_MCAST_DIR_TX]);
792 print_u64(PRINT_ANY, "tx_v2", "v2 %llu\n",
793 mstats->mld_v2reports[BR_MCAST_DIR_TX]);
794 close_json_object();
795
796 open_json_object("mld_leaves");
797 print_string(PRINT_FP, NULL,
798 "%-16s MLD leaves: ", "");
799 print_u64(PRINT_ANY, "rx", "RX: %llu ",
800 mstats->mld_leaves[BR_MCAST_DIR_RX]);
801 print_u64(PRINT_ANY, "tx", "TX: %llu\n",
802 mstats->mld_leaves[BR_MCAST_DIR_TX]);
803 close_json_object();
804
805 print_string(PRINT_FP, NULL,
806 "%-16s MLD parse errors: ", "");
807 print_u64(PRINT_ANY, "mld_parse_errors", "%llu\n",
808 mstats->mld_parse_errors);
809 close_json_object();
60ec0ecf 810 break;
0dcf36db
VD
811 case BRIDGE_XSTATS_STP:
812 sstats = RTA_DATA(i);
813 open_json_object("stp");
814 print_string(PRINT_FP, NULL,
815 "%-16s STP BPDU: ", "");
816 print_u64(PRINT_ANY, "rx_bpdu", "RX: %llu ",
817 sstats->rx_bpdu);
818 print_u64(PRINT_ANY, "tx_bpdu", "TX: %llu\n",
819 sstats->tx_bpdu);
820 print_string(PRINT_FP, NULL,
821 "%-16s STP TCN: ", "");
822 print_u64(PRINT_ANY, "rx_tcn", "RX: %llu ",
823 sstats->rx_tcn);
824 print_u64(PRINT_ANY, "tx_tcn", "TX: %llu\n",
825 sstats->tx_tcn);
826 print_string(PRINT_FP, NULL,
827 "%-16s STP Transitions: ", "");
828 print_u64(PRINT_ANY, "transition_blk", "Blocked: %llu ",
829 sstats->transition_blk);
830 print_u64(PRINT_ANY, "transition_fwd", "Forwarding: %llu\n",
831 sstats->transition_fwd);
832 close_json_object();
833 break;
60ec0ecf
NA
834 }
835 }
a9bc23a7 836 close_json_object();
60ec0ecf
NA
837}
838
cd554f2c 839int bridge_print_xstats(struct nlmsghdr *n, void *arg)
60ec0ecf
NA
840{
841 struct if_stats_msg *ifsm = NLMSG_DATA(n);
842 struct rtattr *tb[IFLA_STATS_MAX+1];
843 int len = n->nlmsg_len;
60ec0ecf
NA
844
845 len -= NLMSG_LENGTH(sizeof(*ifsm));
846 if (len < 0) {
847 fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
848 return -1;
849 }
850 if (filter_index && filter_index != ifsm->ifindex)
851 return 0;
852
853 parse_rtattr(tb, IFLA_STATS_MAX, IFLA_STATS_RTA(ifsm), len);
854 if (tb[IFLA_STATS_LINK_XSTATS])
a9bc23a7 855 bridge_print_stats_attr(tb[IFLA_STATS_LINK_XSTATS],
60ec0ecf
NA
856 ifsm->ifindex);
857
858 if (tb[IFLA_STATS_LINK_XSTATS_SLAVE])
a9bc23a7 859 bridge_print_stats_attr(tb[IFLA_STATS_LINK_XSTATS_SLAVE],
60ec0ecf
NA
860 ifsm->ifindex);
861
862 return 0;
863}
864
217264a0 865int bridge_parse_xstats(struct link_util *lu, int argc, char **argv)
60ec0ecf
NA
866{
867 while (argc > 0) {
868 if (strcmp(*argv, "igmp") == 0 || strcmp(*argv, "mcast") == 0) {
869 xstats_print_attr = BRIDGE_XSTATS_MCAST;
0dcf36db
VD
870 } else if (strcmp(*argv, "stp") == 0) {
871 xstats_print_attr = BRIDGE_XSTATS_STP;
60ec0ecf
NA
872 } else if (strcmp(*argv, "dev") == 0) {
873 NEXT_ARG();
7a14358b 874 filter_index = ll_name_to_index(*argv);
fe99adbc
SP
875 if (!filter_index)
876 return nodev(*argv);
60ec0ecf
NA
877 } else if (strcmp(*argv, "help") == 0) {
878 bridge_print_xstats_help(lu, stdout);
879 exit(0);
880 } else {
881 invarg("unknown attribute", *argv);
882 }
883 argc--; argv++;
884 }
885
886 return 0;
887}
888
28d84b42
JP
889struct link_util bridge_link_util = {
890 .id = "bridge",
891 .maxattr = IFLA_BR_MAX,
892 .parse_opt = bridge_parse_opt,
893 .print_opt = bridge_print_opt,
43367ef7 894 .print_help = bridge_print_help,
60ec0ecf
NA
895 .parse_ifla_xstats = bridge_parse_xstats,
896 .print_ifla_xstats = bridge_print_xstats,
28d84b42 897};