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