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 /* 228306SSowmini.Varadhan@Sun.COM * Copyright 2008 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 108*8453SAnurag.Maskey@Sun.COM i_dladm_get_spdx(dladm_handle_t handle, datalink_id_t linkid, 109*8453SAnurag.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++) { 118*8453SAnurag.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 * 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 * 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 * 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 268*8453SAnurag.Maskey@Sun.COM dladm_ether_info(dladm_handle_t handle, datalink_id_t linkid, 269*8453SAnurag.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)); 278*8453SAnurag.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 291*8453SAnurag.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 295*8453SAnurag.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*8453SAnurag.Maskey@Sun.COM status = i_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 309*8453SAnurag.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 314*8453SAnurag.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 319*8453SAnurag.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; 330*8453SAnurag.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 */ 337*8453SAnurag.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 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