4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * IEEE 802.3ad Link Aggregation -- IOCTL processing.
31 #include <sys/aggr_impl.h>
32 #include <sys/policy.h>
35 * Process a LAIOC_MODIFY request.
39 aggr_ioc_modify(void *karg
, intptr_t arg
, int mode
, cred_t
*cred
, int *rvalp
)
41 laioc_modify_t
*modify_arg
= karg
;
44 uchar_t mac_addr
[ETHERADDRL
];
45 uint8_t modify_mask_arg
, modify_mask
= 0;
46 aggr_lacp_mode_t lacp_mode
;
47 aggr_lacp_timer_t lacp_timer
;
49 modify_mask_arg
= modify_arg
->lu_modify_mask
;
51 if (modify_mask_arg
& LAIOC_MODIFY_POLICY
) {
52 modify_mask
|= AGGR_MODIFY_POLICY
;
53 policy
= modify_arg
->lu_policy
;
56 if (modify_mask_arg
& LAIOC_MODIFY_MAC
) {
57 modify_mask
|= AGGR_MODIFY_MAC
;
58 bcopy(modify_arg
->lu_mac
, mac_addr
, ETHERADDRL
);
59 mac_fixed
= modify_arg
->lu_mac_fixed
;
62 if (modify_mask_arg
& LAIOC_MODIFY_LACP_MODE
) {
63 modify_mask
|= AGGR_MODIFY_LACP_MODE
;
64 lacp_mode
= modify_arg
->lu_lacp_mode
;
67 if (modify_mask_arg
& LAIOC_MODIFY_LACP_TIMER
) {
68 modify_mask
|= AGGR_MODIFY_LACP_TIMER
;
69 lacp_timer
= modify_arg
->lu_lacp_timer
;
72 return (aggr_grp_modify(modify_arg
->lu_linkid
, modify_mask
, policy
,
73 mac_fixed
, mac_addr
, lacp_mode
, lacp_timer
));
77 * Process a LAIOC_CREATE request.
81 aggr_ioc_create(void *karg
, intptr_t arg
, int mode
, cred_t
*cred
, int *rvalp
)
83 laioc_create_t
*create_arg
= karg
;
85 laioc_port_t
*ports
= NULL
;
90 uchar_t mac_addr
[ETHERADDRL
];
91 aggr_lacp_mode_t lacp_mode
;
92 aggr_lacp_timer_t lacp_timer
;
95 nports
= create_arg
->lc_nports
;
96 if (nports
> AGGR_MAX_PORTS
)
99 policy
= create_arg
->lc_policy
;
100 lacp_mode
= create_arg
->lc_lacp_mode
;
101 lacp_timer
= create_arg
->lc_lacp_timer
;
103 ports_size
= nports
* sizeof (laioc_port_t
);
104 ports
= kmem_alloc(ports_size
, KM_SLEEP
);
106 if (ddi_copyin((uchar_t
*)arg
+ sizeof (*create_arg
), ports
,
107 ports_size
, mode
) != 0) {
112 bcopy(create_arg
->lc_mac
, mac_addr
, ETHERADDRL
);
113 mac_fixed
= create_arg
->lc_mac_fixed
;
114 force
= create_arg
->lc_force
;
116 rc
= aggr_grp_create(create_arg
->lc_linkid
, create_arg
->lc_key
, nports
,
117 ports
, policy
, mac_fixed
, force
, mac_addr
, lacp_mode
, lacp_timer
,
121 kmem_free(ports
, ports_size
);
127 aggr_ioc_delete(void *karg
, intptr_t arg
, int mode
, cred_t
*cred
, int *rvalp
)
129 laioc_delete_t
*delete_arg
= karg
;
131 return (aggr_grp_delete(delete_arg
->ld_linkid
, cred
));
134 typedef struct aggr_ioc_info_state
{
136 uchar_t
*where
; /* in user buffer */
138 } aggr_ioc_info_state_t
;
141 aggr_ioc_info_new_grp(void *arg
, datalink_id_t linkid
, uint32_t key
,
142 uchar_t
*mac
, boolean_t mac_fixed
, boolean_t force
, uint32_t policy
,
143 uint32_t nports
, aggr_lacp_mode_t lacp_mode
, aggr_lacp_timer_t lacp_timer
)
145 aggr_ioc_info_state_t
*state
= arg
;
146 laioc_info_group_t grp
;
148 if (state
->bytes_left
< sizeof (grp
))
151 grp
.lg_linkid
= linkid
;
153 bcopy(mac
, grp
.lg_mac
, ETHERADDRL
);
154 grp
.lg_mac_fixed
= mac_fixed
;
155 grp
.lg_force
= force
;
156 grp
.lg_policy
= policy
;
157 grp
.lg_nports
= nports
;
158 grp
.lg_lacp_mode
= lacp_mode
;
159 grp
.lg_lacp_timer
= lacp_timer
;
161 if (ddi_copyout(&grp
, state
->where
, sizeof (grp
), state
->mode
) != 0)
164 state
->where
+= sizeof (grp
);
165 state
->bytes_left
-= sizeof (grp
);
171 aggr_ioc_info_new_port(void *arg
, datalink_id_t linkid
, uchar_t
*mac
,
172 aggr_port_state_t portstate
, aggr_lacp_state_t
*lacp_state
)
174 aggr_ioc_info_state_t
*state
= arg
;
175 laioc_info_port_t port
;
177 if (state
->bytes_left
< sizeof (port
))
180 port
.lp_linkid
= linkid
;
181 bcopy(mac
, port
.lp_mac
, ETHERADDRL
);
182 port
.lp_state
= portstate
;
183 port
.lp_lacp_state
= *lacp_state
;
185 if (ddi_copyout(&port
, state
->where
, sizeof (port
), state
->mode
) != 0)
188 state
->where
+= sizeof (port
);
189 state
->bytes_left
-= sizeof (port
);
196 aggr_ioc_info(void *karg
, intptr_t arg
, int mode
, cred_t
*cred
, int *rvalp
)
198 laioc_info_t
*info_argp
= karg
;
199 aggr_ioc_info_state_t state
;
201 state
.bytes_left
= info_argp
->li_bufsize
- sizeof (laioc_info_t
);
202 state
.where
= (uchar_t
*)arg
+ sizeof (laioc_info_t
);
205 return (aggr_grp_info(info_argp
->li_group_linkid
, &state
,
206 aggr_ioc_info_new_grp
, aggr_ioc_info_new_port
, cred
));
210 aggr_ioc_add_remove(laioc_add_rem_t
*add_rem_arg
, intptr_t arg
, int cmd
,
214 laioc_port_t
*ports
= NULL
;
218 nports
= add_rem_arg
->la_nports
;
219 if (nports
> AGGR_MAX_PORTS
)
222 ports_size
= nports
* sizeof (laioc_port_t
);
223 ports
= kmem_alloc(ports_size
, KM_SLEEP
);
224 if (ddi_copyin((uchar_t
*)arg
+ sizeof (*add_rem_arg
), ports
,
225 ports_size
, mode
) != 0) {
232 rc
= aggr_grp_add_ports(add_rem_arg
->la_linkid
, nports
,
233 add_rem_arg
->la_force
, ports
);
236 rc
= aggr_grp_rem_ports(add_rem_arg
->la_linkid
, nports
, ports
);
241 kmem_free(ports
, ports_size
);
247 aggr_ioc_add(void *karg
, intptr_t arg
, int mode
, cred_t
*cred
, int *rvalp
)
249 return (aggr_ioc_add_remove(karg
, arg
, LAIOC_ADD
, mode
));
254 aggr_ioc_remove(void *karg
, intptr_t arg
, int mode
, cred_t
*cred
, int *rvalp
)
256 return (aggr_ioc_add_remove(karg
, arg
, LAIOC_REMOVE
, mode
));
259 static dld_ioc_info_t aggr_ioc_list
[] = {
260 {LAIOC_CREATE
, DLDCOPYIN
, sizeof (laioc_create_t
), aggr_ioc_create
,
261 secpolicy_dl_config
},
262 {LAIOC_DELETE
, DLDCOPYIN
, sizeof (laioc_delete_t
), aggr_ioc_delete
,
263 secpolicy_dl_config
},
264 {LAIOC_INFO
, DLDCOPYINOUT
, sizeof (laioc_info_t
), aggr_ioc_info
, NULL
},
265 {LAIOC_ADD
, DLDCOPYIN
, sizeof (laioc_add_rem_t
), aggr_ioc_add
,
266 secpolicy_dl_config
},
267 {LAIOC_REMOVE
, DLDCOPYIN
, sizeof (laioc_add_rem_t
), aggr_ioc_remove
,
268 secpolicy_dl_config
},
269 {LAIOC_MODIFY
, DLDCOPYIN
, sizeof (laioc_modify_t
), aggr_ioc_modify
,
276 return (dld_ioc_register(AGGR_IOC
, aggr_ioc_list
,
277 DLDIOCCNT(aggr_ioc_list
)));
283 dld_ioc_unregister(AGGR_IOC
);