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