xref: /illumos-gate/usr/src/uts/common/io/mac/mac_stat.c (revision 1b83305cfc332b1e19ad6a194b73b2975e6bf79a)
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