]> git.proxmox.com Git - mirror_iproute2.git/blob - ip/iplink_bridge.c
Merge branch 'merge-4.10' into next-merge
[mirror_iproute2.git] / ip / iplink_bridge.c
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>
15 #include <linux/if_link.h>
16 #include <netinet/ether.h>
17
18 #include "rt_names.h"
19 #include "utils.h"
20 #include "ip_common.h"
21
22 static void print_explain(FILE *f)
23 {
24 fprintf(f,
25 "Usage: ... bridge [ fdb_flush ]\n"
26 " [ forward_delay FORWARD_DELAY ]\n"
27 " [ hello_time HELLO_TIME ]\n"
28 " [ max_age MAX_AGE ]\n"
29 " [ ageing_time AGEING_TIME ]\n"
30 " [ stp_state STP_STATE ]\n"
31 " [ priority PRIORITY ]\n"
32 " [ group_fwd_mask MASK ]\n"
33 " [ group_address ADDRESS ]\n"
34 " [ vlan_filtering VLAN_FILTERING ]\n"
35 " [ vlan_protocol VLAN_PROTOCOL ]\n"
36 " [ vlan_default_pvid VLAN_DEFAULT_PVID ]\n"
37 " [ vlan_stats_enabled VLAN_STATS_ENABLED ]\n"
38 " [ mcast_snooping MULTICAST_SNOOPING ]\n"
39 " [ mcast_router MULTICAST_ROUTER ]\n"
40 " [ mcast_query_use_ifaddr MCAST_QUERY_USE_IFADDR ]\n"
41 " [ mcast_querier MULTICAST_QUERIER ]\n"
42 " [ mcast_hash_elasticity HASH_ELASTICITY ]\n"
43 " [ mcast_hash_max HASH_MAX ]\n"
44 " [ mcast_last_member_count LAST_MEMBER_COUNT ]\n"
45 " [ mcast_startup_query_count STARTUP_QUERY_COUNT ]\n"
46 " [ mcast_last_member_interval LAST_MEMBER_INTERVAL ]\n"
47 " [ mcast_membership_interval MEMBERSHIP_INTERVAL ]\n"
48 " [ mcast_querier_interval QUERIER_INTERVAL ]\n"
49 " [ mcast_query_interval QUERY_INTERVAL ]\n"
50 " [ mcast_query_response_interval QUERY_RESPONSE_INTERVAL ]\n"
51 " [ mcast_startup_query_interval STARTUP_QUERY_INTERVAL ]\n"
52 " [ mcast_stats_enabled MCAST_STATS_ENABLED ]\n"
53 " [ mcast_igmp_version IGMP_VERSION ]\n"
54 " [ mcast_mld_version MLD_VERSION ]\n"
55 " [ nf_call_iptables NF_CALL_IPTABLES ]\n"
56 " [ nf_call_ip6tables NF_CALL_IP6TABLES ]\n"
57 " [ nf_call_arptables NF_CALL_ARPTABLES ]\n"
58 "\n"
59 "Where: VLAN_PROTOCOL := { 802.1Q | 802.1ad }\n"
60 );
61 }
62
63 static void explain(void)
64 {
65 print_explain(stderr);
66 }
67
68 void br_dump_bridge_id(const struct ifla_bridge_id *id, char *buf, size_t len)
69 {
70 char eaddr[32];
71
72 ether_ntoa_r((const struct ether_addr *)id->addr, eaddr);
73 snprintf(buf, len, "%.2x%.2x.%s", id->prio[0], id->prio[1], eaddr);
74 }
75
76 static int bridge_parse_opt(struct link_util *lu, int argc, char **argv,
77 struct nlmsghdr *n)
78 {
79 __u32 val;
80
81 while (argc > 0) {
82 if (matches(*argv, "forward_delay") == 0) {
83 NEXT_ARG();
84 if (get_u32(&val, *argv, 0))
85 invarg("invalid forward_delay", *argv);
86
87 addattr32(n, 1024, IFLA_BR_FORWARD_DELAY, val);
88 } else if (matches(*argv, "hello_time") == 0) {
89 NEXT_ARG();
90 if (get_u32(&val, *argv, 0))
91 invarg("invalid hello_time", *argv);
92
93 addattr32(n, 1024, IFLA_BR_HELLO_TIME, val);
94 } else if (matches(*argv, "max_age") == 0) {
95 NEXT_ARG();
96 if (get_u32(&val, *argv, 0))
97 invarg("invalid max_age", *argv);
98
99 addattr32(n, 1024, IFLA_BR_MAX_AGE, val);
100 } else if (matches(*argv, "ageing_time") == 0) {
101 NEXT_ARG();
102 if (get_u32(&val, *argv, 0))
103 invarg("invalid ageing_time", *argv);
104
105 addattr32(n, 1024, IFLA_BR_AGEING_TIME, val);
106 } else if (matches(*argv, "stp_state") == 0) {
107 NEXT_ARG();
108 if (get_u32(&val, *argv, 0))
109 invarg("invalid stp_state", *argv);
110
111 addattr32(n, 1024, IFLA_BR_STP_STATE, val);
112 } else if (matches(*argv, "priority") == 0) {
113 __u16 prio;
114
115 NEXT_ARG();
116 if (get_u16(&prio, *argv, 0))
117 invarg("invalid priority", *argv);
118
119 addattr16(n, 1024, IFLA_BR_PRIORITY, prio);
120 } else if (matches(*argv, "vlan_filtering") == 0) {
121 __u8 vlan_filter;
122
123 NEXT_ARG();
124 if (get_u8(&vlan_filter, *argv, 0))
125 invarg("invalid vlan_filtering", *argv);
126
127 addattr8(n, 1024, IFLA_BR_VLAN_FILTERING, vlan_filter);
128 } else if (matches(*argv, "vlan_protocol") == 0) {
129 __u16 vlan_proto;
130
131 NEXT_ARG();
132 if (ll_proto_a2n(&vlan_proto, *argv))
133 invarg("invalid vlan_protocol", *argv);
134
135 addattr16(n, 1024, IFLA_BR_VLAN_PROTOCOL, vlan_proto);
136 } else if (matches(*argv, "group_fwd_mask") == 0) {
137 __u16 fwd_mask;
138
139 NEXT_ARG();
140 if (get_u16(&fwd_mask, *argv, 0))
141 invarg("invalid group_fwd_mask", *argv);
142
143 addattr16(n, 1024, IFLA_BR_GROUP_FWD_MASK, fwd_mask);
144 } else if (matches(*argv, "group_address") == 0) {
145 char llabuf[32];
146 int len;
147
148 NEXT_ARG();
149 len = ll_addr_a2n(llabuf, sizeof(llabuf), *argv);
150 if (len < 0)
151 return -1;
152 addattr_l(n, 1024, IFLA_BR_GROUP_ADDR, llabuf, len);
153 } else if (matches(*argv, "fdb_flush") == 0) {
154 addattr(n, 1024, IFLA_BR_FDB_FLUSH);
155 } else if (matches(*argv, "vlan_default_pvid") == 0) {
156 __u16 default_pvid;
157
158 NEXT_ARG();
159 if (get_u16(&default_pvid, *argv, 0))
160 invarg("invalid vlan_default_pvid", *argv);
161
162 addattr16(n, 1024, IFLA_BR_VLAN_DEFAULT_PVID,
163 default_pvid);
164 } else if (matches(*argv, "vlan_stats_enabled") == 0) {
165 __u8 vlan_stats_enabled;
166
167 NEXT_ARG();
168 if (get_u8(&vlan_stats_enabled, *argv, 0))
169 invarg("invalid vlan_stats_enabled", *argv);
170 addattr8(n, 1024, IFLA_BR_VLAN_STATS_ENABLED,
171 vlan_stats_enabled);
172 } else if (matches(*argv, "mcast_router") == 0) {
173 __u8 mcast_router;
174
175 NEXT_ARG();
176 if (get_u8(&mcast_router, *argv, 0))
177 invarg("invalid mcast_router", *argv);
178
179 addattr8(n, 1024, IFLA_BR_MCAST_ROUTER, mcast_router);
180 } else if (matches(*argv, "mcast_snooping") == 0) {
181 __u8 mcast_snoop;
182
183 NEXT_ARG();
184 if (get_u8(&mcast_snoop, *argv, 0))
185 invarg("invalid mcast_snooping", *argv);
186
187 addattr8(n, 1024, IFLA_BR_MCAST_SNOOPING, mcast_snoop);
188 } else if (matches(*argv, "mcast_query_use_ifaddr") == 0) {
189 __u8 mcast_qui;
190
191 NEXT_ARG();
192 if (get_u8(&mcast_qui, *argv, 0))
193 invarg("invalid mcast_query_use_ifaddr",
194 *argv);
195
196 addattr8(n, 1024, IFLA_BR_MCAST_QUERY_USE_IFADDR,
197 mcast_qui);
198 } else if (matches(*argv, "mcast_querier") == 0) {
199 __u8 mcast_querier;
200
201 NEXT_ARG();
202 if (get_u8(&mcast_querier, *argv, 0))
203 invarg("invalid mcast_querier", *argv);
204
205 addattr8(n, 1024, IFLA_BR_MCAST_QUERIER, mcast_querier);
206 } else if (matches(*argv, "mcast_hash_elasticity") == 0) {
207 __u32 mcast_hash_el;
208
209 NEXT_ARG();
210 if (get_u32(&mcast_hash_el, *argv, 0))
211 invarg("invalid mcast_hash_elasticity",
212 *argv);
213
214 addattr32(n, 1024, IFLA_BR_MCAST_HASH_ELASTICITY,
215 mcast_hash_el);
216 } else if (matches(*argv, "mcast_hash_max") == 0) {
217 __u32 mcast_hash_max;
218
219 NEXT_ARG();
220 if (get_u32(&mcast_hash_max, *argv, 0))
221 invarg("invalid mcast_hash_max", *argv);
222
223 addattr32(n, 1024, IFLA_BR_MCAST_HASH_MAX,
224 mcast_hash_max);
225 } else if (matches(*argv, "mcast_last_member_count") == 0) {
226 __u32 mcast_lmc;
227
228 NEXT_ARG();
229 if (get_u32(&mcast_lmc, *argv, 0))
230 invarg("invalid mcast_last_member_count",
231 *argv);
232
233 addattr32(n, 1024, IFLA_BR_MCAST_LAST_MEMBER_CNT,
234 mcast_lmc);
235 } else if (matches(*argv, "mcast_startup_query_count") == 0) {
236 __u32 mcast_sqc;
237
238 NEXT_ARG();
239 if (get_u32(&mcast_sqc, *argv, 0))
240 invarg("invalid mcast_startup_query_count",
241 *argv);
242
243 addattr32(n, 1024, IFLA_BR_MCAST_STARTUP_QUERY_CNT,
244 mcast_sqc);
245 } else if (matches(*argv, "mcast_last_member_interval") == 0) {
246 __u64 mcast_last_member_intvl;
247
248 NEXT_ARG();
249 if (get_u64(&mcast_last_member_intvl, *argv, 0))
250 invarg("invalid mcast_last_member_interval",
251 *argv);
252
253 addattr64(n, 1024, IFLA_BR_MCAST_LAST_MEMBER_INTVL,
254 mcast_last_member_intvl);
255 } else if (matches(*argv, "mcast_membership_interval") == 0) {
256 __u64 mcast_membership_intvl;
257
258 NEXT_ARG();
259 if (get_u64(&mcast_membership_intvl, *argv, 0))
260 invarg("invalid mcast_membership_interval",
261 *argv);
262
263 addattr64(n, 1024, IFLA_BR_MCAST_MEMBERSHIP_INTVL,
264 mcast_membership_intvl);
265 } else if (matches(*argv, "mcast_querier_interval") == 0) {
266 __u64 mcast_querier_intvl;
267
268 NEXT_ARG();
269 if (get_u64(&mcast_querier_intvl, *argv, 0))
270 invarg("invalid mcast_querier_interval",
271 *argv);
272
273 addattr64(n, 1024, IFLA_BR_MCAST_QUERIER_INTVL,
274 mcast_querier_intvl);
275 } else if (matches(*argv, "mcast_query_interval") == 0) {
276 __u64 mcast_query_intvl;
277
278 NEXT_ARG();
279 if (get_u64(&mcast_query_intvl, *argv, 0))
280 invarg("invalid mcast_query_interval",
281 *argv);
282
283 addattr64(n, 1024, IFLA_BR_MCAST_QUERY_INTVL,
284 mcast_query_intvl);
285 } else if (!matches(*argv, "mcast_query_response_interval")) {
286 __u64 mcast_query_resp_intvl;
287
288 NEXT_ARG();
289 if (get_u64(&mcast_query_resp_intvl, *argv, 0))
290 invarg("invalid mcast_query_response_interval",
291 *argv);
292
293 addattr64(n, 1024, IFLA_BR_MCAST_QUERY_RESPONSE_INTVL,
294 mcast_query_resp_intvl);
295 } else if (!matches(*argv, "mcast_startup_query_interval")) {
296 __u64 mcast_startup_query_intvl;
297
298 NEXT_ARG();
299 if (get_u64(&mcast_startup_query_intvl, *argv, 0))
300 invarg("invalid mcast_startup_query_interval",
301 *argv);
302
303 addattr64(n, 1024, IFLA_BR_MCAST_STARTUP_QUERY_INTVL,
304 mcast_startup_query_intvl);
305 } else if (matches(*argv, "mcast_stats_enabled") == 0) {
306 __u8 mcast_stats_enabled;
307
308 NEXT_ARG();
309 if (get_u8(&mcast_stats_enabled, *argv, 0))
310 invarg("invalid mcast_stats_enabled", *argv);
311 addattr8(n, 1024, IFLA_BR_MCAST_STATS_ENABLED,
312 mcast_stats_enabled);
313 } else if (matches(*argv, "mcast_igmp_version") == 0) {
314 __u8 igmp_version;
315
316 NEXT_ARG();
317 if (get_u8(&igmp_version, *argv, 0))
318 invarg("invalid mcast_igmp_version", *argv);
319 addattr8(n, 1024, IFLA_BR_MCAST_IGMP_VERSION,
320 igmp_version);
321 } else if (matches(*argv, "mcast_mld_version") == 0) {
322 __u8 mld_version;
323
324 NEXT_ARG();
325 if (get_u8(&mld_version, *argv, 0))
326 invarg("invalid mcast_mld_version", *argv);
327 addattr8(n, 1024, IFLA_BR_MCAST_MLD_VERSION,
328 mld_version);
329 } else if (matches(*argv, "nf_call_iptables") == 0) {
330 __u8 nf_call_ipt;
331
332 NEXT_ARG();
333 if (get_u8(&nf_call_ipt, *argv, 0))
334 invarg("invalid nf_call_iptables", *argv);
335
336 addattr8(n, 1024, IFLA_BR_NF_CALL_IPTABLES,
337 nf_call_ipt);
338 } else if (matches(*argv, "nf_call_ip6tables") == 0) {
339 __u8 nf_call_ip6t;
340
341 NEXT_ARG();
342 if (get_u8(&nf_call_ip6t, *argv, 0))
343 invarg("invalid nf_call_ip6tables", *argv);
344
345 addattr8(n, 1024, IFLA_BR_NF_CALL_IP6TABLES,
346 nf_call_ip6t);
347 } else if (matches(*argv, "nf_call_arptables") == 0) {
348 __u8 nf_call_arpt;
349
350 NEXT_ARG();
351 if (get_u8(&nf_call_arpt, *argv, 0))
352 invarg("invalid nf_call_arptables", *argv);
353
354 addattr8(n, 1024, IFLA_BR_NF_CALL_ARPTABLES,
355 nf_call_arpt);
356 } else if (matches(*argv, "help") == 0) {
357 explain();
358 return -1;
359 } else {
360 fprintf(stderr, "bridge: unknown command \"%s\"?\n", *argv);
361 explain();
362 return -1;
363 }
364 argc--, argv++;
365 }
366
367 return 0;
368 }
369
370 static void bridge_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
371 {
372 if (!tb)
373 return;
374
375 if (tb[IFLA_BR_FORWARD_DELAY])
376 fprintf(f, "forward_delay %u ",
377 rta_getattr_u32(tb[IFLA_BR_FORWARD_DELAY]));
378
379 if (tb[IFLA_BR_HELLO_TIME])
380 fprintf(f, "hello_time %u ",
381 rta_getattr_u32(tb[IFLA_BR_HELLO_TIME]));
382
383 if (tb[IFLA_BR_MAX_AGE])
384 fprintf(f, "max_age %u ",
385 rta_getattr_u32(tb[IFLA_BR_MAX_AGE]));
386
387 if (tb[IFLA_BR_AGEING_TIME])
388 fprintf(f, "ageing_time %u ",
389 rta_getattr_u32(tb[IFLA_BR_AGEING_TIME]));
390
391 if (tb[IFLA_BR_STP_STATE])
392 fprintf(f, "stp_state %u ",
393 rta_getattr_u32(tb[IFLA_BR_STP_STATE]));
394
395 if (tb[IFLA_BR_PRIORITY])
396 fprintf(f, "priority %u ",
397 rta_getattr_u16(tb[IFLA_BR_PRIORITY]));
398
399 if (tb[IFLA_BR_VLAN_FILTERING])
400 fprintf(f, "vlan_filtering %u ",
401 rta_getattr_u8(tb[IFLA_BR_VLAN_FILTERING]));
402
403 if (tb[IFLA_BR_VLAN_PROTOCOL]) {
404 SPRINT_BUF(b1);
405
406 fprintf(f, "vlan_protocol %s ",
407 ll_proto_n2a(rta_getattr_u16(tb[IFLA_BR_VLAN_PROTOCOL]),
408 b1, sizeof(b1)));
409 }
410
411 if (tb[IFLA_BR_BRIDGE_ID]) {
412 char bridge_id[32];
413
414 br_dump_bridge_id(RTA_DATA(tb[IFLA_BR_BRIDGE_ID]), bridge_id,
415 sizeof(bridge_id));
416 fprintf(f, "bridge_id %s ", bridge_id);
417 }
418
419 if (tb[IFLA_BR_ROOT_ID]) {
420 char root_id[32];
421
422 br_dump_bridge_id(RTA_DATA(tb[IFLA_BR_BRIDGE_ID]), root_id,
423 sizeof(root_id));
424 fprintf(f, "designated_root %s ", root_id);
425 }
426
427 if (tb[IFLA_BR_ROOT_PORT])
428 fprintf(f, "root_port %u ",
429 rta_getattr_u16(tb[IFLA_BR_ROOT_PORT]));
430
431 if (tb[IFLA_BR_ROOT_PATH_COST])
432 fprintf(f, "root_path_cost %u ",
433 rta_getattr_u32(tb[IFLA_BR_ROOT_PATH_COST]));
434
435 if (tb[IFLA_BR_TOPOLOGY_CHANGE])
436 fprintf(f, "topology_change %u ",
437 rta_getattr_u8(tb[IFLA_BR_TOPOLOGY_CHANGE]));
438
439 if (tb[IFLA_BR_TOPOLOGY_CHANGE_DETECTED])
440 fprintf(f, "topology_change_detected %u ",
441 rta_getattr_u8(tb[IFLA_BR_TOPOLOGY_CHANGE_DETECTED]));
442
443 if (tb[IFLA_BR_HELLO_TIMER]) {
444 struct timeval tv;
445
446 __jiffies_to_tv(&tv, rta_getattr_u64(tb[IFLA_BR_HELLO_TIMER]));
447 fprintf(f, "hello_timer %4i.%.2i ", (int)tv.tv_sec,
448 (int)tv.tv_usec/10000);
449 }
450
451 if (tb[IFLA_BR_TCN_TIMER]) {
452 struct timeval tv;
453
454 __jiffies_to_tv(&tv, rta_getattr_u64(tb[IFLA_BR_TCN_TIMER]));
455 fprintf(f, "tcn_timer %4i.%.2i ", (int)tv.tv_sec,
456 (int)tv.tv_usec/10000);
457 }
458
459 if (tb[IFLA_BR_TOPOLOGY_CHANGE_TIMER]) {
460 unsigned long jiffies;
461 struct timeval tv;
462
463 jiffies = rta_getattr_u64(tb[IFLA_BR_TOPOLOGY_CHANGE_TIMER]);
464 __jiffies_to_tv(&tv, jiffies);
465 fprintf(f, "topology_change_timer %4i.%.2i ", (int)tv.tv_sec,
466 (int)tv.tv_usec/10000);
467 }
468
469 if (tb[IFLA_BR_GC_TIMER]) {
470 struct timeval tv;
471
472 __jiffies_to_tv(&tv, rta_getattr_u64(tb[IFLA_BR_GC_TIMER]));
473 fprintf(f, "gc_timer %4i.%.2i ", (int)tv.tv_sec,
474 (int)tv.tv_usec/10000);
475 }
476
477 if (tb[IFLA_BR_VLAN_DEFAULT_PVID])
478 fprintf(f, "vlan_default_pvid %u ",
479 rta_getattr_u16(tb[IFLA_BR_VLAN_DEFAULT_PVID]));
480
481 if (tb[IFLA_BR_VLAN_STATS_ENABLED])
482 fprintf(f, "vlan_stats_enabled %u ",
483 rta_getattr_u8(tb[IFLA_BR_VLAN_STATS_ENABLED]));
484
485 if (tb[IFLA_BR_GROUP_FWD_MASK])
486 fprintf(f, "group_fwd_mask %#x ",
487 rta_getattr_u16(tb[IFLA_BR_GROUP_FWD_MASK]));
488
489 if (tb[IFLA_BR_GROUP_ADDR]) {
490 SPRINT_BUF(mac);
491
492 fprintf(f, "group_address %s ",
493 ll_addr_n2a(RTA_DATA(tb[IFLA_BR_GROUP_ADDR]),
494 RTA_PAYLOAD(tb[IFLA_BR_GROUP_ADDR]),
495 1 /*ARPHDR_ETHER*/, mac, sizeof(mac)));
496 }
497
498 if (tb[IFLA_BR_MCAST_SNOOPING])
499 fprintf(f, "mcast_snooping %u ",
500 rta_getattr_u8(tb[IFLA_BR_MCAST_SNOOPING]));
501
502 if (tb[IFLA_BR_MCAST_ROUTER])
503 fprintf(f, "mcast_router %u ",
504 rta_getattr_u8(tb[IFLA_BR_MCAST_ROUTER]));
505
506 if (tb[IFLA_BR_MCAST_QUERY_USE_IFADDR])
507 fprintf(f, "mcast_query_use_ifaddr %u ",
508 rta_getattr_u8(tb[IFLA_BR_MCAST_QUERY_USE_IFADDR]));
509
510 if (tb[IFLA_BR_MCAST_QUERIER])
511 fprintf(f, "mcast_querier %u ",
512 rta_getattr_u8(tb[IFLA_BR_MCAST_QUERIER]));
513
514 if (tb[IFLA_BR_MCAST_HASH_ELASTICITY])
515 fprintf(f, "mcast_hash_elasticity %u ",
516 rta_getattr_u32(tb[IFLA_BR_MCAST_HASH_ELASTICITY]));
517
518 if (tb[IFLA_BR_MCAST_HASH_MAX])
519 fprintf(f, "mcast_hash_max %u ",
520 rta_getattr_u32(tb[IFLA_BR_MCAST_HASH_MAX]));
521
522 if (tb[IFLA_BR_MCAST_LAST_MEMBER_CNT])
523 fprintf(f, "mcast_last_member_count %u ",
524 rta_getattr_u32(tb[IFLA_BR_MCAST_LAST_MEMBER_CNT]));
525
526 if (tb[IFLA_BR_MCAST_STARTUP_QUERY_CNT])
527 fprintf(f, "mcast_startup_query_count %u ",
528 rta_getattr_u32(tb[IFLA_BR_MCAST_STARTUP_QUERY_CNT]));
529
530 if (tb[IFLA_BR_MCAST_LAST_MEMBER_INTVL])
531 fprintf(f, "mcast_last_member_interval %llu ",
532 rta_getattr_u64(tb[IFLA_BR_MCAST_LAST_MEMBER_INTVL]));
533
534 if (tb[IFLA_BR_MCAST_MEMBERSHIP_INTVL])
535 fprintf(f, "mcast_membership_interval %llu ",
536 rta_getattr_u64(tb[IFLA_BR_MCAST_MEMBERSHIP_INTVL]));
537
538 if (tb[IFLA_BR_MCAST_QUERIER_INTVL])
539 fprintf(f, "mcast_querier_interval %llu ",
540 rta_getattr_u64(tb[IFLA_BR_MCAST_QUERIER_INTVL]));
541
542 if (tb[IFLA_BR_MCAST_QUERY_INTVL])
543 fprintf(f, "mcast_query_interval %llu ",
544 rta_getattr_u64(tb[IFLA_BR_MCAST_QUERY_INTVL]));
545
546 if (tb[IFLA_BR_MCAST_QUERY_RESPONSE_INTVL])
547 fprintf(f, "mcast_query_response_interval %llu ",
548 rta_getattr_u64(tb[IFLA_BR_MCAST_QUERY_RESPONSE_INTVL]));
549
550 if (tb[IFLA_BR_MCAST_STARTUP_QUERY_INTVL])
551 fprintf(f, "mcast_startup_query_interval %llu ",
552 rta_getattr_u64(tb[IFLA_BR_MCAST_STARTUP_QUERY_INTVL]));
553
554 if (tb[IFLA_BR_MCAST_STATS_ENABLED])
555 fprintf(f, "mcast_stats_enabled %u ",
556 rta_getattr_u8(tb[IFLA_BR_MCAST_STATS_ENABLED]));
557
558 if (tb[IFLA_BR_MCAST_IGMP_VERSION])
559 fprintf(f, "mcast_igmp_version %u ",
560 rta_getattr_u8(tb[IFLA_BR_MCAST_IGMP_VERSION]));
561
562 if (tb[IFLA_BR_MCAST_MLD_VERSION])
563 fprintf(f, "mcast_mld_version %u ",
564 rta_getattr_u8(tb[IFLA_BR_MCAST_MLD_VERSION]));
565
566 if (tb[IFLA_BR_NF_CALL_IPTABLES])
567 fprintf(f, "nf_call_iptables %u ",
568 rta_getattr_u8(tb[IFLA_BR_NF_CALL_IPTABLES]));
569
570 if (tb[IFLA_BR_NF_CALL_IP6TABLES])
571 fprintf(f, "nf_call_ip6tables %u ",
572 rta_getattr_u8(tb[IFLA_BR_NF_CALL_IP6TABLES]));
573
574 if (tb[IFLA_BR_NF_CALL_ARPTABLES])
575 fprintf(f, "nf_call_arptables %u ",
576 rta_getattr_u8(tb[IFLA_BR_NF_CALL_ARPTABLES]));
577 }
578
579 static void bridge_print_help(struct link_util *lu, int argc, char **argv,
580 FILE *f)
581 {
582 print_explain(f);
583 }
584
585 struct link_util bridge_link_util = {
586 .id = "bridge",
587 .maxattr = IFLA_BR_MAX,
588 .parse_opt = bridge_parse_opt,
589 .print_opt = bridge_print_opt,
590 .print_help = bridge_print_help,
591 };