2 * iplink_bridge_slave.c Bridge slave 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>
13 #include <sys/socket.h>
14 #include <netinet/in.h>
15 #include <linux/if_link.h>
16 #include <linux/if_bridge.h>
20 #include "ip_common.h"
22 static void print_explain(FILE *f
)
25 "Usage: ... bridge_slave [ state STATE ] [ priority PRIO ] [cost COST ]\n"
26 " [ guard {on | off} ]\n"
27 " [ hairpin {on | off} ] \n"
28 " [ fastleave {on | off} ]\n"
29 " [ root_block {on | off} ]\n"
30 " [ learning {on | off} ]\n"
31 " [ flood {on | off} ]\n"
32 " [ proxy_arp {on | off} ]\n"
33 " [ proxy_arp_wifi {on | off} ]\n"
34 " [ mcast_router MULTICAST_ROUTER ]\n"
38 static void explain(void)
40 print_explain(stderr
);
43 static const char *port_states
[] = {
44 [BR_STATE_DISABLED
] = "disabled",
45 [BR_STATE_LISTENING
] = "listening",
46 [BR_STATE_LEARNING
] = "learning",
47 [BR_STATE_FORWARDING
] = "forwarding",
48 [BR_STATE_BLOCKING
] = "blocking",
51 static void print_portstate(FILE *f
, __u8 state
)
53 if (state
<= BR_STATE_BLOCKING
)
54 fprintf(f
, "state %s ", port_states
[state
]);
56 fprintf(f
, "state (%d) ", state
);
59 static void print_onoff(FILE *f
, char *flag
, __u8 val
)
61 fprintf(f
, "%s %s ", flag
, val
? "on" : "off");
64 static void bridge_slave_print_opt(struct link_util
*lu
, FILE *f
,
70 if (tb
[IFLA_BRPORT_STATE
])
71 print_portstate(f
, rta_getattr_u8(tb
[IFLA_BRPORT_STATE
]));
73 if (tb
[IFLA_BRPORT_PRIORITY
])
74 fprintf(f
, "priority %d ",
75 rta_getattr_u16(tb
[IFLA_BRPORT_PRIORITY
]));
77 if (tb
[IFLA_BRPORT_COST
])
78 fprintf(f
, "cost %d ",
79 rta_getattr_u32(tb
[IFLA_BRPORT_COST
]));
81 if (tb
[IFLA_BRPORT_MODE
])
82 print_onoff(f
, "hairpin",
83 rta_getattr_u8(tb
[IFLA_BRPORT_MODE
]));
85 if (tb
[IFLA_BRPORT_GUARD
])
86 print_onoff(f
, "guard",
87 rta_getattr_u8(tb
[IFLA_BRPORT_GUARD
]));
89 if (tb
[IFLA_BRPORT_PROTECT
])
90 print_onoff(f
, "root_block",
91 rta_getattr_u8(tb
[IFLA_BRPORT_PROTECT
]));
93 if (tb
[IFLA_BRPORT_FAST_LEAVE
])
94 print_onoff(f
, "fastleave",
95 rta_getattr_u8(tb
[IFLA_BRPORT_FAST_LEAVE
]));
97 if (tb
[IFLA_BRPORT_LEARNING
])
98 print_onoff(f
, "learning",
99 rta_getattr_u8(tb
[IFLA_BRPORT_LEARNING
]));
101 if (tb
[IFLA_BRPORT_UNICAST_FLOOD
])
102 print_onoff(f
, "flood",
103 rta_getattr_u8(tb
[IFLA_BRPORT_UNICAST_FLOOD
]));
105 if (tb
[IFLA_BRPORT_ID
])
106 fprintf(f
, "port_id 0x%x ",
107 rta_getattr_u16(tb
[IFLA_BRPORT_ID
]));
109 if (tb
[IFLA_BRPORT_NO
])
110 fprintf(f
, "port_no 0x%x ",
111 rta_getattr_u16(tb
[IFLA_BRPORT_NO
]));
113 if (tb
[IFLA_BRPORT_DESIGNATED_PORT
])
114 fprintf(f
, "designated_port %u ",
115 rta_getattr_u16(tb
[IFLA_BRPORT_DESIGNATED_PORT
]));
117 if (tb
[IFLA_BRPORT_DESIGNATED_COST
])
118 fprintf(f
, "designated_cost %u ",
119 rta_getattr_u16(tb
[IFLA_BRPORT_DESIGNATED_COST
]));
121 if (tb
[IFLA_BRPORT_BRIDGE_ID
]) {
124 br_dump_bridge_id(RTA_DATA(tb
[IFLA_BRPORT_BRIDGE_ID
]),
125 bridge_id
, sizeof(bridge_id
));
126 fprintf(f
, "designated_bridge %s ", bridge_id
);
129 if (tb
[IFLA_BRPORT_ROOT_ID
]) {
132 br_dump_bridge_id(RTA_DATA(tb
[IFLA_BRPORT_ROOT_ID
]),
133 root_id
, sizeof(root_id
));
134 fprintf(f
, "designated_root %s ", root_id
);
137 if (tb
[IFLA_BRPORT_HOLD_TIMER
]) {
141 htimer
= rta_getattr_u64(tb
[IFLA_BRPORT_HOLD_TIMER
]);
142 __jiffies_to_tv(&tv
, htimer
);
143 fprintf(f
, "hold_timer %4i.%.2i ", (int)tv
.tv_sec
,
144 (int)tv
.tv_usec
/10000);
147 if (tb
[IFLA_BRPORT_MESSAGE_AGE_TIMER
]) {
151 agetimer
= rta_getattr_u64(tb
[IFLA_BRPORT_MESSAGE_AGE_TIMER
]);
152 __jiffies_to_tv(&tv
, agetimer
);
153 fprintf(f
, "message_age_timer %4i.%.2i ", (int)tv
.tv_sec
,
154 (int)tv
.tv_usec
/10000);
157 if (tb
[IFLA_BRPORT_FORWARD_DELAY_TIMER
]) {
161 fwdtimer
= rta_getattr_u64(tb
[IFLA_BRPORT_FORWARD_DELAY_TIMER
]);
162 __jiffies_to_tv(&tv
, fwdtimer
);
163 fprintf(f
, "forward_delay_timer %4i.%.2i ", (int)tv
.tv_sec
,
164 (int)tv
.tv_usec
/10000);
167 if (tb
[IFLA_BRPORT_TOPOLOGY_CHANGE_ACK
])
168 fprintf(f
, "topology_change_ack %u ",
169 rta_getattr_u8(tb
[IFLA_BRPORT_TOPOLOGY_CHANGE_ACK
]));
171 if (tb
[IFLA_BRPORT_CONFIG_PENDING
])
172 fprintf(f
, "config_pending %u ",
173 rta_getattr_u8(tb
[IFLA_BRPORT_CONFIG_PENDING
]));
174 if (tb
[IFLA_BRPORT_PROXYARP
])
175 print_onoff(f
, "proxy_arp",
176 rta_getattr_u8(tb
[IFLA_BRPORT_PROXYARP
]));
178 if (tb
[IFLA_BRPORT_PROXYARP_WIFI
])
179 print_onoff(f
, "proxy_arp_wifi",
180 rta_getattr_u8(tb
[IFLA_BRPORT_PROXYARP_WIFI
]));
182 if (tb
[IFLA_BRPORT_MULTICAST_ROUTER
])
183 fprintf(f
, "mcast_router %u ",
184 rta_getattr_u8(tb
[IFLA_BRPORT_MULTICAST_ROUTER
]));
187 static void bridge_slave_parse_on_off(char *arg_name
, char *arg_val
,
188 struct nlmsghdr
*n
, int type
)
192 if (strcmp(arg_val
, "on") == 0)
194 else if (strcmp(arg_val
, "off") == 0)
197 invarg("should be \"on\" or \"off\"", arg_name
);
199 addattr8(n
, 1024, type
, val
);
202 static int bridge_slave_parse_opt(struct link_util
*lu
, int argc
, char **argv
,
210 if (matches(*argv
, "state") == 0) {
212 if (get_u8(&state
, *argv
, 0))
213 invarg("state is invalid", *argv
);
214 addattr8(n
, 1024, IFLA_BRPORT_STATE
, state
);
215 } else if (matches(*argv
, "priority") == 0) {
217 if (get_u16(&priority
, *argv
, 0))
218 invarg("priority is invalid", *argv
);
219 addattr16(n
, 1024, IFLA_BRPORT_PRIORITY
, priority
);
220 } else if (matches(*argv
, "cost") == 0) {
222 if (get_u32(&cost
, *argv
, 0))
223 invarg("cost is invalid", *argv
);
224 addattr32(n
, 1024, IFLA_BRPORT_COST
, cost
);
225 } else if (matches(*argv
, "hairpin") == 0) {
227 bridge_slave_parse_on_off("hairpin", *argv
, n
,
229 } else if (matches(*argv
, "guard") == 0) {
231 bridge_slave_parse_on_off("guard", *argv
, n
,
233 } else if (matches(*argv
, "root_block") == 0) {
235 bridge_slave_parse_on_off("root_block", *argv
, n
,
236 IFLA_BRPORT_PROTECT
);
237 } else if (matches(*argv
, "fastleave") == 0) {
239 bridge_slave_parse_on_off("fastleave", *argv
, n
,
240 IFLA_BRPORT_FAST_LEAVE
);
241 } else if (matches(*argv
, "learning") == 0) {
243 bridge_slave_parse_on_off("learning", *argv
, n
,
244 IFLA_BRPORT_LEARNING
);
245 } else if (matches(*argv
, "flood") == 0) {
247 bridge_slave_parse_on_off("flood", *argv
, n
,
248 IFLA_BRPORT_UNICAST_FLOOD
);
249 } else if (matches(*argv
, "proxy_arp") == 0) {
251 bridge_slave_parse_on_off("proxy_arp", *argv
, n
,
252 IFLA_BRPORT_PROXYARP
);
253 } else if (matches(*argv
, "proxy_arp_wifi") == 0) {
255 bridge_slave_parse_on_off("proxy_arp_wifi", *argv
, n
,
256 IFLA_BRPORT_PROXYARP_WIFI
);
257 } else if (matches(*argv
, "mcast_router") == 0) {
261 if (get_u8(&mcast_router
, *argv
, 0))
262 invarg("invalid mcast_router", *argv
);
263 addattr8(n
, 1024, IFLA_BRPORT_MULTICAST_ROUTER
,
265 } else if (matches(*argv
, "help") == 0) {
269 fprintf(stderr
, "bridge_slave: unknown option \"%s\"?\n",
280 static void bridge_slave_print_help(struct link_util
*lu
, int argc
, char **argv
,
286 struct link_util bridge_slave_link_util
= {
288 .maxattr
= IFLA_BRPORT_MAX
,
289 .print_opt
= bridge_slave_print_opt
,
290 .parse_opt
= bridge_slave_parse_opt
,
291 .print_help
= bridge_slave_print_help
,