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 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 #include <sys/types.h>
37 #include <net/if_types.h>
38 #include <net/if_dl.h>
39 #include <libdladm_impl.h>
40 #include <libdllink.h>
41 #include <libdlvnic.h>
44 * VNIC administration library.
47 /* Limits on buffer size for VNIC_IOC_INFO request */
48 #define MIN_INFO_SIZE (4*1024)
49 #define MAX_INFO_SIZE (128*1024)
51 /* configuration database entry */
52 typedef struct dladm_vnic_attr_db
{
53 datalink_id_t vt_vnic_id
;
54 datalink_id_t vt_link_id
;
55 vnic_mac_addr_type_t vt_mac_addr_type
;
57 uchar_t vt_mac_addr
[MAXMACADDRLEN
];
58 } dladm_vnic_attr_db_t
;
60 typedef struct dladm_vnic_modify_attr
{
61 vnic_mac_addr_type_t vm_mac_addr_type
;
63 uchar_t vm_mac_addr
[MAXMACADDRLEN
];
64 } dladm_vnic_modify_attr_t
;
67 * Send a create command to the VNIC driver.
70 i_dladm_vnic_create_sys(int fd
, dladm_vnic_attr_db_t
*attr
)
72 vnic_ioc_create_t ioc
;
74 ioc
.vc_vnic_id
= attr
->vt_vnic_id
;
75 ioc
.vc_link_id
= attr
->vt_link_id
;
76 ioc
.vc_mac_addr_type
= attr
->vt_mac_addr_type
;
77 ioc
.vc_mac_len
= attr
->vt_mac_len
;
78 bcopy(attr
->vt_mac_addr
, ioc
.vc_mac_addr
, attr
->vt_mac_len
);
80 if (ioctl(fd
, VNIC_IOC_CREATE
, &ioc
) < 0)
81 return (dladm_errno2status(errno
));
83 return (DLADM_STATUS_OK
);
87 * Send a modify command to the VNIC driver.
90 i_dladm_vnic_modify_sys(datalink_id_t vnic_id
, uint32_t modify_mask
,
91 dladm_vnic_modify_attr_t
*attr
)
93 dladm_status_t status
= DLADM_STATUS_OK
;
95 vnic_ioc_modify_t ioc
;
97 ioc
.vm_vnic_id
= vnic_id
;
99 ioc
.vm_modify_mask
= 0;
100 if (modify_mask
& DLADM_VNIC_MODIFY_ADDR
)
101 ioc
.vm_modify_mask
|= VNIC_IOC_MODIFY_ADDR
;
103 ioc
.vm_mac_addr_type
= attr
->vm_mac_addr_type
;
104 ioc
.vm_mac_len
= attr
->vm_mac_len
;
105 bcopy(attr
->vm_mac_addr
, ioc
.vm_mac_addr
, MAXMACADDRLEN
);
107 if ((fd
= open(DLD_CONTROL_DEV
, O_RDWR
)) < 0)
108 return (dladm_errno2status(errno
));
110 if (ioctl(fd
, VNIC_IOC_MODIFY
, &ioc
) < 0)
111 status
= dladm_errno2status(errno
);
118 * Get the configuration information of the given VNIC.
121 dladm_vnic_info(datalink_id_t vnic_id
, dladm_vnic_attr_sys_t
*attrp
,
124 vnic_ioc_info_t
*ioc
;
125 vnic_ioc_info_vnic_t
*vnic
;
127 dladm_status_t status
= DLADM_STATUS_OK
;
129 /* for now, only temporary creations are supported */
130 if (flags
& DLADM_OPT_PERSIST
)
131 return (dladm_errno2status(ENOTSUP
));
133 if ((fd
= open(DLD_CONTROL_DEV
, O_RDWR
)) == -1)
134 return (dladm_errno2status(errno
));
136 bufsize
= sizeof (vnic_ioc_info_t
) + sizeof (vnic_ioc_info_vnic_t
);
137 ioc
= (vnic_ioc_info_t
*)calloc(1, bufsize
);
140 return (dladm_errno2status(ENOMEM
));
143 ioc
->vi_vnic_id
= vnic_id
;
144 ioc
->vi_size
= bufsize
- sizeof (vnic_ioc_info_t
);
145 if (ioctl(fd
, VNIC_IOC_INFO
, ioc
) != 0) {
146 status
= dladm_errno2status(errno
);
150 vnic
= (vnic_ioc_info_vnic_t
*)(ioc
+ 1);
152 attrp
->va_vnic_id
= vnic
->vn_vnic_id
;
153 attrp
->va_link_id
= vnic
->vn_link_id
;
154 attrp
->va_mac_addr_type
= vnic
->vn_mac_addr_type
;
155 bcopy(vnic
->vn_mac_addr
, attrp
->va_mac_addr
, ETHERADDRL
);
156 attrp
->va_mac_len
= vnic
->vn_mac_len
;
165 * Remove a VNIC from the kernel.
167 static dladm_status_t
168 i_dladm_vnic_delete_sys(int fd
, dladm_vnic_attr_sys_t
*attr
)
170 vnic_ioc_delete_t ioc
;
172 ioc
.vd_vnic_id
= attr
->va_vnic_id
;
174 if (ioctl(fd
, VNIC_IOC_DELETE
, &ioc
) < 0)
175 return (dladm_errno2status(errno
));
177 return (DLADM_STATUS_OK
);
181 * Convert between MAC address types and their string representations.
184 typedef struct dladm_vnic_addr_type_s
{
186 vnic_mac_addr_type_t va_type
;
187 } dladm_vnic_addr_type_t
;
189 static dladm_vnic_addr_type_t addr_types
[] = {
190 {"fixed", VNIC_MAC_ADDR_TYPE_FIXED
},
193 #define NADDR_TYPES (sizeof (addr_types) / sizeof (dladm_vnic_addr_type_t))
196 * Return DLADM_STATUS_OK if a matching type was found,
197 * DLADM_STATUS_BADARG otherwise
200 dladm_vnic_str2macaddrtype(const char *str
, vnic_mac_addr_type_t
*val
)
203 dladm_vnic_addr_type_t
*type
;
205 for (i
= 0; i
< NADDR_TYPES
; i
++) {
206 type
= &addr_types
[i
];
207 if (strncmp(str
, type
->va_str
, strlen(type
->va_str
)) == 0) {
208 *val
= type
->va_type
;
209 return (DLADM_STATUS_OK
);
213 return (DLADM_STATUS_BADARG
);
217 * Create a new VNIC. Update the configuration file and bring it up.
220 dladm_vnic_create(const char *vnic
, datalink_id_t linkid
,
221 vnic_mac_addr_type_t mac_addr_type
, uchar_t
*mac_addr
, int mac_len
,
222 datalink_id_t
*vnic_id_out
, uint32_t flags
)
224 dladm_vnic_attr_db_t attr
;
226 datalink_id_t vnic_id
;
227 datalink_class_t
class;
229 char *name
= (char *)vnic
;
230 dladm_status_t status
;
233 * Sanity test arguments.
235 if (flags
& DLADM_OPT_PERSIST
)
236 return (dladm_errno2status(ENOTSUP
));
238 if (mac_len
> MAXMACADDRLEN
)
239 return (DLADM_STATUS_INVALIDMACADDRLEN
);
241 for (i
= 0; i
< NADDR_TYPES
; i
++) {
242 if (mac_addr_type
== addr_types
[i
].va_type
)
245 if (i
== NADDR_TYPES
)
246 return (DLADM_STATUS_INVALIDMACADDRTYPE
);
248 if ((status
= dladm_datalink_id2info(linkid
, NULL
, &class, &media
,
249 NULL
, 0)) != DLADM_STATUS_OK
) {
253 if (class == DATALINK_CLASS_VNIC
)
254 return (DLADM_STATUS_BADARG
);
257 flags
|= DLADM_OPT_PREFIX
;
261 if ((status
= dladm_create_datalink_id(name
, DATALINK_CLASS_VNIC
,
262 media
, flags
, &vnic_id
)) != DLADM_STATUS_OK
) {
266 bzero(&attr
, sizeof (attr
));
267 attr
.vt_vnic_id
= vnic_id
;
268 attr
.vt_link_id
= linkid
;
269 attr
.vt_mac_addr_type
= mac_addr_type
;
270 attr
.vt_mac_len
= mac_len
;
271 bcopy(mac_addr
, attr
.vt_mac_addr
, mac_len
);
273 if ((fd
= open(DLD_CONTROL_DEV
, O_RDWR
)) < 0) {
274 status
= dladm_errno2status(errno
);
278 status
= i_dladm_vnic_create_sys(fd
, &attr
);
282 if (status
!= DLADM_STATUS_OK
) {
283 (void) dladm_destroy_datalink_id(vnic_id
,
284 flags
& ~DLADM_OPT_PREFIX
);
286 *vnic_id_out
= vnic_id
;
293 * Modify the properties of a VNIC.
296 dladm_vnic_modify(datalink_id_t vnic_id
, uint32_t modify_mask
,
297 vnic_mac_addr_type_t mac_addr_type
, uint_t mac_len
, uchar_t
*mac_addr
,
300 dladm_vnic_modify_attr_t new_attr
;
302 /* for now, only temporary creations are supported */
303 if (flags
& DLADM_OPT_PERSIST
)
304 return (dladm_errno2status(ENOTSUP
));
306 bzero(&new_attr
, sizeof (new_attr
));
308 if (modify_mask
& DLADM_VNIC_MODIFY_ADDR
) {
309 new_attr
.vm_mac_addr_type
= mac_addr_type
;
310 new_attr
.vm_mac_len
= mac_len
;
311 bcopy(mac_addr
, new_attr
.vm_mac_addr
, MAXMACADDRLEN
);
314 /* update the properties of the existing VNIC */
315 return (i_dladm_vnic_modify_sys(vnic_id
, modify_mask
, &new_attr
));
322 dladm_vnic_delete(datalink_id_t vnic_id
, uint32_t flags
)
324 dladm_status_t status
;
325 dladm_vnic_attr_sys_t sys_attr
;
328 /* for now, only temporary deletes are supported */
329 if (flags
& DLADM_OPT_PERSIST
)
330 return (dladm_errno2status(ENOTSUP
));
332 if ((fd
= open(DLD_CONTROL_DEV
, O_RDWR
)) < 0)
333 return (dladm_errno2status(errno
));
335 sys_attr
.va_vnic_id
= vnic_id
;
336 status
= i_dladm_vnic_delete_sys(fd
, &sys_attr
);
339 if (status
!= DLADM_STATUS_OK
)
342 (void) dladm_destroy_datalink_id(vnic_id
, flags
);