1*9815SRishi.Srivatsavai@Sun.COM /*
2*9815SRishi.Srivatsavai@Sun.COM  * CDDL HEADER START
3*9815SRishi.Srivatsavai@Sun.COM  *
4*9815SRishi.Srivatsavai@Sun.COM  * The contents of this file are subject to the terms of the
5*9815SRishi.Srivatsavai@Sun.COM  * Common Development and Distribution License (the "License").
6*9815SRishi.Srivatsavai@Sun.COM  * You may not use this file except in compliance with the License.
7*9815SRishi.Srivatsavai@Sun.COM  *
8*9815SRishi.Srivatsavai@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*9815SRishi.Srivatsavai@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*9815SRishi.Srivatsavai@Sun.COM  * See the License for the specific language governing permissions
11*9815SRishi.Srivatsavai@Sun.COM  * and limitations under the License.
12*9815SRishi.Srivatsavai@Sun.COM  *
13*9815SRishi.Srivatsavai@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*9815SRishi.Srivatsavai@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*9815SRishi.Srivatsavai@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*9815SRishi.Srivatsavai@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*9815SRishi.Srivatsavai@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*9815SRishi.Srivatsavai@Sun.COM  *
19*9815SRishi.Srivatsavai@Sun.COM  * CDDL HEADER END
20*9815SRishi.Srivatsavai@Sun.COM  */
21*9815SRishi.Srivatsavai@Sun.COM /*
22*9815SRishi.Srivatsavai@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23*9815SRishi.Srivatsavai@Sun.COM  * Use is subject to license terms.
24*9815SRishi.Srivatsavai@Sun.COM  */
25*9815SRishi.Srivatsavai@Sun.COM 
26*9815SRishi.Srivatsavai@Sun.COM #include <sys/types.h>
27*9815SRishi.Srivatsavai@Sun.COM #include <string.h>
28*9815SRishi.Srivatsavai@Sun.COM #include <strings.h>
29*9815SRishi.Srivatsavai@Sun.COM #include <sys/mac.h>
30*9815SRishi.Srivatsavai@Sun.COM #include <sys/dls_mgmt.h>
31*9815SRishi.Srivatsavai@Sun.COM #include <sys/dlpi.h>
32*9815SRishi.Srivatsavai@Sun.COM #include <net/simnet.h>
33*9815SRishi.Srivatsavai@Sun.COM #include <errno.h>
34*9815SRishi.Srivatsavai@Sun.COM #include <unistd.h>
35*9815SRishi.Srivatsavai@Sun.COM 
36*9815SRishi.Srivatsavai@Sun.COM #include <libdladm_impl.h>
37*9815SRishi.Srivatsavai@Sun.COM #include <libdllink.h>
38*9815SRishi.Srivatsavai@Sun.COM #include <libdlaggr.h>
39*9815SRishi.Srivatsavai@Sun.COM #include <libdlsim.h>
40*9815SRishi.Srivatsavai@Sun.COM 
41*9815SRishi.Srivatsavai@Sun.COM static dladm_status_t dladm_simnet_persist_conf(dladm_handle_t, const char *,
42*9815SRishi.Srivatsavai@Sun.COM     dladm_simnet_attr_t *);
43*9815SRishi.Srivatsavai@Sun.COM 
44*9815SRishi.Srivatsavai@Sun.COM /* New simnet instance creation */
45*9815SRishi.Srivatsavai@Sun.COM static dladm_status_t
46*9815SRishi.Srivatsavai@Sun.COM i_dladm_create_simnet(dladm_handle_t handle, dladm_simnet_attr_t *attrp)
47*9815SRishi.Srivatsavai@Sun.COM {
48*9815SRishi.Srivatsavai@Sun.COM 	int rc;
49*9815SRishi.Srivatsavai@Sun.COM 	dladm_status_t status = DLADM_STATUS_OK;
50*9815SRishi.Srivatsavai@Sun.COM 	simnet_ioc_create_t ioc;
51*9815SRishi.Srivatsavai@Sun.COM 
52*9815SRishi.Srivatsavai@Sun.COM 	bzero(&ioc, sizeof (ioc));
53*9815SRishi.Srivatsavai@Sun.COM 	ioc.sic_link_id = attrp->sna_link_id;
54*9815SRishi.Srivatsavai@Sun.COM 	ioc.sic_type = attrp->sna_type;
55*9815SRishi.Srivatsavai@Sun.COM 	if (attrp->sna_mac_len > 0 && attrp->sna_mac_len <= MAXMACADDRLEN) {
56*9815SRishi.Srivatsavai@Sun.COM 		ioc.sic_mac_len = attrp->sna_mac_len;
57*9815SRishi.Srivatsavai@Sun.COM 		bcopy(attrp->sna_mac_addr, ioc.sic_mac_addr, ioc.sic_mac_len);
58*9815SRishi.Srivatsavai@Sun.COM 	}
59*9815SRishi.Srivatsavai@Sun.COM 
60*9815SRishi.Srivatsavai@Sun.COM 	rc = ioctl(dladm_dld_fd(handle), SIMNET_IOC_CREATE, &ioc);
61*9815SRishi.Srivatsavai@Sun.COM 	if (rc < 0)
62*9815SRishi.Srivatsavai@Sun.COM 		status = dladm_errno2status(errno);
63*9815SRishi.Srivatsavai@Sun.COM 
64*9815SRishi.Srivatsavai@Sun.COM 	if (status != DLADM_STATUS_OK)
65*9815SRishi.Srivatsavai@Sun.COM 		return (status);
66*9815SRishi.Srivatsavai@Sun.COM 
67*9815SRishi.Srivatsavai@Sun.COM 	bcopy(ioc.sic_mac_addr, attrp->sna_mac_addr, MAXMACADDRLEN);
68*9815SRishi.Srivatsavai@Sun.COM 	attrp->sna_mac_len = ioc.sic_mac_len;
69*9815SRishi.Srivatsavai@Sun.COM 	return (status);
70*9815SRishi.Srivatsavai@Sun.COM }
71*9815SRishi.Srivatsavai@Sun.COM 
72*9815SRishi.Srivatsavai@Sun.COM /* Modify existing simnet instance */
73*9815SRishi.Srivatsavai@Sun.COM static dladm_status_t
74*9815SRishi.Srivatsavai@Sun.COM i_dladm_modify_simnet(dladm_handle_t handle, dladm_simnet_attr_t *attrp)
75*9815SRishi.Srivatsavai@Sun.COM {
76*9815SRishi.Srivatsavai@Sun.COM 	int rc;
77*9815SRishi.Srivatsavai@Sun.COM 	dladm_status_t status = DLADM_STATUS_OK;
78*9815SRishi.Srivatsavai@Sun.COM 	simnet_ioc_modify_t ioc;
79*9815SRishi.Srivatsavai@Sun.COM 
80*9815SRishi.Srivatsavai@Sun.COM 	bzero(&ioc, sizeof (ioc));
81*9815SRishi.Srivatsavai@Sun.COM 	ioc.sim_link_id = attrp->sna_link_id;
82*9815SRishi.Srivatsavai@Sun.COM 	ioc.sim_peer_link_id = attrp->sna_peer_link_id;
83*9815SRishi.Srivatsavai@Sun.COM 
84*9815SRishi.Srivatsavai@Sun.COM 	rc = ioctl(dladm_dld_fd(handle), SIMNET_IOC_MODIFY, &ioc);
85*9815SRishi.Srivatsavai@Sun.COM 	if (rc < 0)
86*9815SRishi.Srivatsavai@Sun.COM 		status = dladm_errno2status(errno);
87*9815SRishi.Srivatsavai@Sun.COM 
88*9815SRishi.Srivatsavai@Sun.COM 	return (status);
89*9815SRishi.Srivatsavai@Sun.COM }
90*9815SRishi.Srivatsavai@Sun.COM 
91*9815SRishi.Srivatsavai@Sun.COM /* Delete simnet instance */
92*9815SRishi.Srivatsavai@Sun.COM static dladm_status_t
93*9815SRishi.Srivatsavai@Sun.COM i_dladm_delete_simnet(dladm_handle_t handle, dladm_simnet_attr_t *attrp)
94*9815SRishi.Srivatsavai@Sun.COM {
95*9815SRishi.Srivatsavai@Sun.COM 	int rc;
96*9815SRishi.Srivatsavai@Sun.COM 	dladm_status_t status = DLADM_STATUS_OK;
97*9815SRishi.Srivatsavai@Sun.COM 	simnet_ioc_delete_t ioc;
98*9815SRishi.Srivatsavai@Sun.COM 
99*9815SRishi.Srivatsavai@Sun.COM 	bzero(&ioc, sizeof (ioc));
100*9815SRishi.Srivatsavai@Sun.COM 	ioc.sid_link_id = attrp->sna_link_id;
101*9815SRishi.Srivatsavai@Sun.COM 
102*9815SRishi.Srivatsavai@Sun.COM 	rc = ioctl(dladm_dld_fd(handle), SIMNET_IOC_DELETE, &ioc);
103*9815SRishi.Srivatsavai@Sun.COM 	if (rc < 0)
104*9815SRishi.Srivatsavai@Sun.COM 		status = dladm_errno2status(errno);
105*9815SRishi.Srivatsavai@Sun.COM 
106*9815SRishi.Srivatsavai@Sun.COM 	return (status);
107*9815SRishi.Srivatsavai@Sun.COM }
108*9815SRishi.Srivatsavai@Sun.COM 
109*9815SRishi.Srivatsavai@Sun.COM /* Retrieve simnet instance information */
110*9815SRishi.Srivatsavai@Sun.COM static dladm_status_t
111*9815SRishi.Srivatsavai@Sun.COM i_dladm_get_simnet_info(dladm_handle_t handle, dladm_simnet_attr_t *attrp)
112*9815SRishi.Srivatsavai@Sun.COM {
113*9815SRishi.Srivatsavai@Sun.COM 	int rc;
114*9815SRishi.Srivatsavai@Sun.COM 	dladm_status_t status = DLADM_STATUS_OK;
115*9815SRishi.Srivatsavai@Sun.COM 	simnet_ioc_info_t ioc;
116*9815SRishi.Srivatsavai@Sun.COM 
117*9815SRishi.Srivatsavai@Sun.COM 	bzero(&ioc, sizeof (ioc));
118*9815SRishi.Srivatsavai@Sun.COM 	ioc.sii_link_id = attrp->sna_link_id;
119*9815SRishi.Srivatsavai@Sun.COM 
120*9815SRishi.Srivatsavai@Sun.COM 	rc = ioctl(dladm_dld_fd(handle), SIMNET_IOC_INFO, &ioc);
121*9815SRishi.Srivatsavai@Sun.COM 	if (rc < 0) {
122*9815SRishi.Srivatsavai@Sun.COM 		status = dladm_errno2status(errno);
123*9815SRishi.Srivatsavai@Sun.COM 		return (status);
124*9815SRishi.Srivatsavai@Sun.COM 	}
125*9815SRishi.Srivatsavai@Sun.COM 
126*9815SRishi.Srivatsavai@Sun.COM 	bcopy(ioc.sii_mac_addr, attrp->sna_mac_addr, MAXMACADDRLEN);
127*9815SRishi.Srivatsavai@Sun.COM 	attrp->sna_mac_len = ioc.sii_mac_len;
128*9815SRishi.Srivatsavai@Sun.COM 	attrp->sna_peer_link_id = ioc.sii_peer_link_id;
129*9815SRishi.Srivatsavai@Sun.COM 	attrp->sna_type = ioc.sii_type;
130*9815SRishi.Srivatsavai@Sun.COM 	return (status);
131*9815SRishi.Srivatsavai@Sun.COM }
132*9815SRishi.Srivatsavai@Sun.COM 
133*9815SRishi.Srivatsavai@Sun.COM /* Retrieve simnet configuratin */
134*9815SRishi.Srivatsavai@Sun.COM static dladm_status_t
135*9815SRishi.Srivatsavai@Sun.COM i_dladm_get_simnet_info_persist(dladm_handle_t handle,
136*9815SRishi.Srivatsavai@Sun.COM     dladm_simnet_attr_t *attrp)
137*9815SRishi.Srivatsavai@Sun.COM {
138*9815SRishi.Srivatsavai@Sun.COM 	dladm_conf_t conf;
139*9815SRishi.Srivatsavai@Sun.COM 	dladm_status_t status;
140*9815SRishi.Srivatsavai@Sun.COM 	char macstr[ETHERADDRL * 3];
141*9815SRishi.Srivatsavai@Sun.COM 	uint64_t u64;
142*9815SRishi.Srivatsavai@Sun.COM 	boolean_t mac_fixed;
143*9815SRishi.Srivatsavai@Sun.COM 
144*9815SRishi.Srivatsavai@Sun.COM 	if ((status = dladm_read_conf(handle, attrp->sna_link_id, &conf)) !=
145*9815SRishi.Srivatsavai@Sun.COM 	    DLADM_STATUS_OK)
146*9815SRishi.Srivatsavai@Sun.COM 		return (status);
147*9815SRishi.Srivatsavai@Sun.COM 
148*9815SRishi.Srivatsavai@Sun.COM 	status = dladm_get_conf_field(handle, conf, FSIMNETTYPE, &u64,
149*9815SRishi.Srivatsavai@Sun.COM 	    sizeof (u64));
150*9815SRishi.Srivatsavai@Sun.COM 	if (status != DLADM_STATUS_OK)
151*9815SRishi.Srivatsavai@Sun.COM 		goto done;
152*9815SRishi.Srivatsavai@Sun.COM 	attrp->sna_type = (uint_t)u64;
153*9815SRishi.Srivatsavai@Sun.COM 
154*9815SRishi.Srivatsavai@Sun.COM 	status = dladm_get_conf_field(handle, conf, FMADDRLEN, &u64,
155*9815SRishi.Srivatsavai@Sun.COM 	    sizeof (u64));
156*9815SRishi.Srivatsavai@Sun.COM 	if (status != DLADM_STATUS_OK)
157*9815SRishi.Srivatsavai@Sun.COM 		goto done;
158*9815SRishi.Srivatsavai@Sun.COM 	attrp->sna_mac_len = (uint_t)u64;
159*9815SRishi.Srivatsavai@Sun.COM 
160*9815SRishi.Srivatsavai@Sun.COM 	status = dladm_get_conf_field(handle, conf, FMACADDR, macstr,
161*9815SRishi.Srivatsavai@Sun.COM 	    sizeof (macstr));
162*9815SRishi.Srivatsavai@Sun.COM 	if (status != DLADM_STATUS_OK)
163*9815SRishi.Srivatsavai@Sun.COM 		goto done;
164*9815SRishi.Srivatsavai@Sun.COM 	(void) dladm_aggr_str2macaddr(macstr, &mac_fixed, attrp->sna_mac_addr);
165*9815SRishi.Srivatsavai@Sun.COM 
166*9815SRishi.Srivatsavai@Sun.COM 	/* Peer field is optional and only set when peer is attached */
167*9815SRishi.Srivatsavai@Sun.COM 	if (dladm_get_conf_field(handle, conf, FSIMNETPEER, &u64,
168*9815SRishi.Srivatsavai@Sun.COM 	    sizeof (u64)) == DLADM_STATUS_OK)
169*9815SRishi.Srivatsavai@Sun.COM 		attrp->sna_peer_link_id = (datalink_id_t)u64;
170*9815SRishi.Srivatsavai@Sun.COM 	else
171*9815SRishi.Srivatsavai@Sun.COM 		attrp->sna_peer_link_id = DATALINK_INVALID_LINKID;
172*9815SRishi.Srivatsavai@Sun.COM done:
173*9815SRishi.Srivatsavai@Sun.COM 	dladm_destroy_conf(handle, conf);
174*9815SRishi.Srivatsavai@Sun.COM 	return (status);
175*9815SRishi.Srivatsavai@Sun.COM }
176*9815SRishi.Srivatsavai@Sun.COM 
177*9815SRishi.Srivatsavai@Sun.COM dladm_status_t
178*9815SRishi.Srivatsavai@Sun.COM dladm_simnet_create(dladm_handle_t handle, const char *simnetname,
179*9815SRishi.Srivatsavai@Sun.COM     uint_t media, uint32_t flags)
180*9815SRishi.Srivatsavai@Sun.COM {
181*9815SRishi.Srivatsavai@Sun.COM 	datalink_id_t simnet_id;
182*9815SRishi.Srivatsavai@Sun.COM 	dladm_status_t status;
183*9815SRishi.Srivatsavai@Sun.COM 	dladm_simnet_attr_t attr;
184*9815SRishi.Srivatsavai@Sun.COM 
185*9815SRishi.Srivatsavai@Sun.COM 	if (!(flags & DLADM_OPT_ACTIVE))
186*9815SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_NOTSUP);
187*9815SRishi.Srivatsavai@Sun.COM 
188*9815SRishi.Srivatsavai@Sun.COM 	flags &= (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST);
189*9815SRishi.Srivatsavai@Sun.COM 	if ((status = dladm_create_datalink_id(handle, simnetname,
190*9815SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_SIMNET, media, flags,
191*9815SRishi.Srivatsavai@Sun.COM 	    &simnet_id)) != DLADM_STATUS_OK)
192*9815SRishi.Srivatsavai@Sun.COM 		return (status);
193*9815SRishi.Srivatsavai@Sun.COM 
194*9815SRishi.Srivatsavai@Sun.COM 	bzero(&attr, sizeof (attr));
195*9815SRishi.Srivatsavai@Sun.COM 	attr.sna_link_id = simnet_id;
196*9815SRishi.Srivatsavai@Sun.COM 	attr.sna_type = media;
197*9815SRishi.Srivatsavai@Sun.COM 	status = i_dladm_create_simnet(handle, &attr);
198*9815SRishi.Srivatsavai@Sun.COM 	if (status != DLADM_STATUS_OK)
199*9815SRishi.Srivatsavai@Sun.COM 		goto done;
200*9815SRishi.Srivatsavai@Sun.COM 
201*9815SRishi.Srivatsavai@Sun.COM 	if (!(flags & DLADM_OPT_PERSIST))
202*9815SRishi.Srivatsavai@Sun.COM 		goto done;
203*9815SRishi.Srivatsavai@Sun.COM 
204*9815SRishi.Srivatsavai@Sun.COM 	status = dladm_simnet_persist_conf(handle, simnetname, &attr);
205*9815SRishi.Srivatsavai@Sun.COM 	if (status != DLADM_STATUS_OK) {
206*9815SRishi.Srivatsavai@Sun.COM 		(void) i_dladm_delete_simnet(handle, &attr);
207*9815SRishi.Srivatsavai@Sun.COM 		goto done;
208*9815SRishi.Srivatsavai@Sun.COM 	}
209*9815SRishi.Srivatsavai@Sun.COM 
210*9815SRishi.Srivatsavai@Sun.COM 	(void) dladm_set_linkprop(handle, simnet_id, NULL, NULL, 0, flags);
211*9815SRishi.Srivatsavai@Sun.COM 
212*9815SRishi.Srivatsavai@Sun.COM done:
213*9815SRishi.Srivatsavai@Sun.COM 	if (status != DLADM_STATUS_OK) {
214*9815SRishi.Srivatsavai@Sun.COM 		(void) dladm_destroy_datalink_id(handle, simnet_id, flags);
215*9815SRishi.Srivatsavai@Sun.COM 	}
216*9815SRishi.Srivatsavai@Sun.COM 	return (status);
217*9815SRishi.Srivatsavai@Sun.COM }
218*9815SRishi.Srivatsavai@Sun.COM 
219*9815SRishi.Srivatsavai@Sun.COM /* Update existing simnet configuration */
220*9815SRishi.Srivatsavai@Sun.COM static dladm_status_t
221*9815SRishi.Srivatsavai@Sun.COM i_dladm_simnet_update_conf(dladm_handle_t handle, datalink_id_t simnet_id,
222*9815SRishi.Srivatsavai@Sun.COM     datalink_id_t peer_simnet_id)
223*9815SRishi.Srivatsavai@Sun.COM {
224*9815SRishi.Srivatsavai@Sun.COM 	dladm_status_t status;
225*9815SRishi.Srivatsavai@Sun.COM 	dladm_conf_t conf;
226*9815SRishi.Srivatsavai@Sun.COM 	uint64_t u64;
227*9815SRishi.Srivatsavai@Sun.COM 
228*9815SRishi.Srivatsavai@Sun.COM 	status = dladm_read_conf(handle, simnet_id, &conf);
229*9815SRishi.Srivatsavai@Sun.COM 	if (status != DLADM_STATUS_OK)
230*9815SRishi.Srivatsavai@Sun.COM 		return (status);
231*9815SRishi.Srivatsavai@Sun.COM 
232*9815SRishi.Srivatsavai@Sun.COM 	/* First clear previous peer if any in configuration */
233*9815SRishi.Srivatsavai@Sun.COM 	(void) dladm_unset_conf_field(handle, conf, FSIMNETPEER);
234*9815SRishi.Srivatsavai@Sun.COM 	if (peer_simnet_id != DATALINK_INVALID_LINKID) {
235*9815SRishi.Srivatsavai@Sun.COM 		u64 = peer_simnet_id;
236*9815SRishi.Srivatsavai@Sun.COM 		if ((status = dladm_datalink_id2info(handle,
237*9815SRishi.Srivatsavai@Sun.COM 		    peer_simnet_id, NULL, NULL, NULL, NULL,
238*9815SRishi.Srivatsavai@Sun.COM 		    0)) == DLADM_STATUS_OK)
239*9815SRishi.Srivatsavai@Sun.COM 			status = dladm_set_conf_field(handle, conf,
240*9815SRishi.Srivatsavai@Sun.COM 			    FSIMNETPEER, DLADM_TYPE_UINT64, &u64);
241*9815SRishi.Srivatsavai@Sun.COM 		if (status != DLADM_STATUS_OK)
242*9815SRishi.Srivatsavai@Sun.COM 			goto fail;
243*9815SRishi.Srivatsavai@Sun.COM 	}
244*9815SRishi.Srivatsavai@Sun.COM 
245*9815SRishi.Srivatsavai@Sun.COM 	status = dladm_write_conf(handle, conf);
246*9815SRishi.Srivatsavai@Sun.COM fail:
247*9815SRishi.Srivatsavai@Sun.COM 	dladm_destroy_conf(handle, conf);
248*9815SRishi.Srivatsavai@Sun.COM 	return (status);
249*9815SRishi.Srivatsavai@Sun.COM }
250*9815SRishi.Srivatsavai@Sun.COM 
251*9815SRishi.Srivatsavai@Sun.COM /* Modify attached simnet peer */
252*9815SRishi.Srivatsavai@Sun.COM dladm_status_t
253*9815SRishi.Srivatsavai@Sun.COM dladm_simnet_modify(dladm_handle_t handle, datalink_id_t simnet_id,
254*9815SRishi.Srivatsavai@Sun.COM     datalink_id_t peer_simnet_id, uint32_t flags)
255*9815SRishi.Srivatsavai@Sun.COM {
256*9815SRishi.Srivatsavai@Sun.COM 	dladm_simnet_attr_t attr;
257*9815SRishi.Srivatsavai@Sun.COM 	dladm_simnet_attr_t prevattr;
258*9815SRishi.Srivatsavai@Sun.COM 	dladm_status_t status;
259*9815SRishi.Srivatsavai@Sun.COM 	datalink_class_t class;
260*9815SRishi.Srivatsavai@Sun.COM 	uint32_t linkflags;
261*9815SRishi.Srivatsavai@Sun.COM 	uint32_t peerlinkflags;
262*9815SRishi.Srivatsavai@Sun.COM 
263*9815SRishi.Srivatsavai@Sun.COM 	if (!(flags & DLADM_OPT_ACTIVE))
264*9815SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_NOTSUP);
265*9815SRishi.Srivatsavai@Sun.COM 
266*9815SRishi.Srivatsavai@Sun.COM 	if ((dladm_datalink_id2info(handle, simnet_id, &linkflags, &class,
267*9815SRishi.Srivatsavai@Sun.COM 	    NULL, NULL, 0) != DLADM_STATUS_OK))
268*9815SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_BADARG);
269*9815SRishi.Srivatsavai@Sun.COM 	if (class != DATALINK_CLASS_SIMNET)
270*9815SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_BADARG);
271*9815SRishi.Srivatsavai@Sun.COM 
272*9815SRishi.Srivatsavai@Sun.COM 	if (peer_simnet_id != DATALINK_INVALID_LINKID) {
273*9815SRishi.Srivatsavai@Sun.COM 		if (dladm_datalink_id2info(handle, peer_simnet_id,
274*9815SRishi.Srivatsavai@Sun.COM 		    &peerlinkflags, &class, NULL, NULL, 0) != DLADM_STATUS_OK)
275*9815SRishi.Srivatsavai@Sun.COM 			return (DLADM_STATUS_BADARG);
276*9815SRishi.Srivatsavai@Sun.COM 		if (class != DATALINK_CLASS_SIMNET)
277*9815SRishi.Srivatsavai@Sun.COM 			return (DLADM_STATUS_BADARG);
278*9815SRishi.Srivatsavai@Sun.COM 		/* Check to ensure the peer link has identical flags */
279*9815SRishi.Srivatsavai@Sun.COM 		if (peerlinkflags != linkflags)
280*9815SRishi.Srivatsavai@Sun.COM 			return (DLADM_STATUS_BADARG);
281*9815SRishi.Srivatsavai@Sun.COM 	}
282*9815SRishi.Srivatsavai@Sun.COM 
283*9815SRishi.Srivatsavai@Sun.COM 	/* Retrieve previous attrs before modification */
284*9815SRishi.Srivatsavai@Sun.COM 	bzero(&prevattr, sizeof (prevattr));
285*9815SRishi.Srivatsavai@Sun.COM 	if ((status = dladm_simnet_info(handle, simnet_id, &prevattr,
286*9815SRishi.Srivatsavai@Sun.COM 	    flags)) != DLADM_STATUS_OK)
287*9815SRishi.Srivatsavai@Sun.COM 		return (status);
288*9815SRishi.Srivatsavai@Sun.COM 
289*9815SRishi.Srivatsavai@Sun.COM 	bzero(&attr, sizeof (attr));
290*9815SRishi.Srivatsavai@Sun.COM 	attr.sna_link_id = simnet_id;
291*9815SRishi.Srivatsavai@Sun.COM 	attr.sna_peer_link_id = peer_simnet_id;
292*9815SRishi.Srivatsavai@Sun.COM 	status = i_dladm_modify_simnet(handle, &attr);
293*9815SRishi.Srivatsavai@Sun.COM 	if ((status != DLADM_STATUS_OK) || !(flags & DLADM_OPT_PERSIST))
294*9815SRishi.Srivatsavai@Sun.COM 		return (status);
295*9815SRishi.Srivatsavai@Sun.COM 
296*9815SRishi.Srivatsavai@Sun.COM 	/* First we clear link's existing peer field in config */
297*9815SRishi.Srivatsavai@Sun.COM 	status = i_dladm_simnet_update_conf(handle, simnet_id,
298*9815SRishi.Srivatsavai@Sun.COM 	    DATALINK_INVALID_LINKID);
299*9815SRishi.Srivatsavai@Sun.COM 	if (status != DLADM_STATUS_OK)
300*9815SRishi.Srivatsavai@Sun.COM 		return (status);
301*9815SRishi.Srivatsavai@Sun.COM 
302*9815SRishi.Srivatsavai@Sun.COM 	/* Clear the previous peer link's existing peer field in config */
303*9815SRishi.Srivatsavai@Sun.COM 	if (prevattr.sna_peer_link_id != DATALINK_INVALID_LINKID) {
304*9815SRishi.Srivatsavai@Sun.COM 		status = i_dladm_simnet_update_conf(handle,
305*9815SRishi.Srivatsavai@Sun.COM 		    prevattr.sna_peer_link_id, DATALINK_INVALID_LINKID);
306*9815SRishi.Srivatsavai@Sun.COM 		if (status != DLADM_STATUS_OK)
307*9815SRishi.Srivatsavai@Sun.COM 			return (status);
308*9815SRishi.Srivatsavai@Sun.COM 	}
309*9815SRishi.Srivatsavai@Sun.COM 
310*9815SRishi.Srivatsavai@Sun.COM 	/* Update the configuration in both simnets with any new peer link */
311*9815SRishi.Srivatsavai@Sun.COM 	if (peer_simnet_id != DATALINK_INVALID_LINKID) {
312*9815SRishi.Srivatsavai@Sun.COM 		status = i_dladm_simnet_update_conf(handle, simnet_id,
313*9815SRishi.Srivatsavai@Sun.COM 		    peer_simnet_id);
314*9815SRishi.Srivatsavai@Sun.COM 		if (status == DLADM_STATUS_OK)
315*9815SRishi.Srivatsavai@Sun.COM 			status = i_dladm_simnet_update_conf(handle,
316*9815SRishi.Srivatsavai@Sun.COM 			    peer_simnet_id, simnet_id);
317*9815SRishi.Srivatsavai@Sun.COM 	}
318*9815SRishi.Srivatsavai@Sun.COM 
319*9815SRishi.Srivatsavai@Sun.COM 	return (status);
320*9815SRishi.Srivatsavai@Sun.COM }
321*9815SRishi.Srivatsavai@Sun.COM 
322*9815SRishi.Srivatsavai@Sun.COM dladm_status_t
323*9815SRishi.Srivatsavai@Sun.COM dladm_simnet_delete(dladm_handle_t handle, datalink_id_t simnet_id,
324*9815SRishi.Srivatsavai@Sun.COM     uint32_t flags)
325*9815SRishi.Srivatsavai@Sun.COM {
326*9815SRishi.Srivatsavai@Sun.COM 	dladm_simnet_attr_t attr;
327*9815SRishi.Srivatsavai@Sun.COM 	dladm_simnet_attr_t prevattr;
328*9815SRishi.Srivatsavai@Sun.COM 	dladm_status_t status;
329*9815SRishi.Srivatsavai@Sun.COM 	datalink_class_t class;
330*9815SRishi.Srivatsavai@Sun.COM 
331*9815SRishi.Srivatsavai@Sun.COM 	if ((dladm_datalink_id2info(handle, simnet_id, NULL, &class,
332*9815SRishi.Srivatsavai@Sun.COM 	    NULL, NULL, 0) != DLADM_STATUS_OK))
333*9815SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_BADARG);
334*9815SRishi.Srivatsavai@Sun.COM 
335*9815SRishi.Srivatsavai@Sun.COM 	if (class != DATALINK_CLASS_SIMNET)
336*9815SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_BADARG);
337*9815SRishi.Srivatsavai@Sun.COM 
338*9815SRishi.Srivatsavai@Sun.COM 	/* Check current simnet attributes before deletion */
339*9815SRishi.Srivatsavai@Sun.COM 	flags &= (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST);
340*9815SRishi.Srivatsavai@Sun.COM 	bzero(&prevattr, sizeof (prevattr));
341*9815SRishi.Srivatsavai@Sun.COM 	if ((status = dladm_simnet_info(handle, simnet_id, &prevattr,
342*9815SRishi.Srivatsavai@Sun.COM 	    flags)) != DLADM_STATUS_OK)
343*9815SRishi.Srivatsavai@Sun.COM 		return (status);
344*9815SRishi.Srivatsavai@Sun.COM 
345*9815SRishi.Srivatsavai@Sun.COM 	bzero(&attr, sizeof (attr));
346*9815SRishi.Srivatsavai@Sun.COM 	attr.sna_link_id = simnet_id;
347*9815SRishi.Srivatsavai@Sun.COM 	if (flags & DLADM_OPT_ACTIVE) {
348*9815SRishi.Srivatsavai@Sun.COM 		status = i_dladm_delete_simnet(handle, &attr);
349*9815SRishi.Srivatsavai@Sun.COM 		if (status == DLADM_STATUS_OK) {
350*9815SRishi.Srivatsavai@Sun.COM 			(void) dladm_set_linkprop(handle, simnet_id, NULL,
351*9815SRishi.Srivatsavai@Sun.COM 			    NULL, 0, DLADM_OPT_ACTIVE);
352*9815SRishi.Srivatsavai@Sun.COM 			(void) dladm_destroy_datalink_id(handle, simnet_id,
353*9815SRishi.Srivatsavai@Sun.COM 			    DLADM_OPT_ACTIVE);
354*9815SRishi.Srivatsavai@Sun.COM 		} else if (status != DLADM_STATUS_NOTFOUND) {
355*9815SRishi.Srivatsavai@Sun.COM 			return (status);
356*9815SRishi.Srivatsavai@Sun.COM 		}
357*9815SRishi.Srivatsavai@Sun.COM 	}
358*9815SRishi.Srivatsavai@Sun.COM 
359*9815SRishi.Srivatsavai@Sun.COM 	if (flags & DLADM_OPT_PERSIST) {
360*9815SRishi.Srivatsavai@Sun.COM 		(void) dladm_destroy_datalink_id(handle, simnet_id,
361*9815SRishi.Srivatsavai@Sun.COM 		    DLADM_OPT_PERSIST);
362*9815SRishi.Srivatsavai@Sun.COM 		(void) dladm_remove_conf(handle, simnet_id);
363*9815SRishi.Srivatsavai@Sun.COM 
364*9815SRishi.Srivatsavai@Sun.COM 		/* Update any attached peer configuration */
365*9815SRishi.Srivatsavai@Sun.COM 		if (prevattr.sna_peer_link_id != DATALINK_INVALID_LINKID)
366*9815SRishi.Srivatsavai@Sun.COM 			status = i_dladm_simnet_update_conf(handle,
367*9815SRishi.Srivatsavai@Sun.COM 			    prevattr.sna_peer_link_id, DATALINK_INVALID_LINKID);
368*9815SRishi.Srivatsavai@Sun.COM 	}
369*9815SRishi.Srivatsavai@Sun.COM 	return (status);
370*9815SRishi.Srivatsavai@Sun.COM }
371*9815SRishi.Srivatsavai@Sun.COM 
372*9815SRishi.Srivatsavai@Sun.COM /* Retrieve simnet information either active or from configuration */
373*9815SRishi.Srivatsavai@Sun.COM dladm_status_t
374*9815SRishi.Srivatsavai@Sun.COM dladm_simnet_info(dladm_handle_t handle, datalink_id_t simnet_id,
375*9815SRishi.Srivatsavai@Sun.COM     dladm_simnet_attr_t *attrp, uint32_t flags)
376*9815SRishi.Srivatsavai@Sun.COM {
377*9815SRishi.Srivatsavai@Sun.COM 	datalink_class_t class;
378*9815SRishi.Srivatsavai@Sun.COM 	dladm_status_t status;
379*9815SRishi.Srivatsavai@Sun.COM 
380*9815SRishi.Srivatsavai@Sun.COM 	if ((dladm_datalink_id2info(handle, simnet_id, NULL, &class,
381*9815SRishi.Srivatsavai@Sun.COM 	    NULL, NULL, 0) != DLADM_STATUS_OK))
382*9815SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_BADARG);
383*9815SRishi.Srivatsavai@Sun.COM 
384*9815SRishi.Srivatsavai@Sun.COM 	if (class != DATALINK_CLASS_SIMNET)
385*9815SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_BADARG);
386*9815SRishi.Srivatsavai@Sun.COM 
387*9815SRishi.Srivatsavai@Sun.COM 	bzero(attrp, sizeof (attrp));
388*9815SRishi.Srivatsavai@Sun.COM 	attrp->sna_link_id = simnet_id;
389*9815SRishi.Srivatsavai@Sun.COM 
390*9815SRishi.Srivatsavai@Sun.COM 	if (flags & DLADM_OPT_ACTIVE) {
391*9815SRishi.Srivatsavai@Sun.COM 		status = i_dladm_get_simnet_info(handle, attrp);
392*9815SRishi.Srivatsavai@Sun.COM 		/*
393*9815SRishi.Srivatsavai@Sun.COM 		 * If no active simnet found then return any simnet
394*9815SRishi.Srivatsavai@Sun.COM 		 * from stored config if requested.
395*9815SRishi.Srivatsavai@Sun.COM 		 */
396*9815SRishi.Srivatsavai@Sun.COM 		if (status == DLADM_STATUS_NOTFOUND &&
397*9815SRishi.Srivatsavai@Sun.COM 		    (flags & DLADM_OPT_PERSIST))
398*9815SRishi.Srivatsavai@Sun.COM 			return (i_dladm_get_simnet_info_persist(handle, attrp));
399*9815SRishi.Srivatsavai@Sun.COM 		return (status);
400*9815SRishi.Srivatsavai@Sun.COM 	} else if (flags & DLADM_OPT_PERSIST) {
401*9815SRishi.Srivatsavai@Sun.COM 		return (i_dladm_get_simnet_info_persist(handle, attrp));
402*9815SRishi.Srivatsavai@Sun.COM 	} else {
403*9815SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_BADARG);
404*9815SRishi.Srivatsavai@Sun.COM 	}
405*9815SRishi.Srivatsavai@Sun.COM }
406*9815SRishi.Srivatsavai@Sun.COM 
407*9815SRishi.Srivatsavai@Sun.COM /* Bring up simnet from stored configuration */
408*9815SRishi.Srivatsavai@Sun.COM static int
409*9815SRishi.Srivatsavai@Sun.COM i_dladm_simnet_up(dladm_handle_t handle, datalink_id_t simnet_id, void *arg)
410*9815SRishi.Srivatsavai@Sun.COM {
411*9815SRishi.Srivatsavai@Sun.COM 	dladm_status_t *statusp = arg;
412*9815SRishi.Srivatsavai@Sun.COM 	dladm_status_t status;
413*9815SRishi.Srivatsavai@Sun.COM 	dladm_simnet_attr_t attr;
414*9815SRishi.Srivatsavai@Sun.COM 	dladm_simnet_attr_t peer_attr;
415*9815SRishi.Srivatsavai@Sun.COM 
416*9815SRishi.Srivatsavai@Sun.COM 	bzero(&attr, sizeof (attr));
417*9815SRishi.Srivatsavai@Sun.COM 	attr.sna_link_id = simnet_id;
418*9815SRishi.Srivatsavai@Sun.COM 	status = dladm_simnet_info(handle, simnet_id, &attr,
419*9815SRishi.Srivatsavai@Sun.COM 	    DLADM_OPT_PERSIST);
420*9815SRishi.Srivatsavai@Sun.COM 	if (status != DLADM_STATUS_OK)
421*9815SRishi.Srivatsavai@Sun.COM 		goto done;
422*9815SRishi.Srivatsavai@Sun.COM 
423*9815SRishi.Srivatsavai@Sun.COM 	status = i_dladm_create_simnet(handle, &attr);
424*9815SRishi.Srivatsavai@Sun.COM 	if (status != DLADM_STATUS_OK)
425*9815SRishi.Srivatsavai@Sun.COM 		goto done;
426*9815SRishi.Srivatsavai@Sun.COM 
427*9815SRishi.Srivatsavai@Sun.COM 	/*
428*9815SRishi.Srivatsavai@Sun.COM 	 * When bringing up check if the peer link is available, if it
429*9815SRishi.Srivatsavai@Sun.COM 	 * is then modify the simnet and attach the peer link.
430*9815SRishi.Srivatsavai@Sun.COM 	 */
431*9815SRishi.Srivatsavai@Sun.COM 	if ((attr.sna_peer_link_id != DATALINK_INVALID_LINKID) &&
432*9815SRishi.Srivatsavai@Sun.COM 	    (dladm_simnet_info(handle, attr.sna_peer_link_id, &peer_attr,
433*9815SRishi.Srivatsavai@Sun.COM 	    DLADM_OPT_ACTIVE) == DLADM_STATUS_OK)) {
434*9815SRishi.Srivatsavai@Sun.COM 		status = i_dladm_modify_simnet(handle, &attr);
435*9815SRishi.Srivatsavai@Sun.COM 		if (status != DLADM_STATUS_OK)
436*9815SRishi.Srivatsavai@Sun.COM 			goto done;
437*9815SRishi.Srivatsavai@Sun.COM 	}
438*9815SRishi.Srivatsavai@Sun.COM 
439*9815SRishi.Srivatsavai@Sun.COM 	if ((status = dladm_up_datalink_id(handle, simnet_id)) !=
440*9815SRishi.Srivatsavai@Sun.COM 	    DLADM_STATUS_OK) {
441*9815SRishi.Srivatsavai@Sun.COM 		(void) dladm_simnet_delete(handle, simnet_id,
442*9815SRishi.Srivatsavai@Sun.COM 		    DLADM_OPT_PERSIST);
443*9815SRishi.Srivatsavai@Sun.COM 		goto done;
444*9815SRishi.Srivatsavai@Sun.COM 	}
445*9815SRishi.Srivatsavai@Sun.COM done:
446*9815SRishi.Srivatsavai@Sun.COM 	*statusp = status;
447*9815SRishi.Srivatsavai@Sun.COM 	return (DLADM_WALK_CONTINUE);
448*9815SRishi.Srivatsavai@Sun.COM }
449*9815SRishi.Srivatsavai@Sun.COM 
450*9815SRishi.Srivatsavai@Sun.COM /* Bring up simnet instance(s) from configuration */
451*9815SRishi.Srivatsavai@Sun.COM /* ARGSUSED */
452*9815SRishi.Srivatsavai@Sun.COM dladm_status_t
453*9815SRishi.Srivatsavai@Sun.COM dladm_simnet_up(dladm_handle_t handle, datalink_id_t simnet_id,
454*9815SRishi.Srivatsavai@Sun.COM     uint32_t flags)
455*9815SRishi.Srivatsavai@Sun.COM {
456*9815SRishi.Srivatsavai@Sun.COM 	dladm_status_t status;
457*9815SRishi.Srivatsavai@Sun.COM 
458*9815SRishi.Srivatsavai@Sun.COM 	if (simnet_id == DATALINK_ALL_LINKID) {
459*9815SRishi.Srivatsavai@Sun.COM 		(void) dladm_walk_datalink_id(i_dladm_simnet_up, handle,
460*9815SRishi.Srivatsavai@Sun.COM 		    &status, DATALINK_CLASS_SIMNET, DATALINK_ANY_MEDIATYPE,
461*9815SRishi.Srivatsavai@Sun.COM 		    DLADM_OPT_PERSIST);
462*9815SRishi.Srivatsavai@Sun.COM 		return (DLADM_STATUS_OK);
463*9815SRishi.Srivatsavai@Sun.COM 	} else {
464*9815SRishi.Srivatsavai@Sun.COM 		(void) i_dladm_simnet_up(handle, simnet_id, &status);
465*9815SRishi.Srivatsavai@Sun.COM 		return (status);
466*9815SRishi.Srivatsavai@Sun.COM 	}
467*9815SRishi.Srivatsavai@Sun.COM }
468*9815SRishi.Srivatsavai@Sun.COM 
469*9815SRishi.Srivatsavai@Sun.COM /* Store simnet configuration */
470*9815SRishi.Srivatsavai@Sun.COM static dladm_status_t
471*9815SRishi.Srivatsavai@Sun.COM dladm_simnet_persist_conf(dladm_handle_t handle, const char *name,
472*9815SRishi.Srivatsavai@Sun.COM     dladm_simnet_attr_t *attrp)
473*9815SRishi.Srivatsavai@Sun.COM {
474*9815SRishi.Srivatsavai@Sun.COM 	dladm_conf_t conf = DLADM_INVALID_CONF;
475*9815SRishi.Srivatsavai@Sun.COM 	dladm_status_t status;
476*9815SRishi.Srivatsavai@Sun.COM 	char mstr[ETHERADDRL * 3];
477*9815SRishi.Srivatsavai@Sun.COM 	uint64_t u64;
478*9815SRishi.Srivatsavai@Sun.COM 
479*9815SRishi.Srivatsavai@Sun.COM 	if ((status = dladm_create_conf(handle, name, attrp->sna_link_id,
480*9815SRishi.Srivatsavai@Sun.COM 	    DATALINK_CLASS_SIMNET, attrp->sna_type, &conf)) != DLADM_STATUS_OK)
481*9815SRishi.Srivatsavai@Sun.COM 		return (status);
482*9815SRishi.Srivatsavai@Sun.COM 
483*9815SRishi.Srivatsavai@Sun.COM 	status = dladm_set_conf_field(handle, conf, FMACADDR,
484*9815SRishi.Srivatsavai@Sun.COM 	    DLADM_TYPE_STR, dladm_aggr_macaddr2str(attrp->sna_mac_addr, mstr));
485*9815SRishi.Srivatsavai@Sun.COM 	if (status != DLADM_STATUS_OK)
486*9815SRishi.Srivatsavai@Sun.COM 		goto done;
487*9815SRishi.Srivatsavai@Sun.COM 
488*9815SRishi.Srivatsavai@Sun.COM 	u64 = attrp->sna_type;
489*9815SRishi.Srivatsavai@Sun.COM 	status = dladm_set_conf_field(handle, conf, FSIMNETTYPE,
490*9815SRishi.Srivatsavai@Sun.COM 	    DLADM_TYPE_UINT64, &u64);
491*9815SRishi.Srivatsavai@Sun.COM 	if (status != DLADM_STATUS_OK)
492*9815SRishi.Srivatsavai@Sun.COM 		goto done;
493*9815SRishi.Srivatsavai@Sun.COM 
494*9815SRishi.Srivatsavai@Sun.COM 	u64 = attrp->sna_mac_len;
495*9815SRishi.Srivatsavai@Sun.COM 	status = dladm_set_conf_field(handle, conf, FMADDRLEN,
496*9815SRishi.Srivatsavai@Sun.COM 	    DLADM_TYPE_UINT64, &u64);
497*9815SRishi.Srivatsavai@Sun.COM 	if (status != DLADM_STATUS_OK)
498*9815SRishi.Srivatsavai@Sun.COM 		goto done;
499*9815SRishi.Srivatsavai@Sun.COM 
500*9815SRishi.Srivatsavai@Sun.COM 	status = dladm_write_conf(handle, conf);
501*9815SRishi.Srivatsavai@Sun.COM done:
502*9815SRishi.Srivatsavai@Sun.COM 	dladm_destroy_conf(handle, conf);
503*9815SRishi.Srivatsavai@Sun.COM 	return (status);
504*9815SRishi.Srivatsavai@Sun.COM }
505