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