xref: /illumos-gate/usr/src/uts/common/inet/sctp/sctp_snmp.c (revision d0698e0d179f97729cacdbc2f13446a6b0a3f22a)
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 /*
23  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
24  */
25 
26 #include <sys/types.h>
27 #include <sys/stream.h>
28 #include <sys/cmn_err.h>
29 #define	_SUN_TPI_VERSION 2
30 #include <sys/tihdr.h>
31 #include <sys/ddi.h>
32 #include <sys/sunddi.h>
33 #include <sys/tsol/tndb.h>
34 
35 #include <netinet/in.h>
36 
37 #include <inet/common.h>
38 #include <inet/ip.h>
39 #include <inet/mib2.h>
40 #include <inet/snmpcom.h>
41 #include <inet/kstatcom.h>
42 #include <inet/ipclassifier.h>
43 #include "sctp_impl.h"
44 #include "sctp_addr.h"
45 
46 static void sctp_clr_kstats2(sctp_kstat_t *);
47 static void sctp_add_kstats2(sctp_kstat_counter_t *, sctp_kstat_t *);
48 static int sctp_snmp_state(sctp_t *);
49 static void sctp_sum_mib(sctp_stack_t *, mib2_sctp_t *);
50 static void sctp_add_mib(mib2_sctp_t *, mib2_sctp_t *);
51 
52 static int
53 sctp_kstat_update(kstat_t *kp, int rw)
54 {
55 	sctp_named_kstat_t	*sctpkp;
56 	sctp_t			*sctp, *sctp_prev;
57 	zoneid_t	myzoneid;
58 	netstackid_t	stackid = (netstackid_t)(uintptr_t)kp->ks_private;
59 	netstack_t	*ns;
60 	sctp_stack_t	*sctps;
61 	mib2_sctp_t	sctp_mib;
62 
63 	if (kp == NULL|| kp->ks_data == NULL)
64 		return (EIO);
65 
66 	if (rw == KSTAT_WRITE)
67 		return (EACCES);
68 
69 	ns = netstack_find_by_stackid(stackid);
70 	if (ns == NULL)
71 		return (-1);
72 	sctps = ns->netstack_sctp;
73 	if (sctps == NULL) {
74 		netstack_rele(ns);
75 		return (-1);
76 	}
77 
78 	/*
79 	 * For all exclusive netstacks, the zone ID is always GLOBAL_ZONEID.
80 	 */
81 	if (stackid != GLOBAL_NETSTACKID)
82 		myzoneid = GLOBAL_ZONEID;
83 	else
84 		myzoneid = curproc->p_zone->zone_id;
85 
86 	bzero(&sctp_mib, sizeof (sctp_mib));
87 
88 	/*
89 	 * Get the number of current associations and gather their
90 	 * individual set of statistics.
91 	 */
92 	sctp_prev = NULL;
93 	mutex_enter(&sctps->sctps_g_lock);
94 	sctp = list_head(&sctps->sctps_g_list);
95 	while (sctp != NULL) {
96 		mutex_enter(&sctp->sctp_reflock);
97 		if (sctp->sctp_condemned) {
98 			mutex_exit(&sctp->sctp_reflock);
99 			sctp = list_next(&sctps->sctps_g_list, sctp);
100 			continue;
101 		}
102 		sctp->sctp_refcnt++;
103 		mutex_exit(&sctp->sctp_reflock);
104 		mutex_exit(&sctps->sctps_g_lock);
105 		if (sctp_prev != NULL)
106 			SCTP_REFRELE(sctp_prev);
107 		if (sctp->sctp_connp->conn_zoneid != myzoneid)
108 			goto next_sctp;
109 		if (sctp->sctp_state == SCTPS_ESTABLISHED ||
110 		    sctp->sctp_state == SCTPS_SHUTDOWN_PENDING ||
111 		    sctp->sctp_state == SCTPS_SHUTDOWN_RECEIVED) {
112 			/*
113 			 * Just bump the local sctp_mib.  The number of
114 			 * existing associations is not kept in kernel.
115 			 */
116 			BUMP_MIB(&sctp_mib, sctpCurrEstab);
117 		}
118 
119 		if (sctp->sctp_opkts) {
120 			SCTPS_UPDATE_MIB(sctps, sctpOutSCTPPkts,
121 			    sctp->sctp_opkts);
122 			sctp->sctp_opkts = 0;
123 		}
124 
125 		if (sctp->sctp_obchunks) {
126 			SCTPS_UPDATE_MIB(sctps, sctpOutCtrlChunks,
127 			    sctp->sctp_obchunks);
128 			UPDATE_LOCAL(sctp->sctp_cum_obchunks,
129 			    sctp->sctp_obchunks);
130 			sctp->sctp_obchunks = 0;
131 		}
132 
133 		if (sctp->sctp_odchunks) {
134 			SCTPS_UPDATE_MIB(sctps, sctpOutOrderChunks,
135 			    sctp->sctp_odchunks);
136 			UPDATE_LOCAL(sctp->sctp_cum_odchunks,
137 			    sctp->sctp_odchunks);
138 			sctp->sctp_odchunks = 0;
139 		}
140 
141 		if (sctp->sctp_oudchunks) {
142 			SCTPS_UPDATE_MIB(sctps, sctpOutUnorderChunks,
143 			    sctp->sctp_oudchunks);
144 			UPDATE_LOCAL(sctp->sctp_cum_oudchunks,
145 			    sctp->sctp_oudchunks);
146 			sctp->sctp_oudchunks = 0;
147 		}
148 
149 		if (sctp->sctp_rxtchunks) {
150 			SCTPS_UPDATE_MIB(sctps, sctpRetransChunks,
151 			    sctp->sctp_rxtchunks);
152 			UPDATE_LOCAL(sctp->sctp_cum_rxtchunks,
153 			    sctp->sctp_rxtchunks);
154 			sctp->sctp_rxtchunks = 0;
155 		}
156 
157 		if (sctp->sctp_ipkts) {
158 			SCTPS_UPDATE_MIB(sctps, sctpInSCTPPkts,
159 			    sctp->sctp_ipkts);
160 			sctp->sctp_ipkts = 0;
161 		}
162 
163 		if (sctp->sctp_ibchunks) {
164 			SCTPS_UPDATE_MIB(sctps, sctpInCtrlChunks,
165 			    sctp->sctp_ibchunks);
166 			UPDATE_LOCAL(sctp->sctp_cum_ibchunks,
167 			    sctp->sctp_ibchunks);
168 			sctp->sctp_ibchunks = 0;
169 		}
170 
171 		if (sctp->sctp_idchunks) {
172 			SCTPS_UPDATE_MIB(sctps, sctpInOrderChunks,
173 			    sctp->sctp_idchunks);
174 			UPDATE_LOCAL(sctp->sctp_cum_idchunks,
175 			    sctp->sctp_idchunks);
176 			sctp->sctp_idchunks = 0;
177 		}
178 
179 		if (sctp->sctp_iudchunks) {
180 			SCTPS_UPDATE_MIB(sctps, sctpInUnorderChunks,
181 			    sctp->sctp_iudchunks);
182 			UPDATE_LOCAL(sctp->sctp_cum_iudchunks,
183 			    sctp->sctp_iudchunks);
184 			sctp->sctp_iudchunks = 0;
185 		}
186 
187 		if (sctp->sctp_fragdmsgs) {
188 			SCTPS_UPDATE_MIB(sctps, sctpFragUsrMsgs,
189 			    sctp->sctp_fragdmsgs);
190 			sctp->sctp_fragdmsgs = 0;
191 		}
192 
193 		if (sctp->sctp_reassmsgs) {
194 			SCTPS_UPDATE_MIB(sctps, sctpReasmUsrMsgs,
195 			    sctp->sctp_reassmsgs);
196 			sctp->sctp_reassmsgs = 0;
197 		}
198 
199 next_sctp:
200 		sctp_prev = sctp;
201 		mutex_enter(&sctps->sctps_g_lock);
202 		sctp = list_next(&sctps->sctps_g_list, sctp);
203 	}
204 	mutex_exit(&sctps->sctps_g_lock);
205 	if (sctp_prev != NULL)
206 		SCTP_REFRELE(sctp_prev);
207 
208 	sctp_sum_mib(sctps, &sctp_mib);
209 
210 	/* Copy data from the SCTP MIB */
211 	sctpkp = (sctp_named_kstat_t *)kp->ks_data;
212 
213 	/* These are from global ndd params. */
214 	sctpkp->sctpRtoMin.value.ui32 = sctps->sctps_rto_ming;
215 	sctpkp->sctpRtoMax.value.ui32 = sctps->sctps_rto_maxg;
216 	sctpkp->sctpRtoInitial.value.ui32 = sctps->sctps_rto_initialg;
217 	sctpkp->sctpValCookieLife.value.ui32 = sctps->sctps_cookie_life;
218 	sctpkp->sctpMaxInitRetr.value.ui32 = sctps->sctps_max_init_retr;
219 
220 	/* Copy data from the local sctp_mib to the provided kstat. */
221 	sctpkp->sctpCurrEstab.value.i32 = sctp_mib.sctpCurrEstab;
222 	sctpkp->sctpActiveEstab.value.i32 = sctp_mib.sctpActiveEstab;
223 	sctpkp->sctpPassiveEstab.value.i32 = sctp_mib.sctpPassiveEstab;
224 	sctpkp->sctpAborted.value.i32 = sctp_mib.sctpAborted;
225 	sctpkp->sctpShutdowns.value.i32 = sctp_mib.sctpShutdowns;
226 	sctpkp->sctpOutOfBlue.value.i32 = sctp_mib.sctpOutOfBlue;
227 	sctpkp->sctpChecksumError.value.i32 = sctp_mib.sctpChecksumError;
228 	sctpkp->sctpOutCtrlChunks.value.i64 = sctp_mib.sctpOutCtrlChunks;
229 	sctpkp->sctpOutOrderChunks.value.i64 = sctp_mib.sctpOutOrderChunks;
230 	sctpkp->sctpOutUnorderChunks.value.i64 = sctp_mib.sctpOutUnorderChunks;
231 	sctpkp->sctpRetransChunks.value.i64 = sctp_mib.sctpRetransChunks;
232 	sctpkp->sctpOutAck.value.i32 = sctp_mib.sctpOutAck;
233 	sctpkp->sctpOutAckDelayed.value.i32 = sctp_mib.sctpOutAckDelayed;
234 	sctpkp->sctpOutWinUpdate.value.i32 = sctp_mib.sctpOutWinUpdate;
235 	sctpkp->sctpOutFastRetrans.value.i32 = sctp_mib.sctpOutFastRetrans;
236 	sctpkp->sctpOutWinProbe.value.i32 = sctp_mib.sctpOutWinProbe;
237 	sctpkp->sctpInCtrlChunks.value.i64 = sctp_mib.sctpInCtrlChunks;
238 	sctpkp->sctpInOrderChunks.value.i64 = sctp_mib.sctpInOrderChunks;
239 	sctpkp->sctpInUnorderChunks.value.i64 = sctp_mib.sctpInUnorderChunks;
240 	sctpkp->sctpInAck.value.i32 = sctp_mib.sctpInAck;
241 	sctpkp->sctpInDupAck.value.i32 = sctp_mib.sctpInDupAck;
242 	sctpkp->sctpInAckUnsent.value.i32 = sctp_mib.sctpInAckUnsent;
243 	sctpkp->sctpFragUsrMsgs.value.i64 = sctp_mib.sctpFragUsrMsgs;
244 	sctpkp->sctpReasmUsrMsgs.value.i64 = sctp_mib.sctpReasmUsrMsgs;
245 	sctpkp->sctpOutSCTPPkts.value.i64 = sctp_mib.sctpOutSCTPPkts;
246 	sctpkp->sctpInSCTPPkts.value.i64 = sctp_mib.sctpInSCTPPkts;
247 	sctpkp->sctpInInvalidCookie.value.i32 = sctp_mib.sctpInInvalidCookie;
248 	sctpkp->sctpTimRetrans.value.i32 = sctp_mib.sctpTimRetrans;
249 	sctpkp->sctpTimRetransDrop.value.i32 = sctp_mib.sctpTimRetransDrop;
250 	sctpkp->sctpTimHeartBeatProbe.value.i32 =
251 	    sctp_mib.sctpTimHeartBeatProbe;
252 	sctpkp->sctpTimHeartBeatDrop.value.i32 = sctp_mib.sctpTimHeartBeatDrop;
253 	sctpkp->sctpListenDrop.value.i32 = sctp_mib.sctpListenDrop;
254 	sctpkp->sctpInClosed.value.i32 = sctp_mib.sctpInClosed;
255 
256 	netstack_rele(ns);
257 	return (0);
258 }
259 
260 void *
261 sctp_kstat_init(netstackid_t stackid)
262 {
263 	kstat_t	*ksp;
264 
265 	sctp_named_kstat_t template = {
266 		{ "sctpRtoAlgorithm",		KSTAT_DATA_INT32, 0 },
267 		{ "sctpRtoMin",			KSTAT_DATA_UINT32, 0 },
268 		{ "sctpRtoMax",			KSTAT_DATA_UINT32, 0 },
269 		{ "sctpRtoInitial",		KSTAT_DATA_UINT32, 0 },
270 		{ "sctpMaxAssocs",		KSTAT_DATA_INT32, 0 },
271 		{ "sctpValCookieLife",		KSTAT_DATA_UINT32, 0 },
272 		{ "sctpMaxInitRetr",		KSTAT_DATA_UINT32, 0 },
273 		{ "sctpCurrEstab",		KSTAT_DATA_INT32, 0 },
274 		{ "sctpActiveEstab",		KSTAT_DATA_INT32, 0 },
275 		{ "sctpPassiveEstab",		KSTAT_DATA_INT32, 0 },
276 		{ "sctpAborted",		KSTAT_DATA_INT32, 0 },
277 		{ "sctpShutdowns",		KSTAT_DATA_INT32, 0 },
278 		{ "sctpOutOfBlue",		KSTAT_DATA_INT32, 0 },
279 		{ "sctpChecksumError",		KSTAT_DATA_INT32, 0 },
280 		{ "sctpOutCtrlChunks",		KSTAT_DATA_INT64, 0 },
281 		{ "sctpOutOrderChunks",		KSTAT_DATA_INT64, 0 },
282 		{ "sctpOutUnorderChunks",	KSTAT_DATA_INT64, 0 },
283 		{ "sctpRetransChunks",		KSTAT_DATA_INT64, 0 },
284 		{ "sctpOutAck",			KSTAT_DATA_INT32, 0 },
285 		{ "sctpOutAckDelayed",		KSTAT_DATA_INT32, 0 },
286 		{ "sctpOutWinUpdate",		KSTAT_DATA_INT32, 0 },
287 		{ "sctpOutFastRetrans",		KSTAT_DATA_INT32, 0 },
288 		{ "sctpOutWinProbe",		KSTAT_DATA_INT32, 0 },
289 		{ "sctpInCtrlChunks",		KSTAT_DATA_INT64, 0 },
290 		{ "sctpInOrderChunks",		KSTAT_DATA_INT64, 0 },
291 		{ "sctpInUnorderChunks",	KSTAT_DATA_INT64, 0 },
292 		{ "sctpInAck",			KSTAT_DATA_INT32, 0 },
293 		{ "sctpInDupAck",		KSTAT_DATA_INT32, 0 },
294 		{ "sctpInAckUnsent",		KSTAT_DATA_INT32, 0 },
295 		{ "sctpFragUsrMsgs",		KSTAT_DATA_INT64, 0 },
296 		{ "sctpReasmUsrMsgs",		KSTAT_DATA_INT64, 0 },
297 		{ "sctpOutSCTPPkts",		KSTAT_DATA_INT64, 0 },
298 		{ "sctpInSCTPPkts",		KSTAT_DATA_INT64, 0 },
299 		{ "sctpInInvalidCookie",	KSTAT_DATA_INT32, 0 },
300 		{ "sctpTimRetrans",		KSTAT_DATA_INT32, 0 },
301 		{ "sctpTimRetransDrop",		KSTAT_DATA_INT32, 0 },
302 		{ "sctpTimHearBeatProbe",	KSTAT_DATA_INT32, 0 },
303 		{ "sctpTimHearBeatDrop",	KSTAT_DATA_INT32, 0 },
304 		{ "sctpListenDrop",		KSTAT_DATA_INT32, 0 },
305 		{ "sctpInClosed",		KSTAT_DATA_INT32, 0 }
306 	};
307 
308 	ksp = kstat_create_netstack(SCTP_MOD_NAME, 0, "sctp", "mib2",
309 	    KSTAT_TYPE_NAMED, NUM_OF_FIELDS(sctp_named_kstat_t), 0, stackid);
310 
311 	if (ksp == NULL)
312 		return (NULL);
313 
314 	/* These won't change. */
315 	template.sctpRtoAlgorithm.value.i32 = MIB2_SCTP_RTOALGO_VANJ;
316 	template.sctpMaxAssocs.value.i32 = -1;
317 
318 	bcopy(&template, ksp->ks_data, sizeof (template));
319 	ksp->ks_update = sctp_kstat_update;
320 	ksp->ks_private = (void *)(uintptr_t)stackid;
321 
322 	kstat_install(ksp);
323 	return (ksp);
324 }
325 
326 /*
327  * To set all sctp_stat_t counters to 0.
328  */
329 static void
330 sctp_clr_kstats2(sctp_kstat_t *stats)
331 {
332 	stats->sctp_add_faddr.value.ui64 = 0;
333 	stats->sctp_add_timer.value.ui64 = 0;
334 	stats->sctp_conn_create.value.ui64 = 0;
335 	stats->sctp_find_next_tq.value.ui64 = 0;
336 	stats->sctp_fr_add_hdr.value.ui64 = 0;
337 	stats->sctp_fr_not_found.value.ui64 = 0;
338 	stats->sctp_output_failed.value.ui64 = 0;
339 	stats->sctp_rexmit_failed.value.ui64 = 0;
340 	stats->sctp_send_init_failed.value.ui64 = 0;
341 	stats->sctp_send_cookie_failed.value.ui64 = 0;
342 	stats->sctp_send_cookie_ack_failed.value.ui64 = 0;
343 	stats->sctp_send_err_failed.value.ui64 = 0;
344 	stats->sctp_send_sack_failed.value.ui64 = 0;
345 	stats->sctp_send_shutdown_failed.value.ui64 = 0;
346 	stats->sctp_send_shutdown_ack_failed.value.ui64 = 0;
347 	stats->sctp_send_shutdown_comp_failed.value.ui64 = 0;
348 	stats->sctp_send_user_abort_failed.value.ui64 = 0;
349 	stats->sctp_send_asconf_failed.value.ui64 = 0;
350 	stats->sctp_send_asconf_ack_failed.value.ui64 = 0;
351 	stats->sctp_send_ftsn_failed.value.ui64 = 0;
352 	stats->sctp_send_hb_failed.value.ui64 = 0;
353 	stats->sctp_return_hb_failed.value.ui64 = 0;
354 	stats->sctp_ss_rexmit_failed.value.ui64 = 0;
355 	stats->sctp_cl_connect.value.ui64 = 0;
356 	stats->sctp_cl_assoc_change.value.ui64 = 0;
357 	stats->sctp_cl_check_addrs.value.ui64 = 0;
358 	stats->sctp_reclaim_cnt.value.ui64 = 0;
359 	stats->sctp_listen_cnt_drop.value.ui64 = 0;
360 }
361 
362 /*
363  * To add counters from the per CPU sctp_kstat_counter_t to the stack
364  * sctp_kstat_t.
365  */
366 static void
367 sctp_add_kstats2(sctp_kstat_counter_t *from, sctp_kstat_t *to)
368 {
369 	to->sctp_add_faddr.value.ui64 += from->sctp_add_faddr;
370 	to->sctp_add_timer.value.ui64 += from->sctp_add_timer;
371 	to->sctp_conn_create.value.ui64 += from->sctp_conn_create;
372 	to->sctp_find_next_tq.value.ui64 += from->sctp_find_next_tq;
373 	to->sctp_fr_add_hdr.value.ui64 += from->sctp_fr_add_hdr;
374 	to->sctp_fr_not_found.value.ui64 += from->sctp_fr_not_found;
375 	to->sctp_output_failed.value.ui64 += from->sctp_output_failed;
376 	to->sctp_rexmit_failed.value.ui64 += from->sctp_rexmit_failed;
377 	to->sctp_send_init_failed.value.ui64 += from->sctp_send_init_failed;
378 	to->sctp_send_cookie_failed.value.ui64 += from->sctp_send_cookie_failed;
379 	to->sctp_send_cookie_ack_failed.value.ui64 +=
380 	    from->sctp_send_cookie_ack_failed;
381 	to->sctp_send_err_failed.value.ui64 += from->sctp_send_err_failed;
382 	to->sctp_send_sack_failed.value.ui64 += from->sctp_send_sack_failed;
383 	to->sctp_send_shutdown_failed.value.ui64 +=
384 	    from->sctp_send_shutdown_failed;
385 	to->sctp_send_shutdown_ack_failed.value.ui64 +=
386 	    from->sctp_send_shutdown_ack_failed;
387 	to->sctp_send_shutdown_comp_failed.value.ui64 +=
388 	    from->sctp_send_shutdown_comp_failed;
389 	to->sctp_send_user_abort_failed.value.ui64 +=
390 	    from->sctp_send_user_abort_failed;
391 	to->sctp_send_asconf_failed.value.ui64 += from->sctp_send_asconf_failed;
392 	to->sctp_send_asconf_ack_failed.value.ui64 +=
393 	    from->sctp_send_asconf_ack_failed;
394 	to->sctp_send_ftsn_failed.value.ui64 += from->sctp_send_ftsn_failed;
395 	to->sctp_send_hb_failed.value.ui64 += from->sctp_send_hb_failed;
396 	to->sctp_return_hb_failed.value.ui64 += from->sctp_return_hb_failed;
397 	to->sctp_ss_rexmit_failed.value.ui64 += from->sctp_ss_rexmit_failed;
398 	to->sctp_cl_connect.value.ui64 += from->sctp_cl_connect;
399 	to->sctp_cl_assoc_change.value.ui64 += from->sctp_cl_assoc_change;
400 	to->sctp_cl_check_addrs.value.ui64 += from->sctp_cl_check_addrs;
401 }
402 
403 /*
404  * Sum up all per CPU tcp_stat_t kstat counters.
405  */
406 static int
407 sctp_kstat2_update(kstat_t *kp, int rw)
408 {
409 	netstackid_t	stackid = (netstackid_t)(uintptr_t)kp->ks_private;
410 	netstack_t	*ns;
411 	sctp_stack_t	*sctps;
412 	sctp_kstat_t	*stats;
413 	int		i;
414 	int		cnt;
415 
416 	if (rw == KSTAT_WRITE)
417 		return (EACCES);
418 
419 	ns = netstack_find_by_stackid(stackid);
420 	if (ns == NULL)
421 		return (-1);
422 	sctps = ns->netstack_sctp;
423 	if (sctps == NULL) {
424 		netstack_rele(ns);
425 		return (-1);
426 	}
427 
428 	stats = (sctp_kstat_t *)kp->ks_data;
429 	sctp_clr_kstats2(stats);
430 
431 	/*
432 	 * sctps_sc_cnt may change in the middle of the loop.  It is better
433 	 * to get its value first.
434 	 */
435 	cnt = sctps->sctps_sc_cnt;
436 	for (i = 0; i < cnt; i++)
437 		sctp_add_kstats2(&sctps->sctps_sc[i]->sctp_sc_stats, stats);
438 
439 	netstack_rele(ns);
440 	return (0);
441 }
442 
443 /*
444  * The following kstats are for debugging purposes.  They keep
445  * track of problems which should not happen normally.  But in
446  * those cases which they do happen, these kstats would be handy
447  * for engineers to diagnose the problems.  They are not intended
448  * to be consumed by customers.
449  */
450 void *
451 sctp_kstat2_init(netstackid_t stackid)
452 {
453 	kstat_t *ksp;
454 
455 	sctp_kstat_t template = {
456 		{ "sctp_add_faddr",			KSTAT_DATA_UINT64 },
457 		{ "sctp_add_timer",			KSTAT_DATA_UINT64 },
458 		{ "sctp_conn_create",			KSTAT_DATA_UINT64 },
459 		{ "sctp_find_next_tq",			KSTAT_DATA_UINT64 },
460 		{ "sctp_fr_add_hdr",			KSTAT_DATA_UINT64 },
461 		{ "sctp_fr_not_found",			KSTAT_DATA_UINT64 },
462 		{ "sctp_output_failed",			KSTAT_DATA_UINT64 },
463 		{ "sctp_rexmit_failed",			KSTAT_DATA_UINT64 },
464 		{ "sctp_send_init_failed",		KSTAT_DATA_UINT64 },
465 		{ "sctp_send_cookie_failed",		KSTAT_DATA_UINT64 },
466 		{ "sctp_send_cookie_ack_failed",	KSTAT_DATA_UINT64 },
467 		{ "sctp_send_err_failed",		KSTAT_DATA_UINT64 },
468 		{ "sctp_send_sack_failed",		KSTAT_DATA_UINT64 },
469 		{ "sctp_send_shutdown_failed",		KSTAT_DATA_UINT64 },
470 		{ "sctp_send_shutdown_ack_failed",	KSTAT_DATA_UINT64 },
471 		{ "sctp_send_shutdown_comp_failed",	KSTAT_DATA_UINT64 },
472 		{ "sctp_send_user_abort_failed",	KSTAT_DATA_UINT64 },
473 		{ "sctp_send_asconf_failed",		KSTAT_DATA_UINT64 },
474 		{ "sctp_send_asconf_ack_failed",	KSTAT_DATA_UINT64 },
475 		{ "sctp_send_ftsn_failed",		KSTAT_DATA_UINT64 },
476 		{ "sctp_send_hb_failed",		KSTAT_DATA_UINT64 },
477 		{ "sctp_return_hb_failed",		KSTAT_DATA_UINT64 },
478 		{ "sctp_ss_rexmit_failed",		KSTAT_DATA_UINT64 },
479 		{ "sctp_cl_connect",			KSTAT_DATA_UINT64 },
480 		{ "sctp_cl_assoc_change",		KSTAT_DATA_UINT64 },
481 		{ "sctp_cl_check_addrs",		KSTAT_DATA_UINT64 },
482 		{ "sctp_reclaim_drop",			KSTAT_DATA_UINT64 },
483 		{ "sctp_listen_cnt_drop",		KSTAT_DATA_UINT64 },
484 	};
485 
486 	ksp = kstat_create_netstack(SCTP_MOD_NAME, 0, "sctpstat", "net",
487 	    KSTAT_TYPE_NAMED, NUM_OF_FIELDS(template), 0, stackid);
488 
489 	if (ksp == NULL)
490 		return (NULL);
491 
492 	bcopy(&template, ksp->ks_data, sizeof (template));
493 	ksp->ks_private = (void *)(uintptr_t)stackid;
494 	ksp->ks_update = sctp_kstat2_update;
495 
496 	kstat_install(ksp);
497 	return (ksp);
498 }
499 
500 void
501 sctp_kstat_fini(netstackid_t stackid, kstat_t *ksp)
502 {
503 	if (ksp != NULL) {
504 		ASSERT(stackid == (netstackid_t)(uintptr_t)ksp->ks_private);
505 		kstat_delete_netstack(ksp, stackid);
506 	}
507 }
508 
509 void
510 sctp_kstat2_fini(netstackid_t stackid, kstat_t *ksp)
511 {
512 	if (ksp != NULL) {
513 		ASSERT(stackid == (netstackid_t)(uintptr_t)ksp->ks_private);
514 		kstat_delete_netstack(ksp, stackid);
515 	}
516 }
517 
518 /*
519  * Return SNMP global stats in buffer in mpdata.
520  * Return associatiation table in mp_conn_data,
521  * local address table in mp_local_data, and
522  * remote address table in mp_rem_data.
523  */
524 mblk_t *
525 sctp_snmp_get_mib2(queue_t *q, mblk_t *mpctl, sctp_stack_t *sctps)
526 {
527 	mblk_t			*mpdata, *mp_ret;
528 	mblk_t			*mp_conn_ctl = NULL;
529 	mblk_t			*mp_conn_data;
530 	mblk_t			*mp_conn_tail = NULL;
531 	mblk_t			*mp_local_ctl = NULL;
532 	mblk_t			*mp_local_data;
533 	mblk_t			*mp_local_tail = NULL;
534 	mblk_t			*mp_rem_ctl = NULL;
535 	mblk_t			*mp_rem_data;
536 	mblk_t			*mp_rem_tail = NULL;
537 	mblk_t			*mp_attr_ctl = NULL;
538 	mblk_t			*mp_attr_data;
539 	mblk_t			*mp_attr_tail = NULL;
540 	struct opthdr		*optp;
541 	sctp_t			*sctp, *sctp_prev = NULL;
542 	sctp_faddr_t		*fp;
543 	mib2_sctpConnEntry_t	sce;
544 	mib2_sctpConnLocalEntry_t	scle;
545 	mib2_sctpConnRemoteEntry_t	scre;
546 	mib2_transportMLPEntry_t	mlp;
547 	int			i;
548 	int			l;
549 	int			scanned = 0;
550 	zoneid_t		zoneid = Q_TO_CONN(q)->conn_zoneid;
551 	conn_t			*connp;
552 	boolean_t		needattr;
553 	int			idx;
554 	mib2_sctp_t		sctp_mib;
555 
556 	/*
557 	 * Make copies of the original message.
558 	 * mpctl will hold SCTP counters,
559 	 * mp_conn_ctl will hold list of connections.
560 	 */
561 	mp_ret = copymsg(mpctl);
562 	mp_conn_ctl = copymsg(mpctl);
563 	mp_local_ctl = copymsg(mpctl);
564 	mp_rem_ctl = copymsg(mpctl);
565 	mp_attr_ctl = copymsg(mpctl);
566 
567 	mpdata = mpctl->b_cont;
568 
569 	if (mp_conn_ctl == NULL || mp_local_ctl == NULL ||
570 	    mp_rem_ctl == NULL || mp_attr_ctl == NULL || mpdata == NULL) {
571 		freemsg(mp_attr_ctl);
572 		freemsg(mp_rem_ctl);
573 		freemsg(mp_local_ctl);
574 		freemsg(mp_conn_ctl);
575 		freemsg(mp_ret);
576 		freemsg(mpctl);
577 		return (NULL);
578 	}
579 	mp_conn_data = mp_conn_ctl->b_cont;
580 	mp_local_data = mp_local_ctl->b_cont;
581 	mp_rem_data = mp_rem_ctl->b_cont;
582 	mp_attr_data = mp_attr_ctl->b_cont;
583 
584 	bzero(&sctp_mib, sizeof (sctp_mib));
585 
586 	/* hostname address parameters are not supported in Solaris */
587 	sce.sctpAssocRemHostName.o_length = 0;
588 	sce.sctpAssocRemHostName.o_bytes[0] = 0;
589 
590 	/* build table of connections -- need count in fixed part */
591 
592 	idx = 0;
593 	mutex_enter(&sctps->sctps_g_lock);
594 	sctp = list_head(&sctps->sctps_g_list);
595 	while (sctp != NULL) {
596 		mutex_enter(&sctp->sctp_reflock);
597 		if (sctp->sctp_condemned) {
598 			mutex_exit(&sctp->sctp_reflock);
599 			sctp = list_next(&sctps->sctps_g_list, sctp);
600 			continue;
601 		}
602 		sctp->sctp_refcnt++;
603 		mutex_exit(&sctp->sctp_reflock);
604 		mutex_exit(&sctps->sctps_g_lock);
605 		if (sctp_prev != NULL)
606 			SCTP_REFRELE(sctp_prev);
607 		if (sctp->sctp_connp->conn_zoneid != zoneid)
608 			goto next_sctp;
609 		if (sctp->sctp_state == SCTPS_ESTABLISHED ||
610 		    sctp->sctp_state == SCTPS_SHUTDOWN_PENDING ||
611 		    sctp->sctp_state == SCTPS_SHUTDOWN_RECEIVED) {
612 			/*
613 			 * Just bump the local sctp_mib.  The number of
614 			 * existing associations is not kept in kernel.
615 			 */
616 			BUMP_MIB(&sctp_mib, sctpCurrEstab);
617 		}
618 		SCTPS_UPDATE_MIB(sctps, sctpOutSCTPPkts, sctp->sctp_opkts);
619 		sctp->sctp_opkts = 0;
620 		SCTPS_UPDATE_MIB(sctps, sctpOutCtrlChunks, sctp->sctp_obchunks);
621 		UPDATE_LOCAL(sctp->sctp_cum_obchunks,
622 		    sctp->sctp_obchunks);
623 		sctp->sctp_obchunks = 0;
624 		SCTPS_UPDATE_MIB(sctps, sctpOutOrderChunks,
625 		    sctp->sctp_odchunks);
626 		UPDATE_LOCAL(sctp->sctp_cum_odchunks,
627 		    sctp->sctp_odchunks);
628 		sctp->sctp_odchunks = 0;
629 		SCTPS_UPDATE_MIB(sctps, sctpOutUnorderChunks,
630 		    sctp->sctp_oudchunks);
631 		UPDATE_LOCAL(sctp->sctp_cum_oudchunks,
632 		    sctp->sctp_oudchunks);
633 		sctp->sctp_oudchunks = 0;
634 		SCTPS_UPDATE_MIB(sctps, sctpRetransChunks,
635 		    sctp->sctp_rxtchunks);
636 		UPDATE_LOCAL(sctp->sctp_cum_rxtchunks,
637 		    sctp->sctp_rxtchunks);
638 		sctp->sctp_rxtchunks = 0;
639 		SCTPS_UPDATE_MIB(sctps, sctpInSCTPPkts, sctp->sctp_ipkts);
640 		sctp->sctp_ipkts = 0;
641 		SCTPS_UPDATE_MIB(sctps, sctpInCtrlChunks, sctp->sctp_ibchunks);
642 		UPDATE_LOCAL(sctp->sctp_cum_ibchunks,
643 		    sctp->sctp_ibchunks);
644 		sctp->sctp_ibchunks = 0;
645 		SCTPS_UPDATE_MIB(sctps, sctpInOrderChunks, sctp->sctp_idchunks);
646 		UPDATE_LOCAL(sctp->sctp_cum_idchunks,
647 		    sctp->sctp_idchunks);
648 		sctp->sctp_idchunks = 0;
649 		SCTPS_UPDATE_MIB(sctps, sctpInUnorderChunks,
650 		    sctp->sctp_iudchunks);
651 		UPDATE_LOCAL(sctp->sctp_cum_iudchunks,
652 		    sctp->sctp_iudchunks);
653 		sctp->sctp_iudchunks = 0;
654 		SCTPS_UPDATE_MIB(sctps, sctpFragUsrMsgs, sctp->sctp_fragdmsgs);
655 		sctp->sctp_fragdmsgs = 0;
656 		SCTPS_UPDATE_MIB(sctps, sctpReasmUsrMsgs, sctp->sctp_reassmsgs);
657 		sctp->sctp_reassmsgs = 0;
658 
659 		sce.sctpAssocId = ntohl(sctp->sctp_lvtag);
660 		sce.sctpAssocLocalPort = ntohs(sctp->sctp_connp->conn_lport);
661 		sce.sctpAssocRemPort = ntohs(sctp->sctp_connp->conn_fport);
662 
663 		RUN_SCTP(sctp);
664 		if (sctp->sctp_primary != NULL) {
665 			fp = sctp->sctp_primary;
666 
667 			if (IN6_IS_ADDR_V4MAPPED(&fp->sf_faddr)) {
668 				sce.sctpAssocRemPrimAddrType =
669 				    MIB2_SCTP_ADDR_V4;
670 			} else {
671 				sce.sctpAssocRemPrimAddrType =
672 				    MIB2_SCTP_ADDR_V6;
673 			}
674 			sce.sctpAssocRemPrimAddr = fp->sf_faddr;
675 			sce.sctpAssocLocPrimAddr = fp->sf_saddr;
676 			sce.sctpAssocHeartBeatInterval = TICK_TO_MSEC(
677 			    fp->sf_hb_interval);
678 		} else {
679 			sce.sctpAssocRemPrimAddrType = MIB2_SCTP_ADDR_V4;
680 			bzero(&sce.sctpAssocRemPrimAddr,
681 			    sizeof (sce.sctpAssocRemPrimAddr));
682 			bzero(&sce.sctpAssocLocPrimAddr,
683 			    sizeof (sce.sctpAssocLocPrimAddr));
684 			sce.sctpAssocHeartBeatInterval =
685 			    sctps->sctps_heartbeat_interval;
686 		}
687 
688 		/*
689 		 * Table for local addresses
690 		 */
691 		scanned = 0;
692 		for (i = 0; i < SCTP_IPIF_HASH; i++) {
693 			sctp_saddr_ipif_t	*obj;
694 
695 			if (sctp->sctp_saddrs[i].ipif_count == 0)
696 				continue;
697 			obj = list_head(&sctp->sctp_saddrs[i].sctp_ipif_list);
698 			for (l = 0; l < sctp->sctp_saddrs[i].ipif_count; l++) {
699 				sctp_ipif_t	*sctp_ipif;
700 				in6_addr_t	addr;
701 
702 				sctp_ipif = obj->saddr_ipifp;
703 				addr = sctp_ipif->sctp_ipif_saddr;
704 				scanned++;
705 				scle.sctpAssocId = ntohl(sctp->sctp_lvtag);
706 				if (IN6_IS_ADDR_V4MAPPED(&addr)) {
707 					scle.sctpAssocLocalAddrType =
708 					    MIB2_SCTP_ADDR_V4;
709 				} else {
710 					scle.sctpAssocLocalAddrType =
711 					    MIB2_SCTP_ADDR_V6;
712 				}
713 				scle.sctpAssocLocalAddr = addr;
714 				(void) snmp_append_data2(mp_local_data,
715 				    &mp_local_tail, (char *)&scle,
716 				    sizeof (scle));
717 				if (scanned >= sctp->sctp_nsaddrs)
718 					goto done;
719 				obj = list_next(&sctp->
720 				    sctp_saddrs[i].sctp_ipif_list, obj);
721 			}
722 		}
723 done:
724 		/*
725 		 * Table for remote addresses
726 		 */
727 		for (fp = sctp->sctp_faddrs; fp; fp = fp->sf_next) {
728 			scre.sctpAssocId = ntohl(sctp->sctp_lvtag);
729 			if (IN6_IS_ADDR_V4MAPPED(&fp->sf_faddr)) {
730 				scre.sctpAssocRemAddrType = MIB2_SCTP_ADDR_V4;
731 			} else {
732 				scre.sctpAssocRemAddrType = MIB2_SCTP_ADDR_V6;
733 			}
734 			scre.sctpAssocRemAddr = fp->sf_faddr;
735 			if (fp->sf_state == SCTP_FADDRS_ALIVE) {
736 				scre.sctpAssocRemAddrActive =
737 				    scre.sctpAssocRemAddrHBActive =
738 				    MIB2_SCTP_ACTIVE;
739 			} else {
740 				scre.sctpAssocRemAddrActive =
741 				    scre.sctpAssocRemAddrHBActive =
742 				    MIB2_SCTP_INACTIVE;
743 			}
744 			scre.sctpAssocRemAddrRTO = TICK_TO_MSEC(fp->sf_rto);
745 			scre.sctpAssocRemAddrMaxPathRtx = fp->sf_max_retr;
746 			scre.sctpAssocRemAddrRtx = fp->sf_T3expire;
747 			(void) snmp_append_data2(mp_rem_data, &mp_rem_tail,
748 			    (char *)&scre, sizeof (scre));
749 		}
750 		connp = sctp->sctp_connp;
751 		needattr = B_FALSE;
752 		bzero(&mlp, sizeof (mlp));
753 		if (connp->conn_mlp_type != mlptSingle) {
754 			if (connp->conn_mlp_type == mlptShared ||
755 			    connp->conn_mlp_type == mlptBoth)
756 				mlp.tme_flags |= MIB2_TMEF_SHARED;
757 			if (connp->conn_mlp_type == mlptPrivate ||
758 			    connp->conn_mlp_type == mlptBoth)
759 				mlp.tme_flags |= MIB2_TMEF_PRIVATE;
760 			needattr = B_TRUE;
761 		}
762 		if (connp->conn_anon_mlp) {
763 			mlp.tme_flags |= MIB2_TMEF_ANONMLP;
764 			needattr = B_TRUE;
765 		}
766 		switch (connp->conn_mac_mode) {
767 		case CONN_MAC_DEFAULT:
768 			break;
769 		case CONN_MAC_AWARE:
770 			mlp.tme_flags |= MIB2_TMEF_MACEXEMPT;
771 			needattr = B_TRUE;
772 			break;
773 		case CONN_MAC_IMPLICIT:
774 			mlp.tme_flags |= MIB2_TMEF_MACIMPLICIT;
775 			needattr = B_TRUE;
776 			break;
777 		}
778 		if (sctp->sctp_connp->conn_ixa->ixa_tsl != NULL) {
779 			ts_label_t *tsl;
780 
781 			tsl = sctp->sctp_connp->conn_ixa->ixa_tsl;
782 			mlp.tme_flags |= MIB2_TMEF_IS_LABELED;
783 			mlp.tme_doi = label2doi(tsl);
784 			mlp.tme_label = *label2bslabel(tsl);
785 			needattr = B_TRUE;
786 		}
787 		WAKE_SCTP(sctp);
788 		sce.sctpAssocState = sctp_snmp_state(sctp);
789 		sce.sctpAssocInStreams = sctp->sctp_num_istr;
790 		sce.sctpAssocOutStreams = sctp->sctp_num_ostr;
791 		sce.sctpAssocMaxRetr = sctp->sctp_pa_max_rxt;
792 		/* A 0 here indicates that no primary process is known */
793 		sce.sctpAssocPrimProcess = 0;
794 		sce.sctpAssocT1expired = sctp->sctp_T1expire;
795 		sce.sctpAssocT2expired = sctp->sctp_T2expire;
796 		sce.sctpAssocRtxChunks = sctp->sctp_T3expire;
797 		sce.sctpAssocStartTime = sctp->sctp_assoc_start_time;
798 		sce.sctpConnEntryInfo.ce_sendq = sctp->sctp_unacked +
799 		    sctp->sctp_unsent;
800 		sce.sctpConnEntryInfo.ce_recvq = sctp->sctp_rxqueued;
801 		sce.sctpConnEntryInfo.ce_swnd = sctp->sctp_frwnd;
802 		sce.sctpConnEntryInfo.ce_rwnd = sctp->sctp_rwnd;
803 		sce.sctpConnEntryInfo.ce_mss = sctp->sctp_mss;
804 		(void) snmp_append_data2(mp_conn_data, &mp_conn_tail,
805 		    (char *)&sce, sizeof (sce));
806 		mlp.tme_connidx = idx++;
807 		if (needattr)
808 			(void) snmp_append_data2(mp_attr_ctl->b_cont,
809 			    &mp_attr_tail, (char *)&mlp, sizeof (mlp));
810 next_sctp:
811 		sctp_prev = sctp;
812 		mutex_enter(&sctps->sctps_g_lock);
813 		sctp = list_next(&sctps->sctps_g_list, sctp);
814 	}
815 	mutex_exit(&sctps->sctps_g_lock);
816 	if (sctp_prev != NULL)
817 		SCTP_REFRELE(sctp_prev);
818 
819 	sctp_sum_mib(sctps, &sctp_mib);
820 
821 	optp = (struct opthdr *)&mpctl->b_rptr[sizeof (struct T_optmgmt_ack)];
822 	optp->level = MIB2_SCTP;
823 	optp->name = 0;
824 	(void) snmp_append_data(mpdata, (char *)&sctp_mib, sizeof (sctp_mib));
825 	optp->len = msgdsize(mpdata);
826 	qreply(q, mpctl);
827 
828 	/* table of connections... */
829 	optp = (struct opthdr *)&mp_conn_ctl->b_rptr[
830 	    sizeof (struct T_optmgmt_ack)];
831 	optp->level = MIB2_SCTP;
832 	optp->name = MIB2_SCTP_CONN;
833 	optp->len = msgdsize(mp_conn_data);
834 	qreply(q, mp_conn_ctl);
835 
836 	/* assoc local address table */
837 	optp = (struct opthdr *)&mp_local_ctl->b_rptr[
838 	    sizeof (struct T_optmgmt_ack)];
839 	optp->level = MIB2_SCTP;
840 	optp->name = MIB2_SCTP_CONN_LOCAL;
841 	optp->len = msgdsize(mp_local_data);
842 	qreply(q, mp_local_ctl);
843 
844 	/* assoc remote address table */
845 	optp = (struct opthdr *)&mp_rem_ctl->b_rptr[
846 	    sizeof (struct T_optmgmt_ack)];
847 	optp->level = MIB2_SCTP;
848 	optp->name = MIB2_SCTP_CONN_REMOTE;
849 	optp->len = msgdsize(mp_rem_data);
850 	qreply(q, mp_rem_ctl);
851 
852 	/* table of MLP attributes */
853 	optp = (struct opthdr *)&mp_attr_ctl->b_rptr[
854 	    sizeof (struct T_optmgmt_ack)];
855 	optp->level = MIB2_SCTP;
856 	optp->name = EXPER_XPORT_MLP;
857 	optp->len = msgdsize(mp_attr_data);
858 	if (optp->len == 0)
859 		freemsg(mp_attr_ctl);
860 	else
861 		qreply(q, mp_attr_ctl);
862 
863 	return (mp_ret);
864 }
865 
866 /* Translate SCTP state to MIB2 SCTP state. */
867 static int
868 sctp_snmp_state(sctp_t *sctp)
869 {
870 	if (sctp == NULL)
871 		return (0);
872 
873 	switch (sctp->sctp_state) {
874 	case SCTPS_IDLE:
875 	case SCTPS_BOUND:
876 		return (MIB2_SCTP_closed);
877 	case SCTPS_LISTEN:
878 		return (MIB2_SCTP_listen);
879 	case SCTPS_COOKIE_WAIT:
880 		return (MIB2_SCTP_cookieWait);
881 	case SCTPS_COOKIE_ECHOED:
882 		return (MIB2_SCTP_cookieEchoed);
883 	case SCTPS_ESTABLISHED:
884 		return (MIB2_SCTP_established);
885 	case SCTPS_SHUTDOWN_PENDING:
886 		return (MIB2_SCTP_shutdownPending);
887 	case SCTPS_SHUTDOWN_SENT:
888 		return (MIB2_SCTP_shutdownSent);
889 	case SCTPS_SHUTDOWN_RECEIVED:
890 		return (MIB2_SCTP_shutdownReceived);
891 	case SCTPS_SHUTDOWN_ACK_SENT:
892 		return (MIB2_SCTP_shutdownAckSent);
893 	default:
894 		return (0);
895 	}
896 }
897 
898 /*
899  * To sum up all MIB2 stats for a sctp_stack_t from all per CPU stats.  The
900  * caller should initialize the target mib2_sctp_t properly as this function
901  * just adds up all the per CPU stats.
902  */
903 static void
904 sctp_sum_mib(sctp_stack_t *sctps, mib2_sctp_t *sctp_mib)
905 {
906 	int i;
907 	int cnt;
908 
909 	/* Static componets of mib2_sctp_t. */
910 	SET_MIB(sctp_mib->sctpRtoAlgorithm, MIB2_SCTP_RTOALGO_VANJ);
911 	SET_MIB(sctp_mib->sctpRtoMin, sctps->sctps_rto_ming);
912 	SET_MIB(sctp_mib->sctpRtoMax, sctps->sctps_rto_maxg);
913 	SET_MIB(sctp_mib->sctpRtoInitial, sctps->sctps_rto_initialg);
914 	SET_MIB(sctp_mib->sctpMaxAssocs, -1);
915 	SET_MIB(sctp_mib->sctpValCookieLife, sctps->sctps_cookie_life);
916 	SET_MIB(sctp_mib->sctpMaxInitRetr, sctps->sctps_max_init_retr);
917 
918 	/* fixed length structure for IPv4 and IPv6 counters */
919 	SET_MIB(sctp_mib->sctpEntrySize, sizeof (mib2_sctpConnEntry_t));
920 	SET_MIB(sctp_mib->sctpLocalEntrySize,
921 	    sizeof (mib2_sctpConnLocalEntry_t));
922 	SET_MIB(sctp_mib->sctpRemoteEntrySize,
923 	    sizeof (mib2_sctpConnRemoteEntry_t));
924 
925 	/*
926 	 * sctps_sc_cnt may change in the middle of the loop.  It is better
927 	 * to get its value first.
928 	 */
929 	cnt = sctps->sctps_sc_cnt;
930 	for (i = 0; i < cnt; i++)
931 		sctp_add_mib(&sctps->sctps_sc[i]->sctp_sc_mib, sctp_mib);
932 }
933 
934 static void
935 sctp_add_mib(mib2_sctp_t *from, mib2_sctp_t *to)
936 {
937 	to->sctpActiveEstab += from->sctpActiveEstab;
938 	to->sctpPassiveEstab += from->sctpPassiveEstab;
939 	to->sctpAborted += from->sctpAborted;
940 	to->sctpShutdowns += from->sctpShutdowns;
941 	to->sctpOutOfBlue += from->sctpOutOfBlue;
942 	to->sctpChecksumError += from->sctpChecksumError;
943 	to->sctpOutCtrlChunks += from->sctpOutCtrlChunks;
944 	to->sctpOutOrderChunks += from->sctpOutOrderChunks;
945 	to->sctpOutUnorderChunks += from->sctpOutUnorderChunks;
946 	to->sctpRetransChunks += from->sctpRetransChunks;
947 	to->sctpOutAck += from->sctpOutAck;
948 	to->sctpOutAckDelayed += from->sctpOutAckDelayed;
949 	to->sctpOutWinUpdate += from->sctpOutWinUpdate;
950 	to->sctpOutFastRetrans += from->sctpOutFastRetrans;
951 	to->sctpOutWinProbe += from->sctpOutWinProbe;
952 	to->sctpInCtrlChunks += from->sctpInCtrlChunks;
953 	to->sctpInOrderChunks += from->sctpInOrderChunks;
954 	to->sctpInUnorderChunks += from->sctpInUnorderChunks;
955 	to->sctpInAck += from->sctpInAck;
956 	to->sctpInDupAck += from->sctpInDupAck;
957 	to->sctpInAckUnsent += from->sctpInAckUnsent;
958 	to->sctpFragUsrMsgs += from->sctpFragUsrMsgs;
959 	to->sctpReasmUsrMsgs += from->sctpReasmUsrMsgs;
960 	to->sctpOutSCTPPkts += from->sctpOutSCTPPkts;
961 	to->sctpInSCTPPkts += from->sctpInSCTPPkts;
962 	to->sctpInInvalidCookie += from->sctpInInvalidCookie;
963 	to->sctpTimRetrans += from->sctpTimRetrans;
964 	to->sctpTimRetransDrop += from->sctpTimRetransDrop;
965 	to->sctpTimHeartBeatProbe += from->sctpTimHeartBeatProbe;
966 	to->sctpTimHeartBeatDrop += from->sctpTimHeartBeatDrop;
967 	to->sctpListenDrop += from->sctpListenDrop;
968 	to->sctpInClosed += from->sctpInClosed;
969 }
970