1f595a68aSyz147064 /*
2f595a68aSyz147064 * CDDL HEADER START
3f595a68aSyz147064 *
4f595a68aSyz147064 * The contents of this file are subject to the terms of the
5f595a68aSyz147064 * Common Development and Distribution License (the "License").
6f595a68aSyz147064 * You may not use this file except in compliance with the License.
7f595a68aSyz147064 *
8f595a68aSyz147064 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9f595a68aSyz147064 * or http://www.opensolaris.org/os/licensing.
10f595a68aSyz147064 * See the License for the specific language governing permissions
11f595a68aSyz147064 * and limitations under the License.
12f595a68aSyz147064 *
13f595a68aSyz147064 * When distributing Covered Code, include this CDDL HEADER in each
14f595a68aSyz147064 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15f595a68aSyz147064 * If applicable, add the following below this CDDL HEADER, with the
16f595a68aSyz147064 * fields enclosed by brackets "[]" replaced with your own identifying
17f595a68aSyz147064 * information: Portions Copyright [yyyy] [name of copyright owner]
18f595a68aSyz147064 *
19f595a68aSyz147064 * CDDL HEADER END
20f595a68aSyz147064 */
21f595a68aSyz147064 /*
221cfa752fSRamaswamy Tummala * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23f595a68aSyz147064 */
24f595a68aSyz147064
25f595a68aSyz147064 #include <sys/types.h>
26f595a68aSyz147064 #include <unistd.h>
27f595a68aSyz147064 #include <errno.h>
28f595a68aSyz147064 #include <fcntl.h>
29d62bc4baSyz147064 #include <assert.h>
30d62bc4baSyz147064 #include <ctype.h>
31f595a68aSyz147064 #include <strings.h>
32f595a68aSyz147064 #include <sys/stat.h>
33f595a68aSyz147064 #include <sys/dld.h>
34d62bc4baSyz147064 #include <sys/vlan.h>
353bc21d0aSAruna Ramakrishna - Sun Microsystems #include <zone.h>
36d62bc4baSyz147064 #include <librcm.h>
37f595a68aSyz147064 #include <libdlpi.h>
38f595a68aSyz147064 #include <libdevinfo.h>
39d62bc4baSyz147064 #include <libdlaggr.h>
40d62bc4baSyz147064 #include <libdlvlan.h>
410dc2366fSVenugopal Iyer #include <libdlvnic.h>
421cfa752fSRamaswamy Tummala #include <libdlib.h>
43f595a68aSyz147064 #include <libdllink.h>
44d62bc4baSyz147064 #include <libdlmgmt.h>
45f595a68aSyz147064 #include <libdladm_impl.h>
46e7801d59Ssowmini #include <libinetutil.h>
47f595a68aSyz147064
48f595a68aSyz147064 /*
49f595a68aSyz147064 * Return the attributes of the specified datalink from the DLD driver.
50f595a68aSyz147064 */
51d62bc4baSyz147064 static dladm_status_t
i_dladm_info(dladm_handle_t handle,const datalink_id_t linkid,dladm_attr_t * dap)524ac67f02SAnurag S. Maskey i_dladm_info(dladm_handle_t handle, const datalink_id_t linkid,
534ac67f02SAnurag S. Maskey dladm_attr_t *dap)
54f595a68aSyz147064 {
55f595a68aSyz147064 dld_ioc_attr_t dia;
56f595a68aSyz147064
57d62bc4baSyz147064 dia.dia_linkid = linkid;
58f595a68aSyz147064
594ac67f02SAnurag S. Maskey if (ioctl(dladm_dld_fd(handle), DLDIOC_ATTR, &dia) < 0)
60d62bc4baSyz147064 return (dladm_errno2status(errno));
61f595a68aSyz147064
62f595a68aSyz147064 dap->da_max_sdu = dia.dia_max_sdu;
63f595a68aSyz147064
64d62bc4baSyz147064 return (DLADM_STATUS_OK);
65f595a68aSyz147064 }
66f595a68aSyz147064
67da14cebeSEric Cheng static dladm_status_t
dladm_usagelog(dladm_handle_t handle,dladm_logtype_t type,dld_ioc_usagelog_t * log_info)684ac67f02SAnurag S. Maskey dladm_usagelog(dladm_handle_t handle, dladm_logtype_t type,
694ac67f02SAnurag S. Maskey dld_ioc_usagelog_t *log_info)
70da14cebeSEric Cheng {
71da14cebeSEric Cheng if (type == DLADM_LOGTYPE_FLOW)
72da14cebeSEric Cheng log_info->ul_type = MAC_LOGTYPE_FLOW;
73da14cebeSEric Cheng else
74da14cebeSEric Cheng log_info->ul_type = MAC_LOGTYPE_LINK;
75da14cebeSEric Cheng
764ac67f02SAnurag S. Maskey if (ioctl(dladm_dld_fd(handle), DLDIOC_USAGELOG, log_info) < 0)
77da14cebeSEric Cheng return (DLADM_STATUS_IOERR);
784ac67f02SAnurag S. Maskey
79da14cebeSEric Cheng return (DLADM_STATUS_OK);
80da14cebeSEric Cheng }
81da14cebeSEric Cheng
82da14cebeSEric Cheng dladm_status_t
dladm_start_usagelog(dladm_handle_t handle,dladm_logtype_t type,uint_t interval)834ac67f02SAnurag S. Maskey dladm_start_usagelog(dladm_handle_t handle, dladm_logtype_t type,
844ac67f02SAnurag S. Maskey uint_t interval)
85da14cebeSEric Cheng {
86da14cebeSEric Cheng dld_ioc_usagelog_t log_info;
87da14cebeSEric Cheng
88da14cebeSEric Cheng log_info.ul_onoff = B_TRUE;
89da14cebeSEric Cheng log_info.ul_interval = interval;
90da14cebeSEric Cheng
914ac67f02SAnurag S. Maskey return (dladm_usagelog(handle, type, &log_info));
92da14cebeSEric Cheng }
93da14cebeSEric Cheng
94da14cebeSEric Cheng dladm_status_t
dladm_stop_usagelog(dladm_handle_t handle,dladm_logtype_t type)954ac67f02SAnurag S. Maskey dladm_stop_usagelog(dladm_handle_t handle, dladm_logtype_t type)
96da14cebeSEric Cheng {
97da14cebeSEric Cheng dld_ioc_usagelog_t log_info;
98da14cebeSEric Cheng
99da14cebeSEric Cheng log_info.ul_onoff = B_FALSE;
100da14cebeSEric Cheng log_info.ul_interval = 0;
101da14cebeSEric Cheng
1024ac67f02SAnurag S. Maskey return (dladm_usagelog(handle, type, &log_info));
103da14cebeSEric Cheng }
104da14cebeSEric Cheng
105d62bc4baSyz147064 struct i_dladm_walk_arg {
106d62bc4baSyz147064 dladm_walkcb_t *fn;
107d62bc4baSyz147064 void *arg;
108d62bc4baSyz147064 };
109f595a68aSyz147064
110f595a68aSyz147064 static int
i_dladm_walk(dladm_handle_t handle,datalink_id_t linkid,void * arg)1114ac67f02SAnurag S. Maskey i_dladm_walk(dladm_handle_t handle, datalink_id_t linkid, void *arg)
112f595a68aSyz147064 {
113d62bc4baSyz147064 struct i_dladm_walk_arg *walk_arg = arg;
114d62bc4baSyz147064 char link[MAXLINKNAMELEN];
115f595a68aSyz147064
1164ac67f02SAnurag S. Maskey if (dladm_datalink_id2info(handle, linkid, NULL, NULL, NULL, link,
117d62bc4baSyz147064 sizeof (link)) == DLADM_STATUS_OK) {
118d62bc4baSyz147064 return (walk_arg->fn(link, walk_arg->arg));
119f595a68aSyz147064 }
120d62bc4baSyz147064
121d62bc4baSyz147064 return (DLADM_WALK_CONTINUE);
122f595a68aSyz147064 }
123f595a68aSyz147064
124f595a68aSyz147064 /*
125d62bc4baSyz147064 * Walk all datalinks.
126f595a68aSyz147064 */
127d62bc4baSyz147064 dladm_status_t
dladm_walk(dladm_walkcb_t * fn,dladm_handle_t handle,void * arg,datalink_class_t class,datalink_media_t dmedia,uint32_t flags)1284ac67f02SAnurag S. Maskey dladm_walk(dladm_walkcb_t *fn, dladm_handle_t handle, void *arg,
1294ac67f02SAnurag S. Maskey datalink_class_t class, datalink_media_t dmedia, uint32_t flags)
130f595a68aSyz147064 {
131d62bc4baSyz147064 struct i_dladm_walk_arg walk_arg;
132f595a68aSyz147064
133d62bc4baSyz147064 walk_arg.fn = fn;
134d62bc4baSyz147064 walk_arg.arg = arg;
1354ac67f02SAnurag S. Maskey return (dladm_walk_datalink_id(i_dladm_walk, handle, &walk_arg,
136d62bc4baSyz147064 class, dmedia, flags));
137f595a68aSyz147064 }
138f595a68aSyz147064
139da14cebeSEric Cheng #define MAXGRPPERLINK 64
140da14cebeSEric Cheng
141da14cebeSEric Cheng int
dladm_walk_hwgrp(dladm_handle_t handle,datalink_id_t linkid,void * arg,boolean_t (* fn)(void *,dladm_hwgrp_attr_t *))1424ac67f02SAnurag S. Maskey dladm_walk_hwgrp(dladm_handle_t handle, datalink_id_t linkid, void *arg,
143da14cebeSEric Cheng boolean_t (*fn)(void *, dladm_hwgrp_attr_t *))
144da14cebeSEric Cheng {
1454ac67f02SAnurag S. Maskey int bufsize, ret;
146da14cebeSEric Cheng int nhwgrp = MAXGRPPERLINK;
147da14cebeSEric Cheng dld_ioc_hwgrpget_t *iomp = NULL;
148da14cebeSEric Cheng
149da14cebeSEric Cheng bufsize = sizeof (dld_ioc_hwgrpget_t) +
150da14cebeSEric Cheng nhwgrp * sizeof (dld_hwgrpinfo_t);
151da14cebeSEric Cheng
152da14cebeSEric Cheng if ((iomp = (dld_ioc_hwgrpget_t *)calloc(1, bufsize)) == NULL)
153da14cebeSEric Cheng return (-1);
154da14cebeSEric Cheng
155da14cebeSEric Cheng iomp->dih_size = nhwgrp * sizeof (dld_hwgrpinfo_t);
156da14cebeSEric Cheng iomp->dih_linkid = linkid;
157da14cebeSEric Cheng
1584ac67f02SAnurag S. Maskey ret = ioctl(dladm_dld_fd(handle), DLDIOC_GETHWGRP, iomp);
159da14cebeSEric Cheng if (ret == 0) {
160*4202e8bfSToomas Soome uint_t i;
161*4202e8bfSToomas Soome uint_t j;
162da14cebeSEric Cheng dld_hwgrpinfo_t *dhip;
163da14cebeSEric Cheng dladm_hwgrp_attr_t attr;
164da14cebeSEric Cheng
165da14cebeSEric Cheng dhip = (dld_hwgrpinfo_t *)(iomp + 1);
166da14cebeSEric Cheng for (i = 0; i < iomp->dih_n_groups; i++) {
167da14cebeSEric Cheng bzero(&attr, sizeof (attr));
168da14cebeSEric Cheng
169da14cebeSEric Cheng (void) strlcpy(attr.hg_link_name,
170da14cebeSEric Cheng dhip->dhi_link_name, sizeof (attr.hg_link_name));
171da14cebeSEric Cheng attr.hg_grp_num = dhip->dhi_grp_num;
172da14cebeSEric Cheng attr.hg_grp_type = dhip->dhi_grp_type;
173da14cebeSEric Cheng attr.hg_n_rings = dhip->dhi_n_rings;
1740dc2366fSVenugopal Iyer for (j = 0; j < dhip->dhi_n_rings; j++)
1750dc2366fSVenugopal Iyer attr.hg_rings[j] = dhip->dhi_rings[j];
1760dc2366fSVenugopal Iyer dladm_sort_index_list(attr.hg_rings, attr.hg_n_rings);
177da14cebeSEric Cheng attr.hg_n_clnts = dhip->dhi_n_clnts;
178da14cebeSEric Cheng (void) strlcpy(attr.hg_client_names,
179da14cebeSEric Cheng dhip->dhi_clnts, sizeof (attr.hg_client_names));
180da14cebeSEric Cheng
181da14cebeSEric Cheng if (!(*fn)(arg, &attr))
182da14cebeSEric Cheng break;
183da14cebeSEric Cheng dhip++;
184da14cebeSEric Cheng }
185da14cebeSEric Cheng }
186da14cebeSEric Cheng free(iomp);
187da14cebeSEric Cheng return (ret);
188da14cebeSEric Cheng }
189da14cebeSEric Cheng
190da14cebeSEric Cheng /*
191da14cebeSEric Cheng * Invoke the specified callback for each MAC address entry defined on
192da14cebeSEric Cheng * the specified device.
193da14cebeSEric Cheng */
194da14cebeSEric Cheng int
dladm_walk_macaddr(dladm_handle_t handle,datalink_id_t linkid,void * arg,boolean_t (* fn)(void *,dladm_macaddr_attr_t *))1954ac67f02SAnurag S. Maskey dladm_walk_macaddr(dladm_handle_t handle, datalink_id_t linkid, void *arg,
196da14cebeSEric Cheng boolean_t (*fn)(void *, dladm_macaddr_attr_t *))
197da14cebeSEric Cheng {
1984ac67f02SAnurag S. Maskey int bufsize, ret;
199da14cebeSEric Cheng int nmacaddr = 1024;
200da14cebeSEric Cheng dld_ioc_macaddrget_t *iomp = NULL;
201da14cebeSEric Cheng
202da14cebeSEric Cheng bufsize = sizeof (dld_ioc_macaddrget_t) +
203da14cebeSEric Cheng nmacaddr * sizeof (dld_macaddrinfo_t);
204da14cebeSEric Cheng
205da14cebeSEric Cheng if ((iomp = (dld_ioc_macaddrget_t *)calloc(1, bufsize)) == NULL)
206da14cebeSEric Cheng return (-1);
207da14cebeSEric Cheng
208da14cebeSEric Cheng iomp->dig_size = nmacaddr * sizeof (dld_macaddrinfo_t);
209da14cebeSEric Cheng iomp->dig_linkid = linkid;
210da14cebeSEric Cheng
2114ac67f02SAnurag S. Maskey ret = ioctl(dladm_dld_fd(handle), DLDIOC_MACADDRGET, iomp);
212da14cebeSEric Cheng if (ret == 0) {
213*4202e8bfSToomas Soome uint_t i;
214da14cebeSEric Cheng dld_macaddrinfo_t *dmip;
215da14cebeSEric Cheng dladm_macaddr_attr_t attr;
216da14cebeSEric Cheng
217da14cebeSEric Cheng dmip = (dld_macaddrinfo_t *)(iomp + 1);
218da14cebeSEric Cheng for (i = 0; i < iomp->dig_count; i++) {
219da14cebeSEric Cheng bzero(&attr, sizeof (attr));
220da14cebeSEric Cheng
221da14cebeSEric Cheng attr.ma_slot = dmip->dmi_slot;
222da14cebeSEric Cheng attr.ma_flags = 0;
223da14cebeSEric Cheng if (dmip->dmi_flags & DLDIOCMACADDR_USED)
224da14cebeSEric Cheng attr.ma_flags |= DLADM_MACADDR_USED;
225da14cebeSEric Cheng bcopy(dmip->dmi_addr, attr.ma_addr,
226da14cebeSEric Cheng dmip->dmi_addrlen);
227da14cebeSEric Cheng attr.ma_addrlen = dmip->dmi_addrlen;
228da14cebeSEric Cheng (void) strlcpy(attr.ma_client_name,
229da14cebeSEric Cheng dmip->dmi_client_name, MAXNAMELEN);
230da14cebeSEric Cheng attr.ma_client_linkid = dmip->dma_client_linkid;
231da14cebeSEric Cheng
232da14cebeSEric Cheng if (!(*fn)(arg, &attr))
233da14cebeSEric Cheng break;
234da14cebeSEric Cheng dmip++;
235da14cebeSEric Cheng }
236da14cebeSEric Cheng }
237da14cebeSEric Cheng free(iomp);
238da14cebeSEric Cheng return (ret);
239da14cebeSEric Cheng }
240da14cebeSEric Cheng
241f595a68aSyz147064 /*
242bbf21555SRichard Lowe * These routines are used by administration tools such as dladm(8) to
243f595a68aSyz147064 * iterate through the list of MAC interfaces
244f595a68aSyz147064 */
245f595a68aSyz147064
246f595a68aSyz147064 typedef struct dladm_mac_dev {
247f595a68aSyz147064 char dm_name[MAXNAMELEN];
248f595a68aSyz147064 struct dladm_mac_dev *dm_next;
249f595a68aSyz147064 } dladm_mac_dev_t;
250f595a68aSyz147064
251f595a68aSyz147064 typedef struct macadm_walk {
252f595a68aSyz147064 dladm_mac_dev_t *dmd_dev_list;
253f595a68aSyz147064 } dladm_mac_walk_t;
254f595a68aSyz147064
255f595a68aSyz147064 /*
256f595a68aSyz147064 * Local callback invoked for each DDI_NT_NET node.
257f595a68aSyz147064 */
258f595a68aSyz147064 static int
i_dladm_mac_walk(di_node_t node,di_minor_t minor __unused,void * arg)25920535e13SToomas Soome i_dladm_mac_walk(di_node_t node, di_minor_t minor __unused, void *arg)
260f595a68aSyz147064 {
261f595a68aSyz147064 dladm_mac_walk_t *dmwp = arg;
262f595a68aSyz147064 dladm_mac_dev_t *dmdp = dmwp->dmd_dev_list;
263f595a68aSyz147064 dladm_mac_dev_t **last_dmdp = &dmwp->dmd_dev_list;
264f595a68aSyz147064 char mac[MAXNAMELEN];
265f595a68aSyz147064
266f595a68aSyz147064 (void) snprintf(mac, MAXNAMELEN, "%s%d",
267f595a68aSyz147064 di_driver_name(node), di_instance(node));
268f595a68aSyz147064
269f595a68aSyz147064 /*
270f595a68aSyz147064 * Skip aggregations.
271f595a68aSyz147064 */
272f595a68aSyz147064 if (strcmp("aggr", di_driver_name(node)) == 0)
273f595a68aSyz147064 return (DI_WALK_CONTINUE);
274f595a68aSyz147064
275d62bc4baSyz147064 /*
276d62bc4baSyz147064 * Skip softmacs.
277d62bc4baSyz147064 */
278d62bc4baSyz147064 if (strcmp("softmac", di_driver_name(node)) == 0)
279d62bc4baSyz147064 return (DI_WALK_CONTINUE);
280d62bc4baSyz147064
281f595a68aSyz147064 while (dmdp) {
282f595a68aSyz147064 /*
283f595a68aSyz147064 * Skip duplicates.
284f595a68aSyz147064 */
285f595a68aSyz147064 if (strcmp(dmdp->dm_name, mac) == 0)
286f595a68aSyz147064 return (DI_WALK_CONTINUE);
287f595a68aSyz147064
288f595a68aSyz147064 last_dmdp = &dmdp->dm_next;
289f595a68aSyz147064 dmdp = dmdp->dm_next;
290f595a68aSyz147064 }
291f595a68aSyz147064
292f595a68aSyz147064 if ((dmdp = malloc(sizeof (*dmdp))) == NULL)
293f595a68aSyz147064 return (DI_WALK_CONTINUE);
294f595a68aSyz147064
295f595a68aSyz147064 (void) strlcpy(dmdp->dm_name, mac, MAXNAMELEN);
296f595a68aSyz147064 dmdp->dm_next = NULL;
297f595a68aSyz147064 *last_dmdp = dmdp;
298f595a68aSyz147064
299f595a68aSyz147064 return (DI_WALK_CONTINUE);
300f595a68aSyz147064 }
301f595a68aSyz147064
302f595a68aSyz147064 /*
303d62bc4baSyz147064 * Invoke the specified callback for each DDI_NT_NET node.
304f595a68aSyz147064 */
305d62bc4baSyz147064 dladm_status_t
dladm_mac_walk(int (* fn)(const char *,void * arg),void * arg)306d62bc4baSyz147064 dladm_mac_walk(int (*fn)(const char *, void *arg), void *arg)
307f595a68aSyz147064 {
308f595a68aSyz147064 di_node_t root;
309f595a68aSyz147064 dladm_mac_walk_t dmw;
310f595a68aSyz147064 dladm_mac_dev_t *dmdp, *next;
311d62bc4baSyz147064 boolean_t done = B_FALSE;
312f595a68aSyz147064
313f595a68aSyz147064 if ((root = di_init("/", DINFOCACHE)) == DI_NODE_NIL)
314d62bc4baSyz147064 return (dladm_errno2status(errno));
315f595a68aSyz147064
316f595a68aSyz147064 dmw.dmd_dev_list = NULL;
317f595a68aSyz147064
318f595a68aSyz147064 (void) di_walk_minor(root, DDI_NT_NET, DI_CHECK_ALIAS, &dmw,
319f595a68aSyz147064 i_dladm_mac_walk);
320f595a68aSyz147064
321f595a68aSyz147064 di_fini(root);
322f595a68aSyz147064
323f595a68aSyz147064 dmdp = dmw.dmd_dev_list;
324f595a68aSyz147064 for (dmdp = dmw.dmd_dev_list; dmdp != NULL; dmdp = next) {
325f595a68aSyz147064 next = dmdp->dm_next;
326d62bc4baSyz147064 if (!done &&
327d62bc4baSyz147064 ((*fn)(dmdp->dm_name, arg) == DLADM_WALK_TERMINATE)) {
328d62bc4baSyz147064 done = B_TRUE;
329d62bc4baSyz147064 }
330f595a68aSyz147064 free(dmdp);
331f595a68aSyz147064 }
332f595a68aSyz147064
333d62bc4baSyz147064 return (DLADM_STATUS_OK);
334f595a68aSyz147064 }
335f595a68aSyz147064
336f595a68aSyz147064 /*
337d62bc4baSyz147064 * Get the current attributes of the specified datalink.
338f595a68aSyz147064 */
339d62bc4baSyz147064 dladm_status_t
dladm_info(dladm_handle_t handle,datalink_id_t linkid,dladm_attr_t * dap)3404ac67f02SAnurag S. Maskey dladm_info(dladm_handle_t handle, datalink_id_t linkid, dladm_attr_t *dap)
341f595a68aSyz147064 {
3424ac67f02SAnurag S. Maskey return (i_dladm_info(handle, linkid, dap));
343f595a68aSyz147064 }
344f595a68aSyz147064
345f595a68aSyz147064 const char *
dladm_linkstate2str(link_state_t state,char * buf)346f595a68aSyz147064 dladm_linkstate2str(link_state_t state, char *buf)
347f595a68aSyz147064 {
348f595a68aSyz147064 const char *s;
349f595a68aSyz147064
350f595a68aSyz147064 switch (state) {
351f595a68aSyz147064 case LINK_STATE_UP:
352f595a68aSyz147064 s = "up";
353f595a68aSyz147064 break;
354f595a68aSyz147064 case LINK_STATE_DOWN:
355f595a68aSyz147064 s = "down";
356f595a68aSyz147064 break;
357f595a68aSyz147064 default:
358f595a68aSyz147064 s = "unknown";
359f595a68aSyz147064 break;
360f595a68aSyz147064 }
361f595a68aSyz147064 (void) snprintf(buf, DLADM_STRSIZE, "%s", s);
362f595a68aSyz147064 return (buf);
363f595a68aSyz147064 }
364f595a68aSyz147064
365f595a68aSyz147064 const char *
dladm_linkduplex2str(link_duplex_t duplex,char * buf)366f595a68aSyz147064 dladm_linkduplex2str(link_duplex_t duplex, char *buf)
367f595a68aSyz147064 {
368f595a68aSyz147064 const char *s;
369f595a68aSyz147064
370f595a68aSyz147064 switch (duplex) {
371f595a68aSyz147064 case LINK_DUPLEX_FULL:
372f595a68aSyz147064 s = "full";
373f595a68aSyz147064 break;
374f595a68aSyz147064 case LINK_DUPLEX_HALF:
375f595a68aSyz147064 s = "half";
376f595a68aSyz147064 break;
377f595a68aSyz147064 default:
378f595a68aSyz147064 s = "unknown";
379f595a68aSyz147064 break;
380f595a68aSyz147064 }
381f595a68aSyz147064 (void) snprintf(buf, DLADM_STRSIZE, "%s", s);
382f595a68aSyz147064 return (buf);
383f595a68aSyz147064 }
384f595a68aSyz147064
385f595a68aSyz147064 /*
386d62bc4baSyz147064 * Case 1: rename an existing link1 to a link2 that does not exist.
387d62bc4baSyz147064 * Result: <linkid1, link2>
388d62bc4baSyz147064 */
389d62bc4baSyz147064 static dladm_status_t
i_dladm_rename_link_c1(dladm_handle_t handle,datalink_id_t linkid1,const char * link1,const char * link2,uint32_t flags)3904ac67f02SAnurag S. Maskey i_dladm_rename_link_c1(dladm_handle_t handle, datalink_id_t linkid1,
3914ac67f02SAnurag S. Maskey const char *link1, const char *link2, uint32_t flags)
392d62bc4baSyz147064 {
393d62bc4baSyz147064 dld_ioc_rename_t dir;
394d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_OK;
395d62bc4baSyz147064
396d62bc4baSyz147064 /*
397d62bc4baSyz147064 * Link is currently available. Check to see whether anything is
398d62bc4baSyz147064 * holding this link to prevent a rename operation.
399d62bc4baSyz147064 */
400d62bc4baSyz147064 if (flags & DLADM_OPT_ACTIVE) {
401d62bc4baSyz147064 dir.dir_linkid1 = linkid1;
402d62bc4baSyz147064 dir.dir_linkid2 = DATALINK_INVALID_LINKID;
403d62bc4baSyz147064 (void) strlcpy(dir.dir_link, link2, MAXLINKNAMELEN);
404d62bc4baSyz147064
4054ac67f02SAnurag S. Maskey if (ioctl(dladm_dld_fd(handle), DLDIOC_RENAME, &dir) < 0) {
406d62bc4baSyz147064 status = dladm_errno2status(errno);
407d62bc4baSyz147064 return (status);
408d62bc4baSyz147064 }
409d62bc4baSyz147064 }
410d62bc4baSyz147064
4114ac67f02SAnurag S. Maskey status = dladm_remap_datalink_id(handle, linkid1, link2);
4122b24ab6bSSebastien Roy if (status != DLADM_STATUS_OK && (flags & DLADM_OPT_ACTIVE)) {
413d62bc4baSyz147064 (void) strlcpy(dir.dir_link, link1, MAXLINKNAMELEN);
4144ac67f02SAnurag S. Maskey (void) ioctl(dladm_dld_fd(handle), DLDIOC_RENAME, &dir);
415d62bc4baSyz147064 }
416d62bc4baSyz147064 return (status);
417d62bc4baSyz147064 }
418d62bc4baSyz147064
419d62bc4baSyz147064 typedef struct link_hold_arg_s {
420d62bc4baSyz147064 datalink_id_t linkid;
421d62bc4baSyz147064 datalink_id_t holder;
422d62bc4baSyz147064 uint32_t flags;
423d62bc4baSyz147064 } link_hold_arg_t;
424d62bc4baSyz147064
425d62bc4baSyz147064 static int
i_dladm_aggr_link_hold(dladm_handle_t handle,datalink_id_t aggrid,void * arg)4264ac67f02SAnurag S. Maskey i_dladm_aggr_link_hold(dladm_handle_t handle, datalink_id_t aggrid, void *arg)
427d62bc4baSyz147064 {
428d62bc4baSyz147064 link_hold_arg_t *hold_arg = arg;
429d62bc4baSyz147064 dladm_aggr_grp_attr_t ginfo;
430d62bc4baSyz147064 dladm_status_t status;
431*4202e8bfSToomas Soome uint_t i;
432d62bc4baSyz147064
4334ac67f02SAnurag S. Maskey status = dladm_aggr_info(handle, aggrid, &ginfo, hold_arg->flags);
434d62bc4baSyz147064 if (status != DLADM_STATUS_OK)
435d62bc4baSyz147064 return (DLADM_WALK_CONTINUE);
436d62bc4baSyz147064
437d62bc4baSyz147064 for (i = 0; i < ginfo.lg_nports; i++) {
438d62bc4baSyz147064 if (ginfo.lg_ports[i].lp_linkid == hold_arg->linkid) {
439d62bc4baSyz147064 hold_arg->holder = aggrid;
440d62bc4baSyz147064 return (DLADM_WALK_TERMINATE);
441d62bc4baSyz147064 }
442d62bc4baSyz147064 }
443d62bc4baSyz147064 return (DLADM_WALK_CONTINUE);
444d62bc4baSyz147064 }
445d62bc4baSyz147064
446d62bc4baSyz147064 static int
i_dladm_vlan_link_hold(dladm_handle_t handle,datalink_id_t vlanid,void * arg)4474ac67f02SAnurag S. Maskey i_dladm_vlan_link_hold(dladm_handle_t handle, datalink_id_t vlanid, void *arg)
448d62bc4baSyz147064 {
449d62bc4baSyz147064 link_hold_arg_t *hold_arg = arg;
450d62bc4baSyz147064 dladm_vlan_attr_t vinfo;
451d62bc4baSyz147064 dladm_status_t status;
452d62bc4baSyz147064
4534ac67f02SAnurag S. Maskey status = dladm_vlan_info(handle, vlanid, &vinfo, hold_arg->flags);
454d62bc4baSyz147064 if (status != DLADM_STATUS_OK)
455d62bc4baSyz147064 return (DLADM_WALK_CONTINUE);
456d62bc4baSyz147064
457d62bc4baSyz147064 if (vinfo.dv_linkid == hold_arg->linkid) {
458d62bc4baSyz147064 hold_arg->holder = vlanid;
459d62bc4baSyz147064 return (DLADM_WALK_TERMINATE);
460d62bc4baSyz147064 }
461d62bc4baSyz147064 return (DLADM_WALK_CONTINUE);
462d62bc4baSyz147064 }
463d62bc4baSyz147064
464d62bc4baSyz147064 /*
465d62bc4baSyz147064 * Case 2: rename an available physical link link1 to a REMOVED physical link
466d62bc4baSyz147064 * link2. As a result, link1 directly inherits all datalinks configured
467d62bc4baSyz147064 * over link2 (linkid2).
468d62bc4baSyz147064 * Result: <linkid2, link2, link1_phymaj, link1_phyinst, link1_devname,
469d62bc4baSyz147064 * link2_other_attr>
470d62bc4baSyz147064 */
471d62bc4baSyz147064 static dladm_status_t
i_dladm_rename_link_c2(dladm_handle_t handle,datalink_id_t linkid1,datalink_id_t linkid2)4724ac67f02SAnurag S. Maskey i_dladm_rename_link_c2(dladm_handle_t handle, datalink_id_t linkid1,
4734ac67f02SAnurag S. Maskey datalink_id_t linkid2)
474d62bc4baSyz147064 {
475d62bc4baSyz147064 rcm_handle_t *rcm_hdl = NULL;
476d62bc4baSyz147064 nvlist_t *nvl = NULL;
477d62bc4baSyz147064 link_hold_arg_t arg;
478d62bc4baSyz147064 dld_ioc_rename_t dir;
479d62bc4baSyz147064 dladm_conf_t conf1, conf2;
480d62bc4baSyz147064 char devname[MAXLINKNAMELEN];
481d62bc4baSyz147064 uint64_t phymaj, phyinst;
482d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_OK;
483d62bc4baSyz147064
484d62bc4baSyz147064 /*
485d62bc4baSyz147064 * First check if linkid1 is associated with any persistent
486d62bc4baSyz147064 * aggregations or VLANs. If yes, return BUSY.
487d62bc4baSyz147064 */
488d62bc4baSyz147064 arg.linkid = linkid1;
489d62bc4baSyz147064 arg.holder = DATALINK_INVALID_LINKID;
490d62bc4baSyz147064 arg.flags = DLADM_OPT_PERSIST;
4914ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(i_dladm_aggr_link_hold, handle, &arg,
492d62bc4baSyz147064 DATALINK_CLASS_AGGR, DATALINK_ANY_MEDIATYPE, DLADM_OPT_PERSIST);
493d62bc4baSyz147064 if (arg.holder != DATALINK_INVALID_LINKID)
494d62bc4baSyz147064 return (DLADM_STATUS_LINKBUSY);
495d62bc4baSyz147064
496d62bc4baSyz147064 arg.flags = DLADM_OPT_PERSIST;
4974ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(i_dladm_vlan_link_hold, handle, &arg,
498d62bc4baSyz147064 DATALINK_CLASS_VLAN, DATALINK_ANY_MEDIATYPE, DLADM_OPT_PERSIST);
499d62bc4baSyz147064 if (arg.holder != DATALINK_INVALID_LINKID)
500d62bc4baSyz147064 return (DLADM_STATUS_LINKBUSY);
501d62bc4baSyz147064
502d62bc4baSyz147064 /*
503d62bc4baSyz147064 * Send DLDIOC_RENAME to request to rename link1's linkid to
504d62bc4baSyz147064 * be linkid2. This will check whether link1 is used by any
505d62bc4baSyz147064 * aggregations or VLANs, or is held by any application. If yes,
506d62bc4baSyz147064 * return failure.
507d62bc4baSyz147064 */
508d62bc4baSyz147064 dir.dir_linkid1 = linkid1;
509d62bc4baSyz147064 dir.dir_linkid2 = linkid2;
5104ac67f02SAnurag S. Maskey if (ioctl(dladm_dld_fd(handle), DLDIOC_RENAME, &dir) < 0)
511d62bc4baSyz147064 status = dladm_errno2status(errno);
512d62bc4baSyz147064
513d62bc4baSyz147064 if (status != DLADM_STATUS_OK) {
514d62bc4baSyz147064 return (status);
515d62bc4baSyz147064 }
516d62bc4baSyz147064
517d62bc4baSyz147064 /*
518d62bc4baSyz147064 * Now change the phymaj, phyinst and devname associated with linkid1
519d62bc4baSyz147064 * to be associated with linkid2. Before doing that, the old active
520d62bc4baSyz147064 * linkprop of linkid1 should be deleted.
521d62bc4baSyz147064 */
5224ac67f02SAnurag S. Maskey (void) dladm_set_linkprop(handle, linkid1, NULL, NULL, 0,
5234ac67f02SAnurag S. Maskey DLADM_OPT_ACTIVE);
524d62bc4baSyz147064
52532715170SCathy Zhou if (((status = dladm_getsnap_conf(handle, linkid1, &conf1)) !=
5264ac67f02SAnurag S. Maskey DLADM_STATUS_OK) ||
5274ac67f02SAnurag S. Maskey ((status = dladm_get_conf_field(handle, conf1, FDEVNAME, devname,
528d62bc4baSyz147064 MAXLINKNAMELEN)) != DLADM_STATUS_OK) ||
5294ac67f02SAnurag S. Maskey ((status = dladm_get_conf_field(handle, conf1, FPHYMAJ, &phymaj,
530d62bc4baSyz147064 sizeof (uint64_t))) != DLADM_STATUS_OK) ||
5314ac67f02SAnurag S. Maskey ((status = dladm_get_conf_field(handle, conf1, FPHYINST, &phyinst,
532d62bc4baSyz147064 sizeof (uint64_t))) != DLADM_STATUS_OK) ||
53332715170SCathy Zhou ((status = dladm_open_conf(handle, linkid2, &conf2)) !=
5344ac67f02SAnurag S. Maskey DLADM_STATUS_OK)) {
535d62bc4baSyz147064 dir.dir_linkid1 = linkid2;
536d62bc4baSyz147064 dir.dir_linkid2 = linkid1;
5374ac67f02SAnurag S. Maskey (void) dladm_init_linkprop(handle, linkid1, B_FALSE);
5384ac67f02SAnurag S. Maskey (void) ioctl(dladm_dld_fd(handle), DLDIOC_RENAME, &dir);
539d62bc4baSyz147064 return (status);
540d62bc4baSyz147064 }
541d62bc4baSyz147064
5424ac67f02SAnurag S. Maskey dladm_destroy_conf(handle, conf1);
5434ac67f02SAnurag S. Maskey (void) dladm_set_conf_field(handle, conf2, FDEVNAME, DLADM_TYPE_STR,
5444ac67f02SAnurag S. Maskey devname);
5454ac67f02SAnurag S. Maskey (void) dladm_set_conf_field(handle, conf2, FPHYMAJ, DLADM_TYPE_UINT64,
5464ac67f02SAnurag S. Maskey &phymaj);
5474ac67f02SAnurag S. Maskey (void) dladm_set_conf_field(handle, conf2, FPHYINST,
548d62bc4baSyz147064 DLADM_TYPE_UINT64, &phyinst);
5494ac67f02SAnurag S. Maskey (void) dladm_write_conf(handle, conf2);
5504ac67f02SAnurag S. Maskey dladm_destroy_conf(handle, conf2);
551d62bc4baSyz147064
552d62bc4baSyz147064 /*
553d62bc4baSyz147064 * Delete link1 and mark link2 up.
554d62bc4baSyz147064 */
5552b24ab6bSSebastien Roy (void) dladm_remove_conf(handle, linkid1);
5564ac67f02SAnurag S. Maskey (void) dladm_destroy_datalink_id(handle, linkid1, DLADM_OPT_ACTIVE |
557d62bc4baSyz147064 DLADM_OPT_PERSIST);
5584ac67f02SAnurag S. Maskey (void) dladm_up_datalink_id(handle, linkid2);
559d62bc4baSyz147064
560d62bc4baSyz147064 /*
561d62bc4baSyz147064 * Now generate the RCM_RESOURCE_LINK_NEW sysevent which can be
562d62bc4baSyz147064 * consumed by the RCM framework to restore all the datalink and
563d62bc4baSyz147064 * IP configuration.
564d62bc4baSyz147064 */
565d62bc4baSyz147064 status = DLADM_STATUS_FAILED;
566d62bc4baSyz147064 if ((nvlist_alloc(&nvl, 0, 0) != 0) ||
567d62bc4baSyz147064 (nvlist_add_uint64(nvl, RCM_NV_LINKID, linkid2) != 0)) {
568d62bc4baSyz147064 goto done;
569d62bc4baSyz147064 }
570d62bc4baSyz147064
571d62bc4baSyz147064 if (rcm_alloc_handle(NULL, 0, NULL, &rcm_hdl) != RCM_SUCCESS)
572d62bc4baSyz147064 goto done;
573d62bc4baSyz147064
574d62bc4baSyz147064 if (rcm_notify_event(rcm_hdl, RCM_RESOURCE_LINK_NEW, 0, nvl, NULL) ==
575d62bc4baSyz147064 RCM_SUCCESS) {
576d62bc4baSyz147064 status = DLADM_STATUS_OK;
577d62bc4baSyz147064 }
578d62bc4baSyz147064
579d62bc4baSyz147064 done:
580d62bc4baSyz147064 if (rcm_hdl != NULL)
581d62bc4baSyz147064 (void) rcm_free_handle(rcm_hdl);
582d62bc4baSyz147064 nvlist_free(nvl);
583d62bc4baSyz147064 return (status);
584d62bc4baSyz147064 }
585d62bc4baSyz147064
586d62bc4baSyz147064 /*
587d62bc4baSyz147064 * case 3: rename a non-existent link to a REMOVED physical link.
588d62bc4baSyz147064 * Set the removed physical link's device name to link1, so that
589d62bc4baSyz147064 * when link1 attaches, it inherits all the link configuration of
590d62bc4baSyz147064 * the removed physical link.
591d62bc4baSyz147064 */
592d62bc4baSyz147064 static dladm_status_t
i_dladm_rename_link_c3(dladm_handle_t handle,const char * link1,datalink_id_t linkid2)5934ac67f02SAnurag S. Maskey i_dladm_rename_link_c3(dladm_handle_t handle, const char *link1,
5944ac67f02SAnurag S. Maskey datalink_id_t linkid2)
595d62bc4baSyz147064 {
596d62bc4baSyz147064 dladm_conf_t conf;
597d62bc4baSyz147064 dladm_status_t status;
598d62bc4baSyz147064
599d62bc4baSyz147064 if (!dladm_valid_linkname(link1))
600d62bc4baSyz147064 return (DLADM_STATUS_LINKINVAL);
601d62bc4baSyz147064
60232715170SCathy Zhou status = dladm_open_conf(handle, linkid2, &conf);
603d62bc4baSyz147064 if (status != DLADM_STATUS_OK)
604d62bc4baSyz147064 goto done;
605d62bc4baSyz147064
6064ac67f02SAnurag S. Maskey if ((status = dladm_set_conf_field(handle, conf, FDEVNAME,
6074ac67f02SAnurag S. Maskey DLADM_TYPE_STR, link1)) == DLADM_STATUS_OK) {
6084ac67f02SAnurag S. Maskey status = dladm_write_conf(handle, conf);
609d62bc4baSyz147064 }
610d62bc4baSyz147064
6114ac67f02SAnurag S. Maskey dladm_destroy_conf(handle, conf);
612d62bc4baSyz147064
613d62bc4baSyz147064 done:
614d62bc4baSyz147064 return (status);
615d62bc4baSyz147064 }
616d62bc4baSyz147064
617d62bc4baSyz147064 dladm_status_t
dladm_rename_link(dladm_handle_t handle,const char * link1,const char * link2)6184ac67f02SAnurag S. Maskey dladm_rename_link(dladm_handle_t handle, const char *link1, const char *link2)
619d62bc4baSyz147064 {
620d62bc4baSyz147064 datalink_id_t linkid1 = DATALINK_INVALID_LINKID;
621d62bc4baSyz147064 datalink_id_t linkid2 = DATALINK_INVALID_LINKID;
622d62bc4baSyz147064 uint32_t flags1, flags2;
623d62bc4baSyz147064 datalink_class_t class1, class2;
624d62bc4baSyz147064 uint32_t media1, media2;
625d62bc4baSyz147064 boolean_t remphy2 = B_FALSE;
626d62bc4baSyz147064 dladm_status_t status;
627d62bc4baSyz147064
6284ac67f02SAnurag S. Maskey (void) dladm_name2info(handle, link1, &linkid1, &flags1, &class1,
6294ac67f02SAnurag S. Maskey &media1);
6304ac67f02SAnurag S. Maskey if ((dladm_name2info(handle, link2, &linkid2, &flags2, &class2,
6314ac67f02SAnurag S. Maskey &media2) == DLADM_STATUS_OK) && (class2 == DATALINK_CLASS_PHYS) &&
632d62bc4baSyz147064 (flags2 == DLADM_OPT_PERSIST)) {
633d62bc4baSyz147064 /*
634d62bc4baSyz147064 * see whether link2 is a removed physical link.
635d62bc4baSyz147064 */
636d62bc4baSyz147064 remphy2 = B_TRUE;
637d62bc4baSyz147064 }
638d62bc4baSyz147064
639d62bc4baSyz147064 if (linkid1 != DATALINK_INVALID_LINKID) {
640d62bc4baSyz147064 if (linkid2 == DATALINK_INVALID_LINKID) {
641d62bc4baSyz147064 /*
642d62bc4baSyz147064 * case 1: rename an existing link to a link that
643d62bc4baSyz147064 * does not exist.
644d62bc4baSyz147064 */
6454ac67f02SAnurag S. Maskey status = i_dladm_rename_link_c1(handle, linkid1, link1,
6464ac67f02SAnurag S. Maskey link2, flags1);
647d62bc4baSyz147064 } else if (remphy2) {
648d62bc4baSyz147064 /*
649d62bc4baSyz147064 * case 2: rename an available link to a REMOVED
650d62bc4baSyz147064 * physical link. Return failure if link1 is not
651d62bc4baSyz147064 * an active physical link.
652d62bc4baSyz147064 */
653d62bc4baSyz147064 if ((class1 != class2) || (media1 != media2) ||
654d62bc4baSyz147064 !(flags1 & DLADM_OPT_ACTIVE)) {
655d62bc4baSyz147064 status = DLADM_STATUS_BADARG;
656d62bc4baSyz147064 } else {
6574ac67f02SAnurag S. Maskey status = i_dladm_rename_link_c2(handle, linkid1,
658d62bc4baSyz147064 linkid2);
659d62bc4baSyz147064 }
660d62bc4baSyz147064 } else {
661d62bc4baSyz147064 status = DLADM_STATUS_EXIST;
662d62bc4baSyz147064 }
663d62bc4baSyz147064 } else if (remphy2) {
6644ac67f02SAnurag S. Maskey status = i_dladm_rename_link_c3(handle, link1, linkid2);
665d62bc4baSyz147064 } else {
666d62bc4baSyz147064 status = DLADM_STATUS_NOTFOUND;
667d62bc4baSyz147064 }
668d62bc4baSyz147064 return (status);
669d62bc4baSyz147064 }
670d62bc4baSyz147064
671d62bc4baSyz147064 typedef struct consumer_del_phys_arg_s {
672d62bc4baSyz147064 datalink_id_t linkid;
673d62bc4baSyz147064 } consumer_del_phys_arg_t;
674d62bc4baSyz147064
675d62bc4baSyz147064 static int
i_dladm_vlan_link_del(dladm_handle_t handle,datalink_id_t vlanid,void * arg)6764ac67f02SAnurag S. Maskey i_dladm_vlan_link_del(dladm_handle_t handle, datalink_id_t vlanid, void *arg)
677d62bc4baSyz147064 {
678d62bc4baSyz147064 consumer_del_phys_arg_t *del_arg = arg;
679d62bc4baSyz147064 dladm_vlan_attr_t vinfo;
680d62bc4baSyz147064 dladm_status_t status;
681d62bc4baSyz147064
6824ac67f02SAnurag S. Maskey status = dladm_vlan_info(handle, vlanid, &vinfo, DLADM_OPT_PERSIST);
683d62bc4baSyz147064 if (status != DLADM_STATUS_OK)
684d62bc4baSyz147064 return (DLADM_WALK_CONTINUE);
685d62bc4baSyz147064
686d62bc4baSyz147064 if (vinfo.dv_linkid == del_arg->linkid)
6874ac67f02SAnurag S. Maskey (void) dladm_vlan_delete(handle, vlanid, DLADM_OPT_PERSIST);
688d62bc4baSyz147064 return (DLADM_WALK_CONTINUE);
689d62bc4baSyz147064 }
690d62bc4baSyz147064
691d62bc4baSyz147064 static int
i_dladm_part_link_del(dladm_handle_t handle,datalink_id_t partid,void * arg)6921cfa752fSRamaswamy Tummala i_dladm_part_link_del(dladm_handle_t handle, datalink_id_t partid, void *arg)
6931cfa752fSRamaswamy Tummala {
6941cfa752fSRamaswamy Tummala consumer_del_phys_arg_t *del_arg = arg;
6951cfa752fSRamaswamy Tummala dladm_part_attr_t pinfo;
6961cfa752fSRamaswamy Tummala dladm_status_t status;
6971cfa752fSRamaswamy Tummala
6981cfa752fSRamaswamy Tummala status = dladm_part_info(handle, partid, &pinfo, DLADM_OPT_PERSIST);
6991cfa752fSRamaswamy Tummala if (status != DLADM_STATUS_OK)
7001cfa752fSRamaswamy Tummala return (DLADM_WALK_CONTINUE);
7011cfa752fSRamaswamy Tummala
7021cfa752fSRamaswamy Tummala if (pinfo.dia_physlinkid == del_arg->linkid)
7031cfa752fSRamaswamy Tummala (void) dladm_part_delete(handle, partid, DLADM_OPT_PERSIST);
7041cfa752fSRamaswamy Tummala return (DLADM_WALK_CONTINUE);
7051cfa752fSRamaswamy Tummala }
7061cfa752fSRamaswamy Tummala
7071cfa752fSRamaswamy Tummala static int
i_dladm_aggr_link_del(dladm_handle_t handle,datalink_id_t aggrid,void * arg)7084ac67f02SAnurag S. Maskey i_dladm_aggr_link_del(dladm_handle_t handle, datalink_id_t aggrid, void *arg)
709d62bc4baSyz147064 {
710d62bc4baSyz147064 consumer_del_phys_arg_t *del_arg = arg;
711d62bc4baSyz147064 dladm_aggr_grp_attr_t ginfo;
712d62bc4baSyz147064 dladm_status_t status;
713d62bc4baSyz147064 dladm_aggr_port_attr_db_t port[1];
714*4202e8bfSToomas Soome uint_t i;
715d62bc4baSyz147064
7164ac67f02SAnurag S. Maskey status = dladm_aggr_info(handle, aggrid, &ginfo, DLADM_OPT_PERSIST);
717d62bc4baSyz147064 if (status != DLADM_STATUS_OK)
718d62bc4baSyz147064 return (DLADM_WALK_CONTINUE);
719d62bc4baSyz147064
720d62bc4baSyz147064 for (i = 0; i < ginfo.lg_nports; i++)
721d62bc4baSyz147064 if (ginfo.lg_ports[i].lp_linkid == del_arg->linkid)
722d62bc4baSyz147064 break;
723d62bc4baSyz147064
724d62bc4baSyz147064 if (i != ginfo.lg_nports) {
725d62bc4baSyz147064 if (ginfo.lg_nports == 1 && i == 0) {
726d62bc4baSyz147064 consumer_del_phys_arg_t aggr_del_arg;
727d62bc4baSyz147064
728d62bc4baSyz147064 /*
729d62bc4baSyz147064 * First delete all the VLANs on this aggregation, then
730d62bc4baSyz147064 * delete the aggregation itself.
731d62bc4baSyz147064 */
732d62bc4baSyz147064 aggr_del_arg.linkid = aggrid;
733d62bc4baSyz147064 (void) dladm_walk_datalink_id(i_dladm_vlan_link_del,
7344ac67f02SAnurag S. Maskey handle, &aggr_del_arg, DATALINK_CLASS_VLAN,
735d62bc4baSyz147064 DATALINK_ANY_MEDIATYPE, DLADM_OPT_PERSIST);
7364ac67f02SAnurag S. Maskey (void) dladm_aggr_delete(handle, aggrid,
7374ac67f02SAnurag S. Maskey DLADM_OPT_PERSIST);
738d62bc4baSyz147064 } else {
739d62bc4baSyz147064 port[0].lp_linkid = del_arg->linkid;
7404ac67f02SAnurag S. Maskey (void) dladm_aggr_remove(handle, aggrid, 1, port,
741d62bc4baSyz147064 DLADM_OPT_PERSIST);
742d62bc4baSyz147064 }
743d62bc4baSyz147064 }
744d62bc4baSyz147064 return (DLADM_WALK_CONTINUE);
745d62bc4baSyz147064 }
746d62bc4baSyz147064
747d62bc4baSyz147064 typedef struct del_phys_arg_s {
748d62bc4baSyz147064 dladm_status_t rval;
749d62bc4baSyz147064 } del_phys_arg_t;
750d62bc4baSyz147064
751d62bc4baSyz147064 static int
i_dladm_phys_delete(dladm_handle_t handle,datalink_id_t linkid,void * arg)7524ac67f02SAnurag S. Maskey i_dladm_phys_delete(dladm_handle_t handle, datalink_id_t linkid, void *arg)
753d62bc4baSyz147064 {
754d62bc4baSyz147064 uint32_t flags;
755d62bc4baSyz147064 datalink_class_t class;
756d62bc4baSyz147064 uint32_t media;
757d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_OK;
758d62bc4baSyz147064 del_phys_arg_t *del_phys_arg = arg;
759d62bc4baSyz147064 consumer_del_phys_arg_t del_arg;
760d62bc4baSyz147064
7614ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(handle, linkid, &flags, &class,
762d62bc4baSyz147064 &media, NULL, 0)) != DLADM_STATUS_OK) {
763d62bc4baSyz147064 goto done;
764d62bc4baSyz147064 }
765d62bc4baSyz147064
766d62bc4baSyz147064 /*
767d62bc4baSyz147064 * see whether this link is a removed physical link.
768d62bc4baSyz147064 */
769d62bc4baSyz147064 if ((class != DATALINK_CLASS_PHYS) || !(flags & DLADM_OPT_PERSIST) ||
770d62bc4baSyz147064 (flags & DLADM_OPT_ACTIVE)) {
771d62bc4baSyz147064 status = DLADM_STATUS_BADARG;
772d62bc4baSyz147064 goto done;
773d62bc4baSyz147064 }
774d62bc4baSyz147064
775d62bc4baSyz147064 if (media == DL_ETHER) {
776d62bc4baSyz147064 del_arg.linkid = linkid;
7774ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(i_dladm_aggr_link_del, handle,
7784ac67f02SAnurag S. Maskey &del_arg, DATALINK_CLASS_AGGR, DATALINK_ANY_MEDIATYPE,
779d62bc4baSyz147064 DLADM_OPT_PERSIST);
7804ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(i_dladm_vlan_link_del, handle,
7814ac67f02SAnurag S. Maskey &del_arg, DATALINK_CLASS_VLAN, DATALINK_ANY_MEDIATYPE,
782d62bc4baSyz147064 DLADM_OPT_PERSIST);
7831cfa752fSRamaswamy Tummala } else if (media == DL_IB) {
7841cfa752fSRamaswamy Tummala del_arg.linkid = linkid;
7851cfa752fSRamaswamy Tummala (void) dladm_walk_datalink_id(i_dladm_part_link_del, handle,
7861cfa752fSRamaswamy Tummala &del_arg, DATALINK_CLASS_PART, DL_IB, DLADM_OPT_PERSIST);
787d62bc4baSyz147064 }
788d62bc4baSyz147064
7894ac67f02SAnurag S. Maskey (void) dladm_remove_conf(handle, linkid);
7902b24ab6bSSebastien Roy (void) dladm_destroy_datalink_id(handle, linkid, DLADM_OPT_PERSIST);
791d62bc4baSyz147064 done:
792d62bc4baSyz147064 del_phys_arg->rval = status;
793d62bc4baSyz147064 return (DLADM_WALK_CONTINUE);
794d62bc4baSyz147064 }
795d62bc4baSyz147064
796d62bc4baSyz147064 dladm_status_t
dladm_phys_delete(dladm_handle_t handle,datalink_id_t linkid)7974ac67f02SAnurag S. Maskey dladm_phys_delete(dladm_handle_t handle, datalink_id_t linkid)
798d62bc4baSyz147064 {
799d62bc4baSyz147064 del_phys_arg_t arg = {DLADM_STATUS_OK};
800d62bc4baSyz147064
801d62bc4baSyz147064 if (linkid == DATALINK_ALL_LINKID) {
8024ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(i_dladm_phys_delete, handle, &arg,
803d62bc4baSyz147064 DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE,
804d62bc4baSyz147064 DLADM_OPT_PERSIST);
805d62bc4baSyz147064 return (DLADM_STATUS_OK);
806d62bc4baSyz147064 } else {
8074ac67f02SAnurag S. Maskey (void) i_dladm_phys_delete(handle, linkid, &arg);
808d62bc4baSyz147064 return (arg.rval);
809d62bc4baSyz147064 }
810d62bc4baSyz147064 }
811d62bc4baSyz147064
812d62bc4baSyz147064 dladm_status_t
dladm_phys_info(dladm_handle_t handle,datalink_id_t linkid,dladm_phys_attr_t * dpap,uint32_t flags)8134ac67f02SAnurag S. Maskey dladm_phys_info(dladm_handle_t handle, datalink_id_t linkid,
8144ac67f02SAnurag S. Maskey dladm_phys_attr_t *dpap, uint32_t flags)
815d62bc4baSyz147064 {
816d62bc4baSyz147064 dladm_status_t status;
817d62bc4baSyz147064
818d62bc4baSyz147064 assert(flags == DLADM_OPT_ACTIVE || flags == DLADM_OPT_PERSIST);
819d62bc4baSyz147064
820d62bc4baSyz147064 switch (flags) {
821d62bc4baSyz147064 case DLADM_OPT_PERSIST: {
822d62bc4baSyz147064 dladm_conf_t conf;
823d62bc4baSyz147064
82432715170SCathy Zhou status = dladm_getsnap_conf(handle, linkid, &conf);
825d62bc4baSyz147064 if (status != DLADM_STATUS_OK)
826d62bc4baSyz147064 return (status);
827d62bc4baSyz147064
8284ac67f02SAnurag S. Maskey status = dladm_get_conf_field(handle, conf, FDEVNAME,
8294ac67f02SAnurag S. Maskey dpap->dp_dev, MAXLINKNAMELEN);
8304ac67f02SAnurag S. Maskey dladm_destroy_conf(handle, conf);
831d62bc4baSyz147064 return (status);
832d62bc4baSyz147064 }
833d62bc4baSyz147064 case DLADM_OPT_ACTIVE: {
834d62bc4baSyz147064 dld_ioc_phys_attr_t dip;
835d62bc4baSyz147064
836d62bc4baSyz147064 dip.dip_linkid = linkid;
8374ac67f02SAnurag S. Maskey if (ioctl(dladm_dld_fd(handle), DLDIOC_PHYS_ATTR, &dip) < 0) {
838d62bc4baSyz147064 status = dladm_errno2status(errno);
839d62bc4baSyz147064 return (status);
840d62bc4baSyz147064 }
841d62bc4baSyz147064 dpap->dp_novanity = dip.dip_novanity;
842d62bc4baSyz147064 (void) strlcpy(dpap->dp_dev, dip.dip_dev, MAXLINKNAMELEN);
843d62bc4baSyz147064 return (DLADM_STATUS_OK);
844d62bc4baSyz147064 }
845d62bc4baSyz147064 default:
846d62bc4baSyz147064 return (DLADM_STATUS_BADARG);
847d62bc4baSyz147064 }
848d62bc4baSyz147064 }
849d62bc4baSyz147064
850d62bc4baSyz147064 typedef struct i_walk_dev_state_s {
851d62bc4baSyz147064 const char *devname;
852d62bc4baSyz147064 datalink_id_t linkid;
853d62bc4baSyz147064 boolean_t found;
854d62bc4baSyz147064 } i_walk_dev_state_t;
855d62bc4baSyz147064
856d62bc4baSyz147064 int
i_dladm_walk_dev2linkid(dladm_handle_t handle,datalink_id_t linkid,void * arg)8574ac67f02SAnurag S. Maskey i_dladm_walk_dev2linkid(dladm_handle_t handle, datalink_id_t linkid, void *arg)
858d62bc4baSyz147064 {
859d62bc4baSyz147064 dladm_phys_attr_t dpa;
860d62bc4baSyz147064 dladm_status_t status;
861d62bc4baSyz147064 i_walk_dev_state_t *statep = arg;
862d62bc4baSyz147064
8634ac67f02SAnurag S. Maskey status = dladm_phys_info(handle, linkid, &dpa, DLADM_OPT_PERSIST);
864d62bc4baSyz147064 if ((status == DLADM_STATUS_OK) &&
865d62bc4baSyz147064 (strcmp(statep->devname, dpa.dp_dev) == 0)) {
866d62bc4baSyz147064 statep->found = B_TRUE;
867d62bc4baSyz147064 statep->linkid = linkid;
868d62bc4baSyz147064 return (DLADM_WALK_TERMINATE);
869d62bc4baSyz147064 }
870d62bc4baSyz147064 return (DLADM_WALK_CONTINUE);
871d62bc4baSyz147064 }
872d62bc4baSyz147064
873d62bc4baSyz147064 /*
874d62bc4baSyz147064 * Get the linkid from the physical device name.
875d62bc4baSyz147064 */
876d62bc4baSyz147064 dladm_status_t
dladm_dev2linkid(dladm_handle_t handle,const char * devname,datalink_id_t * linkidp)8774ac67f02SAnurag S. Maskey dladm_dev2linkid(dladm_handle_t handle, const char *devname,
8784ac67f02SAnurag S. Maskey datalink_id_t *linkidp)
879d62bc4baSyz147064 {
880d62bc4baSyz147064 i_walk_dev_state_t state;
881d62bc4baSyz147064
882d62bc4baSyz147064 state.found = B_FALSE;
883d62bc4baSyz147064 state.devname = devname;
884d62bc4baSyz147064
8854ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(i_dladm_walk_dev2linkid, handle, &state,
886d62bc4baSyz147064 DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE, DLADM_OPT_PERSIST);
887d62bc4baSyz147064 if (state.found == B_TRUE) {
888d62bc4baSyz147064 *linkidp = state.linkid;
889d62bc4baSyz147064 return (DLADM_STATUS_OK);
890d62bc4baSyz147064 } else {
891d62bc4baSyz147064 return (dladm_errno2status(ENOENT));
892d62bc4baSyz147064 }
893d62bc4baSyz147064 }
894d62bc4baSyz147064
895d62bc4baSyz147064 static int
parse_devname(const char * devname,char * driver,uint_t * ppa,size_t maxlen)896d62bc4baSyz147064 parse_devname(const char *devname, char *driver, uint_t *ppa, size_t maxlen)
897d62bc4baSyz147064 {
898d62bc4baSyz147064 char *cp, *tp;
899d62bc4baSyz147064 int len;
900d62bc4baSyz147064
901d62bc4baSyz147064 /*
902d62bc4baSyz147064 * device name length must not be 0, and it must end with digit.
903d62bc4baSyz147064 */
904d62bc4baSyz147064 if (((len = strlen(devname)) == 0) || !isdigit(devname[len - 1]))
905d62bc4baSyz147064 return (EINVAL);
906d62bc4baSyz147064
907d62bc4baSyz147064 (void) strlcpy(driver, devname, maxlen);
908d62bc4baSyz147064 cp = (char *)&driver[len - 1];
909d62bc4baSyz147064
910d62bc4baSyz147064 for (tp = cp; isdigit(*tp); tp--) {
911d62bc4baSyz147064 if (tp <= driver)
912d62bc4baSyz147064 return (EINVAL);
913d62bc4baSyz147064 }
914d62bc4baSyz147064
915d62bc4baSyz147064 *ppa = atoi(tp + 1);
916d62bc4baSyz147064 *(tp + 1) = '\0';
917d62bc4baSyz147064 return (0);
918d62bc4baSyz147064 }
919d62bc4baSyz147064
920d62bc4baSyz147064 dladm_status_t
dladm_linkid2legacyname(dladm_handle_t handle,datalink_id_t linkid,char * dev,size_t len)9214ac67f02SAnurag S. Maskey dladm_linkid2legacyname(dladm_handle_t handle, datalink_id_t linkid, char *dev,
9224ac67f02SAnurag S. Maskey size_t len)
923d62bc4baSyz147064 {
924d62bc4baSyz147064 char devname[MAXLINKNAMELEN];
925d62bc4baSyz147064 uint16_t vid = VLAN_ID_NONE;
926d62bc4baSyz147064 datalink_class_t class;
927d62bc4baSyz147064 dladm_status_t status;
928d62bc4baSyz147064
9294ac67f02SAnurag S. Maskey status = dladm_datalink_id2info(handle, linkid, NULL, &class, NULL,
9304ac67f02SAnurag S. Maskey NULL, 0);
931d62bc4baSyz147064 if (status != DLADM_STATUS_OK)
932d62bc4baSyz147064 goto done;
933d62bc4baSyz147064
934d62bc4baSyz147064 /*
935d62bc4baSyz147064 * If this is a VLAN, we must first determine the class and linkid of
936d62bc4baSyz147064 * the link the VLAN has been created over.
937d62bc4baSyz147064 */
938d62bc4baSyz147064 if (class == DATALINK_CLASS_VLAN) {
939d62bc4baSyz147064 dladm_vlan_attr_t dva;
940d62bc4baSyz147064
9414ac67f02SAnurag S. Maskey status = dladm_vlan_info(handle, linkid, &dva,
9424ac67f02SAnurag S. Maskey DLADM_OPT_ACTIVE);
943d62bc4baSyz147064 if (status != DLADM_STATUS_OK)
944d62bc4baSyz147064 goto done;
945d62bc4baSyz147064 linkid = dva.dv_linkid;
946d62bc4baSyz147064 vid = dva.dv_vid;
947d62bc4baSyz147064
9484ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(handle, linkid, NULL,
9494ac67f02SAnurag S. Maskey &class, NULL, NULL, 0)) != DLADM_STATUS_OK) {
950d62bc4baSyz147064 goto done;
951d62bc4baSyz147064 }
952d62bc4baSyz147064 }
953d62bc4baSyz147064
954d62bc4baSyz147064 switch (class) {
955d62bc4baSyz147064 case DATALINK_CLASS_AGGR: {
956d62bc4baSyz147064 dladm_aggr_grp_attr_t dga;
957d62bc4baSyz147064
9584ac67f02SAnurag S. Maskey status = dladm_aggr_info(handle, linkid, &dga,
9594ac67f02SAnurag S. Maskey DLADM_OPT_ACTIVE);
960d62bc4baSyz147064 if (status != DLADM_STATUS_OK)
961d62bc4baSyz147064 goto done;
962d62bc4baSyz147064
963d62bc4baSyz147064 if (dga.lg_key == 0) {
964d62bc4baSyz147064 /*
965d62bc4baSyz147064 * If the key was not specified when the aggregation
966d62bc4baSyz147064 * is created, we cannot guess its /dev node name.
967d62bc4baSyz147064 */
968d62bc4baSyz147064 status = DLADM_STATUS_BADARG;
969d62bc4baSyz147064 goto done;
970d62bc4baSyz147064 }
971d62bc4baSyz147064 (void) snprintf(devname, MAXLINKNAMELEN, "aggr%d", dga.lg_key);
972d62bc4baSyz147064 break;
973d62bc4baSyz147064 }
974d62bc4baSyz147064 case DATALINK_CLASS_PHYS: {
975d62bc4baSyz147064 dladm_phys_attr_t dpa;
976d62bc4baSyz147064
9774ac67f02SAnurag S. Maskey status = dladm_phys_info(handle, linkid, &dpa,
9784ac67f02SAnurag S. Maskey DLADM_OPT_PERSIST);
979d62bc4baSyz147064 if (status != DLADM_STATUS_OK)
980d62bc4baSyz147064 goto done;
981d62bc4baSyz147064
982d62bc4baSyz147064 (void) strlcpy(devname, dpa.dp_dev, MAXLINKNAMELEN);
983d62bc4baSyz147064 break;
984d62bc4baSyz147064 }
985d62bc4baSyz147064 default:
986d62bc4baSyz147064 status = DLADM_STATUS_BADARG;
987d62bc4baSyz147064 goto done;
988d62bc4baSyz147064 }
989d62bc4baSyz147064
990d62bc4baSyz147064 if (vid != VLAN_ID_NONE) {
991d62bc4baSyz147064 char drv[MAXNAMELEN];
992d62bc4baSyz147064 uint_t ppa;
993*4202e8bfSToomas Soome int rv;
994d62bc4baSyz147064
995d62bc4baSyz147064 if (parse_devname(devname, drv, &ppa, MAXNAMELEN) != 0) {
996d62bc4baSyz147064 status = DLADM_STATUS_BADARG;
997d62bc4baSyz147064 goto done;
998d62bc4baSyz147064 }
999*4202e8bfSToomas Soome rv = snprintf(dev, len, "%s%d", drv, vid * 1000 + ppa);
1000*4202e8bfSToomas Soome if (rv < 0)
1001*4202e8bfSToomas Soome status = DLADM_STATUS_FAILED;
1002*4202e8bfSToomas Soome else if ((size_t)rv >= len)
1003d62bc4baSyz147064 status = DLADM_STATUS_TOOSMALL;
1004d62bc4baSyz147064 } else {
1005d62bc4baSyz147064 if (strlcpy(dev, devname, len) >= len)
1006d62bc4baSyz147064 status = DLADM_STATUS_TOOSMALL;
1007d62bc4baSyz147064 }
1008d62bc4baSyz147064
1009d62bc4baSyz147064 done:
1010d62bc4baSyz147064 return (status);
1011f595a68aSyz147064 }
1012e7801d59Ssowmini
1013e7801d59Ssowmini dladm_status_t
dladm_parselink(const char * dev,char * provider,uint_t * ppa)1014e7801d59Ssowmini dladm_parselink(const char *dev, char *provider, uint_t *ppa)
1015e7801d59Ssowmini {
1016e7801d59Ssowmini ifspec_t ifsp;
1017e7801d59Ssowmini
1018e7801d59Ssowmini if (dev == NULL || !ifparse_ifspec(dev, &ifsp))
1019e7801d59Ssowmini return (DLADM_STATUS_LINKINVAL);
1020e7801d59Ssowmini
1021e7801d59Ssowmini if (provider != NULL)
1022e7801d59Ssowmini (void) strlcpy(provider, ifsp.ifsp_devnm, DLPI_LINKNAME_MAX);
1023e7801d59Ssowmini
1024e7801d59Ssowmini if (ppa != NULL)
1025e7801d59Ssowmini *ppa = ifsp.ifsp_ppa;
1026e7801d59Ssowmini
1027e7801d59Ssowmini return (DLADM_STATUS_OK);
1028e7801d59Ssowmini }
1029