xref: /titanic_52/usr/src/lib/libdladm/common/libdlether.c (revision 422542c189efc4f3182b740c580bb58497805c45)
14784fcbdSSowmini Varadhan /*
24784fcbdSSowmini Varadhan  * CDDL HEADER START
34784fcbdSSowmini Varadhan  *
44784fcbdSSowmini Varadhan  * The contents of this file are subject to the terms of the
54784fcbdSSowmini Varadhan  * Common Development and Distribution License (the "License").
64784fcbdSSowmini Varadhan  * You may not use this file except in compliance with the License.
74784fcbdSSowmini Varadhan  *
84784fcbdSSowmini Varadhan  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
94784fcbdSSowmini Varadhan  * or http://www.opensolaris.org/os/licensing.
104784fcbdSSowmini Varadhan  * See the License for the specific language governing permissions
114784fcbdSSowmini Varadhan  * and limitations under the License.
124784fcbdSSowmini Varadhan  *
134784fcbdSSowmini Varadhan  * When distributing Covered Code, include this CDDL HEADER in each
144784fcbdSSowmini Varadhan  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
154784fcbdSSowmini Varadhan  * If applicable, add the following below this CDDL HEADER, with the
164784fcbdSSowmini Varadhan  * fields enclosed by brackets "[]" replaced with your own identifying
174784fcbdSSowmini Varadhan  * information: Portions Copyright [yyyy] [name of copyright owner]
184784fcbdSSowmini Varadhan  *
194784fcbdSSowmini Varadhan  * CDDL HEADER END
204784fcbdSSowmini Varadhan  */
214784fcbdSSowmini Varadhan /*
220dc2366fSVenugopal Iyer  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
234784fcbdSSowmini Varadhan  * Use is subject to license terms.
243bc4925dSGarrett D'Amore  *
253bc4925dSGarrett D'Amore  * Copyright 2015 Garrett D'Amore <garrett@damore.org>
264784fcbdSSowmini Varadhan  */
274784fcbdSSowmini Varadhan 
284784fcbdSSowmini Varadhan #include <stdlib.h>
294784fcbdSSowmini Varadhan #include <string.h>
304784fcbdSSowmini Varadhan #include <strings.h>
314784fcbdSSowmini Varadhan #include <sys/types.h>
324784fcbdSSowmini Varadhan #include <libdladm_impl.h>
334784fcbdSSowmini Varadhan #include <libdllink.h>
344784fcbdSSowmini Varadhan #include <libdlstat.h>
354784fcbdSSowmini Varadhan #include <libdlether.h>
364784fcbdSSowmini Varadhan 
374784fcbdSSowmini Varadhan /*
384784fcbdSSowmini Varadhan  * Ethernet administration library.
394784fcbdSSowmini Varadhan  */
404784fcbdSSowmini Varadhan 
414784fcbdSSowmini Varadhan /*
424784fcbdSSowmini Varadhan  * kstat names for extracting attributes.
434784fcbdSSowmini Varadhan  */
444784fcbdSSowmini Varadhan typedef struct ether_spdx_s {
454784fcbdSSowmini Varadhan 	dladm_ether_spdx_t eth_spdx;
464784fcbdSSowmini Varadhan 	char *eth_spdx_stat_name;
474784fcbdSSowmini Varadhan } ether_spdx_t;
484784fcbdSSowmini Varadhan 
494784fcbdSSowmini Varadhan static ether_spdx_t cap_spdx[] = {
50*422542c1SRobert Mustacchi 	{{100000, LINK_DUPLEX_FULL}, "cap_100gfdx"},
51*422542c1SRobert Mustacchi 	{{50000, LINK_DUPLEX_FULL}, "cap_50gfdx"},
52*422542c1SRobert Mustacchi 	{{40000, LINK_DUPLEX_FULL}, "cap_40gfdx"},
53*422542c1SRobert Mustacchi 	{{25000, LINK_DUPLEX_FULL}, "cap_25gfdx"},
54*422542c1SRobert Mustacchi 	{{10000, LINK_DUPLEX_FULL}, "cap_10gfdx"},
55*422542c1SRobert Mustacchi 	{{5000, LINK_DUPLEX_FULL}, "cap_5000fdx"},
56*422542c1SRobert Mustacchi 	{{2500, LINK_DUPLEX_FULL}, "cap_2500fdx"},
574784fcbdSSowmini Varadhan 	{{1000, LINK_DUPLEX_FULL}, "cap_1000fdx"},
584784fcbdSSowmini Varadhan 	{{1000, LINK_DUPLEX_HALF}, "cap_1000hdx"},
594784fcbdSSowmini Varadhan 	{{100, LINK_DUPLEX_FULL}, "cap_100fdx"},
604784fcbdSSowmini Varadhan 	{{100, LINK_DUPLEX_HALF}, "cap_100hdx"},
614784fcbdSSowmini Varadhan 	{{10, LINK_DUPLEX_FULL}, "cap_10fdx"},
624784fcbdSSowmini Varadhan 	{{10, LINK_DUPLEX_HALF}, "cap_10hdx"},
634784fcbdSSowmini Varadhan 	{{0, LINK_DUPLEX_UNKNOWN}, NULL}
644784fcbdSSowmini Varadhan };
654784fcbdSSowmini Varadhan 
664784fcbdSSowmini Varadhan static ether_spdx_t adv_cap_spdx[] = {
67*422542c1SRobert Mustacchi 	{{100000, LINK_DUPLEX_FULL}, "adv_cap_100gfdx"},
68*422542c1SRobert Mustacchi 	{{50000, LINK_DUPLEX_FULL}, "adv_cap_50gfdx"},
69*422542c1SRobert Mustacchi 	{{40000, LINK_DUPLEX_FULL}, "adv_cap_40gfdx"},
70*422542c1SRobert Mustacchi 	{{25000, LINK_DUPLEX_FULL}, "adv_cap_25gfdx"},
71*422542c1SRobert Mustacchi 	{{10000, LINK_DUPLEX_FULL}, "adv_cap_10gfdx"},
72*422542c1SRobert Mustacchi 	{{5000, LINK_DUPLEX_FULL}, "adv_cap_5000fdx"},
73*422542c1SRobert Mustacchi 	{{2500, LINK_DUPLEX_FULL}, "adv_cap_2500fdx"},
744784fcbdSSowmini Varadhan 	{{1000, LINK_DUPLEX_FULL}, "adv_cap_1000fdx"},
754784fcbdSSowmini Varadhan 	{{1000, LINK_DUPLEX_HALF}, "adv_cap_1000hdx"},
764784fcbdSSowmini Varadhan 	{{100, LINK_DUPLEX_FULL}, "adv_cap_100fdx"},
774784fcbdSSowmini Varadhan 	{{100, LINK_DUPLEX_HALF}, "adv_cap_100hdx"},
784784fcbdSSowmini Varadhan 	{{10, LINK_DUPLEX_FULL}, "adv_cap_10fdx"},
794784fcbdSSowmini Varadhan 	{{10, LINK_DUPLEX_HALF}, "adv_cap_10hdx"},
804784fcbdSSowmini Varadhan 	{{0, LINK_DUPLEX_UNKNOWN}, NULL}
814784fcbdSSowmini Varadhan };
824784fcbdSSowmini Varadhan 
834784fcbdSSowmini Varadhan static ether_spdx_t lp_cap_spdx[] = {
84*422542c1SRobert Mustacchi 	{{100000, LINK_DUPLEX_FULL}, "lp_cap_100gfdx"},
85*422542c1SRobert Mustacchi 	{{50000, LINK_DUPLEX_FULL}, "lp_cap_50gfdx"},
86*422542c1SRobert Mustacchi 	{{40000, LINK_DUPLEX_FULL}, "lp_cap_40gfdx"},
87*422542c1SRobert Mustacchi 	{{25000, LINK_DUPLEX_FULL}, "lp_cap_25gfdx"},
88*422542c1SRobert Mustacchi 	{{10000, LINK_DUPLEX_FULL}, "lp_cap_10gfdx"},
89*422542c1SRobert Mustacchi 	{{5000, LINK_DUPLEX_FULL}, "lp_cap_5000fdx"},
90*422542c1SRobert Mustacchi 	{{2500, LINK_DUPLEX_FULL}, "lp_cap_2500fdx"},
914784fcbdSSowmini Varadhan 	{{1000, LINK_DUPLEX_FULL}, "lp_cap_1000fdx"},
924784fcbdSSowmini Varadhan 	{{1000, LINK_DUPLEX_HALF}, "lp_cap_1000hdx"},
934784fcbdSSowmini Varadhan 	{{100, LINK_DUPLEX_FULL}, "lp_cap_100fdx"},
944784fcbdSSowmini Varadhan 	{{100, LINK_DUPLEX_HALF}, "lp_cap_100hdx"},
954784fcbdSSowmini Varadhan 	{{10, LINK_DUPLEX_FULL}, "lp_cap_10fdx"},
964784fcbdSSowmini Varadhan 	{{10, LINK_DUPLEX_HALF}, "lp_cap_10hdx"},
974784fcbdSSowmini Varadhan 	{{0, LINK_DUPLEX_UNKNOWN}, NULL}
984784fcbdSSowmini Varadhan };
994784fcbdSSowmini Varadhan 
1004784fcbdSSowmini Varadhan typedef struct attr_kstat_s {
1014784fcbdSSowmini Varadhan 	char *autoneg_stat;
1024784fcbdSSowmini Varadhan 	char *pause_stat;
1034784fcbdSSowmini Varadhan 	char *asmpause_stat;
1044784fcbdSSowmini Varadhan 	char *fault_stat;
1054784fcbdSSowmini Varadhan 	ether_spdx_t *spdx_stat;
1064784fcbdSSowmini Varadhan } attr_kstat_t;
1074784fcbdSSowmini Varadhan 
1084784fcbdSSowmini Varadhan static attr_kstat_t attrstat[] =  {
1094784fcbdSSowmini Varadhan 	{"link_autoneg",	/* current */
1104784fcbdSSowmini Varadhan 	    "link_pause",	"link_asmpause",	NULL,
1114784fcbdSSowmini Varadhan 	    NULL},
1124784fcbdSSowmini Varadhan 
1134784fcbdSSowmini Varadhan 	{"cap_autoneg",		/* capable */
1144784fcbdSSowmini Varadhan 	    "cap_pause",	"cap_asmpause",		"cap_rem_fault",
1154784fcbdSSowmini Varadhan 	    cap_spdx},
1164784fcbdSSowmini Varadhan 
1174784fcbdSSowmini Varadhan 	{"adv_cap_autoneg",	/* advertised */
1184784fcbdSSowmini Varadhan 	    "adv_cap_pause",	"adv_cap_asmpause",	"adv_rem_fault",
1194784fcbdSSowmini Varadhan 	    adv_cap_spdx},
1204784fcbdSSowmini Varadhan 
1214784fcbdSSowmini Varadhan 	{"lp_cap_autoneg",	/* peer advertised */
1224784fcbdSSowmini Varadhan 	    "lp_cap_pause",	"lp_cap_asmpause",	"lp_rem_fault",
1234784fcbdSSowmini Varadhan 	    lp_cap_spdx}
1244784fcbdSSowmini Varadhan };
1254784fcbdSSowmini Varadhan 
1264784fcbdSSowmini Varadhan /*
1274784fcbdSSowmini Varadhan  * Get the speed-duplex stats specified in the ether_spdx_t table passed in
1284784fcbdSSowmini Varadhan  * by querying the appropriate kstat for each entry in the table.
1294784fcbdSSowmini Varadhan  */
1304784fcbdSSowmini Varadhan static dladm_status_t
1314ac67f02SAnurag S. Maskey i_dladm_get_spdx(dladm_handle_t handle, datalink_id_t linkid,
1324ac67f02SAnurag S. Maskey     dladm_ether_attr_t *eattr, ether_spdx_t *spdx_stat)
1334784fcbdSSowmini Varadhan {
1344784fcbdSSowmini Varadhan 	int		i, nspdx = 0;
1354784fcbdSSowmini Varadhan 	uint32_t	speed;
1364784fcbdSSowmini Varadhan 	dladm_status_t	status;
1374784fcbdSSowmini Varadhan 	void		*ptr;
1384784fcbdSSowmini Varadhan 
1394784fcbdSSowmini Varadhan 	eattr->le_spdx = NULL;
1404784fcbdSSowmini Varadhan 	for (i = 0; spdx_stat[i].eth_spdx_stat_name != NULL; i++) {
1414ac67f02SAnurag S. Maskey 		if ((status = dladm_get_single_mac_stat(handle, linkid,
1424784fcbdSSowmini Varadhan 		    spdx_stat[i].eth_spdx_stat_name,
1434784fcbdSSowmini Varadhan 		    KSTAT_DATA_UINT32, &speed)) != DLADM_STATUS_OK) {
1444784fcbdSSowmini Varadhan 
1454784fcbdSSowmini Varadhan 			if (status == DLADM_STATUS_NOTFOUND) {
1464784fcbdSSowmini Varadhan 				/*
1474784fcbdSSowmini Varadhan 				 * Missing statistic.
1484784fcbdSSowmini Varadhan 				 * Skip this one and try the rest.
1494784fcbdSSowmini Varadhan 				 */
1504784fcbdSSowmini Varadhan 				continue;
1514784fcbdSSowmini Varadhan 			} else {
1524784fcbdSSowmini Varadhan 				free(eattr->le_spdx);
1534784fcbdSSowmini Varadhan 				eattr->le_num_spdx = 0;
1544784fcbdSSowmini Varadhan 				return (status);
1554784fcbdSSowmini Varadhan 			}
1564784fcbdSSowmini Varadhan 		}
1574784fcbdSSowmini Varadhan 		if (speed == 0)
1584784fcbdSSowmini Varadhan 			continue;
1594784fcbdSSowmini Varadhan 		nspdx++;
1604784fcbdSSowmini Varadhan 		ptr = realloc(eattr->le_spdx,
1614784fcbdSSowmini Varadhan 		    nspdx * sizeof (dladm_ether_spdx_t));
1624784fcbdSSowmini Varadhan 		if (ptr != NULL) {
1634784fcbdSSowmini Varadhan 			eattr->le_spdx = ptr;
1644784fcbdSSowmini Varadhan 		} else {
1654784fcbdSSowmini Varadhan 			free(eattr->le_spdx);
1664784fcbdSSowmini Varadhan 			eattr->le_num_spdx = 0;
1674784fcbdSSowmini Varadhan 			return (DLADM_STATUS_NOMEM);
1684784fcbdSSowmini Varadhan 		}
1694784fcbdSSowmini Varadhan 		eattr->le_spdx[nspdx - 1] = spdx_stat[i].eth_spdx;
1704784fcbdSSowmini Varadhan 	}
1714784fcbdSSowmini Varadhan 	eattr->le_num_spdx = nspdx;
1724784fcbdSSowmini Varadhan 	return (DLADM_STATUS_OK);
1734784fcbdSSowmini Varadhan }
1744784fcbdSSowmini Varadhan 
1754784fcbdSSowmini Varadhan /*
1764784fcbdSSowmini Varadhan  * Returns "yes" or "no" based on the autonegotion capabilities
1774784fcbdSSowmini Varadhan  * for the parameter type indicated by ptype. The permissible
1784784fcbdSSowmini Varadhan  * values for ptype are CURRENT, CAPABLE, ADV, PEERADV.
1794784fcbdSSowmini Varadhan  */
1804784fcbdSSowmini Varadhan char *
1814784fcbdSSowmini Varadhan dladm_ether_autoneg2str(char *buf, size_t buflen, dladm_ether_info_t *eattr,
1824784fcbdSSowmini Varadhan     int ptype)
1834784fcbdSSowmini Varadhan {
1844784fcbdSSowmini Varadhan 	boolean_t autoneg = eattr->lei_attr[ptype].le_autoneg;
1854784fcbdSSowmini Varadhan 
1864784fcbdSSowmini Varadhan 	(void) strlcpy(buf, (autoneg ? "yes" : "no"), buflen);
1874784fcbdSSowmini Varadhan 	return (buf);
1884784fcbdSSowmini Varadhan }
1894784fcbdSSowmini Varadhan 
1904784fcbdSSowmini Varadhan /*
1914784fcbdSSowmini Varadhan  * Returns {"bi", "tx", "none"} based on the flow-control capabilities
1924784fcbdSSowmini Varadhan  * for the parameter type indicated by ptype. The permissible
1934784fcbdSSowmini Varadhan  * values for ptype are CURRENT, CAPABLE, ADV, PEERADV.
1944784fcbdSSowmini Varadhan  */
1954784fcbdSSowmini Varadhan char *
1964784fcbdSSowmini Varadhan dladm_ether_pause2str(char *buf, size_t buflen, dladm_ether_info_t *eattr,
1974784fcbdSSowmini Varadhan     int ptype)
1984784fcbdSSowmini Varadhan {
1994784fcbdSSowmini Varadhan 	boolean_t pause = eattr->lei_attr[ptype].le_pause;
2004784fcbdSSowmini Varadhan 	boolean_t asmpause = eattr->lei_attr[ptype].le_asmpause;
2014784fcbdSSowmini Varadhan 
2024784fcbdSSowmini Varadhan 	if (pause)
2034784fcbdSSowmini Varadhan 		(void) strlcpy(buf, "bi", buflen);
2044784fcbdSSowmini Varadhan 	else if (asmpause)
2054784fcbdSSowmini Varadhan 		(void) strlcpy(buf, "tx", buflen);
2064784fcbdSSowmini Varadhan 	else
2074784fcbdSSowmini Varadhan 		(void) strlcpy(buf, "none", buflen);
2084784fcbdSSowmini Varadhan 	return (buf);
2094784fcbdSSowmini Varadhan }
2104784fcbdSSowmini Varadhan 
2114784fcbdSSowmini Varadhan /*
2124784fcbdSSowmini Varadhan  * For a given param type, parse the list of speed-duplex pairs in
2134784fcbdSSowmini Varadhan  * the dladm_ether_info_t and return a  comma-separated string formatted
2144784fcbdSSowmini Varadhan  * as <speed><speed-unit-char>-<duplex-chars> where <speed> is the value of
2154784fcbdSSowmini Varadhan  * speed, in units specifid by the <speed-unit-char> which is one
2164784fcbdSSowmini Varadhan  * of 'M' (Mbits/sec) or 'G' (Gigabits/sec).  The permissible values of
2174784fcbdSSowmini Varadhan  * <duplex-chars> are 'u' (indicating duplex is "unknown") or one/both of
2184784fcbdSSowmini Varadhan  * 'f', 'h' (indicating full-duplex and half-duplex respectively)
2194784fcbdSSowmini Varadhan  */
2204784fcbdSSowmini Varadhan extern char *
2214784fcbdSSowmini Varadhan dladm_ether_spdx2str(char *buf, size_t buflen, dladm_ether_info_t *eattr,
2224784fcbdSSowmini Varadhan     int ptype)
2234784fcbdSSowmini Varadhan {
2244784fcbdSSowmini Varadhan 	int		i, j;
2254784fcbdSSowmini Varadhan 	boolean_t	is_full, is_half;
2264784fcbdSSowmini Varadhan 	int		speed;
2274784fcbdSSowmini Varadhan 	char		speed_unit;
2284784fcbdSSowmini Varadhan 	char		tmpbuf[DLADM_STRSIZE];
2294784fcbdSSowmini Varadhan 	dladm_ether_spdx_t *spdx;
2304784fcbdSSowmini Varadhan 	uint32_t	nspdx;
2314784fcbdSSowmini Varadhan 
2324784fcbdSSowmini Varadhan 	spdx = eattr->lei_attr[ptype].le_spdx;
2334784fcbdSSowmini Varadhan 	nspdx = eattr->lei_attr[ptype].le_num_spdx;
2344784fcbdSSowmini Varadhan 	for (i = 0; i < nspdx; i++) {
2354784fcbdSSowmini Varadhan 
2364784fcbdSSowmini Varadhan 		speed = spdx[i].lesd_speed;
2374784fcbdSSowmini Varadhan 
2384784fcbdSSowmini Varadhan 		/*
2394784fcbdSSowmini Varadhan 		 * if we have already covered this speed for
2404784fcbdSSowmini Varadhan 		 * the <other>-duplex case before this, skip it
2414784fcbdSSowmini Varadhan 		 */
2424784fcbdSSowmini Varadhan 		for (j = 0; j < i; j++) {
2434784fcbdSSowmini Varadhan 			if (speed == spdx[j].lesd_speed)
2444784fcbdSSowmini Varadhan 				break;
2454784fcbdSSowmini Varadhan 		}
2464784fcbdSSowmini Varadhan 		if (j < i)
2474784fcbdSSowmini Varadhan 			continue;
2484784fcbdSSowmini Varadhan 
2493bc4925dSGarrett D'Amore 		if ((speed % 1000) == 0) {
2504784fcbdSSowmini Varadhan 			speed = speed/1000;
2514784fcbdSSowmini Varadhan 			speed_unit = 'G';
2524784fcbdSSowmini Varadhan 		} else {
2534784fcbdSSowmini Varadhan 			speed_unit = 'M';
2544784fcbdSSowmini Varadhan 		}
2554784fcbdSSowmini Varadhan 		(void) snprintf(tmpbuf, DLADM_STRSIZE, "%d%c",
2564784fcbdSSowmini Varadhan 		    speed, speed_unit);
2574784fcbdSSowmini Varadhan 		if (i > 0)
2584784fcbdSSowmini Varadhan 			(void) strncat(buf, ",", buflen);
2594784fcbdSSowmini Varadhan 		(void) strncat(buf, tmpbuf, buflen);
2604784fcbdSSowmini Varadhan 
2614784fcbdSSowmini Varadhan 		is_full = is_half = B_FALSE;
2624784fcbdSSowmini Varadhan 		/*
2634784fcbdSSowmini Varadhan 		 * Find all the supported duplex values for this speed.
2644784fcbdSSowmini Varadhan 		 */
2654784fcbdSSowmini Varadhan 		for (j = 0; j < nspdx; j++) {
2664784fcbdSSowmini Varadhan 			if (spdx[j].lesd_speed != spdx[i].lesd_speed)
2674784fcbdSSowmini Varadhan 				continue;
2684784fcbdSSowmini Varadhan 			if (spdx[j].lesd_duplex == LINK_DUPLEX_FULL)
2694784fcbdSSowmini Varadhan 				is_full = B_TRUE;
2704784fcbdSSowmini Varadhan 			if (spdx[j].lesd_duplex == LINK_DUPLEX_HALF)
2714784fcbdSSowmini Varadhan 				is_half = B_TRUE;
2724784fcbdSSowmini Varadhan 		}
2734784fcbdSSowmini Varadhan 		if (is_full && is_half)
2744784fcbdSSowmini Varadhan 			(void) strncat(buf, "-fh", buflen);
2754784fcbdSSowmini Varadhan 		else if (is_full)
2764784fcbdSSowmini Varadhan 			(void) strncat(buf, "-f", buflen);
2774784fcbdSSowmini Varadhan 		else if (is_half)
2784784fcbdSSowmini Varadhan 			(void) strncat(buf, "-h", buflen);
2794784fcbdSSowmini Varadhan 	}
2804784fcbdSSowmini Varadhan 	return (buf);
2814784fcbdSSowmini Varadhan }
2824784fcbdSSowmini Varadhan 
2834784fcbdSSowmini Varadhan /*
2844784fcbdSSowmini Varadhan  * Extract Ethernet attributes of the link specified by linkid.
2854784fcbdSSowmini Varadhan  * Information for the CURRENT, CAPABLE, ADV and PEERADV parameter
2864784fcbdSSowmini Varadhan  * types is extracted into the lei_attr[] entries in the dladm_ether_info_t.
2874784fcbdSSowmini Varadhan  * On succesful return, the memory allocated in this function should be
2884784fcbdSSowmini Varadhan  * freed by calling dladm_ether_info_done().
2894784fcbdSSowmini Varadhan  */
2904784fcbdSSowmini Varadhan extern dladm_status_t
2914ac67f02SAnurag S. Maskey dladm_ether_info(dladm_handle_t handle, datalink_id_t linkid,
2924ac67f02SAnurag S. Maskey     dladm_ether_info_t *eattr)
2934784fcbdSSowmini Varadhan {
2944784fcbdSSowmini Varadhan 	uint32_t	autoneg, pause, asmpause, fault;
2954784fcbdSSowmini Varadhan 	uint64_t	sp64;
2964784fcbdSSowmini Varadhan 	dladm_status_t	status;
2974784fcbdSSowmini Varadhan 	int		i;
2984784fcbdSSowmini Varadhan 	link_duplex_t	link_duplex;
2994784fcbdSSowmini Varadhan 
3004784fcbdSSowmini Varadhan 	bzero(eattr, sizeof (*eattr));
3014ac67f02SAnurag S. Maskey 	status = dladm_datalink_id2info(handle, linkid, NULL, NULL, NULL,
3024784fcbdSSowmini Varadhan 	    eattr->lei_linkname, sizeof (eattr->lei_linkname));
3034784fcbdSSowmini Varadhan 	if (status != DLADM_STATUS_OK)
3044784fcbdSSowmini Varadhan 		goto bail;
3054784fcbdSSowmini Varadhan 
3064784fcbdSSowmini Varadhan 	/* get current values of speed, duplex, state of link */
3074784fcbdSSowmini Varadhan 	eattr->lei_attr[CURRENT].le_num_spdx = 1;
3084784fcbdSSowmini Varadhan 	eattr->lei_attr[CURRENT].le_spdx = malloc(sizeof (dladm_ether_spdx_t));
3094784fcbdSSowmini Varadhan 	if (eattr->lei_attr[CURRENT].le_spdx == NULL) {
3104784fcbdSSowmini Varadhan 		status = DLADM_STATUS_NOMEM;
3114784fcbdSSowmini Varadhan 		goto bail;
3124784fcbdSSowmini Varadhan 	}
3134784fcbdSSowmini Varadhan 
3144ac67f02SAnurag S. Maskey 	if ((status = dladm_get_single_mac_stat(handle, linkid, "ifspeed",
3154784fcbdSSowmini Varadhan 	    KSTAT_DATA_UINT64, &sp64)) != DLADM_STATUS_OK)
3164784fcbdSSowmini Varadhan 		goto bail;
3174784fcbdSSowmini Varadhan 
3184ac67f02SAnurag S. Maskey 	if ((status = dladm_get_single_mac_stat(handle, linkid, "link_duplex",
3194784fcbdSSowmini Varadhan 	    KSTAT_DATA_UINT32, &link_duplex)) != DLADM_STATUS_OK)
3204784fcbdSSowmini Varadhan 		goto bail;
3214784fcbdSSowmini Varadhan 
3224784fcbdSSowmini Varadhan 	eattr->lei_attr[CURRENT].le_spdx->lesd_speed = (int)(sp64/1000000ull);
3234784fcbdSSowmini Varadhan 	eattr->lei_attr[CURRENT].le_spdx->lesd_duplex = link_duplex;
3244784fcbdSSowmini Varadhan 
3250dc2366fSVenugopal Iyer 	status = dladm_get_state(handle, linkid, &eattr->lei_state);
3264784fcbdSSowmini Varadhan 	if (status != DLADM_STATUS_OK)
3274784fcbdSSowmini Varadhan 		goto bail;
3284784fcbdSSowmini Varadhan 
3294784fcbdSSowmini Varadhan 	/* get the auto, pause, asmpause, fault values */
3304784fcbdSSowmini Varadhan 	for (i = CURRENT; i <= PEERADV; i++)  {
3314784fcbdSSowmini Varadhan 
3324ac67f02SAnurag S. Maskey 		status = dladm_get_single_mac_stat(handle, linkid,
3334784fcbdSSowmini Varadhan 		    attrstat[i].autoneg_stat, KSTAT_DATA_UINT32, &autoneg);
3344784fcbdSSowmini Varadhan 		if (status != DLADM_STATUS_OK)
3354784fcbdSSowmini Varadhan 			goto bail;
3364784fcbdSSowmini Varadhan 
3374ac67f02SAnurag S. Maskey 		status = dladm_get_single_mac_stat(handle, linkid,
3384784fcbdSSowmini Varadhan 		    attrstat[i].pause_stat, KSTAT_DATA_UINT32, &pause);
3394784fcbdSSowmini Varadhan 		if (status != DLADM_STATUS_OK)
3404784fcbdSSowmini Varadhan 			goto bail;
3414784fcbdSSowmini Varadhan 
3424ac67f02SAnurag S. Maskey 		status = dladm_get_single_mac_stat(handle, linkid,
3434784fcbdSSowmini Varadhan 		    attrstat[i].asmpause_stat, KSTAT_DATA_UINT32, &asmpause);
3444784fcbdSSowmini Varadhan 		if (status != DLADM_STATUS_OK)
3454784fcbdSSowmini Varadhan 			goto bail;
3464784fcbdSSowmini Varadhan 
3474784fcbdSSowmini Varadhan 		eattr->lei_attr[i].le_autoneg = (autoneg != 0);
3484784fcbdSSowmini Varadhan 		eattr->lei_attr[i].le_pause = (pause != 0);
3494784fcbdSSowmini Varadhan 		eattr->lei_attr[i].le_asmpause = (asmpause != 0);
3504784fcbdSSowmini Varadhan 
3514784fcbdSSowmini Varadhan 		if (i == CURRENT)
3524784fcbdSSowmini Varadhan 			continue;
3534ac67f02SAnurag S. Maskey 		status = dladm_get_single_mac_stat(handle, linkid,
3544784fcbdSSowmini Varadhan 		    attrstat[i].fault_stat, KSTAT_DATA_UINT32, &fault);
3554784fcbdSSowmini Varadhan 		if (status != DLADM_STATUS_OK)
3564784fcbdSSowmini Varadhan 			goto bail;
3574784fcbdSSowmini Varadhan 		eattr->lei_attr[i].le_fault = (pause != 0);
3584784fcbdSSowmini Varadhan 
3594784fcbdSSowmini Varadhan 		/* get all the supported speed/duplex values */
3604ac67f02SAnurag S. Maskey 		status = i_dladm_get_spdx(handle, linkid, &eattr->lei_attr[i],
3614784fcbdSSowmini Varadhan 		    attrstat[i].spdx_stat);
3624784fcbdSSowmini Varadhan 		if (status != DLADM_STATUS_OK)
3634784fcbdSSowmini Varadhan 			goto bail;
3644784fcbdSSowmini Varadhan 	}
3654784fcbdSSowmini Varadhan 	eattr->lei_attr[CURRENT].le_fault =
3664784fcbdSSowmini Varadhan 	    eattr->lei_attr[ADV].le_fault || eattr->lei_attr[PEERADV].le_fault;
3674784fcbdSSowmini Varadhan bail:
3684784fcbdSSowmini Varadhan 	if (status != DLADM_STATUS_OK)
3694784fcbdSSowmini Varadhan 		dladm_ether_info_done(eattr);
3704784fcbdSSowmini Varadhan 	return (status);
3714784fcbdSSowmini Varadhan }
3724784fcbdSSowmini Varadhan 
3734784fcbdSSowmini Varadhan extern void
3744784fcbdSSowmini Varadhan dladm_ether_info_done(dladm_ether_info_t *eattr)
3754784fcbdSSowmini Varadhan {
3764784fcbdSSowmini Varadhan 	int i;
3774784fcbdSSowmini Varadhan 
3784784fcbdSSowmini Varadhan 	for (i = CURRENT; i <= PEERADV; i++)
3794784fcbdSSowmini Varadhan 		free(eattr->lei_attr[i].le_spdx);
3804784fcbdSSowmini Varadhan }
381