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/kstat.h> 37 #include <sys/vlan.h> 38 #include <sys/mac.h> 39 #include <sys/ctype.h> 40 #include <sys/dls.h> 41 #include <sys/dls_impl.h> 42 43 typedef struct i_dls_stat_info_s { 44 enum mac_stat dsi_stat; 45 char *dsi_name; 46 uint_t dsi_type; 47 } i_mac_stat_info_t; 48 49 static i_mac_stat_info_t i_dls_si[] = { 50 { MAC_STAT_IFSPEED, "ifspeed", KSTAT_DATA_UINT64 }, 51 { MAC_STAT_MULTIRCV, "multircv", KSTAT_DATA_UINT32 }, 52 { MAC_STAT_BRDCSTRCV, "brdcstrcv", KSTAT_DATA_UINT32 }, 53 { MAC_STAT_MULTIXMT, "multixmt", KSTAT_DATA_UINT32 }, 54 { MAC_STAT_BRDCSTXMT, "brdcstxmt", KSTAT_DATA_UINT32 }, 55 { MAC_STAT_NORCVBUF, "norcvbuf", KSTAT_DATA_UINT32 }, 56 { MAC_STAT_IERRORS, "ierrors", KSTAT_DATA_UINT32 }, 57 { MAC_STAT_NOXMTBUF, "noxmtbuf", KSTAT_DATA_UINT32 }, 58 { MAC_STAT_OERRORS, "oerrors", KSTAT_DATA_UINT32 }, 59 { MAC_STAT_COLLISIONS, "collisions", KSTAT_DATA_UINT32 }, 60 { MAC_STAT_RBYTES, "rbytes", KSTAT_DATA_UINT32 }, 61 { MAC_STAT_IPACKETS, "ipackets", KSTAT_DATA_UINT32 }, 62 { MAC_STAT_OBYTES, "obytes", KSTAT_DATA_UINT32 }, 63 { MAC_STAT_OPACKETS, "opackets", KSTAT_DATA_UINT32 }, 64 { MAC_STAT_RBYTES, "rbytes64", KSTAT_DATA_UINT64 }, 65 { MAC_STAT_IPACKETS, "ipackets64", KSTAT_DATA_UINT64 }, 66 { MAC_STAT_OBYTES, "obytes64", KSTAT_DATA_UINT64 }, 67 { MAC_STAT_OPACKETS, "opackets64", KSTAT_DATA_UINT64 } 68 }; 69 70 #define STAT_INFO_COUNT (sizeof (i_dls_si) / sizeof (i_dls_si[0])) 71 72 /* 73 * Private functions. 74 */ 75 76 static int 77 i_dls_stat_update(kstat_t *ksp, int rw) 78 { 79 dls_vlan_t *dvp = ksp->ks_private; 80 dls_link_t *dlp = dvp->dv_dlp; 81 kstat_named_t *knp; 82 uint_t i; 83 uint64_t val; 84 int err; 85 86 if (rw != KSTAT_READ) 87 return (EACCES); 88 89 if ((err = dls_mac_hold(dlp)) != 0) 90 return (err); 91 92 knp = (kstat_named_t *)ksp->ks_data; 93 for (i = 0; i < STAT_INFO_COUNT; i++) { 94 if (!(dlp->dl_mip->mi_stat[i_dls_si[i].dsi_stat])) 95 continue; 96 97 val = mac_stat_get(dlp->dl_mh, i_dls_si[i].dsi_stat); 98 99 switch (i_dls_si[i].dsi_type) { 100 case KSTAT_DATA_UINT64: 101 knp->value.ui64 = val; 102 break; 103 case KSTAT_DATA_UINT32: 104 knp->value.ui32 = (uint32_t)val; 105 break; 106 default: 107 ASSERT(B_FALSE); 108 } 109 110 knp++; 111 } 112 113 knp->value.ui32 = dlp->dl_unknowns; 114 dls_mac_rele(dlp); 115 116 return (0); 117 } 118 119 /* 120 * Exported functions. 121 */ 122 123 void 124 dls_stat_create(dls_vlan_t *dvp) 125 { 126 dls_link_t *dlp = dvp->dv_dlp; 127 char module[IFNAMSIZ]; 128 uint_t instance; 129 kstat_t *ksp; 130 kstat_named_t *knp; 131 uint_t i; 132 uint_t count; 133 int err; 134 135 if (dls_mac_hold(dlp) != 0) 136 return; 137 138 count = 0; 139 for (i = 0; i < STAT_INFO_COUNT; i++) { 140 if (dlp->dl_mip->mi_stat[i_dls_si[i].dsi_stat]) 141 count++; 142 } 143 144 err = ddi_parse(dvp->dv_name, module, &instance); 145 ASSERT(err == DDI_SUCCESS); 146 147 if ((ksp = kstat_create(module, instance, NULL, "net", 148 KSTAT_TYPE_NAMED, count + 1, 0)) == NULL) 149 goto done; 150 151 ksp->ks_update = i_dls_stat_update; 152 ksp->ks_private = (void *)dvp; 153 dvp->dv_ksp = ksp; 154 155 knp = (kstat_named_t *)ksp->ks_data; 156 for (i = 0; i < STAT_INFO_COUNT; i++) { 157 if (!(dlp->dl_mip->mi_stat[i_dls_si[i].dsi_stat])) 158 continue; 159 160 kstat_named_init(knp, i_dls_si[i].dsi_name, 161 i_dls_si[i].dsi_type); 162 knp++; 163 --count; 164 } 165 ASSERT(count == 0); 166 167 kstat_named_init(knp, "unknowns", KSTAT_DATA_UINT32); 168 169 kstat_install(ksp); 170 done: 171 dls_mac_rele(dlp); 172 } 173 174 void 175 dls_stat_destroy(dls_vlan_t *dvp) 176 { 177 kstat_delete(dvp->dv_ksp); 178 dvp->dv_ksp = NULL; 179 } 180