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