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 2006 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_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 156 count = MAC_MOD_NKSTAT + MAC_NKSTAT + mip->mi_type->mt_statcount; 157 ksp = kstat_create((char *)mip->mi_drvname, mip->mi_instance, 158 MAC_KSTAT_NAME, MAC_KSTAT_CLASS, KSTAT_TYPE_NAMED, count, 0); 159 if (ksp == NULL) 160 return; 161 162 ksp->ks_update = i_mac_stat_update; 163 ksp->ks_private = mip; 164 mip->mi_ksp = ksp; 165 mip->mi_kstat_count = count; 166 167 knp = (kstat_named_t *)ksp->ks_data; 168 i_mac_kstat_init(knp, i_mac_mod_si, MAC_MOD_NKSTAT); 169 knp += MAC_MOD_NKSTAT; 170 i_mac_kstat_init(knp, i_mac_si, MAC_NKSTAT); 171 if (mip->mi_type->mt_statcount > 0) { 172 knp += MAC_NKSTAT; 173 i_mac_kstat_init(knp, mip->mi_type->mt_stats, 174 mip->mi_type->mt_statcount); 175 } 176 177 kstat_install(ksp); 178 } 179 180 /*ARGSUSED*/ 181 void 182 mac_stat_destroy(mac_impl_t *mip) 183 { 184 if (mip->mi_ksp != NULL) { 185 kstat_delete(mip->mi_ksp); 186 mip->mi_ksp = NULL; 187 mip->mi_kstat_count = 0; 188 } 189 } 190 191 uint64_t 192 mac_stat_default(mac_impl_t *mip, uint_t stat) 193 { 194 uint_t stat_index; 195 196 if (IS_MAC_STAT(stat)) { 197 stat_index = stat - MAC_STAT_MIN; 198 return (i_mac_si[stat_index].msi_default); 199 } 200 ASSERT(IS_MACTYPE_STAT(stat)); 201 stat_index = stat - MACTYPE_STAT_MIN; 202 return (mip->mi_type->mt_stats[stat_index].msi_default); 203 } 204