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 (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
25 #include <sys/types.h>
29 #include <sys/dls_mgmt.h>
31 #include <net/simnet.h>
35 #include <libdladm_impl.h>
36 #include <libdllink.h>
37 #include <libdlaggr.h>
40 static dladm_status_t
dladm_simnet_persist_conf(dladm_handle_t
, const char *,
41 dladm_simnet_attr_t
*);
43 /* New simnet instance creation */
45 i_dladm_create_simnet(dladm_handle_t handle
, dladm_simnet_attr_t
*attrp
)
48 dladm_status_t status
= DLADM_STATUS_OK
;
49 simnet_ioc_create_t ioc
;
51 bzero(&ioc
, sizeof (ioc
));
52 ioc
.sic_link_id
= attrp
->sna_link_id
;
53 ioc
.sic_type
= attrp
->sna_type
;
54 if (attrp
->sna_mac_len
> 0 && attrp
->sna_mac_len
<= MAXMACADDRLEN
) {
55 ioc
.sic_mac_len
= attrp
->sna_mac_len
;
56 bcopy(attrp
->sna_mac_addr
, ioc
.sic_mac_addr
, ioc
.sic_mac_len
);
59 rc
= ioctl(dladm_dld_fd(handle
), SIMNET_IOC_CREATE
, &ioc
);
61 status
= dladm_errno2status(errno
);
63 if (status
!= DLADM_STATUS_OK
)
66 bcopy(ioc
.sic_mac_addr
, attrp
->sna_mac_addr
, MAXMACADDRLEN
);
67 attrp
->sna_mac_len
= ioc
.sic_mac_len
;
71 /* Modify existing simnet instance */
73 i_dladm_modify_simnet(dladm_handle_t handle
, dladm_simnet_attr_t
*attrp
)
76 dladm_status_t status
= DLADM_STATUS_OK
;
77 simnet_ioc_modify_t ioc
;
79 bzero(&ioc
, sizeof (ioc
));
80 ioc
.sim_link_id
= attrp
->sna_link_id
;
81 ioc
.sim_peer_link_id
= attrp
->sna_peer_link_id
;
83 rc
= ioctl(dladm_dld_fd(handle
), SIMNET_IOC_MODIFY
, &ioc
);
85 status
= dladm_errno2status(errno
);
90 /* Delete simnet instance */
92 i_dladm_delete_simnet(dladm_handle_t handle
, dladm_simnet_attr_t
*attrp
)
95 dladm_status_t status
= DLADM_STATUS_OK
;
96 simnet_ioc_delete_t ioc
;
98 bzero(&ioc
, sizeof (ioc
));
99 ioc
.sid_link_id
= attrp
->sna_link_id
;
101 rc
= ioctl(dladm_dld_fd(handle
), SIMNET_IOC_DELETE
, &ioc
);
103 status
= dladm_errno2status(errno
);
108 /* Retrieve simnet instance information */
109 static dladm_status_t
110 i_dladm_get_simnet_info(dladm_handle_t handle
, dladm_simnet_attr_t
*attrp
)
113 dladm_status_t status
= DLADM_STATUS_OK
;
114 simnet_ioc_info_t ioc
;
116 bzero(&ioc
, sizeof (ioc
));
117 ioc
.sii_link_id
= attrp
->sna_link_id
;
119 rc
= ioctl(dladm_dld_fd(handle
), SIMNET_IOC_INFO
, &ioc
);
121 status
= dladm_errno2status(errno
);
125 bcopy(ioc
.sii_mac_addr
, attrp
->sna_mac_addr
, MAXMACADDRLEN
);
126 attrp
->sna_mac_len
= ioc
.sii_mac_len
;
127 attrp
->sna_peer_link_id
= ioc
.sii_peer_link_id
;
128 attrp
->sna_type
= ioc
.sii_type
;
132 /* Retrieve simnet configuratin */
133 static dladm_status_t
134 i_dladm_get_simnet_info_persist(dladm_handle_t handle
,
135 dladm_simnet_attr_t
*attrp
)
138 dladm_status_t status
;
139 char macstr
[ETHERADDRL
* 3];
140 char simnetpeer
[MAXLINKNAMELEN
];
144 if ((status
= dladm_getsnap_conf(handle
, attrp
->sna_link_id
,
145 &conf
)) != DLADM_STATUS_OK
)
148 status
= dladm_get_conf_field(handle
, conf
, FSIMNETTYPE
, &u64
,
150 if (status
!= DLADM_STATUS_OK
)
152 attrp
->sna_type
= (uint_t
)u64
;
154 status
= dladm_get_conf_field(handle
, conf
, FMADDRLEN
, &u64
,
156 if (status
!= DLADM_STATUS_OK
)
158 attrp
->sna_mac_len
= (uint_t
)u64
;
160 status
= dladm_get_conf_field(handle
, conf
, FMACADDR
, macstr
,
162 if (status
!= DLADM_STATUS_OK
)
164 (void) dladm_aggr_str2macaddr(macstr
, &mac_fixed
, attrp
->sna_mac_addr
);
166 /* Peer field is optional and only set when peer is attached */
167 if (dladm_get_conf_field(handle
, conf
, FSIMNETPEER
, simnetpeer
,
168 sizeof (simnetpeer
)) == DLADM_STATUS_OK
) {
169 status
= dladm_name2info(handle
, simnetpeer
,
170 &attrp
->sna_peer_link_id
, NULL
, NULL
, NULL
);
172 attrp
->sna_peer_link_id
= DATALINK_INVALID_LINKID
;
175 dladm_destroy_conf(handle
, conf
);
180 dladm_simnet_create(dladm_handle_t handle
, const char *simnetname
,
181 uint_t media
, uint32_t flags
)
183 datalink_id_t simnet_id
;
184 dladm_status_t status
;
185 dladm_simnet_attr_t attr
;
187 if (!(flags
& DLADM_OPT_ACTIVE
))
188 return (DLADM_STATUS_NOTSUP
);
190 flags
&= (DLADM_OPT_ACTIVE
| DLADM_OPT_PERSIST
);
191 if ((status
= dladm_create_datalink_id(handle
, simnetname
,
192 DATALINK_CLASS_SIMNET
, media
, flags
,
193 &simnet_id
)) != DLADM_STATUS_OK
)
196 bzero(&attr
, sizeof (attr
));
197 attr
.sna_link_id
= simnet_id
;
198 attr
.sna_type
= media
;
199 status
= i_dladm_create_simnet(handle
, &attr
);
200 if (status
!= DLADM_STATUS_OK
)
203 if (!(flags
& DLADM_OPT_PERSIST
))
206 status
= dladm_simnet_persist_conf(handle
, simnetname
, &attr
);
207 if (status
!= DLADM_STATUS_OK
) {
208 (void) i_dladm_delete_simnet(handle
, &attr
);
212 (void) dladm_set_linkprop(handle
, simnet_id
, NULL
, NULL
, 0, flags
);
215 if (status
!= DLADM_STATUS_OK
) {
216 (void) dladm_destroy_datalink_id(handle
, simnet_id
, flags
);
221 /* Update existing simnet configuration */
222 static dladm_status_t
223 i_dladm_simnet_update_conf(dladm_handle_t handle
, datalink_id_t simnet_id
,
224 datalink_id_t peer_simnet_id
)
226 dladm_status_t status
;
228 char simnetpeer
[MAXLINKNAMELEN
];
230 status
= dladm_open_conf(handle
, simnet_id
, &conf
);
231 if (status
!= DLADM_STATUS_OK
)
234 /* First clear previous peer if any in configuration */
235 (void) dladm_unset_conf_field(handle
, conf
, FSIMNETPEER
);
236 if (peer_simnet_id
!= DATALINK_INVALID_LINKID
) {
237 if ((status
= dladm_datalink_id2info(handle
,
238 peer_simnet_id
, NULL
, NULL
, NULL
, simnetpeer
,
239 sizeof (simnetpeer
))) == DLADM_STATUS_OK
) {
240 status
= dladm_set_conf_field(handle
, conf
,
241 FSIMNETPEER
, DLADM_TYPE_STR
, simnetpeer
);
243 if (status
!= DLADM_STATUS_OK
)
247 status
= dladm_write_conf(handle
, conf
);
249 dladm_destroy_conf(handle
, conf
);
253 /* Modify attached simnet peer */
255 dladm_simnet_modify(dladm_handle_t handle
, datalink_id_t simnet_id
,
256 datalink_id_t peer_simnet_id
, uint32_t flags
)
258 dladm_simnet_attr_t attr
;
259 dladm_simnet_attr_t prevattr
;
260 dladm_status_t status
;
261 datalink_class_t
class;
263 uint32_t peerlinkflags
;
265 if (!(flags
& DLADM_OPT_ACTIVE
))
266 return (DLADM_STATUS_NOTSUP
);
268 if ((dladm_datalink_id2info(handle
, simnet_id
, &linkflags
, &class,
269 NULL
, NULL
, 0) != DLADM_STATUS_OK
))
270 return (DLADM_STATUS_BADARG
);
271 if (class != DATALINK_CLASS_SIMNET
)
272 return (DLADM_STATUS_BADARG
);
274 if (peer_simnet_id
!= DATALINK_INVALID_LINKID
) {
275 if (dladm_datalink_id2info(handle
, peer_simnet_id
,
276 &peerlinkflags
, &class, NULL
, NULL
, 0) != DLADM_STATUS_OK
)
277 return (DLADM_STATUS_BADARG
);
278 if (class != DATALINK_CLASS_SIMNET
)
279 return (DLADM_STATUS_BADARG
);
280 /* Check to ensure the peer link has identical flags */
281 if (peerlinkflags
!= linkflags
)
282 return (DLADM_STATUS_BADARG
);
285 /* Retrieve previous attrs before modification */
286 bzero(&prevattr
, sizeof (prevattr
));
287 if ((status
= dladm_simnet_info(handle
, simnet_id
, &prevattr
,
288 flags
)) != DLADM_STATUS_OK
)
291 bzero(&attr
, sizeof (attr
));
292 attr
.sna_link_id
= simnet_id
;
293 attr
.sna_peer_link_id
= peer_simnet_id
;
294 status
= i_dladm_modify_simnet(handle
, &attr
);
295 if ((status
!= DLADM_STATUS_OK
) || !(flags
& DLADM_OPT_PERSIST
))
298 /* First we clear link's existing peer field in config */
299 status
= i_dladm_simnet_update_conf(handle
, simnet_id
,
300 DATALINK_INVALID_LINKID
);
301 if (status
!= DLADM_STATUS_OK
)
304 /* Clear the previous peer link's existing peer field in config */
305 if (prevattr
.sna_peer_link_id
!= DATALINK_INVALID_LINKID
) {
306 status
= i_dladm_simnet_update_conf(handle
,
307 prevattr
.sna_peer_link_id
, DATALINK_INVALID_LINKID
);
308 if (status
!= DLADM_STATUS_OK
)
312 /* Update the configuration in both simnets with any new peer link */
313 if (peer_simnet_id
!= DATALINK_INVALID_LINKID
) {
314 status
= i_dladm_simnet_update_conf(handle
, simnet_id
,
316 if (status
== DLADM_STATUS_OK
)
317 status
= i_dladm_simnet_update_conf(handle
,
318 peer_simnet_id
, simnet_id
);
325 dladm_simnet_delete(dladm_handle_t handle
, datalink_id_t simnet_id
,
328 dladm_simnet_attr_t attr
;
329 dladm_simnet_attr_t prevattr
;
330 dladm_status_t status
;
331 datalink_class_t
class;
333 if ((dladm_datalink_id2info(handle
, simnet_id
, NULL
, &class,
334 NULL
, NULL
, 0) != DLADM_STATUS_OK
))
335 return (DLADM_STATUS_BADARG
);
337 if (class != DATALINK_CLASS_SIMNET
)
338 return (DLADM_STATUS_BADARG
);
340 /* Check current simnet attributes before deletion */
341 flags
&= (DLADM_OPT_ACTIVE
| DLADM_OPT_PERSIST
);
342 bzero(&prevattr
, sizeof (prevattr
));
343 if ((status
= dladm_simnet_info(handle
, simnet_id
, &prevattr
,
344 flags
)) != DLADM_STATUS_OK
)
347 bzero(&attr
, sizeof (attr
));
348 attr
.sna_link_id
= simnet_id
;
349 if (flags
& DLADM_OPT_ACTIVE
) {
350 status
= i_dladm_delete_simnet(handle
, &attr
);
351 if (status
== DLADM_STATUS_OK
) {
352 (void) dladm_set_linkprop(handle
, simnet_id
, NULL
,
353 NULL
, 0, DLADM_OPT_ACTIVE
);
354 (void) dladm_destroy_datalink_id(handle
, simnet_id
,
356 } else if (status
!= DLADM_STATUS_NOTFOUND
) {
361 if (flags
& DLADM_OPT_PERSIST
) {
362 (void) dladm_remove_conf(handle
, simnet_id
);
363 (void) dladm_destroy_datalink_id(handle
, simnet_id
,
366 /* Update any attached peer configuration */
367 if (prevattr
.sna_peer_link_id
!= DATALINK_INVALID_LINKID
)
368 status
= i_dladm_simnet_update_conf(handle
,
369 prevattr
.sna_peer_link_id
, DATALINK_INVALID_LINKID
);
374 /* Retrieve simnet information either active or from configuration */
376 dladm_simnet_info(dladm_handle_t handle
, datalink_id_t simnet_id
,
377 dladm_simnet_attr_t
*attrp
, uint32_t flags
)
379 datalink_class_t
class;
380 dladm_status_t status
;
382 if ((dladm_datalink_id2info(handle
, simnet_id
, NULL
, &class,
383 NULL
, NULL
, 0) != DLADM_STATUS_OK
))
384 return (DLADM_STATUS_BADARG
);
386 if (class != DATALINK_CLASS_SIMNET
)
387 return (DLADM_STATUS_BADARG
);
389 bzero(attrp
, sizeof (attrp
));
390 attrp
->sna_link_id
= simnet_id
;
392 if (flags
& DLADM_OPT_ACTIVE
) {
393 status
= i_dladm_get_simnet_info(handle
, attrp
);
395 * If no active simnet found then return any simnet
396 * from stored config if requested.
398 if (status
== DLADM_STATUS_NOTFOUND
&&
399 (flags
& DLADM_OPT_PERSIST
))
400 return (i_dladm_get_simnet_info_persist(handle
, attrp
));
402 } else if (flags
& DLADM_OPT_PERSIST
) {
403 return (i_dladm_get_simnet_info_persist(handle
, attrp
));
405 return (DLADM_STATUS_BADARG
);
409 /* Bring up simnet from stored configuration */
411 i_dladm_simnet_up(dladm_handle_t handle
, datalink_id_t simnet_id
, void *arg
)
413 dladm_status_t
*statusp
= arg
;
414 dladm_status_t status
;
415 dladm_simnet_attr_t attr
;
416 dladm_simnet_attr_t peer_attr
;
418 bzero(&attr
, sizeof (attr
));
419 attr
.sna_link_id
= simnet_id
;
420 status
= dladm_simnet_info(handle
, simnet_id
, &attr
,
422 if (status
!= DLADM_STATUS_OK
)
425 status
= i_dladm_create_simnet(handle
, &attr
);
426 if (status
!= DLADM_STATUS_OK
)
430 * When bringing up check if the peer link is available, if it
431 * is then modify the simnet and attach the peer link.
433 if ((attr
.sna_peer_link_id
!= DATALINK_INVALID_LINKID
) &&
434 (dladm_simnet_info(handle
, attr
.sna_peer_link_id
, &peer_attr
,
435 DLADM_OPT_ACTIVE
) == DLADM_STATUS_OK
)) {
436 status
= i_dladm_modify_simnet(handle
, &attr
);
437 if (status
!= DLADM_STATUS_OK
)
441 if ((status
= dladm_up_datalink_id(handle
, simnet_id
)) !=
443 (void) dladm_simnet_delete(handle
, simnet_id
,
449 return (DLADM_WALK_CONTINUE
);
452 /* Bring up simnet instance(s) from configuration */
455 dladm_simnet_up(dladm_handle_t handle
, datalink_id_t simnet_id
,
458 dladm_status_t status
;
460 if (simnet_id
== DATALINK_ALL_LINKID
) {
461 (void) dladm_walk_datalink_id(i_dladm_simnet_up
, handle
,
462 &status
, DATALINK_CLASS_SIMNET
, DATALINK_ANY_MEDIATYPE
,
464 return (DLADM_STATUS_OK
);
466 (void) i_dladm_simnet_up(handle
, simnet_id
, &status
);
471 /* Store simnet configuration */
472 static dladm_status_t
473 dladm_simnet_persist_conf(dladm_handle_t handle
, const char *name
,
474 dladm_simnet_attr_t
*attrp
)
477 dladm_status_t status
;
478 char mstr
[ETHERADDRL
* 3];
481 if ((status
= dladm_create_conf(handle
, name
, attrp
->sna_link_id
,
482 DATALINK_CLASS_SIMNET
, attrp
->sna_type
, &conf
)) != DLADM_STATUS_OK
)
485 status
= dladm_set_conf_field(handle
, conf
, FMACADDR
,
486 DLADM_TYPE_STR
, dladm_aggr_macaddr2str(attrp
->sna_mac_addr
, mstr
));
487 if (status
!= DLADM_STATUS_OK
)
490 u64
= attrp
->sna_type
;
491 status
= dladm_set_conf_field(handle
, conf
, FSIMNETTYPE
,
492 DLADM_TYPE_UINT64
, &u64
);
493 if (status
!= DLADM_STATUS_OK
)
496 u64
= attrp
->sna_mac_len
;
497 status
= dladm_set_conf_field(handle
, conf
, FMADDRLEN
,
498 DLADM_TYPE_UINT64
, &u64
);
499 if (status
!= DLADM_STATUS_OK
)
502 status
= dladm_write_conf(handle
, conf
);
504 dladm_destroy_conf(handle
, conf
);