xref: /onnv-gate/usr/src/lib/libdladm/common/libdlether.c (revision 11878:ac93462db6d7)
18306SSowmini.Varadhan@Sun.COM /*
28306SSowmini.Varadhan@Sun.COM  * CDDL HEADER START
38306SSowmini.Varadhan@Sun.COM  *
48306SSowmini.Varadhan@Sun.COM  * The contents of this file are subject to the terms of the
58306SSowmini.Varadhan@Sun.COM  * Common Development and Distribution License (the "License").
68306SSowmini.Varadhan@Sun.COM  * You may not use this file except in compliance with the License.
78306SSowmini.Varadhan@Sun.COM  *
88306SSowmini.Varadhan@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
98306SSowmini.Varadhan@Sun.COM  * or http://www.opensolaris.org/os/licensing.
108306SSowmini.Varadhan@Sun.COM  * See the License for the specific language governing permissions
118306SSowmini.Varadhan@Sun.COM  * and limitations under the License.
128306SSowmini.Varadhan@Sun.COM  *
138306SSowmini.Varadhan@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
148306SSowmini.Varadhan@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
158306SSowmini.Varadhan@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
168306SSowmini.Varadhan@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
178306SSowmini.Varadhan@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
188306SSowmini.Varadhan@Sun.COM  *
198306SSowmini.Varadhan@Sun.COM  * CDDL HEADER END
208306SSowmini.Varadhan@Sun.COM  */
218306SSowmini.Varadhan@Sun.COM /*
22*11878SVenu.Iyer@Sun.COM  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
238306SSowmini.Varadhan@Sun.COM  * Use is subject to license terms.
248306SSowmini.Varadhan@Sun.COM  */
258306SSowmini.Varadhan@Sun.COM 
268306SSowmini.Varadhan@Sun.COM #include <stdlib.h>
278306SSowmini.Varadhan@Sun.COM #include <string.h>
288306SSowmini.Varadhan@Sun.COM #include <strings.h>
298306SSowmini.Varadhan@Sun.COM #include <sys/types.h>
308306SSowmini.Varadhan@Sun.COM #include <libdladm_impl.h>
318306SSowmini.Varadhan@Sun.COM #include <libdllink.h>
328306SSowmini.Varadhan@Sun.COM #include <libdlstat.h>
338306SSowmini.Varadhan@Sun.COM #include <libdlether.h>
348306SSowmini.Varadhan@Sun.COM 
358306SSowmini.Varadhan@Sun.COM /*
368306SSowmini.Varadhan@Sun.COM  * Ethernet administration library.
378306SSowmini.Varadhan@Sun.COM  */
388306SSowmini.Varadhan@Sun.COM 
398306SSowmini.Varadhan@Sun.COM /*
408306SSowmini.Varadhan@Sun.COM  * kstat names for extracting attributes.
418306SSowmini.Varadhan@Sun.COM  */
428306SSowmini.Varadhan@Sun.COM typedef struct ether_spdx_s {
438306SSowmini.Varadhan@Sun.COM 	dladm_ether_spdx_t eth_spdx;
448306SSowmini.Varadhan@Sun.COM 	char *eth_spdx_stat_name;
458306SSowmini.Varadhan@Sun.COM } ether_spdx_t;
468306SSowmini.Varadhan@Sun.COM 
478306SSowmini.Varadhan@Sun.COM static ether_spdx_t cap_spdx[] = {
488306SSowmini.Varadhan@Sun.COM 	{{1000, LINK_DUPLEX_FULL}, "cap_1000fdx"},
498306SSowmini.Varadhan@Sun.COM 	{{1000, LINK_DUPLEX_HALF}, "cap_1000hdx"},
508306SSowmini.Varadhan@Sun.COM 	{{100, LINK_DUPLEX_FULL}, "cap_100fdx"},
518306SSowmini.Varadhan@Sun.COM 	{{100, LINK_DUPLEX_HALF}, "cap_100hdx"},
528306SSowmini.Varadhan@Sun.COM 	{{10, LINK_DUPLEX_FULL}, "cap_10fdx"},
538306SSowmini.Varadhan@Sun.COM 	{{10, LINK_DUPLEX_HALF}, "cap_10hdx"},
548306SSowmini.Varadhan@Sun.COM 	{{0, LINK_DUPLEX_UNKNOWN}, NULL}
558306SSowmini.Varadhan@Sun.COM };
568306SSowmini.Varadhan@Sun.COM 
578306SSowmini.Varadhan@Sun.COM static ether_spdx_t adv_cap_spdx[] = {
588306SSowmini.Varadhan@Sun.COM 	{{1000, LINK_DUPLEX_FULL}, "adv_cap_1000fdx"},
598306SSowmini.Varadhan@Sun.COM 	{{1000, LINK_DUPLEX_HALF}, "adv_cap_1000hdx"},
608306SSowmini.Varadhan@Sun.COM 	{{100, LINK_DUPLEX_FULL}, "adv_cap_100fdx"},
618306SSowmini.Varadhan@Sun.COM 	{{100, LINK_DUPLEX_HALF}, "adv_cap_100hdx"},
628306SSowmini.Varadhan@Sun.COM 	{{10, LINK_DUPLEX_FULL}, "adv_cap_10fdx"},
638306SSowmini.Varadhan@Sun.COM 	{{10, LINK_DUPLEX_HALF}, "adv_cap_10hdx"},
648306SSowmini.Varadhan@Sun.COM 	{{0, LINK_DUPLEX_UNKNOWN}, NULL}
658306SSowmini.Varadhan@Sun.COM };
668306SSowmini.Varadhan@Sun.COM 
678306SSowmini.Varadhan@Sun.COM static ether_spdx_t lp_cap_spdx[] = {
688306SSowmini.Varadhan@Sun.COM 	{{1000, LINK_DUPLEX_FULL}, "lp_cap_1000fdx"},
698306SSowmini.Varadhan@Sun.COM 	{{1000, LINK_DUPLEX_HALF}, "lp_cap_1000hdx"},
708306SSowmini.Varadhan@Sun.COM 	{{100, LINK_DUPLEX_FULL}, "lp_cap_100fdx"},
718306SSowmini.Varadhan@Sun.COM 	{{100, LINK_DUPLEX_HALF}, "lp_cap_100hdx"},
728306SSowmini.Varadhan@Sun.COM 	{{10, LINK_DUPLEX_FULL}, "lp_cap_10fdx"},
738306SSowmini.Varadhan@Sun.COM 	{{10, LINK_DUPLEX_HALF}, "lp_cap_10hdx"},
748306SSowmini.Varadhan@Sun.COM 	{{0, LINK_DUPLEX_UNKNOWN}, NULL}
758306SSowmini.Varadhan@Sun.COM };
768306SSowmini.Varadhan@Sun.COM 
778306SSowmini.Varadhan@Sun.COM typedef struct attr_kstat_s {
788306SSowmini.Varadhan@Sun.COM 	char *autoneg_stat;
798306SSowmini.Varadhan@Sun.COM 	char *pause_stat;
808306SSowmini.Varadhan@Sun.COM 	char *asmpause_stat;
818306SSowmini.Varadhan@Sun.COM 	char *fault_stat;
828306SSowmini.Varadhan@Sun.COM 	ether_spdx_t *spdx_stat;
838306SSowmini.Varadhan@Sun.COM } attr_kstat_t;
848306SSowmini.Varadhan@Sun.COM 
858306SSowmini.Varadhan@Sun.COM static attr_kstat_t attrstat[] =  {
868306SSowmini.Varadhan@Sun.COM 	{"link_autoneg",	/* current */
878306SSowmini.Varadhan@Sun.COM 	    "link_pause",	"link_asmpause",	NULL,
888306SSowmini.Varadhan@Sun.COM 	    NULL},
898306SSowmini.Varadhan@Sun.COM 
908306SSowmini.Varadhan@Sun.COM 	{"cap_autoneg",		/* capable */
918306SSowmini.Varadhan@Sun.COM 	    "cap_pause",	"cap_asmpause",		"cap_rem_fault",
928306SSowmini.Varadhan@Sun.COM 	    cap_spdx},
938306SSowmini.Varadhan@Sun.COM 
948306SSowmini.Varadhan@Sun.COM 	{"adv_cap_autoneg",	/* advertised */
958306SSowmini.Varadhan@Sun.COM 	    "adv_cap_pause",	"adv_cap_asmpause",	"adv_rem_fault",
968306SSowmini.Varadhan@Sun.COM 	    adv_cap_spdx},
978306SSowmini.Varadhan@Sun.COM 
988306SSowmini.Varadhan@Sun.COM 	{"lp_cap_autoneg",	/* peer advertised */
998306SSowmini.Varadhan@Sun.COM 	    "lp_cap_pause",	"lp_cap_asmpause",	"lp_rem_fault",
1008306SSowmini.Varadhan@Sun.COM 	    lp_cap_spdx}
1018306SSowmini.Varadhan@Sun.COM };
1028306SSowmini.Varadhan@Sun.COM 
1038306SSowmini.Varadhan@Sun.COM /*
1048306SSowmini.Varadhan@Sun.COM  * Get the speed-duplex stats specified in the ether_spdx_t table passed in
1058306SSowmini.Varadhan@Sun.COM  * by querying the appropriate kstat for each entry in the table.
1068306SSowmini.Varadhan@Sun.COM  */
1078306SSowmini.Varadhan@Sun.COM static dladm_status_t
i_dladm_get_spdx(dladm_handle_t handle,datalink_id_t linkid,dladm_ether_attr_t * eattr,ether_spdx_t * spdx_stat)1088453SAnurag.Maskey@Sun.COM i_dladm_get_spdx(dladm_handle_t handle, datalink_id_t linkid,
1098453SAnurag.Maskey@Sun.COM     dladm_ether_attr_t *eattr, ether_spdx_t *spdx_stat)
1108306SSowmini.Varadhan@Sun.COM {
1118306SSowmini.Varadhan@Sun.COM 	int		i, nspdx = 0;
1128306SSowmini.Varadhan@Sun.COM 	uint32_t	speed;
1138306SSowmini.Varadhan@Sun.COM 	dladm_status_t	status;
1148306SSowmini.Varadhan@Sun.COM 	void		*ptr;
1158306SSowmini.Varadhan@Sun.COM 
1168306SSowmini.Varadhan@Sun.COM 	eattr->le_spdx = NULL;
1178306SSowmini.Varadhan@Sun.COM 	for (i = 0; spdx_stat[i].eth_spdx_stat_name != NULL; i++) {
1188453SAnurag.Maskey@Sun.COM 		if ((status = dladm_get_single_mac_stat(handle, linkid,
1198306SSowmini.Varadhan@Sun.COM 		    spdx_stat[i].eth_spdx_stat_name,
1208306SSowmini.Varadhan@Sun.COM 		    KSTAT_DATA_UINT32, &speed)) != DLADM_STATUS_OK) {
1218306SSowmini.Varadhan@Sun.COM 
1228306SSowmini.Varadhan@Sun.COM 			if (status == DLADM_STATUS_NOTFOUND) {
1238306SSowmini.Varadhan@Sun.COM 				/*
1248306SSowmini.Varadhan@Sun.COM 				 * Missing statistic.
1258306SSowmini.Varadhan@Sun.COM 				 * Skip this one and try the rest.
1268306SSowmini.Varadhan@Sun.COM 				 */
1278306SSowmini.Varadhan@Sun.COM 				continue;
1288306SSowmini.Varadhan@Sun.COM 			} else {
1298306SSowmini.Varadhan@Sun.COM 				free(eattr->le_spdx);
1308306SSowmini.Varadhan@Sun.COM 				eattr->le_num_spdx = 0;
1318306SSowmini.Varadhan@Sun.COM 				return (status);
1328306SSowmini.Varadhan@Sun.COM 			}
1338306SSowmini.Varadhan@Sun.COM 		}
1348306SSowmini.Varadhan@Sun.COM 		if (speed == 0)
1358306SSowmini.Varadhan@Sun.COM 			continue;
1368306SSowmini.Varadhan@Sun.COM 		nspdx++;
1378306SSowmini.Varadhan@Sun.COM 		ptr = realloc(eattr->le_spdx,
1388306SSowmini.Varadhan@Sun.COM 		    nspdx * sizeof (dladm_ether_spdx_t));
1398306SSowmini.Varadhan@Sun.COM 		if (ptr != NULL) {
1408306SSowmini.Varadhan@Sun.COM 			eattr->le_spdx = ptr;
1418306SSowmini.Varadhan@Sun.COM 		} else {
1428306SSowmini.Varadhan@Sun.COM 			free(eattr->le_spdx);
1438306SSowmini.Varadhan@Sun.COM 			eattr->le_num_spdx = 0;
1448306SSowmini.Varadhan@Sun.COM 			return (DLADM_STATUS_NOMEM);
1458306SSowmini.Varadhan@Sun.COM 		}
1468306SSowmini.Varadhan@Sun.COM 		eattr->le_spdx[nspdx - 1] = spdx_stat[i].eth_spdx;
1478306SSowmini.Varadhan@Sun.COM 	}
1488306SSowmini.Varadhan@Sun.COM 	eattr->le_num_spdx = nspdx;
1498306SSowmini.Varadhan@Sun.COM 	return (DLADM_STATUS_OK);
1508306SSowmini.Varadhan@Sun.COM }
1518306SSowmini.Varadhan@Sun.COM 
1528306SSowmini.Varadhan@Sun.COM /*
1538306SSowmini.Varadhan@Sun.COM  * Returns "yes" or "no" based on the autonegotion capabilities
1548306SSowmini.Varadhan@Sun.COM  * for the parameter type indicated by ptype. The permissible
1558306SSowmini.Varadhan@Sun.COM  * values for ptype are CURRENT, CAPABLE, ADV, PEERADV.
1568306SSowmini.Varadhan@Sun.COM  */
1578306SSowmini.Varadhan@Sun.COM char *
dladm_ether_autoneg2str(char * buf,size_t buflen,dladm_ether_info_t * eattr,int ptype)1588306SSowmini.Varadhan@Sun.COM dladm_ether_autoneg2str(char *buf, size_t buflen, dladm_ether_info_t *eattr,
1598306SSowmini.Varadhan@Sun.COM     int ptype)
1608306SSowmini.Varadhan@Sun.COM {
1618306SSowmini.Varadhan@Sun.COM 	boolean_t autoneg = eattr->lei_attr[ptype].le_autoneg;
1628306SSowmini.Varadhan@Sun.COM 
1638306SSowmini.Varadhan@Sun.COM 	(void) strlcpy(buf, (autoneg ? "yes" : "no"), buflen);
1648306SSowmini.Varadhan@Sun.COM 	return (buf);
1658306SSowmini.Varadhan@Sun.COM }
1668306SSowmini.Varadhan@Sun.COM 
1678306SSowmini.Varadhan@Sun.COM /*
1688306SSowmini.Varadhan@Sun.COM  * Returns {"bi", "tx", "none"} based on the flow-control capabilities
1698306SSowmini.Varadhan@Sun.COM  * for the parameter type indicated by ptype. The permissible
1708306SSowmini.Varadhan@Sun.COM  * values for ptype are CURRENT, CAPABLE, ADV, PEERADV.
1718306SSowmini.Varadhan@Sun.COM  */
1728306SSowmini.Varadhan@Sun.COM char *
dladm_ether_pause2str(char * buf,size_t buflen,dladm_ether_info_t * eattr,int ptype)1738306SSowmini.Varadhan@Sun.COM dladm_ether_pause2str(char *buf, size_t buflen, dladm_ether_info_t *eattr,
1748306SSowmini.Varadhan@Sun.COM     int ptype)
1758306SSowmini.Varadhan@Sun.COM {
1768306SSowmini.Varadhan@Sun.COM 	boolean_t pause = eattr->lei_attr[ptype].le_pause;
1778306SSowmini.Varadhan@Sun.COM 	boolean_t asmpause = eattr->lei_attr[ptype].le_asmpause;
1788306SSowmini.Varadhan@Sun.COM 
1798306SSowmini.Varadhan@Sun.COM 	if (pause)
1808306SSowmini.Varadhan@Sun.COM 		(void) strlcpy(buf, "bi", buflen);
1818306SSowmini.Varadhan@Sun.COM 	else if (asmpause)
1828306SSowmini.Varadhan@Sun.COM 		(void) strlcpy(buf, "tx", buflen);
1838306SSowmini.Varadhan@Sun.COM 	else
1848306SSowmini.Varadhan@Sun.COM 		(void) strlcpy(buf, "none", buflen);
1858306SSowmini.Varadhan@Sun.COM 	return (buf);
1868306SSowmini.Varadhan@Sun.COM }
1878306SSowmini.Varadhan@Sun.COM 
1888306SSowmini.Varadhan@Sun.COM /*
1898306SSowmini.Varadhan@Sun.COM  * For a given param type, parse the list of speed-duplex pairs in
1908306SSowmini.Varadhan@Sun.COM  * the dladm_ether_info_t and return a  comma-separated string formatted
1918306SSowmini.Varadhan@Sun.COM  * as <speed><speed-unit-char>-<duplex-chars> where <speed> is the value of
1928306SSowmini.Varadhan@Sun.COM  * speed, in units specifid by the <speed-unit-char> which is one
1938306SSowmini.Varadhan@Sun.COM  * of 'M' (Mbits/sec) or 'G' (Gigabits/sec).  The permissible values of
1948306SSowmini.Varadhan@Sun.COM  * <duplex-chars> are 'u' (indicating duplex is "unknown") or one/both of
1958306SSowmini.Varadhan@Sun.COM  * 'f', 'h' (indicating full-duplex and half-duplex respectively)
1968306SSowmini.Varadhan@Sun.COM  */
1978306SSowmini.Varadhan@Sun.COM extern char *
dladm_ether_spdx2str(char * buf,size_t buflen,dladm_ether_info_t * eattr,int ptype)1988306SSowmini.Varadhan@Sun.COM dladm_ether_spdx2str(char *buf, size_t buflen, dladm_ether_info_t *eattr,
1998306SSowmini.Varadhan@Sun.COM     int ptype)
2008306SSowmini.Varadhan@Sun.COM {
2018306SSowmini.Varadhan@Sun.COM 	int		i, j;
2028306SSowmini.Varadhan@Sun.COM 	boolean_t	is_full, is_half;
2038306SSowmini.Varadhan@Sun.COM 	int		speed;
2048306SSowmini.Varadhan@Sun.COM 	char		speed_unit;
2058306SSowmini.Varadhan@Sun.COM 	char		tmpbuf[DLADM_STRSIZE];
2068306SSowmini.Varadhan@Sun.COM 	dladm_ether_spdx_t *spdx;
2078306SSowmini.Varadhan@Sun.COM 	uint32_t	nspdx;
2088306SSowmini.Varadhan@Sun.COM 
2098306SSowmini.Varadhan@Sun.COM 	spdx = eattr->lei_attr[ptype].le_spdx;
2108306SSowmini.Varadhan@Sun.COM 	nspdx = eattr->lei_attr[ptype].le_num_spdx;
2118306SSowmini.Varadhan@Sun.COM 	for (i = 0; i < nspdx; i++) {
2128306SSowmini.Varadhan@Sun.COM 
2138306SSowmini.Varadhan@Sun.COM 		speed = spdx[i].lesd_speed;
2148306SSowmini.Varadhan@Sun.COM 
2158306SSowmini.Varadhan@Sun.COM 		/*
2168306SSowmini.Varadhan@Sun.COM 		 * if we have already covered this speed for
2178306SSowmini.Varadhan@Sun.COM 		 * the <other>-duplex case before this, skip it
2188306SSowmini.Varadhan@Sun.COM 		 */
2198306SSowmini.Varadhan@Sun.COM 		for (j = 0; j < i; j++) {
2208306SSowmini.Varadhan@Sun.COM 			if (speed == spdx[j].lesd_speed)
2218306SSowmini.Varadhan@Sun.COM 				break;
2228306SSowmini.Varadhan@Sun.COM 		}
2238306SSowmini.Varadhan@Sun.COM 		if (j < i)
2248306SSowmini.Varadhan@Sun.COM 			continue;
2258306SSowmini.Varadhan@Sun.COM 
2268306SSowmini.Varadhan@Sun.COM 		if (speed >= 1000) {
2278306SSowmini.Varadhan@Sun.COM 			speed = speed/1000;
2288306SSowmini.Varadhan@Sun.COM 			speed_unit = 'G';
2298306SSowmini.Varadhan@Sun.COM 		} else {
2308306SSowmini.Varadhan@Sun.COM 			speed_unit = 'M';
2318306SSowmini.Varadhan@Sun.COM 		}
2328306SSowmini.Varadhan@Sun.COM 		(void) snprintf(tmpbuf, DLADM_STRSIZE, "%d%c",
2338306SSowmini.Varadhan@Sun.COM 		    speed, speed_unit);
2348306SSowmini.Varadhan@Sun.COM 		if (i > 0)
2358306SSowmini.Varadhan@Sun.COM 			(void) strncat(buf, ",", buflen);
2368306SSowmini.Varadhan@Sun.COM 		(void) strncat(buf, tmpbuf, buflen);
2378306SSowmini.Varadhan@Sun.COM 
2388306SSowmini.Varadhan@Sun.COM 		is_full = is_half = B_FALSE;
2398306SSowmini.Varadhan@Sun.COM 		/*
2408306SSowmini.Varadhan@Sun.COM 		 * Find all the supported duplex values for this speed.
2418306SSowmini.Varadhan@Sun.COM 		 */
2428306SSowmini.Varadhan@Sun.COM 		for (j = 0; j < nspdx; j++) {
2438306SSowmini.Varadhan@Sun.COM 			if (spdx[j].lesd_speed != spdx[i].lesd_speed)
2448306SSowmini.Varadhan@Sun.COM 				continue;
2458306SSowmini.Varadhan@Sun.COM 			if (spdx[j].lesd_duplex == LINK_DUPLEX_FULL)
2468306SSowmini.Varadhan@Sun.COM 				is_full = B_TRUE;
2478306SSowmini.Varadhan@Sun.COM 			if (spdx[j].lesd_duplex == LINK_DUPLEX_HALF)
2488306SSowmini.Varadhan@Sun.COM 				is_half = B_TRUE;
2498306SSowmini.Varadhan@Sun.COM 		}
2508306SSowmini.Varadhan@Sun.COM 		if (is_full && is_half)
2518306SSowmini.Varadhan@Sun.COM 			(void) strncat(buf, "-fh", buflen);
2528306SSowmini.Varadhan@Sun.COM 		else if (is_full)
2538306SSowmini.Varadhan@Sun.COM 			(void) strncat(buf, "-f", buflen);
2548306SSowmini.Varadhan@Sun.COM 		else if (is_half)
2558306SSowmini.Varadhan@Sun.COM 			(void) strncat(buf, "-h", buflen);
2568306SSowmini.Varadhan@Sun.COM 	}
2578306SSowmini.Varadhan@Sun.COM 	return (buf);
2588306SSowmini.Varadhan@Sun.COM }
2598306SSowmini.Varadhan@Sun.COM 
2608306SSowmini.Varadhan@Sun.COM /*
2618306SSowmini.Varadhan@Sun.COM  * Extract Ethernet attributes of the link specified by linkid.
2628306SSowmini.Varadhan@Sun.COM  * Information for the CURRENT, CAPABLE, ADV and PEERADV parameter
2638306SSowmini.Varadhan@Sun.COM  * types is extracted into the lei_attr[] entries in the dladm_ether_info_t.
2648306SSowmini.Varadhan@Sun.COM  * On succesful return, the memory allocated in this function should be
2658306SSowmini.Varadhan@Sun.COM  * freed by calling dladm_ether_info_done().
2668306SSowmini.Varadhan@Sun.COM  */
2678306SSowmini.Varadhan@Sun.COM extern dladm_status_t
dladm_ether_info(dladm_handle_t handle,datalink_id_t linkid,dladm_ether_info_t * eattr)2688453SAnurag.Maskey@Sun.COM dladm_ether_info(dladm_handle_t handle, datalink_id_t linkid,
2698453SAnurag.Maskey@Sun.COM     dladm_ether_info_t *eattr)
2708306SSowmini.Varadhan@Sun.COM {
2718306SSowmini.Varadhan@Sun.COM 	uint32_t	autoneg, pause, asmpause, fault;
2728306SSowmini.Varadhan@Sun.COM 	uint64_t	sp64;
2738306SSowmini.Varadhan@Sun.COM 	dladm_status_t	status;
2748306SSowmini.Varadhan@Sun.COM 	int		i;
2758306SSowmini.Varadhan@Sun.COM 	link_duplex_t	link_duplex;
2768306SSowmini.Varadhan@Sun.COM 
2778306SSowmini.Varadhan@Sun.COM 	bzero(eattr, sizeof (*eattr));
2788453SAnurag.Maskey@Sun.COM 	status = dladm_datalink_id2info(handle, linkid, NULL, NULL, NULL,
2798306SSowmini.Varadhan@Sun.COM 	    eattr->lei_linkname, sizeof (eattr->lei_linkname));
2808306SSowmini.Varadhan@Sun.COM 	if (status != DLADM_STATUS_OK)
2818306SSowmini.Varadhan@Sun.COM 		goto bail;
2828306SSowmini.Varadhan@Sun.COM 
2838306SSowmini.Varadhan@Sun.COM 	/* get current values of speed, duplex, state of link */
2848306SSowmini.Varadhan@Sun.COM 	eattr->lei_attr[CURRENT].le_num_spdx = 1;
2858306SSowmini.Varadhan@Sun.COM 	eattr->lei_attr[CURRENT].le_spdx = malloc(sizeof (dladm_ether_spdx_t));
2868306SSowmini.Varadhan@Sun.COM 	if (eattr->lei_attr[CURRENT].le_spdx == NULL) {
2878306SSowmini.Varadhan@Sun.COM 		status = DLADM_STATUS_NOMEM;
2888306SSowmini.Varadhan@Sun.COM 		goto bail;
2898306SSowmini.Varadhan@Sun.COM 	}
2908306SSowmini.Varadhan@Sun.COM 
2918453SAnurag.Maskey@Sun.COM 	if ((status = dladm_get_single_mac_stat(handle, linkid, "ifspeed",
2928306SSowmini.Varadhan@Sun.COM 	    KSTAT_DATA_UINT64, &sp64)) != DLADM_STATUS_OK)
2938306SSowmini.Varadhan@Sun.COM 		goto bail;
2948306SSowmini.Varadhan@Sun.COM 
2958453SAnurag.Maskey@Sun.COM 	if ((status = dladm_get_single_mac_stat(handle, linkid, "link_duplex",
2968306SSowmini.Varadhan@Sun.COM 	    KSTAT_DATA_UINT32, &link_duplex)) != DLADM_STATUS_OK)
2978306SSowmini.Varadhan@Sun.COM 		goto bail;
2988306SSowmini.Varadhan@Sun.COM 
2998306SSowmini.Varadhan@Sun.COM 	eattr->lei_attr[CURRENT].le_spdx->lesd_speed = (int)(sp64/1000000ull);
3008306SSowmini.Varadhan@Sun.COM 	eattr->lei_attr[CURRENT].le_spdx->lesd_duplex = link_duplex;
3018306SSowmini.Varadhan@Sun.COM 
302*11878SVenu.Iyer@Sun.COM 	status = dladm_get_state(handle, linkid, &eattr->lei_state);
3038306SSowmini.Varadhan@Sun.COM 	if (status != DLADM_STATUS_OK)
3048306SSowmini.Varadhan@Sun.COM 		goto bail;
3058306SSowmini.Varadhan@Sun.COM 
3068306SSowmini.Varadhan@Sun.COM 	/* get the auto, pause, asmpause, fault values */
3078306SSowmini.Varadhan@Sun.COM 	for (i = CURRENT; i <= PEERADV; i++)  {
3088306SSowmini.Varadhan@Sun.COM 
3098453SAnurag.Maskey@Sun.COM 		status = dladm_get_single_mac_stat(handle, linkid,
3108306SSowmini.Varadhan@Sun.COM 		    attrstat[i].autoneg_stat, KSTAT_DATA_UINT32, &autoneg);
3118306SSowmini.Varadhan@Sun.COM 		if (status != DLADM_STATUS_OK)
3128306SSowmini.Varadhan@Sun.COM 			goto bail;
3138306SSowmini.Varadhan@Sun.COM 
3148453SAnurag.Maskey@Sun.COM 		status = dladm_get_single_mac_stat(handle, linkid,
3158306SSowmini.Varadhan@Sun.COM 		    attrstat[i].pause_stat, KSTAT_DATA_UINT32, &pause);
3168306SSowmini.Varadhan@Sun.COM 		if (status != DLADM_STATUS_OK)
3178306SSowmini.Varadhan@Sun.COM 			goto bail;
3188306SSowmini.Varadhan@Sun.COM 
3198453SAnurag.Maskey@Sun.COM 		status = dladm_get_single_mac_stat(handle, linkid,
3208306SSowmini.Varadhan@Sun.COM 		    attrstat[i].asmpause_stat, KSTAT_DATA_UINT32, &asmpause);
3218306SSowmini.Varadhan@Sun.COM 		if (status != DLADM_STATUS_OK)
3228306SSowmini.Varadhan@Sun.COM 			goto bail;
3238306SSowmini.Varadhan@Sun.COM 
3248306SSowmini.Varadhan@Sun.COM 		eattr->lei_attr[i].le_autoneg = (autoneg != 0);
3258306SSowmini.Varadhan@Sun.COM 		eattr->lei_attr[i].le_pause = (pause != 0);
3268306SSowmini.Varadhan@Sun.COM 		eattr->lei_attr[i].le_asmpause = (asmpause != 0);
3278306SSowmini.Varadhan@Sun.COM 
3288306SSowmini.Varadhan@Sun.COM 		if (i == CURRENT)
3298306SSowmini.Varadhan@Sun.COM 			continue;
3308453SAnurag.Maskey@Sun.COM 		status = dladm_get_single_mac_stat(handle, linkid,
3318306SSowmini.Varadhan@Sun.COM 		    attrstat[i].fault_stat, KSTAT_DATA_UINT32, &fault);
3328306SSowmini.Varadhan@Sun.COM 		if (status != DLADM_STATUS_OK)
3338306SSowmini.Varadhan@Sun.COM 			goto bail;
3348306SSowmini.Varadhan@Sun.COM 		eattr->lei_attr[i].le_fault = (pause != 0);
3358306SSowmini.Varadhan@Sun.COM 
3368306SSowmini.Varadhan@Sun.COM 		/* get all the supported speed/duplex values */
3378453SAnurag.Maskey@Sun.COM 		status = i_dladm_get_spdx(handle, linkid, &eattr->lei_attr[i],
3388306SSowmini.Varadhan@Sun.COM 		    attrstat[i].spdx_stat);
3398306SSowmini.Varadhan@Sun.COM 		if (status != DLADM_STATUS_OK)
3408306SSowmini.Varadhan@Sun.COM 			goto bail;
3418306SSowmini.Varadhan@Sun.COM 	}
3428306SSowmini.Varadhan@Sun.COM 	eattr->lei_attr[CURRENT].le_fault =
3438306SSowmini.Varadhan@Sun.COM 	    eattr->lei_attr[ADV].le_fault || eattr->lei_attr[PEERADV].le_fault;
3448306SSowmini.Varadhan@Sun.COM bail:
3458306SSowmini.Varadhan@Sun.COM 	if (status != DLADM_STATUS_OK)
3468306SSowmini.Varadhan@Sun.COM 		dladm_ether_info_done(eattr);
3478306SSowmini.Varadhan@Sun.COM 	return (status);
3488306SSowmini.Varadhan@Sun.COM }
3498306SSowmini.Varadhan@Sun.COM 
3508306SSowmini.Varadhan@Sun.COM extern void
dladm_ether_info_done(dladm_ether_info_t * eattr)3518306SSowmini.Varadhan@Sun.COM dladm_ether_info_done(dladm_ether_info_t *eattr)
3528306SSowmini.Varadhan@Sun.COM {
3538306SSowmini.Varadhan@Sun.COM 	int i;
3548306SSowmini.Varadhan@Sun.COM 
3558306SSowmini.Varadhan@Sun.COM 	for (i = CURRENT; i <= PEERADV; i++)
3568306SSowmini.Varadhan@Sun.COM 		free(eattr->lei_attr[i].le_spdx);
3578306SSowmini.Varadhan@Sun.COM }
358