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