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 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * MAC Services Module 28 */ 29 30 #include <sys/types.h> 31 #include <sys/sysmacros.h> 32 #include <sys/stream.h> 33 #include <sys/kstat.h> 34 #include <sys/mac.h> 35 #include <sys/mac_impl.h> 36 37 #define MAC_KSTAT_NAME "mac" 38 #define MAC_KSTAT_CLASS "net" 39 40 static mac_stat_info_t i_mac_si[] = { 41 { MAC_STAT_IFSPEED, "ifspeed", KSTAT_DATA_UINT64, 0 }, 42 { MAC_STAT_MULTIRCV, "multircv", KSTAT_DATA_UINT32, 0 }, 43 { MAC_STAT_BRDCSTRCV, "brdcstrcv", KSTAT_DATA_UINT32, 0 }, 44 { MAC_STAT_MULTIXMT, "multixmt", KSTAT_DATA_UINT32, 0 }, 45 { MAC_STAT_BRDCSTXMT, "brdcstxmt", KSTAT_DATA_UINT32, 0 }, 46 { MAC_STAT_NORCVBUF, "norcvbuf", KSTAT_DATA_UINT32, 0 }, 47 { MAC_STAT_IERRORS, "ierrors", KSTAT_DATA_UINT32, 0 }, 48 { MAC_STAT_UNKNOWNS, "unknowns", KSTAT_DATA_UINT32, 0 }, 49 { MAC_STAT_NOXMTBUF, "noxmtbuf", KSTAT_DATA_UINT32, 0 }, 50 { MAC_STAT_OERRORS, "oerrors", KSTAT_DATA_UINT32, 0 }, 51 { MAC_STAT_COLLISIONS, "collisions", KSTAT_DATA_UINT32, 0 }, 52 { MAC_STAT_UNDERFLOWS, "uflo", KSTAT_DATA_UINT32, 0 }, 53 { MAC_STAT_OVERFLOWS, "oflo", KSTAT_DATA_UINT32, 0 }, 54 { MAC_STAT_RBYTES, "rbytes", KSTAT_DATA_UINT32, 0 }, 55 { MAC_STAT_IPACKETS, "ipackets", KSTAT_DATA_UINT32, 0 }, 56 { MAC_STAT_OBYTES, "obytes", KSTAT_DATA_UINT32, 0 }, 57 { MAC_STAT_OPACKETS, "opackets", KSTAT_DATA_UINT32, 0 }, 58 { MAC_STAT_RBYTES, "rbytes64", KSTAT_DATA_UINT64, 0 }, 59 { MAC_STAT_IPACKETS, "ipackets64", KSTAT_DATA_UINT64, 0 }, 60 { MAC_STAT_OBYTES, "obytes64", KSTAT_DATA_UINT64, 0 }, 61 { MAC_STAT_OPACKETS, "opackets64", KSTAT_DATA_UINT64, 0 } 62 }; 63 64 #define MAC_NKSTAT \ 65 (sizeof (i_mac_si) / sizeof (mac_stat_info_t)) 66 67 static mac_stat_info_t i_mac_mod_si[] = { 68 { MAC_STAT_LINK_STATE, "link_state", KSTAT_DATA_UINT32, 69 (uint64_t)LINK_STATE_UNKNOWN }, 70 { MAC_STAT_LINK_UP, "link_up", KSTAT_DATA_UINT32, 0 }, 71 { MAC_STAT_PROMISC, "promisc", KSTAT_DATA_UINT32, 0 } 72 }; 73 74 #define MAC_MOD_NKSTAT \ 75 (sizeof (i_mac_mod_si) / sizeof (mac_stat_info_t)) 76 77 #define MAC_MOD_KSTAT_OFFSET 0 78 #define MAC_KSTAT_OFFSET MAC_MOD_KSTAT_OFFSET + MAC_MOD_NKSTAT 79 #define MAC_TYPE_KSTAT_OFFSET MAC_KSTAT_OFFSET + MAC_NKSTAT 80 81 /* 82 * Private functions. 83 */ 84 85 static int 86 i_mac_stat_update(kstat_t *ksp, int rw) 87 { 88 mac_impl_t *mip = ksp->ks_private; 89 kstat_named_t *knp = ksp->ks_data; 90 uint_t i; 91 uint64_t val; 92 mac_stat_info_t *msi; 93 uint_t msi_index; 94 95 if (rw != KSTAT_READ) 96 return (EACCES); 97 98 for (i = 0; i < mip->mi_kstat_count; i++, msi_index++) { 99 if (i == MAC_MOD_KSTAT_OFFSET) { 100 msi_index = 0; 101 msi = i_mac_mod_si; 102 } else if (i == MAC_KSTAT_OFFSET) { 103 msi_index = 0; 104 msi = i_mac_si; 105 } else if (i == MAC_TYPE_KSTAT_OFFSET) { 106 msi_index = 0; 107 msi = mip->mi_type->mt_stats; 108 } 109 110 val = mac_stat_get((mac_handle_t)mip, msi[msi_index].msi_stat); 111 switch (msi[msi_index].msi_type) { 112 case KSTAT_DATA_UINT64: 113 knp->value.ui64 = val; 114 break; 115 case KSTAT_DATA_UINT32: 116 knp->value.ui32 = (uint32_t)val; 117 break; 118 default: 119 ASSERT(B_FALSE); 120 break; 121 } 122 123 knp++; 124 } 125 126 return (0); 127 } 128 129 static void 130 i_mac_kstat_init(kstat_named_t *knp, mac_stat_info_t *si, uint_t count) 131 { 132 int i; 133 for (i = 0; i < count; i++) { 134 kstat_named_init(knp, si[i].msi_name, si[i].msi_type); 135 knp++; 136 } 137 } 138 139 /* 140 * Exported functions. 141 */ 142 143 /* 144 * Create the "mac" kstat. The "mac" kstat is comprised of three kinds of 145 * statistics: statistics maintained by the mac module itself, generic mac 146 * statistics maintained by the driver, and MAC-type specific statistics 147 * also maintained by the driver. 148 */ 149 void 150 mac_stat_create(mac_impl_t *mip) 151 { 152 kstat_t *ksp; 153 kstat_named_t *knp; 154 uint_t count; 155 major_t major = getmajor(mip->mi_phy_dev); 156 157 count = MAC_MOD_NKSTAT + MAC_NKSTAT + mip->mi_type->mt_statcount; 158 ksp = kstat_create((const char *)ddi_major_to_name(major), 159 getminor(mip->mi_phy_dev) - 1, MAC_KSTAT_NAME, 160 MAC_KSTAT_CLASS, KSTAT_TYPE_NAMED, count, 0); 161 if (ksp == NULL) 162 return; 163 164 ksp->ks_update = i_mac_stat_update; 165 ksp->ks_private = mip; 166 mip->mi_ksp = ksp; 167 mip->mi_kstat_count = count; 168 169 knp = (kstat_named_t *)ksp->ks_data; 170 i_mac_kstat_init(knp, i_mac_mod_si, MAC_MOD_NKSTAT); 171 knp += MAC_MOD_NKSTAT; 172 i_mac_kstat_init(knp, i_mac_si, MAC_NKSTAT); 173 if (mip->mi_type->mt_statcount > 0) { 174 knp += MAC_NKSTAT; 175 i_mac_kstat_init(knp, mip->mi_type->mt_stats, 176 mip->mi_type->mt_statcount); 177 } 178 179 kstat_install(ksp); 180 } 181 182 /*ARGSUSED*/ 183 void 184 mac_stat_destroy(mac_impl_t *mip) 185 { 186 if (mip->mi_ksp != NULL) { 187 kstat_delete(mip->mi_ksp); 188 mip->mi_ksp = NULL; 189 mip->mi_kstat_count = 0; 190 } 191 } 192 193 uint64_t 194 mac_stat_default(mac_impl_t *mip, uint_t stat) 195 { 196 uint_t stat_index; 197 198 if (IS_MAC_STAT(stat)) { 199 stat_index = stat - MAC_STAT_MIN; 200 return (i_mac_si[stat_index].msi_default); 201 } 202 ASSERT(IS_MACTYPE_STAT(stat)); 203 stat_index = stat - MACTYPE_STAT_MIN; 204 return (mip->mi_type->mt_stats[stat_index].msi_default); 205 } 206