xref: /titanic_52/usr/src/lib/libdladm/common/libdlether.c (revision 4784fcbddec533c366d5e92ce1ca3a4a2ce69495)
1*4784fcbdSSowmini Varadhan /*
2*4784fcbdSSowmini Varadhan  * CDDL HEADER START
3*4784fcbdSSowmini Varadhan  *
4*4784fcbdSSowmini Varadhan  * The contents of this file are subject to the terms of the
5*4784fcbdSSowmini Varadhan  * Common Development and Distribution License (the "License").
6*4784fcbdSSowmini Varadhan  * You may not use this file except in compliance with the License.
7*4784fcbdSSowmini Varadhan  *
8*4784fcbdSSowmini Varadhan  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*4784fcbdSSowmini Varadhan  * or http://www.opensolaris.org/os/licensing.
10*4784fcbdSSowmini Varadhan  * See the License for the specific language governing permissions
11*4784fcbdSSowmini Varadhan  * and limitations under the License.
12*4784fcbdSSowmini Varadhan  *
13*4784fcbdSSowmini Varadhan  * When distributing Covered Code, include this CDDL HEADER in each
14*4784fcbdSSowmini Varadhan  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*4784fcbdSSowmini Varadhan  * If applicable, add the following below this CDDL HEADER, with the
16*4784fcbdSSowmini Varadhan  * fields enclosed by brackets "[]" replaced with your own identifying
17*4784fcbdSSowmini Varadhan  * information: Portions Copyright [yyyy] [name of copyright owner]
18*4784fcbdSSowmini Varadhan  *
19*4784fcbdSSowmini Varadhan  * CDDL HEADER END
20*4784fcbdSSowmini Varadhan  */
21*4784fcbdSSowmini Varadhan /*
22*4784fcbdSSowmini Varadhan  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*4784fcbdSSowmini Varadhan  * Use is subject to license terms.
24*4784fcbdSSowmini Varadhan  */
25*4784fcbdSSowmini Varadhan 
26*4784fcbdSSowmini Varadhan #include <stdlib.h>
27*4784fcbdSSowmini Varadhan #include <string.h>
28*4784fcbdSSowmini Varadhan #include <strings.h>
29*4784fcbdSSowmini Varadhan #include <sys/types.h>
30*4784fcbdSSowmini Varadhan #include <libdladm_impl.h>
31*4784fcbdSSowmini Varadhan #include <libdllink.h>
32*4784fcbdSSowmini Varadhan #include <libdlstat.h>
33*4784fcbdSSowmini Varadhan #include <libdlether.h>
34*4784fcbdSSowmini Varadhan 
35*4784fcbdSSowmini Varadhan /*
36*4784fcbdSSowmini Varadhan  * Ethernet administration library.
37*4784fcbdSSowmini Varadhan  */
38*4784fcbdSSowmini Varadhan 
39*4784fcbdSSowmini Varadhan /*
40*4784fcbdSSowmini Varadhan  * kstat names for extracting attributes.
41*4784fcbdSSowmini Varadhan  */
42*4784fcbdSSowmini Varadhan typedef struct ether_spdx_s {
43*4784fcbdSSowmini Varadhan 	dladm_ether_spdx_t eth_spdx;
44*4784fcbdSSowmini Varadhan 	char *eth_spdx_stat_name;
45*4784fcbdSSowmini Varadhan } ether_spdx_t;
46*4784fcbdSSowmini Varadhan 
47*4784fcbdSSowmini Varadhan static ether_spdx_t cap_spdx[] = {
48*4784fcbdSSowmini Varadhan 	{{1000, LINK_DUPLEX_FULL}, "cap_1000fdx"},
49*4784fcbdSSowmini Varadhan 	{{1000, LINK_DUPLEX_HALF}, "cap_1000hdx"},
50*4784fcbdSSowmini Varadhan 	{{100, LINK_DUPLEX_FULL}, "cap_100fdx"},
51*4784fcbdSSowmini Varadhan 	{{100, LINK_DUPLEX_HALF}, "cap_100hdx"},
52*4784fcbdSSowmini Varadhan 	{{10, LINK_DUPLEX_FULL}, "cap_10fdx"},
53*4784fcbdSSowmini Varadhan 	{{10, LINK_DUPLEX_HALF}, "cap_10hdx"},
54*4784fcbdSSowmini Varadhan 	{{0, LINK_DUPLEX_UNKNOWN}, NULL}
55*4784fcbdSSowmini Varadhan };
56*4784fcbdSSowmini Varadhan 
57*4784fcbdSSowmini Varadhan static ether_spdx_t adv_cap_spdx[] = {
58*4784fcbdSSowmini Varadhan 	{{1000, LINK_DUPLEX_FULL}, "adv_cap_1000fdx"},
59*4784fcbdSSowmini Varadhan 	{{1000, LINK_DUPLEX_HALF}, "adv_cap_1000hdx"},
60*4784fcbdSSowmini Varadhan 	{{100, LINK_DUPLEX_FULL}, "adv_cap_100fdx"},
61*4784fcbdSSowmini Varadhan 	{{100, LINK_DUPLEX_HALF}, "adv_cap_100hdx"},
62*4784fcbdSSowmini Varadhan 	{{10, LINK_DUPLEX_FULL}, "adv_cap_10fdx"},
63*4784fcbdSSowmini Varadhan 	{{10, LINK_DUPLEX_HALF}, "adv_cap_10hdx"},
64*4784fcbdSSowmini Varadhan 	{{0, LINK_DUPLEX_UNKNOWN}, NULL}
65*4784fcbdSSowmini Varadhan };
66*4784fcbdSSowmini Varadhan 
67*4784fcbdSSowmini Varadhan static ether_spdx_t lp_cap_spdx[] = {
68*4784fcbdSSowmini Varadhan 	{{1000, LINK_DUPLEX_FULL}, "lp_cap_1000fdx"},
69*4784fcbdSSowmini Varadhan 	{{1000, LINK_DUPLEX_HALF}, "lp_cap_1000hdx"},
70*4784fcbdSSowmini Varadhan 	{{100, LINK_DUPLEX_FULL}, "lp_cap_100fdx"},
71*4784fcbdSSowmini Varadhan 	{{100, LINK_DUPLEX_HALF}, "lp_cap_100hdx"},
72*4784fcbdSSowmini Varadhan 	{{10, LINK_DUPLEX_FULL}, "lp_cap_10fdx"},
73*4784fcbdSSowmini Varadhan 	{{10, LINK_DUPLEX_HALF}, "lp_cap_10hdx"},
74*4784fcbdSSowmini Varadhan 	{{0, LINK_DUPLEX_UNKNOWN}, NULL}
75*4784fcbdSSowmini Varadhan };
76*4784fcbdSSowmini Varadhan 
77*4784fcbdSSowmini Varadhan typedef struct attr_kstat_s {
78*4784fcbdSSowmini Varadhan 	char *autoneg_stat;
79*4784fcbdSSowmini Varadhan 	char *pause_stat;
80*4784fcbdSSowmini Varadhan 	char *asmpause_stat;
81*4784fcbdSSowmini Varadhan 	char *fault_stat;
82*4784fcbdSSowmini Varadhan 	ether_spdx_t *spdx_stat;
83*4784fcbdSSowmini Varadhan } attr_kstat_t;
84*4784fcbdSSowmini Varadhan 
85*4784fcbdSSowmini Varadhan static attr_kstat_t attrstat[] =  {
86*4784fcbdSSowmini Varadhan 	{"link_autoneg",	/* current */
87*4784fcbdSSowmini Varadhan 	    "link_pause",	"link_asmpause",	NULL,
88*4784fcbdSSowmini Varadhan 	    NULL},
89*4784fcbdSSowmini Varadhan 
90*4784fcbdSSowmini Varadhan 	{"cap_autoneg",		/* capable */
91*4784fcbdSSowmini Varadhan 	    "cap_pause",	"cap_asmpause",		"cap_rem_fault",
92*4784fcbdSSowmini Varadhan 	    cap_spdx},
93*4784fcbdSSowmini Varadhan 
94*4784fcbdSSowmini Varadhan 	{"adv_cap_autoneg",	/* advertised */
95*4784fcbdSSowmini Varadhan 	    "adv_cap_pause",	"adv_cap_asmpause",	"adv_rem_fault",
96*4784fcbdSSowmini Varadhan 	    adv_cap_spdx},
97*4784fcbdSSowmini Varadhan 
98*4784fcbdSSowmini Varadhan 	{"lp_cap_autoneg",	/* peer advertised */
99*4784fcbdSSowmini Varadhan 	    "lp_cap_pause",	"lp_cap_asmpause",	"lp_rem_fault",
100*4784fcbdSSowmini Varadhan 	    lp_cap_spdx}
101*4784fcbdSSowmini Varadhan };
102*4784fcbdSSowmini Varadhan 
103*4784fcbdSSowmini Varadhan /*
104*4784fcbdSSowmini Varadhan  * Get the speed-duplex stats specified in the ether_spdx_t table passed in
105*4784fcbdSSowmini Varadhan  * by querying the appropriate kstat for each entry in the table.
106*4784fcbdSSowmini Varadhan  */
107*4784fcbdSSowmini Varadhan static dladm_status_t
108*4784fcbdSSowmini Varadhan i_dladm_get_spdx(datalink_id_t linkid, dladm_ether_attr_t *eattr,
109*4784fcbdSSowmini Varadhan     ether_spdx_t *spdx_stat)
110*4784fcbdSSowmini Varadhan {
111*4784fcbdSSowmini Varadhan 	int		i, nspdx = 0;
112*4784fcbdSSowmini Varadhan 	uint32_t	speed;
113*4784fcbdSSowmini Varadhan 	dladm_status_t	status;
114*4784fcbdSSowmini Varadhan 	void		*ptr;
115*4784fcbdSSowmini Varadhan 
116*4784fcbdSSowmini Varadhan 	eattr->le_spdx = NULL;
117*4784fcbdSSowmini Varadhan 	for (i = 0; spdx_stat[i].eth_spdx_stat_name != NULL; i++) {
118*4784fcbdSSowmini Varadhan 		if ((status = dladm_get_single_mac_stat(linkid,
119*4784fcbdSSowmini Varadhan 		    spdx_stat[i].eth_spdx_stat_name,
120*4784fcbdSSowmini Varadhan 		    KSTAT_DATA_UINT32, &speed)) != DLADM_STATUS_OK) {
121*4784fcbdSSowmini Varadhan 
122*4784fcbdSSowmini Varadhan 			if (status == DLADM_STATUS_NOTFOUND) {
123*4784fcbdSSowmini Varadhan 				/*
124*4784fcbdSSowmini Varadhan 				 * Missing statistic.
125*4784fcbdSSowmini Varadhan 				 * Skip this one and try the rest.
126*4784fcbdSSowmini Varadhan 				 */
127*4784fcbdSSowmini Varadhan 				continue;
128*4784fcbdSSowmini Varadhan 			} else {
129*4784fcbdSSowmini Varadhan 				free(eattr->le_spdx);
130*4784fcbdSSowmini Varadhan 				eattr->le_num_spdx = 0;
131*4784fcbdSSowmini Varadhan 				return (status);
132*4784fcbdSSowmini Varadhan 			}
133*4784fcbdSSowmini Varadhan 		}
134*4784fcbdSSowmini Varadhan 		if (speed == 0)
135*4784fcbdSSowmini Varadhan 			continue;
136*4784fcbdSSowmini Varadhan 		nspdx++;
137*4784fcbdSSowmini Varadhan 		ptr = realloc(eattr->le_spdx,
138*4784fcbdSSowmini Varadhan 		    nspdx * sizeof (dladm_ether_spdx_t));
139*4784fcbdSSowmini Varadhan 		if (ptr != NULL) {
140*4784fcbdSSowmini Varadhan 			eattr->le_spdx = ptr;
141*4784fcbdSSowmini Varadhan 		} else {
142*4784fcbdSSowmini Varadhan 			free(eattr->le_spdx);
143*4784fcbdSSowmini Varadhan 			eattr->le_num_spdx = 0;
144*4784fcbdSSowmini Varadhan 			return (DLADM_STATUS_NOMEM);
145*4784fcbdSSowmini Varadhan 		}
146*4784fcbdSSowmini Varadhan 		eattr->le_spdx[nspdx - 1] = spdx_stat[i].eth_spdx;
147*4784fcbdSSowmini Varadhan 	}
148*4784fcbdSSowmini Varadhan 	eattr->le_num_spdx = nspdx;
149*4784fcbdSSowmini Varadhan 	return (DLADM_STATUS_OK);
150*4784fcbdSSowmini Varadhan }
151*4784fcbdSSowmini Varadhan 
152*4784fcbdSSowmini Varadhan /*
153*4784fcbdSSowmini Varadhan  * Returns "yes" or "no" based on the autonegotion capabilities
154*4784fcbdSSowmini Varadhan  * for the parameter type indicated by ptype. The permissible
155*4784fcbdSSowmini Varadhan  * values for ptype are CURRENT, CAPABLE, ADV, PEERADV.
156*4784fcbdSSowmini Varadhan  */
157*4784fcbdSSowmini Varadhan char *
158*4784fcbdSSowmini Varadhan dladm_ether_autoneg2str(char *buf, size_t buflen, dladm_ether_info_t *eattr,
159*4784fcbdSSowmini Varadhan     int ptype)
160*4784fcbdSSowmini Varadhan {
161*4784fcbdSSowmini Varadhan 	boolean_t autoneg = eattr->lei_attr[ptype].le_autoneg;
162*4784fcbdSSowmini Varadhan 
163*4784fcbdSSowmini Varadhan 	(void) strlcpy(buf, (autoneg ? "yes" : "no"), buflen);
164*4784fcbdSSowmini Varadhan 	return (buf);
165*4784fcbdSSowmini Varadhan }
166*4784fcbdSSowmini Varadhan 
167*4784fcbdSSowmini Varadhan /*
168*4784fcbdSSowmini Varadhan  * Returns {"bi", "tx", "none"} based on the flow-control capabilities
169*4784fcbdSSowmini Varadhan  * for the parameter type indicated by ptype. The permissible
170*4784fcbdSSowmini Varadhan  * values for ptype are CURRENT, CAPABLE, ADV, PEERADV.
171*4784fcbdSSowmini Varadhan  */
172*4784fcbdSSowmini Varadhan char *
173*4784fcbdSSowmini Varadhan dladm_ether_pause2str(char *buf, size_t buflen, dladm_ether_info_t *eattr,
174*4784fcbdSSowmini Varadhan     int ptype)
175*4784fcbdSSowmini Varadhan {
176*4784fcbdSSowmini Varadhan 	boolean_t pause = eattr->lei_attr[ptype].le_pause;
177*4784fcbdSSowmini Varadhan 	boolean_t asmpause = eattr->lei_attr[ptype].le_asmpause;
178*4784fcbdSSowmini Varadhan 
179*4784fcbdSSowmini Varadhan 	if (pause)
180*4784fcbdSSowmini Varadhan 		(void) strlcpy(buf, "bi", buflen);
181*4784fcbdSSowmini Varadhan 	else if (asmpause)
182*4784fcbdSSowmini Varadhan 		(void) strlcpy(buf, "tx", buflen);
183*4784fcbdSSowmini Varadhan 	else
184*4784fcbdSSowmini Varadhan 		(void) strlcpy(buf, "none", buflen);
185*4784fcbdSSowmini Varadhan 	return (buf);
186*4784fcbdSSowmini Varadhan }
187*4784fcbdSSowmini Varadhan 
188*4784fcbdSSowmini Varadhan /*
189*4784fcbdSSowmini Varadhan  * For a given param type, parse the list of speed-duplex pairs in
190*4784fcbdSSowmini Varadhan  * the dladm_ether_info_t and return a  comma-separated string formatted
191*4784fcbdSSowmini Varadhan  * as <speed><speed-unit-char>-<duplex-chars> where <speed> is the value of
192*4784fcbdSSowmini Varadhan  * speed, in units specifid by the <speed-unit-char> which is one
193*4784fcbdSSowmini Varadhan  * of 'M' (Mbits/sec) or 'G' (Gigabits/sec).  The permissible values of
194*4784fcbdSSowmini Varadhan  * <duplex-chars> are 'u' (indicating duplex is "unknown") or one/both of
195*4784fcbdSSowmini Varadhan  * 'f', 'h' (indicating full-duplex and half-duplex respectively)
196*4784fcbdSSowmini Varadhan  */
197*4784fcbdSSowmini Varadhan extern char *
198*4784fcbdSSowmini Varadhan dladm_ether_spdx2str(char *buf, size_t buflen, dladm_ether_info_t *eattr,
199*4784fcbdSSowmini Varadhan     int ptype)
200*4784fcbdSSowmini Varadhan {
201*4784fcbdSSowmini Varadhan 	int		i, j;
202*4784fcbdSSowmini Varadhan 	boolean_t	is_full, is_half;
203*4784fcbdSSowmini Varadhan 	int		speed;
204*4784fcbdSSowmini Varadhan 	char		speed_unit;
205*4784fcbdSSowmini Varadhan 	char		tmpbuf[DLADM_STRSIZE];
206*4784fcbdSSowmini Varadhan 	dladm_ether_spdx_t *spdx;
207*4784fcbdSSowmini Varadhan 	uint32_t	nspdx;
208*4784fcbdSSowmini Varadhan 
209*4784fcbdSSowmini Varadhan 	spdx = eattr->lei_attr[ptype].le_spdx;
210*4784fcbdSSowmini Varadhan 	nspdx = eattr->lei_attr[ptype].le_num_spdx;
211*4784fcbdSSowmini Varadhan 	for (i = 0; i < nspdx; i++) {
212*4784fcbdSSowmini Varadhan 
213*4784fcbdSSowmini Varadhan 		speed = spdx[i].lesd_speed;
214*4784fcbdSSowmini Varadhan 
215*4784fcbdSSowmini Varadhan 		/*
216*4784fcbdSSowmini Varadhan 		 * if we have already covered this speed for
217*4784fcbdSSowmini Varadhan 		 * the <other>-duplex case before this, skip it
218*4784fcbdSSowmini Varadhan 		 */
219*4784fcbdSSowmini Varadhan 		for (j = 0; j < i; j++) {
220*4784fcbdSSowmini Varadhan 			if (speed == spdx[j].lesd_speed)
221*4784fcbdSSowmini Varadhan 				break;
222*4784fcbdSSowmini Varadhan 		}
223*4784fcbdSSowmini Varadhan 		if (j < i)
224*4784fcbdSSowmini Varadhan 			continue;
225*4784fcbdSSowmini Varadhan 
226*4784fcbdSSowmini Varadhan 		if (speed >= 1000) {
227*4784fcbdSSowmini Varadhan 			speed = speed/1000;
228*4784fcbdSSowmini Varadhan 			speed_unit = 'G';
229*4784fcbdSSowmini Varadhan 		} else {
230*4784fcbdSSowmini Varadhan 			speed_unit = 'M';
231*4784fcbdSSowmini Varadhan 		}
232*4784fcbdSSowmini Varadhan 		(void) snprintf(tmpbuf, DLADM_STRSIZE, "%d%c",
233*4784fcbdSSowmini Varadhan 		    speed, speed_unit);
234*4784fcbdSSowmini Varadhan 		if (i > 0)
235*4784fcbdSSowmini Varadhan 			(void) strncat(buf, ",", buflen);
236*4784fcbdSSowmini Varadhan 		(void) strncat(buf, tmpbuf, buflen);
237*4784fcbdSSowmini Varadhan 
238*4784fcbdSSowmini Varadhan 		is_full = is_half = B_FALSE;
239*4784fcbdSSowmini Varadhan 		/*
240*4784fcbdSSowmini Varadhan 		 * Find all the supported duplex values for this speed.
241*4784fcbdSSowmini Varadhan 		 */
242*4784fcbdSSowmini Varadhan 		for (j = 0; j < nspdx; j++) {
243*4784fcbdSSowmini Varadhan 			if (spdx[j].lesd_speed != spdx[i].lesd_speed)
244*4784fcbdSSowmini Varadhan 				continue;
245*4784fcbdSSowmini Varadhan 			if (spdx[j].lesd_duplex == LINK_DUPLEX_FULL)
246*4784fcbdSSowmini Varadhan 				is_full = B_TRUE;
247*4784fcbdSSowmini Varadhan 			if (spdx[j].lesd_duplex == LINK_DUPLEX_HALF)
248*4784fcbdSSowmini Varadhan 				is_half = B_TRUE;
249*4784fcbdSSowmini Varadhan 		}
250*4784fcbdSSowmini Varadhan 		if (is_full && is_half)
251*4784fcbdSSowmini Varadhan 			(void) strncat(buf, "-fh", buflen);
252*4784fcbdSSowmini Varadhan 		else if (is_full)
253*4784fcbdSSowmini Varadhan 			(void) strncat(buf, "-f", buflen);
254*4784fcbdSSowmini Varadhan 		else if (is_half)
255*4784fcbdSSowmini Varadhan 			(void) strncat(buf, "-h", buflen);
256*4784fcbdSSowmini Varadhan 	}
257*4784fcbdSSowmini Varadhan 	return (buf);
258*4784fcbdSSowmini Varadhan }
259*4784fcbdSSowmini Varadhan 
260*4784fcbdSSowmini Varadhan /*
261*4784fcbdSSowmini Varadhan  * Extract Ethernet attributes of the link specified by linkid.
262*4784fcbdSSowmini Varadhan  * Information for the CURRENT, CAPABLE, ADV and PEERADV parameter
263*4784fcbdSSowmini Varadhan  * types is extracted into the lei_attr[] entries in the dladm_ether_info_t.
264*4784fcbdSSowmini Varadhan  * On succesful return, the memory allocated in this function should be
265*4784fcbdSSowmini Varadhan  * freed by calling dladm_ether_info_done().
266*4784fcbdSSowmini Varadhan  */
267*4784fcbdSSowmini Varadhan extern dladm_status_t
268*4784fcbdSSowmini Varadhan dladm_ether_info(datalink_id_t linkid, dladm_ether_info_t *eattr)
269*4784fcbdSSowmini Varadhan {
270*4784fcbdSSowmini Varadhan 	uint32_t	autoneg, pause, asmpause, fault;
271*4784fcbdSSowmini Varadhan 	uint64_t	sp64;
272*4784fcbdSSowmini Varadhan 	dladm_status_t	status;
273*4784fcbdSSowmini Varadhan 	int		i;
274*4784fcbdSSowmini Varadhan 	link_duplex_t	link_duplex;
275*4784fcbdSSowmini Varadhan 
276*4784fcbdSSowmini Varadhan 	bzero(eattr, sizeof (*eattr));
277*4784fcbdSSowmini Varadhan 	status = dladm_datalink_id2info(linkid, NULL, NULL, NULL,
278*4784fcbdSSowmini Varadhan 	    eattr->lei_linkname, sizeof (eattr->lei_linkname));
279*4784fcbdSSowmini Varadhan 	if (status != DLADM_STATUS_OK)
280*4784fcbdSSowmini Varadhan 		goto bail;
281*4784fcbdSSowmini Varadhan 
282*4784fcbdSSowmini Varadhan 	/* get current values of speed, duplex, state of link */
283*4784fcbdSSowmini Varadhan 	eattr->lei_attr[CURRENT].le_num_spdx = 1;
284*4784fcbdSSowmini Varadhan 	eattr->lei_attr[CURRENT].le_spdx = malloc(sizeof (dladm_ether_spdx_t));
285*4784fcbdSSowmini Varadhan 	if (eattr->lei_attr[CURRENT].le_spdx == NULL) {
286*4784fcbdSSowmini Varadhan 		status = DLADM_STATUS_NOMEM;
287*4784fcbdSSowmini Varadhan 		goto bail;
288*4784fcbdSSowmini Varadhan 	}
289*4784fcbdSSowmini Varadhan 
290*4784fcbdSSowmini Varadhan 	if ((status = dladm_get_single_mac_stat(linkid, "ifspeed",
291*4784fcbdSSowmini Varadhan 	    KSTAT_DATA_UINT64, &sp64)) != DLADM_STATUS_OK)
292*4784fcbdSSowmini Varadhan 		goto bail;
293*4784fcbdSSowmini Varadhan 
294*4784fcbdSSowmini Varadhan 	if ((status = dladm_get_single_mac_stat(linkid, "link_duplex",
295*4784fcbdSSowmini Varadhan 	    KSTAT_DATA_UINT32, &link_duplex)) != DLADM_STATUS_OK)
296*4784fcbdSSowmini Varadhan 		goto bail;
297*4784fcbdSSowmini Varadhan 
298*4784fcbdSSowmini Varadhan 	eattr->lei_attr[CURRENT].le_spdx->lesd_speed = (int)(sp64/1000000ull);
299*4784fcbdSSowmini Varadhan 	eattr->lei_attr[CURRENT].le_spdx->lesd_duplex = link_duplex;
300*4784fcbdSSowmini Varadhan 
301*4784fcbdSSowmini Varadhan 	status = i_dladm_get_state(linkid, &eattr->lei_state);
302*4784fcbdSSowmini Varadhan 	if (status != DLADM_STATUS_OK)
303*4784fcbdSSowmini Varadhan 		goto bail;
304*4784fcbdSSowmini Varadhan 
305*4784fcbdSSowmini Varadhan 	/* get the auto, pause, asmpause, fault values */
306*4784fcbdSSowmini Varadhan 	for (i = CURRENT; i <= PEERADV; i++)  {
307*4784fcbdSSowmini Varadhan 
308*4784fcbdSSowmini Varadhan 		status = dladm_get_single_mac_stat(linkid,
309*4784fcbdSSowmini Varadhan 		    attrstat[i].autoneg_stat, KSTAT_DATA_UINT32, &autoneg);
310*4784fcbdSSowmini Varadhan 		if (status != DLADM_STATUS_OK)
311*4784fcbdSSowmini Varadhan 			goto bail;
312*4784fcbdSSowmini Varadhan 
313*4784fcbdSSowmini Varadhan 		status = dladm_get_single_mac_stat(linkid,
314*4784fcbdSSowmini Varadhan 		    attrstat[i].pause_stat, KSTAT_DATA_UINT32, &pause);
315*4784fcbdSSowmini Varadhan 		if (status != DLADM_STATUS_OK)
316*4784fcbdSSowmini Varadhan 			goto bail;
317*4784fcbdSSowmini Varadhan 
318*4784fcbdSSowmini Varadhan 		status = dladm_get_single_mac_stat(linkid,
319*4784fcbdSSowmini Varadhan 		    attrstat[i].asmpause_stat, KSTAT_DATA_UINT32, &asmpause);
320*4784fcbdSSowmini Varadhan 		if (status != DLADM_STATUS_OK)
321*4784fcbdSSowmini Varadhan 			goto bail;
322*4784fcbdSSowmini Varadhan 
323*4784fcbdSSowmini Varadhan 		eattr->lei_attr[i].le_autoneg = (autoneg != 0);
324*4784fcbdSSowmini Varadhan 		eattr->lei_attr[i].le_pause = (pause != 0);
325*4784fcbdSSowmini Varadhan 		eattr->lei_attr[i].le_asmpause = (asmpause != 0);
326*4784fcbdSSowmini Varadhan 
327*4784fcbdSSowmini Varadhan 		if (i == CURRENT)
328*4784fcbdSSowmini Varadhan 			continue;
329*4784fcbdSSowmini Varadhan 		status = dladm_get_single_mac_stat(linkid,
330*4784fcbdSSowmini Varadhan 		    attrstat[i].fault_stat, KSTAT_DATA_UINT32, &fault);
331*4784fcbdSSowmini Varadhan 		if (status != DLADM_STATUS_OK)
332*4784fcbdSSowmini Varadhan 			goto bail;
333*4784fcbdSSowmini Varadhan 		eattr->lei_attr[i].le_fault = (pause != 0);
334*4784fcbdSSowmini Varadhan 
335*4784fcbdSSowmini Varadhan 		/* get all the supported speed/duplex values */
336*4784fcbdSSowmini Varadhan 		status = i_dladm_get_spdx(linkid, &eattr->lei_attr[i],
337*4784fcbdSSowmini Varadhan 		    attrstat[i].spdx_stat);
338*4784fcbdSSowmini Varadhan 		if (status != DLADM_STATUS_OK)
339*4784fcbdSSowmini Varadhan 			goto bail;
340*4784fcbdSSowmini Varadhan 	}
341*4784fcbdSSowmini Varadhan 	eattr->lei_attr[CURRENT].le_fault =
342*4784fcbdSSowmini Varadhan 	    eattr->lei_attr[ADV].le_fault || eattr->lei_attr[PEERADV].le_fault;
343*4784fcbdSSowmini Varadhan bail:
344*4784fcbdSSowmini Varadhan 	if (status != DLADM_STATUS_OK)
345*4784fcbdSSowmini Varadhan 		dladm_ether_info_done(eattr);
346*4784fcbdSSowmini Varadhan 	return (status);
347*4784fcbdSSowmini Varadhan }
348*4784fcbdSSowmini Varadhan 
349*4784fcbdSSowmini Varadhan extern void
350*4784fcbdSSowmini Varadhan dladm_ether_info_done(dladm_ether_info_t *eattr)
351*4784fcbdSSowmini Varadhan {
352*4784fcbdSSowmini Varadhan 	int i;
353*4784fcbdSSowmini Varadhan 
354*4784fcbdSSowmini Varadhan 	for (i = CURRENT; i <= PEERADV; i++)
355*4784fcbdSSowmini Varadhan 		free(eattr->lei_attr[i].le_spdx);
356*4784fcbdSSowmini Varadhan }
357