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