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 <linux/if_link.h>
16 #include <netinet/ether.h>
20 #include "ip_common.h"
22 static void print_explain(FILE *f
)
25 "Usage: ... bridge [ forward_delay FORWARD_DELAY ]\n"
26 " [ hello_time HELLO_TIME ]\n"
27 " [ max_age MAX_AGE ]\n"
28 " [ ageing_time AGEING_TIME ]\n"
29 " [ stp_state STP_STATE ]\n"
30 " [ priority PRIORITY ]\n"
31 " [ group_fwd_mask MASK ]\n"
32 " [ group_address ADDRESS ]\n"
33 " [ vlan_filtering VLAN_FILTERING ]\n"
34 " [ vlan_protocol VLAN_PROTOCOL ]\n"
35 " [ vlan_default_pvid VLAN_DEFAULT_PVID ]\n"
36 " [ mcast_snooping MULTICAST_SNOOPING ]\n"
37 " [ mcast_router MULTICAST_ROUTER ]\n"
38 " [ mcast_query_use_ifaddr MCAST_QUERY_USE_IFADDR ]\n"
39 " [ mcast_querier MULTICAST_QUERIER ]\n"
40 " [ mcast_hash_elasticity HASH_ELASTICITY ]\n"
42 "Where: VLAN_PROTOCOL := { 802.1Q | 802.1ad }\n"
46 static void explain(void)
48 print_explain(stderr
);
51 static void br_dump_bridge_id(const struct ifla_bridge_id
*id
, char *buf
,
56 ether_ntoa_r((const struct ether_addr
*)id
->addr
, eaddr
);
57 snprintf(buf
, len
, "%.2x%.2x.%s", id
->prio
[0], id
->prio
[1], eaddr
);
60 static int bridge_parse_opt(struct link_util
*lu
, int argc
, char **argv
,
66 if (matches(*argv
, "forward_delay") == 0) {
68 if (get_u32(&val
, *argv
, 0))
69 invarg("invalid forward_delay", *argv
);
71 addattr32(n
, 1024, IFLA_BR_FORWARD_DELAY
, val
);
72 } else if (matches(*argv
, "hello_time") == 0) {
74 if (get_u32(&val
, *argv
, 0))
75 invarg("invalid hello_time", *argv
);
77 addattr32(n
, 1024, IFLA_BR_HELLO_TIME
, val
);
78 } else if (matches(*argv
, "max_age") == 0) {
80 if (get_u32(&val
, *argv
, 0))
81 invarg("invalid max_age", *argv
);
83 addattr32(n
, 1024, IFLA_BR_MAX_AGE
, val
);
84 } else if (matches(*argv
, "ageing_time") == 0) {
86 if (get_u32(&val
, *argv
, 0))
87 invarg("invalid ageing_time", *argv
);
89 addattr32(n
, 1024, IFLA_BR_AGEING_TIME
, val
);
90 } else if (matches(*argv
, "stp_state") == 0) {
92 if (get_u32(&val
, *argv
, 0))
93 invarg("invalid stp_state", *argv
);
95 addattr32(n
, 1024, IFLA_BR_STP_STATE
, val
);
96 } else if (matches(*argv
, "priority") == 0) {
100 if (get_u16(&prio
, *argv
, 0))
101 invarg("invalid priority", *argv
);
103 addattr16(n
, 1024, IFLA_BR_PRIORITY
, prio
);
104 } else if (matches(*argv
, "vlan_filtering") == 0) {
108 if (get_u8(&vlan_filter
, *argv
, 0)) {
109 invarg("invalid vlan_filtering", *argv
);
112 addattr8(n
, 1024, IFLA_BR_VLAN_FILTERING
, vlan_filter
);
113 } else if (matches(*argv
, "vlan_protocol") == 0) {
117 if (ll_proto_a2n(&vlan_proto
, *argv
)) {
118 invarg("invalid vlan_protocol", *argv
);
121 addattr16(n
, 1024, IFLA_BR_VLAN_PROTOCOL
, vlan_proto
);
122 } else if (matches(*argv
, "group_fwd_mask") == 0) {
126 if (get_u16(&fwd_mask
, *argv
, 0))
127 invarg("invalid group_fwd_mask", *argv
);
129 addattr16(n
, 1024, IFLA_BR_GROUP_FWD_MASK
, fwd_mask
);
130 } else if (matches(*argv
, "group_address") == 0) {
135 len
= ll_addr_a2n(llabuf
, sizeof(llabuf
), *argv
);
138 addattr_l(n
, 1024, IFLA_BR_GROUP_ADDR
, llabuf
, len
);
139 } else if (matches(*argv
, "vlan_default_pvid") == 0) {
143 if (get_u16(&default_pvid
, *argv
, 0))
144 invarg("invalid vlan_default_pvid", *argv
);
146 addattr16(n
, 1024, IFLA_BR_VLAN_DEFAULT_PVID
,
148 } else if (matches(*argv
, "mcast_router") == 0) {
152 if (get_u8(&mcast_router
, *argv
, 0))
153 invarg("invalid mcast_router", *argv
);
155 addattr8(n
, 1024, IFLA_BR_MCAST_ROUTER
, mcast_router
);
156 } else if (matches(*argv
, "mcast_snooping") == 0) {
160 if (get_u8(&mcast_snoop
, *argv
, 0))
161 invarg("invalid mcast_snooping", *argv
);
163 addattr8(n
, 1024, IFLA_BR_MCAST_SNOOPING
, mcast_snoop
);
164 } else if (matches(*argv
, "mcast_query_use_ifaddr") == 0) {
168 if (get_u8(&mcast_qui
, *argv
, 0))
169 invarg("invalid mcast_query_use_ifaddr",
172 addattr8(n
, 1024, IFLA_BR_MCAST_QUERY_USE_IFADDR
,
174 } else if (matches(*argv
, "mcast_querier") == 0) {
178 if (get_u8(&mcast_querier
, *argv
, 0))
179 invarg("invalid mcast_querier", *argv
);
181 addattr8(n
, 1024, IFLA_BR_MCAST_QUERIER
, mcast_querier
);
182 } else if (matches(*argv
, "mcast_hash_elasticity") == 0) {
186 if (get_u32(&mcast_hash_el
, *argv
, 0))
187 invarg("invalid mcast_hash_elasticity",
190 addattr32(n
, 1024, IFLA_BR_MCAST_HASH_ELASTICITY
,
192 } else if (matches(*argv
, "help") == 0) {
196 fprintf(stderr
, "bridge: unknown command \"%s\"?\n", *argv
);
206 static void bridge_print_opt(struct link_util
*lu
, FILE *f
, struct rtattr
*tb
[])
211 if (tb
[IFLA_BR_FORWARD_DELAY
])
212 fprintf(f
, "forward_delay %u ",
213 rta_getattr_u32(tb
[IFLA_BR_FORWARD_DELAY
]));
215 if (tb
[IFLA_BR_HELLO_TIME
])
216 fprintf(f
, "hello_time %u ",
217 rta_getattr_u32(tb
[IFLA_BR_HELLO_TIME
]));
219 if (tb
[IFLA_BR_MAX_AGE
])
220 fprintf(f
, "max_age %u ",
221 rta_getattr_u32(tb
[IFLA_BR_MAX_AGE
]));
223 if (tb
[IFLA_BR_AGEING_TIME
])
224 fprintf(f
, "ageing_time %u ",
225 rta_getattr_u32(tb
[IFLA_BR_AGEING_TIME
]));
227 if (tb
[IFLA_BR_STP_STATE
])
228 fprintf(f
, "stp_state %u ",
229 rta_getattr_u32(tb
[IFLA_BR_STP_STATE
]));
231 if (tb
[IFLA_BR_PRIORITY
])
232 fprintf(f
, "priority %u ",
233 rta_getattr_u16(tb
[IFLA_BR_PRIORITY
]));
235 if (tb
[IFLA_BR_VLAN_FILTERING
])
236 fprintf(f
, "vlan_filtering %u ",
237 rta_getattr_u8(tb
[IFLA_BR_VLAN_FILTERING
]));
239 if (tb
[IFLA_BR_VLAN_PROTOCOL
]) {
242 fprintf(f
, "vlan_protocol %s ",
243 ll_proto_n2a(rta_getattr_u16(tb
[IFLA_BR_VLAN_PROTOCOL
]),
247 if (tb
[IFLA_BR_BRIDGE_ID
]) {
250 br_dump_bridge_id(RTA_DATA(tb
[IFLA_BR_BRIDGE_ID
]), bridge_id
,
252 fprintf(f
, "bridge_id %s ", bridge_id
);
255 if (tb
[IFLA_BR_ROOT_ID
]) {
258 br_dump_bridge_id(RTA_DATA(tb
[IFLA_BR_BRIDGE_ID
]), root_id
,
260 fprintf(f
, "designated_root %s ", root_id
);
263 if (tb
[IFLA_BR_ROOT_PORT
])
264 fprintf(f
, "root_port %u ",
265 rta_getattr_u16(tb
[IFLA_BR_ROOT_PORT
]));
267 if (tb
[IFLA_BR_ROOT_PATH_COST
])
268 fprintf(f
, "root_path_cost %u ",
269 rta_getattr_u32(tb
[IFLA_BR_ROOT_PATH_COST
]));
271 if (tb
[IFLA_BR_TOPOLOGY_CHANGE
])
272 fprintf(f
, "topology_change %u ",
273 rta_getattr_u8(tb
[IFLA_BR_TOPOLOGY_CHANGE
]));
275 if (tb
[IFLA_BR_TOPOLOGY_CHANGE_DETECTED
])
276 fprintf(f
, "topology_change_detected %u ",
277 rta_getattr_u8(tb
[IFLA_BR_TOPOLOGY_CHANGE_DETECTED
]));
279 if (tb
[IFLA_BR_HELLO_TIMER
]) {
282 __jiffies_to_tv(&tv
, rta_getattr_u64(tb
[IFLA_BR_HELLO_TIMER
]));
283 fprintf(f
, "hello_timer %4i.%.2i ", (int)tv
.tv_sec
,
284 (int)tv
.tv_usec
/10000);
287 if (tb
[IFLA_BR_TCN_TIMER
]) {
290 __jiffies_to_tv(&tv
, rta_getattr_u64(tb
[IFLA_BR_TCN_TIMER
]));
291 fprintf(f
, "tcn_timer %4i.%.2i ", (int)tv
.tv_sec
,
292 (int)tv
.tv_usec
/10000);
295 if (tb
[IFLA_BR_TOPOLOGY_CHANGE_TIMER
]) {
296 unsigned long jiffies
;
299 jiffies
= rta_getattr_u64(tb
[IFLA_BR_TOPOLOGY_CHANGE_TIMER
]);
300 __jiffies_to_tv(&tv
, jiffies
);
301 fprintf(f
, "topology_change_timer %4i.%.2i ", (int)tv
.tv_sec
,
302 (int)tv
.tv_usec
/10000);
305 if (tb
[IFLA_BR_GC_TIMER
]) {
308 __jiffies_to_tv(&tv
, rta_getattr_u64(tb
[IFLA_BR_GC_TIMER
]));
309 fprintf(f
, "gc_timer %4i.%.2i ", (int)tv
.tv_sec
,
310 (int)tv
.tv_usec
/10000);
313 if (tb
[IFLA_BR_VLAN_DEFAULT_PVID
])
314 fprintf(f
, "vlan_default_pvid %u ",
315 rta_getattr_u16(tb
[IFLA_BR_VLAN_DEFAULT_PVID
]));
317 if (tb
[IFLA_BR_GROUP_FWD_MASK
])
318 fprintf(f
, "group_fwd_mask %#x ",
319 rta_getattr_u16(tb
[IFLA_BR_GROUP_FWD_MASK
]));
321 if (tb
[IFLA_BR_GROUP_ADDR
]) {
324 fprintf(f
, "group_address %s ",
325 ll_addr_n2a(RTA_DATA(tb
[IFLA_BR_GROUP_ADDR
]),
326 RTA_PAYLOAD(tb
[IFLA_BR_GROUP_ADDR
]),
327 1 /*ARPHDR_ETHER*/, mac
, sizeof(mac
)));
330 if (tb
[IFLA_BR_MCAST_SNOOPING
])
331 fprintf(f
, "mcast_snooping %u ",
332 rta_getattr_u8(tb
[IFLA_BR_MCAST_SNOOPING
]));
334 if (tb
[IFLA_BR_MCAST_ROUTER
])
335 fprintf(f
, "mcast_router %u ",
336 rta_getattr_u8(tb
[IFLA_BR_MCAST_ROUTER
]));
338 if (tb
[IFLA_BR_MCAST_QUERY_USE_IFADDR
])
339 fprintf(f
, "mcast_query_use_ifaddr %u ",
340 rta_getattr_u8(tb
[IFLA_BR_MCAST_QUERY_USE_IFADDR
]));
342 if (tb
[IFLA_BR_MCAST_QUERIER
])
343 fprintf(f
, "mcast_querier %u ",
344 rta_getattr_u8(tb
[IFLA_BR_MCAST_QUERIER
]));
346 if (tb
[IFLA_BR_MCAST_HASH_ELASTICITY
])
347 fprintf(f
, "mcast_hash_elasticity %u ",
348 rta_getattr_u32(tb
[IFLA_BR_MCAST_HASH_ELASTICITY
]));
351 static void bridge_print_help(struct link_util
*lu
, int argc
, char **argv
,
357 struct link_util bridge_link_util
= {
359 .maxattr
= IFLA_BR_MAX
,
360 .parse_opt
= bridge_parse_opt
,
361 .print_opt
= bridge_print_opt
,
362 .print_help
= bridge_print_help
,