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