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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * MAC Services Module 30 */ 31 32 #include <sys/types.h> 33 #include <sys/sysmacros.h> 34 #include <sys/stream.h> 35 #include <sys/kstat.h> 36 #include <sys/mac.h> 37 #include <sys/mac_impl.h> 38 39 #define MAC_KSTAT_NAME "mac" 40 #define MAC_KSTAT_CLASS "net" 41 42 static mac_stat_info_t i_mac_si[] = { 43 { MAC_STAT_IFSPEED, "ifspeed", KSTAT_DATA_UINT64, 0 }, 44 { MAC_STAT_MULTIRCV, "multircv", KSTAT_DATA_UINT32, 0 }, 45 { MAC_STAT_BRDCSTRCV, "brdcstrcv", KSTAT_DATA_UINT32, 0 }, 46 { MAC_STAT_MULTIXMT, "multixmt", KSTAT_DATA_UINT32, 0 }, 47 { MAC_STAT_BRDCSTXMT, "brdcstxmt", KSTAT_DATA_UINT32, 0 }, 48 { MAC_STAT_NORCVBUF, "norcvbuf", KSTAT_DATA_UINT32, 0 }, 49 { MAC_STAT_IERRORS, "ierrors", KSTAT_DATA_UINT32, 0 }, 50 { MAC_STAT_UNKNOWNS, "unknowns", KSTAT_DATA_UINT32, 0 }, 51 { MAC_STAT_NOXMTBUF, "noxmtbuf", KSTAT_DATA_UINT32, 0 }, 52 { MAC_STAT_OERRORS, "oerrors", KSTAT_DATA_UINT32, 0 }, 53 { MAC_STAT_COLLISIONS, "collisions", KSTAT_DATA_UINT32, 0 }, 54 { MAC_STAT_UNDERFLOWS, "uflo", KSTAT_DATA_UINT32, 0 }, 55 { MAC_STAT_OVERFLOWS, "oflo", KSTAT_DATA_UINT32, 0 }, 56 { MAC_STAT_RBYTES, "rbytes", KSTAT_DATA_UINT32, 0 }, 57 { MAC_STAT_IPACKETS, "ipackets", KSTAT_DATA_UINT32, 0 }, 58 { MAC_STAT_OBYTES, "obytes", KSTAT_DATA_UINT32, 0 }, 59 { MAC_STAT_OPACKETS, "opackets", KSTAT_DATA_UINT32, 0 }, 60 { MAC_STAT_RBYTES, "rbytes64", KSTAT_DATA_UINT64, 0 }, 61 { MAC_STAT_IPACKETS, "ipackets64", KSTAT_DATA_UINT64, 0 }, 62 { MAC_STAT_OBYTES, "obytes64", KSTAT_DATA_UINT64, 0 }, 63 { MAC_STAT_OPACKETS, "opackets64", KSTAT_DATA_UINT64, 0 } 64 }; 65 66 #define MAC_NKSTAT \ 67 (sizeof (i_mac_si) / sizeof (mac_stat_info_t)) 68 69 static mac_stat_info_t i_mac_mod_si[] = { 70 { MAC_STAT_LINK_STATE, "link_state", KSTAT_DATA_UINT32, 71 (uint64_t)LINK_STATE_UNKNOWN }, 72 { MAC_STAT_LINK_UP, "link_up", KSTAT_DATA_UINT32, 0 }, 73 { MAC_STAT_PROMISC, "promisc", KSTAT_DATA_UINT32, 0 } 74 }; 75 76 #define MAC_MOD_NKSTAT \ 77 (sizeof (i_mac_mod_si) / sizeof (mac_stat_info_t)) 78 79 #define MAC_MOD_KSTAT_OFFSET 0 80 #define MAC_KSTAT_OFFSET MAC_MOD_KSTAT_OFFSET + MAC_MOD_NKSTAT 81 #define MAC_TYPE_KSTAT_OFFSET MAC_KSTAT_OFFSET + MAC_NKSTAT 82 83 /* 84 * Private functions. 85 */ 86 87 static int 88 i_mac_stat_update(kstat_t *ksp, int rw) 89 { 90 mac_impl_t *mip = ksp->ks_private; 91 kstat_named_t *knp = ksp->ks_data; 92 uint_t i; 93 uint64_t val; 94 mac_stat_info_t *msi; 95 uint_t msi_index; 96 97 if (rw != KSTAT_READ) 98 return (EACCES); 99 100 for (i = 0; i < mip->mi_kstat_count; i++, msi_index++) { 101 if (i == MAC_MOD_KSTAT_OFFSET) { 102 msi_index = 0; 103 msi = i_mac_mod_si; 104 } else if (i == MAC_KSTAT_OFFSET) { 105 msi_index = 0; 106 msi = i_mac_si; 107 } else if (i == MAC_TYPE_KSTAT_OFFSET) { 108 msi_index = 0; 109 msi = mip->mi_type->mt_stats; 110 } 111 112 val = mac_stat_get((mac_handle_t)mip, msi[msi_index].msi_stat); 113 switch (msi[msi_index].msi_type) { 114 case KSTAT_DATA_UINT64: 115 knp->value.ui64 = val; 116 break; 117 case KSTAT_DATA_UINT32: 118 knp->value.ui32 = (uint32_t)val; 119 break; 120 default: 121 ASSERT(B_FALSE); 122 break; 123 } 124 125 knp++; 126 } 127 128 return (0); 129 } 130 131 static void 132 i_mac_kstat_init(kstat_named_t *knp, mac_stat_info_t *si, uint_t count) 133 { 134 int i; 135 for (i = 0; i < count; i++) { 136 kstat_named_init(knp, si[i].msi_name, si[i].msi_type); 137 knp++; 138 } 139 } 140 141 /* 142 * Exported functions. 143 */ 144 145 /* 146 * Create the "mac" kstat. The "mac" kstat is comprised of three kinds of 147 * statistics: statistics maintained by the mac module itself, generic mac 148 * statistics maintained by the driver, and MAC-type specific statistics 149 * also maintained by the driver. 150 */ 151 void 152 mac_stat_create(mac_impl_t *mip) 153 { 154 kstat_t *ksp; 155 kstat_named_t *knp; 156 uint_t count; 157 major_t major = getmajor(mip->mi_phy_dev); 158 159 count = MAC_MOD_NKSTAT + MAC_NKSTAT + mip->mi_type->mt_statcount; 160 if (!GLDV3_DRV(major)) { 161 ksp = kstat_create((const char *)ddi_major_to_name(major), 162 getminor(mip->mi_phy_dev) - 1, MAC_KSTAT_NAME, 163 MAC_KSTAT_CLASS, KSTAT_TYPE_NAMED, count, 0); 164 } else { 165 major = ddi_driver_major(mip->mi_dip); 166 ksp = kstat_create((const char *)ddi_major_to_name(major), 167 mip->mi_minor - 1, MAC_KSTAT_NAME, 168 MAC_KSTAT_CLASS, KSTAT_TYPE_NAMED, count, 0); 169 } 170 if (ksp == NULL) 171 return; 172 173 ksp->ks_update = i_mac_stat_update; 174 ksp->ks_private = mip; 175 mip->mi_ksp = ksp; 176 mip->mi_kstat_count = count; 177 178 knp = (kstat_named_t *)ksp->ks_data; 179 i_mac_kstat_init(knp, i_mac_mod_si, MAC_MOD_NKSTAT); 180 knp += MAC_MOD_NKSTAT; 181 i_mac_kstat_init(knp, i_mac_si, MAC_NKSTAT); 182 if (mip->mi_type->mt_statcount > 0) { 183 knp += MAC_NKSTAT; 184 i_mac_kstat_init(knp, mip->mi_type->mt_stats, 185 mip->mi_type->mt_statcount); 186 } 187 188 kstat_install(ksp); 189 } 190 191 /*ARGSUSED*/ 192 void 193 mac_stat_destroy(mac_impl_t *mip) 194 { 195 if (mip->mi_ksp != NULL) { 196 kstat_delete(mip->mi_ksp); 197 mip->mi_ksp = NULL; 198 mip->mi_kstat_count = 0; 199 } 200 } 201 202 uint64_t 203 mac_stat_default(mac_impl_t *mip, uint_t stat) 204 { 205 uint_t stat_index; 206 207 if (IS_MAC_STAT(stat)) { 208 stat_index = stat - MAC_STAT_MIN; 209 return (i_mac_si[stat_index].msi_default); 210 } 211 ASSERT(IS_MACTYPE_STAT(stat)); 212 stat_index = stat - MACTYPE_STAT_MIN; 213 return (mip->mi_type->mt_stats[stat_index].msi_default); 214 } 215