1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * Data-Link Services Module 31 */ 32 33 #include <sys/types.h> 34 #include <sys/sysmacros.h> 35 #include <sys/atomic.h> 36 #include <sys/ght.h> 37 #include <sys/kstat.h> 38 #include <sys/vlan.h> 39 #include <sys/mac.h> 40 #include <sys/ctype.h> 41 #include <sys/dls.h> 42 #include <sys/dls_impl.h> 43 44 typedef struct i_dls_stat_info_s { 45 enum mac_stat dsi_stat; 46 char *dsi_name; 47 uint_t dsi_type; 48 } i_mac_stat_info_t; 49 50 static i_mac_stat_info_t i_dls_si[] = { 51 { MAC_STAT_IFSPEED, "ifspeed", KSTAT_DATA_UINT64 }, 52 { MAC_STAT_MULTIRCV, "multircv", KSTAT_DATA_UINT32 }, 53 { MAC_STAT_BRDCSTRCV, "brdcstrcv", KSTAT_DATA_UINT32 }, 54 { MAC_STAT_MULTIXMT, "multixmt", KSTAT_DATA_UINT32 }, 55 { MAC_STAT_BRDCSTXMT, "brdcstxmt", KSTAT_DATA_UINT32 }, 56 { MAC_STAT_NORCVBUF, "norcvbuf", KSTAT_DATA_UINT32 }, 57 { MAC_STAT_IERRORS, "ierrors", KSTAT_DATA_UINT32 }, 58 { MAC_STAT_NOXMTBUF, "noxmtbuf", KSTAT_DATA_UINT32 }, 59 { MAC_STAT_OERRORS, "oerrors", KSTAT_DATA_UINT32 }, 60 { MAC_STAT_COLLISIONS, "collisions", KSTAT_DATA_UINT32 }, 61 { MAC_STAT_RBYTES, "rbytes", KSTAT_DATA_UINT32 }, 62 { MAC_STAT_IPACKETS, "ipackets", KSTAT_DATA_UINT32 }, 63 { MAC_STAT_OBYTES, "obytes", KSTAT_DATA_UINT32 }, 64 { MAC_STAT_OPACKETS, "opackets", KSTAT_DATA_UINT32 }, 65 { MAC_STAT_RBYTES, "rbytes64", KSTAT_DATA_UINT64 }, 66 { MAC_STAT_IPACKETS, "ipackets64", KSTAT_DATA_UINT64 }, 67 { MAC_STAT_OBYTES, "obytes64", KSTAT_DATA_UINT64 }, 68 { MAC_STAT_OPACKETS, "opackets64", KSTAT_DATA_UINT64 } 69 }; 70 71 #define STAT_INFO_COUNT (sizeof (i_dls_si) / sizeof (i_dls_si[0])) 72 73 /* 74 * Private functions. 75 */ 76 77 static int 78 i_dls_stat_update(kstat_t *ksp, int rw) 79 { 80 dls_vlan_t *dvp = ksp->ks_private; 81 dls_link_t *dlp = dvp->dv_dlp; 82 kstat_named_t *knp; 83 uint_t i; 84 uint64_t val; 85 int err; 86 87 if (rw != KSTAT_READ) 88 return (EACCES); 89 90 if ((err = dls_mac_hold(dlp)) != 0) 91 return (err); 92 93 knp = (kstat_named_t *)ksp->ks_data; 94 for (i = 0; i < STAT_INFO_COUNT; i++) { 95 if (!(dlp->dl_mip->mi_stat[i_dls_si[i].dsi_stat])) 96 continue; 97 98 val = mac_stat_get(dlp->dl_mh, i_dls_si[i].dsi_stat); 99 100 switch (i_dls_si[i].dsi_type) { 101 case KSTAT_DATA_UINT64: 102 knp->value.ui64 = val; 103 break; 104 case KSTAT_DATA_UINT32: 105 knp->value.ui32 = (uint32_t)val; 106 break; 107 default: 108 ASSERT(B_FALSE); 109 } 110 111 knp++; 112 } 113 114 knp->value.ui32 = dlp->dl_unknowns; 115 dls_mac_rele(dlp); 116 117 return (0); 118 } 119 120 /* 121 * Exported functions. 122 */ 123 124 void 125 dls_stat_create(dls_vlan_t *dvp) 126 { 127 dls_link_t *dlp = dvp->dv_dlp; 128 char module[IFNAMSIZ]; 129 uint_t instance; 130 kstat_t *ksp; 131 kstat_named_t *knp; 132 uint_t i; 133 uint_t count; 134 int err; 135 136 if (dls_mac_hold(dlp) != 0) 137 return; 138 139 count = 0; 140 for (i = 0; i < STAT_INFO_COUNT; i++) { 141 if (dlp->dl_mip->mi_stat[i_dls_si[i].dsi_stat]) 142 count++; 143 } 144 145 err = ddi_parse(dvp->dv_name, module, &instance); 146 ASSERT(err == DDI_SUCCESS); 147 148 if ((ksp = kstat_create(module, instance, NULL, "net", 149 KSTAT_TYPE_NAMED, count + 1, 0)) == NULL) 150 goto done; 151 152 ksp->ks_update = i_dls_stat_update; 153 ksp->ks_private = (void *)dvp; 154 dvp->dv_ksp = ksp; 155 156 knp = (kstat_named_t *)ksp->ks_data; 157 for (i = 0; i < STAT_INFO_COUNT; i++) { 158 if (!(dlp->dl_mip->mi_stat[i_dls_si[i].dsi_stat])) 159 continue; 160 161 kstat_named_init(knp, i_dls_si[i].dsi_name, 162 i_dls_si[i].dsi_type); 163 knp++; 164 --count; 165 } 166 ASSERT(count == 0); 167 168 kstat_named_init(knp, "unknowns", KSTAT_DATA_UINT32); 169 170 kstat_install(ksp); 171 done: 172 dls_mac_rele(dlp); 173 } 174 175 void 176 dls_stat_destroy(dls_vlan_t *dvp) 177 { 178 kstat_delete(dvp->dv_ksp); 179 dvp->dv_ksp = NULL; 180 } 181