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 * Virtual Network Interface Card (VNIC)
31 #include <sys/modctl.h>
33 #include <sys/vnic_impl.h>
34 #include <sys/policy.h>
36 /* module description */
37 #define VNIC_LINKINFO "Virtual NIC"
39 /* device info ptr, only one for instance 0 */
40 static dev_info_t
*vnic_dip
= NULL
;
41 static int vnic_getinfo(dev_info_t
*, ddi_info_cmd_t
, void *, void **);
42 static int vnic_attach(dev_info_t
*, ddi_attach_cmd_t
);
43 static int vnic_detach(dev_info_t
*, ddi_detach_cmd_t
);
45 static int vnic_ioc_create(void *, intptr_t, int, cred_t
*, int *);
46 static int vnic_ioc_delete(void *, intptr_t, int, cred_t
*, int *);
47 static int vnic_ioc_info(void *, intptr_t, int, cred_t
*, int *);
48 static int vnic_ioc_modify(void *, intptr_t, int, cred_t
*, int *);
50 static dld_ioc_info_t vnic_ioc_list
[] = {
51 {VNIC_IOC_CREATE
, DLDCOPYINOUT
, sizeof (vnic_ioc_create_t
),
52 vnic_ioc_create
, secpolicy_dl_config
},
53 {VNIC_IOC_DELETE
, DLDCOPYIN
, sizeof (vnic_ioc_delete_t
),
54 vnic_ioc_delete
, secpolicy_dl_config
},
55 {VNIC_IOC_INFO
, DLDCOPYINOUT
, sizeof (vnic_ioc_info_t
),
57 {VNIC_IOC_MODIFY
, DLDCOPYIN
, sizeof (vnic_ioc_modify_t
),
58 vnic_ioc_modify
, secpolicy_dl_config
}
61 DDI_DEFINE_STREAM_OPS(vnic_dev_ops
, nulldev
, nulldev
, vnic_attach
, vnic_detach
,
62 nodev
, vnic_getinfo
, D_MP
, NULL
, ddi_quiesce_not_supported
);
64 static struct modldrv vnic_modldrv
= {
65 &mod_driverops
, /* Type of module. This one is a driver */
66 VNIC_LINKINFO
, /* short description */
67 &vnic_dev_ops
/* driver specific ops */
70 static struct modlinkage modlinkage
= {
71 MODREV_1
, &vnic_modldrv
, NULL
79 mac_init_ops(&vnic_dev_ops
, "vnic");
80 status
= mod_install(&modlinkage
);
81 if (status
!= DDI_SUCCESS
)
82 mac_fini_ops(&vnic_dev_ops
);
92 status
= mod_remove(&modlinkage
);
93 if (status
== DDI_SUCCESS
)
94 mac_fini_ops(&vnic_dev_ops
);
100 _info(struct modinfo
*modinfop
)
102 return (mod_info(&modlinkage
, modinfop
));
125 vnic_getinfo(dev_info_t
*dip
, ddi_info_cmd_t infocmd
, void *arg
,
129 case DDI_INFO_DEVT2DEVINFO
:
131 return (DDI_SUCCESS
);
132 case DDI_INFO_DEVT2INSTANCE
:
134 return (DDI_SUCCESS
);
136 return (DDI_FAILURE
);
140 vnic_attach(dev_info_t
*dip
, ddi_attach_cmd_t cmd
)
144 if (ddi_get_instance(dip
) != 0) {
145 /* we only allow instance 0 to attach */
146 return (DDI_FAILURE
);
148 if (dld_ioc_register(VNIC_IOC
, vnic_ioc_list
,
149 DLDIOCCNT(vnic_ioc_list
)) != 0)
150 return (DDI_FAILURE
);
154 return (DDI_SUCCESS
);
157 return (DDI_SUCCESS
);
160 return (DDI_FAILURE
);
166 vnic_detach(dev_info_t
*dip
, ddi_detach_cmd_t cmd
)
171 * Allow the VNIC instance to be detached only if there
172 * are not VNICs configured.
174 if (vnic_dev_count() > 0)
175 return (DDI_FAILURE
);
179 dld_ioc_unregister(VNIC_IOC
);
180 return (DDI_SUCCESS
);
183 return (DDI_SUCCESS
);
186 return (DDI_FAILURE
);
191 * Process a VNICIOC_CREATE request.
195 vnic_ioc_create(void *karg
, intptr_t arg
, int mode
, cred_t
*cred
, int *rvalp
)
197 vnic_ioc_create_t
*create_arg
= karg
;
198 int err
= 0, mac_len
= 0, mac_slot
;
199 uchar_t mac_addr
[MAXMACADDRLEN
];
200 uint_t mac_prefix_len
;
201 vnic_mac_addr_type_t mac_addr_type
;
202 vnic_ioc_diag_t diag
= VNIC_IOC_DIAG_NONE
;
203 boolean_t is_anchor
= create_arg
->vc_flags
& VNIC_IOC_CREATE_ANCHOR
;
206 mac_addr_type
= create_arg
->vc_mac_addr_type
;
211 switch (mac_addr_type
) {
212 case VNIC_MAC_ADDR_TYPE_FIXED
:
213 case VNIC_MAC_ADDR_TYPE_VRID
:
214 mac_len
= create_arg
->vc_mac_len
;
216 * Sanity check the MAC address length. vnic_dev_create()
217 * will perform additional checks to ensure that the
218 * address is a valid unicast address of the appropriate
221 if (mac_len
== 0 || mac_len
> MAXMACADDRLEN
) {
223 diag
= VNIC_IOC_DIAG_MACADDRLEN_INVALID
;
226 bcopy(create_arg
->vc_mac_addr
, mac_addr
, MAXMACADDRLEN
);
228 case VNIC_MAC_ADDR_TYPE_FACTORY
:
229 mac_slot
= create_arg
->vc_mac_slot
;
230 /* sanity check the specified slot number */
231 if (mac_slot
< 0 && mac_slot
!= -1) {
233 diag
= VNIC_IOC_DIAG_MACFACTORYSLOTINVALID
;
237 case VNIC_MAC_ADDR_TYPE_AUTO
:
240 case VNIC_MAC_ADDR_TYPE_RANDOM
:
241 mac_prefix_len
= create_arg
->vc_mac_prefix_len
;
242 if (mac_prefix_len
> MAXMACADDRLEN
) {
244 diag
= VNIC_IOC_DIAG_MACPREFIXLEN_INVALID
;
247 mac_len
= create_arg
->vc_mac_len
;
248 if (mac_len
> MAXMACADDRLEN
) {
250 diag
= VNIC_IOC_DIAG_MACADDRLEN_INVALID
;
253 bcopy(create_arg
->vc_mac_addr
, mac_addr
, MAXMACADDRLEN
);
255 case VNIC_MAC_ADDR_TYPE_PRIMARY
:
257 * We will get the primary address when we add this
267 err
= vnic_dev_create(create_arg
->vc_vnic_id
, create_arg
->vc_link_id
,
268 &mac_addr_type
, &mac_len
, mac_addr
, &mac_slot
, mac_prefix_len
,
269 create_arg
->vc_vid
, create_arg
->vc_vrid
, create_arg
->vc_af
,
270 &create_arg
->vc_resource_props
, create_arg
->vc_flags
, &diag
,
277 create_arg
->vc_mac_addr_type
= mac_addr_type
;
282 switch (mac_addr_type
) {
283 case VNIC_MAC_ADDR_TYPE_FACTORY
:
284 create_arg
->vc_mac_slot
= mac_slot
;
286 case VNIC_MAC_ADDR_TYPE_RANDOM
:
287 bcopy(mac_addr
, create_arg
->vc_mac_addr
, MAXMACADDRLEN
);
288 create_arg
->vc_mac_len
= mac_len
;
293 create_arg
->vc_diag
= diag
;
294 create_arg
->vc_status
= err
;
300 vnic_ioc_modify(void *karg
, intptr_t arg
, int mode
, cred_t
*cred
, int *rvalp
)
302 vnic_ioc_modify_t
*modify_arg
= karg
;
304 return (vnic_dev_modify(modify_arg
->vm_vnic_id
,
305 modify_arg
->vm_modify_mask
, modify_arg
->vm_mac_addr_type
,
306 modify_arg
->vm_mac_len
, modify_arg
->vm_mac_addr
,
307 modify_arg
->vm_mac_slot
, &modify_arg
->vm_resource_props
));
312 vnic_ioc_delete(void *karg
, intptr_t arg
, int mode
, cred_t
*cred
, int *rvalp
)
314 vnic_ioc_delete_t
*delete_arg
= karg
;
316 return (vnic_dev_delete(delete_arg
->vd_vnic_id
, 0, cred
));
321 vnic_ioc_info(void *karg
, intptr_t arg
, int mode
, cred_t
*cred
, int *rvalp
)
323 vnic_ioc_info_t
*info_arg
= karg
;
325 return (vnic_info(&info_arg
->vi_info
, cred
));