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