2 * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
25 * - add and remove interfaces from a bond interface
29 * Modification History:
31 * July 14, 2004 Dieter Siegmund (dieter@apple.com)
35 #include <sys/param.h>
36 #include <sys/ioctl.h>
37 #include <sys/socket.h>
42 #include <net/ethernet.h>
44 #include <net/if_var.h>
45 #include <net/if_bond_var.h>
47 #include <net/route.h>
58 extern int bond_details
;
60 #define EA_FORMAT "%02x:%02x:%02x:%02x:%02x:%02x"
61 #define EA_CH(e, i) ((u_char)((u_char *)(e))[(i)])
62 #define EA_LIST(ea) EA_CH(ea,0),EA_CH(ea,1),EA_CH(ea,2),EA_CH(ea,3),EA_CH(ea,4),EA_CH(ea,5)
64 static __inline__
const char *
65 selected_state_string(u_char s
)
67 static const char * names
[] = { "unselected", "selected", "standby" };
69 if (s
<= IF_BOND_STATUS_SELECTED_STATE_STANDBY
) {
76 bond_print_details(struct if_bond_status
* ibs_p
, int count
)
80 struct if_bond_status
* scan_p
= ibs_p
;
82 for (i
= 0; i
< count
; i
++, scan_p
++) {
83 struct if_bond_partner_state
* ps
;
84 ps
= &scan_p
->ibs_partner_state
;
85 printf("\tbond interface: %s priority: 0x%04x "
86 "state: 0x%02x partner system: 0x%04x,"
88 "key: 0x%04x port: 0x%04x priority: 0x%04x "
90 scan_p
->ibs_if_name
, scan_p
->ibs_port_priority
,
91 scan_p
->ibs_state
, ps
->ibps_system_priority
,
92 EA_LIST(&ps
->ibps_system
), ps
->ibps_key
,
93 ps
->ibps_port
, ps
->ibps_port_priority
,
103 struct if_bond_req ibr
;
104 struct if_bond_status
* ibs_p
;
105 struct if_bond_status_req
* ibsr_p
;
107 const char * mode_str
;
109 bzero((char *)&ibr
, sizeof(ibr
));
110 ibr
.ibr_op
= IF_BOND_OP_GET_STATUS
;
111 ibsr_p
= &ibr
.ibr_ibru
.ibru_status
;
112 ibsr_p
->ibsr_version
= IF_BOND_STATUS_REQ_VERSION
;
113 ifr
.ifr_data
= (caddr_t
)&ibr
;
115 /* how many of them are there? */
116 if (ioctl(s
, SIOCGIFBOND
, (caddr_t
)&ifr
) < 0) {
119 switch (ibsr_p
->ibsr_mode
) {
120 case IF_BOND_MODE_LACP
:
123 case IF_BOND_MODE_STATIC
:
127 snprintf(mode_buf
, sizeof(mode_buf
), "%d", ibsr_p
->ibsr_mode
);
131 if (ibsr_p
->ibsr_total
== 0) {
133 printf("\tbond mode: %s\n"
134 "\tbond key: 0x%04x interfaces: <none>",
135 mode_str
, ibsr_p
->ibsr_key
);
138 printf("\tbond interfaces: <none>\n");
143 = (char *)malloc(sizeof(struct if_bond_status
)
144 * ibsr_p
->ibsr_total
);
145 ibsr_p
->ibsr_count
= ibsr_p
->ibsr_total
;
148 if (ioctl(s
, SIOCGIFBOND
, (caddr_t
)&ifr
) < 0) {
151 if (ibsr_p
->ibsr_total
> 0) {
153 printf("\tbond mode: %s\n"
154 "\tbond key: 0x%04x interfaces:",
155 mode_str
, ibsr_p
->ibsr_key
);
158 printf("\tbond interfaces:");
160 ibs_p
= (struct if_bond_status
*)ibsr_p
->ibsr_buffer
;
161 for (i
= 0; i
< ibsr_p
->ibsr_total
; i
++, ibs_p
++) {
162 printf(" %s", ibs_p
->ibs_if_name
);
164 u_char s
= ibs_p
->ibs_selected_state
;
165 printf(" (%s)", selected_state_string(s
));
170 bond_print_details((struct if_bond_status
*)
175 else if (bond_details
) {
176 printf("\tbond mode: %s\n"
177 "\tbond key: 0x%04x interfaces: <none>\n",
178 mode_str
, ibsr_p
->ibsr_key
);
181 printf("\tbond interfaces: <none>\n");
185 free(ibsr_p
->ibsr_buffer
);
190 DECL_CMD_FUNC(setbonddev
, val
, d
)
192 struct if_bond_req ibr
;
194 bzero((char *)&ibr
, sizeof(ibr
));
195 if ((unsigned int)snprintf(ibr
.ibr_ibru
.ibru_if_name
,
196 sizeof(ibr
.ibr_ibru
.ibru_if_name
),
197 "%s", val
) >= IFNAMSIZ
) {
198 errx(1, "interface name too long");
200 ibr
.ibr_op
= IF_BOND_OP_ADD_INTERFACE
;
201 ifr
.ifr_data
= (caddr_t
)&ibr
;
202 if (ioctl(s
, SIOCSIFBOND
, (caddr_t
)&ifr
) == -1)
203 err(1, "SIOCSIFBOND add interface");
209 DECL_CMD_FUNC(unsetbonddev
, val
, d
)
211 struct if_bond_req ibr
;
213 bzero((char *)&ibr
, sizeof(ibr
));
214 if ((unsigned int)snprintf(ibr
.ibr_ibru
.ibru_if_name
,
215 sizeof(ibr
.ibr_ibru
.ibru_if_name
),
216 "%s", val
) >= IFNAMSIZ
) {
217 errx(1, "interface name too long");
219 ibr
.ibr_op
= IF_BOND_OP_REMOVE_INTERFACE
;
220 ifr
.ifr_data
= (caddr_t
)&ibr
;
221 if (ioctl(s
, SIOCSIFBOND
, (caddr_t
)&ifr
) == -1)
222 err(1, "SIOCSIFBOND remove interface");
228 DECL_CMD_FUNC(setbondmode
, val
, d
)
230 struct if_bond_req ibr
;
233 if (strcmp(val
, "lacp") == 0) {
234 mode
= IF_BOND_MODE_LACP
;
236 else if (strcmp(val
, "static") == 0) {
237 mode
= IF_BOND_MODE_STATIC
;
240 mode
= strtoul(val
, NULL
, 0);
242 errx(1, "invalid mode value "
243 "(must be either \"lacp\" or \"static\")");
247 bzero((char *)&ibr
, sizeof(ibr
));
248 if ((unsigned int)snprintf(ibr
.ibr_ibru
.ibru_if_name
,
249 sizeof(ibr
.ibr_ibru
.ibru_if_name
),
250 "%s", val
) >= IFNAMSIZ
) {
251 errx(1, "interface name too long");
253 ibr
.ibr_op
= IF_BOND_OP_SET_MODE
;
254 ibr
.ibr_ibru
.ibru_int_val
= mode
;
255 ifr
.ifr_data
= (caddr_t
)&ibr
;
256 if (ioctl(s
, SIOCSIFBOND
, (caddr_t
)&ifr
) == -1)
257 err(1, "SIOCSIFBOND set mode");
262 static struct cmd bond_cmds
[] = {
263 DEF_CLONE_CMD_ARG("bonddev", setbonddev
),
264 DEF_CLONE_CMD_ARG("-bonddev", unsetbonddev
),
265 DEF_CMD_ARG("bondmode", setbondmode
),
267 static struct afswtch af_bond
= {
268 .af_name
= "af_bond",
270 .af_other_status
= bond_status
,
273 static __constructor
void
276 #define N(a) (sizeof(a) / sizeof(a[0]))
279 for (i
= 0; i
< N(bond_cmds
); i
++)
280 cmd_register(&bond_cmds
[i
]);
281 af_register(&af_bond
);