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