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.
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.
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]
23 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
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>
32 #include <sys/sunddi.h>
34 #include <netinet/in.h>
36 #include <inet/common.h>
38 #include <inet/mib2.h>
39 #include <inet/snmpcom.h>
40 #include <inet/kstatcom.h>
41 #include <inet/ipclassifier.h>
42 #include <inet/sctp/sctp_impl.h>
43 #include <inet/sctp/sctp_addr.h>
45 static void sctp_clr_kstats2(sctp_kstat_t
*);
46 static void sctp_add_kstats2(sctp_kstat_counter_t
*, sctp_kstat_t
*);
47 static int sctp_snmp_state(sctp_t
*);
48 static void sctp_sum_mib(sctp_stack_t
*, mib2_sctp_t
*);
49 static void sctp_add_mib(mib2_sctp_t
*, mib2_sctp_t
*);
52 sctp_kstat_update(kstat_t
*kp
, int rw
)
54 sctp_named_kstat_t
*sctpkp
;
55 sctp_t
*sctp
, *sctp_prev
;
57 netstackid_t stackid
= (netstackid_t
)(uintptr_t)kp
->ks_private
;
62 if (kp
== NULL
|| kp
->ks_data
== NULL
)
65 if (rw
== KSTAT_WRITE
)
68 ns
= netstack_find_by_stackid(stackid
);
71 sctps
= ns
->netstack_sctp
;
78 * For all exclusive netstacks, the zone ID is always GLOBAL_ZONEID.
80 if (stackid
!= GLOBAL_NETSTACKID
)
81 myzoneid
= GLOBAL_ZONEID
;
83 myzoneid
= curproc
->p_zone
->zone_id
;
85 bzero(&sctp_mib
, sizeof (sctp_mib
));
88 * Get the number of current associations and gather their
89 * individual set of statistics.
92 mutex_enter(&sctps
->sctps_g_lock
);
93 sctp
= list_head(&sctps
->sctps_g_list
);
94 while (sctp
!= NULL
) {
95 mutex_enter(&sctp
->sctp_reflock
);
96 if (sctp
->sctp_condemned
) {
97 mutex_exit(&sctp
->sctp_reflock
);
98 sctp
= list_next(&sctps
->sctps_g_list
, sctp
);
102 mutex_exit(&sctp
->sctp_reflock
);
103 mutex_exit(&sctps
->sctps_g_lock
);
104 if (sctp_prev
!= NULL
)
105 SCTP_REFRELE(sctp_prev
);
106 if (sctp
->sctp_connp
->conn_zoneid
!= myzoneid
)
108 if (sctp
->sctp_state
== SCTPS_ESTABLISHED
||
109 sctp
->sctp_state
== SCTPS_SHUTDOWN_PENDING
||
110 sctp
->sctp_state
== SCTPS_SHUTDOWN_RECEIVED
) {
112 * Just bump the local sctp_mib. The number of
113 * existing associations is not kept in kernel.
115 BUMP_MIB(&sctp_mib
, sctpCurrEstab
);
118 if (sctp
->sctp_opkts
) {
119 SCTPS_UPDATE_MIB(sctps
, sctpOutSCTPPkts
,
121 sctp
->sctp_opkts
= 0;
124 if (sctp
->sctp_obchunks
) {
125 SCTPS_UPDATE_MIB(sctps
, sctpOutCtrlChunks
,
126 sctp
->sctp_obchunks
);
127 UPDATE_LOCAL(sctp
->sctp_cum_obchunks
,
128 sctp
->sctp_obchunks
);
129 sctp
->sctp_obchunks
= 0;
132 if (sctp
->sctp_odchunks
) {
133 SCTPS_UPDATE_MIB(sctps
, sctpOutOrderChunks
,
134 sctp
->sctp_odchunks
);
135 UPDATE_LOCAL(sctp
->sctp_cum_odchunks
,
136 sctp
->sctp_odchunks
);
137 sctp
->sctp_odchunks
= 0;
140 if (sctp
->sctp_oudchunks
) {
141 SCTPS_UPDATE_MIB(sctps
, sctpOutUnorderChunks
,
142 sctp
->sctp_oudchunks
);
143 UPDATE_LOCAL(sctp
->sctp_cum_oudchunks
,
144 sctp
->sctp_oudchunks
);
145 sctp
->sctp_oudchunks
= 0;
148 if (sctp
->sctp_rxtchunks
) {
149 SCTPS_UPDATE_MIB(sctps
, sctpRetransChunks
,
150 sctp
->sctp_rxtchunks
);
151 UPDATE_LOCAL(sctp
->sctp_cum_rxtchunks
,
152 sctp
->sctp_rxtchunks
);
153 sctp
->sctp_rxtchunks
= 0;
156 if (sctp
->sctp_ipkts
) {
157 SCTPS_UPDATE_MIB(sctps
, sctpInSCTPPkts
,
159 sctp
->sctp_ipkts
= 0;
162 if (sctp
->sctp_ibchunks
) {
163 SCTPS_UPDATE_MIB(sctps
, sctpInCtrlChunks
,
164 sctp
->sctp_ibchunks
);
165 UPDATE_LOCAL(sctp
->sctp_cum_ibchunks
,
166 sctp
->sctp_ibchunks
);
167 sctp
->sctp_ibchunks
= 0;
170 if (sctp
->sctp_idchunks
) {
171 SCTPS_UPDATE_MIB(sctps
, sctpInOrderChunks
,
172 sctp
->sctp_idchunks
);
173 UPDATE_LOCAL(sctp
->sctp_cum_idchunks
,
174 sctp
->sctp_idchunks
);
175 sctp
->sctp_idchunks
= 0;
178 if (sctp
->sctp_iudchunks
) {
179 SCTPS_UPDATE_MIB(sctps
, sctpInUnorderChunks
,
180 sctp
->sctp_iudchunks
);
181 UPDATE_LOCAL(sctp
->sctp_cum_iudchunks
,
182 sctp
->sctp_iudchunks
);
183 sctp
->sctp_iudchunks
= 0;
186 if (sctp
->sctp_fragdmsgs
) {
187 SCTPS_UPDATE_MIB(sctps
, sctpFragUsrMsgs
,
188 sctp
->sctp_fragdmsgs
);
189 sctp
->sctp_fragdmsgs
= 0;
192 if (sctp
->sctp_reassmsgs
) {
193 SCTPS_UPDATE_MIB(sctps
, sctpReasmUsrMsgs
,
194 sctp
->sctp_reassmsgs
);
195 sctp
->sctp_reassmsgs
= 0;
200 mutex_enter(&sctps
->sctps_g_lock
);
201 sctp
= list_next(&sctps
->sctps_g_list
, sctp
);
203 mutex_exit(&sctps
->sctps_g_lock
);
204 if (sctp_prev
!= NULL
)
205 SCTP_REFRELE(sctp_prev
);
207 sctp_sum_mib(sctps
, &sctp_mib
);
209 /* Copy data from the SCTP MIB */
210 sctpkp
= (sctp_named_kstat_t
*)kp
->ks_data
;
212 /* These are from global ndd params. */
213 sctpkp
->sctpRtoMin
.value
.ui32
= sctps
->sctps_rto_ming
;
214 sctpkp
->sctpRtoMax
.value
.ui32
= sctps
->sctps_rto_maxg
;
215 sctpkp
->sctpRtoInitial
.value
.ui32
= sctps
->sctps_rto_initialg
;
216 sctpkp
->sctpValCookieLife
.value
.ui32
= sctps
->sctps_cookie_life
;
217 sctpkp
->sctpMaxInitRetr
.value
.ui32
= sctps
->sctps_max_init_retr
;
219 /* Copy data from the local sctp_mib to the provided kstat. */
220 sctpkp
->sctpCurrEstab
.value
.i32
= sctp_mib
.sctpCurrEstab
;
221 sctpkp
->sctpActiveEstab
.value
.i32
= sctp_mib
.sctpActiveEstab
;
222 sctpkp
->sctpPassiveEstab
.value
.i32
= sctp_mib
.sctpPassiveEstab
;
223 sctpkp
->sctpAborted
.value
.i32
= sctp_mib
.sctpAborted
;
224 sctpkp
->sctpShutdowns
.value
.i32
= sctp_mib
.sctpShutdowns
;
225 sctpkp
->sctpOutOfBlue
.value
.i32
= sctp_mib
.sctpOutOfBlue
;
226 sctpkp
->sctpChecksumError
.value
.i32
= sctp_mib
.sctpChecksumError
;
227 sctpkp
->sctpOutCtrlChunks
.value
.i64
= sctp_mib
.sctpOutCtrlChunks
;
228 sctpkp
->sctpOutOrderChunks
.value
.i64
= sctp_mib
.sctpOutOrderChunks
;
229 sctpkp
->sctpOutUnorderChunks
.value
.i64
= sctp_mib
.sctpOutUnorderChunks
;
230 sctpkp
->sctpRetransChunks
.value
.i64
= sctp_mib
.sctpRetransChunks
;
231 sctpkp
->sctpOutAck
.value
.i32
= sctp_mib
.sctpOutAck
;
232 sctpkp
->sctpOutAckDelayed
.value
.i32
= sctp_mib
.sctpOutAckDelayed
;
233 sctpkp
->sctpOutWinUpdate
.value
.i32
= sctp_mib
.sctpOutWinUpdate
;
234 sctpkp
->sctpOutFastRetrans
.value
.i32
= sctp_mib
.sctpOutFastRetrans
;
235 sctpkp
->sctpOutWinProbe
.value
.i32
= sctp_mib
.sctpOutWinProbe
;
236 sctpkp
->sctpInCtrlChunks
.value
.i64
= sctp_mib
.sctpInCtrlChunks
;
237 sctpkp
->sctpInOrderChunks
.value
.i64
= sctp_mib
.sctpInOrderChunks
;
238 sctpkp
->sctpInUnorderChunks
.value
.i64
= sctp_mib
.sctpInUnorderChunks
;
239 sctpkp
->sctpInAck
.value
.i32
= sctp_mib
.sctpInAck
;
240 sctpkp
->sctpInDupAck
.value
.i32
= sctp_mib
.sctpInDupAck
;
241 sctpkp
->sctpInAckUnsent
.value
.i32
= sctp_mib
.sctpInAckUnsent
;
242 sctpkp
->sctpFragUsrMsgs
.value
.i64
= sctp_mib
.sctpFragUsrMsgs
;
243 sctpkp
->sctpReasmUsrMsgs
.value
.i64
= sctp_mib
.sctpReasmUsrMsgs
;
244 sctpkp
->sctpOutSCTPPkts
.value
.i64
= sctp_mib
.sctpOutSCTPPkts
;
245 sctpkp
->sctpInSCTPPkts
.value
.i64
= sctp_mib
.sctpInSCTPPkts
;
246 sctpkp
->sctpInInvalidCookie
.value
.i32
= sctp_mib
.sctpInInvalidCookie
;
247 sctpkp
->sctpTimRetrans
.value
.i32
= sctp_mib
.sctpTimRetrans
;
248 sctpkp
->sctpTimRetransDrop
.value
.i32
= sctp_mib
.sctpTimRetransDrop
;
249 sctpkp
->sctpTimHeartBeatProbe
.value
.i32
=
250 sctp_mib
.sctpTimHeartBeatProbe
;
251 sctpkp
->sctpTimHeartBeatDrop
.value
.i32
= sctp_mib
.sctpTimHeartBeatDrop
;
252 sctpkp
->sctpListenDrop
.value
.i32
= sctp_mib
.sctpListenDrop
;
253 sctpkp
->sctpInClosed
.value
.i32
= sctp_mib
.sctpInClosed
;
260 sctp_kstat_init(netstackid_t stackid
)
264 sctp_named_kstat_t
template = {
265 { "sctpRtoAlgorithm", KSTAT_DATA_INT32
, 0 },
266 { "sctpRtoMin", KSTAT_DATA_UINT32
, 0 },
267 { "sctpRtoMax", KSTAT_DATA_UINT32
, 0 },
268 { "sctpRtoInitial", KSTAT_DATA_UINT32
, 0 },
269 { "sctpMaxAssocs", KSTAT_DATA_INT32
, 0 },
270 { "sctpValCookieLife", KSTAT_DATA_UINT32
, 0 },
271 { "sctpMaxInitRetr", KSTAT_DATA_UINT32
, 0 },
272 { "sctpCurrEstab", KSTAT_DATA_INT32
, 0 },
273 { "sctpActiveEstab", KSTAT_DATA_INT32
, 0 },
274 { "sctpPassiveEstab", KSTAT_DATA_INT32
, 0 },
275 { "sctpAborted", KSTAT_DATA_INT32
, 0 },
276 { "sctpShutdowns", KSTAT_DATA_INT32
, 0 },
277 { "sctpOutOfBlue", KSTAT_DATA_INT32
, 0 },
278 { "sctpChecksumError", KSTAT_DATA_INT32
, 0 },
279 { "sctpOutCtrlChunks", KSTAT_DATA_INT64
, 0 },
280 { "sctpOutOrderChunks", KSTAT_DATA_INT64
, 0 },
281 { "sctpOutUnorderChunks", KSTAT_DATA_INT64
, 0 },
282 { "sctpRetransChunks", KSTAT_DATA_INT64
, 0 },
283 { "sctpOutAck", KSTAT_DATA_INT32
, 0 },
284 { "sctpOutAckDelayed", KSTAT_DATA_INT32
, 0 },
285 { "sctpOutWinUpdate", KSTAT_DATA_INT32
, 0 },
286 { "sctpOutFastRetrans", KSTAT_DATA_INT32
, 0 },
287 { "sctpOutWinProbe", KSTAT_DATA_INT32
, 0 },
288 { "sctpInCtrlChunks", KSTAT_DATA_INT64
, 0 },
289 { "sctpInOrderChunks", KSTAT_DATA_INT64
, 0 },
290 { "sctpInUnorderChunks", KSTAT_DATA_INT64
, 0 },
291 { "sctpInAck", KSTAT_DATA_INT32
, 0 },
292 { "sctpInDupAck", KSTAT_DATA_INT32
, 0 },
293 { "sctpInAckUnsent", KSTAT_DATA_INT32
, 0 },
294 { "sctpFragUsrMsgs", KSTAT_DATA_INT64
, 0 },
295 { "sctpReasmUsrMsgs", KSTAT_DATA_INT64
, 0 },
296 { "sctpOutSCTPPkts", KSTAT_DATA_INT64
, 0 },
297 { "sctpInSCTPPkts", KSTAT_DATA_INT64
, 0 },
298 { "sctpInInvalidCookie", KSTAT_DATA_INT32
, 0 },
299 { "sctpTimRetrans", KSTAT_DATA_INT32
, 0 },
300 { "sctpTimRetransDrop", KSTAT_DATA_INT32
, 0 },
301 { "sctpTimHearBeatProbe", KSTAT_DATA_INT32
, 0 },
302 { "sctpTimHearBeatDrop", KSTAT_DATA_INT32
, 0 },
303 { "sctpListenDrop", KSTAT_DATA_INT32
, 0 },
304 { "sctpInClosed", KSTAT_DATA_INT32
, 0 }
307 ksp
= kstat_create_netstack(SCTP_MOD_NAME
, 0, "sctp", "mib2",
308 KSTAT_TYPE_NAMED
, NUM_OF_FIELDS(sctp_named_kstat_t
), 0, stackid
);
313 /* These won't change. */
314 template.sctpRtoAlgorithm
.value
.i32
= MIB2_SCTP_RTOALGO_VANJ
;
315 template.sctpMaxAssocs
.value
.i32
= -1;
317 bcopy(&template, ksp
->ks_data
, sizeof (template));
318 ksp
->ks_update
= sctp_kstat_update
;
319 ksp
->ks_private
= (void *)(uintptr_t)stackid
;
326 * To set all sctp_stat_t counters to 0.
329 sctp_clr_kstats2(sctp_kstat_t
*stats
)
331 stats
->sctp_add_faddr
.value
.ui64
= 0;
332 stats
->sctp_add_timer
.value
.ui64
= 0;
333 stats
->sctp_conn_create
.value
.ui64
= 0;
334 stats
->sctp_find_next_tq
.value
.ui64
= 0;
335 stats
->sctp_fr_add_hdr
.value
.ui64
= 0;
336 stats
->sctp_fr_not_found
.value
.ui64
= 0;
337 stats
->sctp_output_failed
.value
.ui64
= 0;
338 stats
->sctp_rexmit_failed
.value
.ui64
= 0;
339 stats
->sctp_send_init_failed
.value
.ui64
= 0;
340 stats
->sctp_send_cookie_failed
.value
.ui64
= 0;
341 stats
->sctp_send_cookie_ack_failed
.value
.ui64
= 0;
342 stats
->sctp_send_err_failed
.value
.ui64
= 0;
343 stats
->sctp_send_sack_failed
.value
.ui64
= 0;
344 stats
->sctp_send_shutdown_failed
.value
.ui64
= 0;
345 stats
->sctp_send_shutdown_ack_failed
.value
.ui64
= 0;
346 stats
->sctp_send_shutdown_comp_failed
.value
.ui64
= 0;
347 stats
->sctp_send_user_abort_failed
.value
.ui64
= 0;
348 stats
->sctp_send_asconf_failed
.value
.ui64
= 0;
349 stats
->sctp_send_asconf_ack_failed
.value
.ui64
= 0;
350 stats
->sctp_send_ftsn_failed
.value
.ui64
= 0;
351 stats
->sctp_send_hb_failed
.value
.ui64
= 0;
352 stats
->sctp_return_hb_failed
.value
.ui64
= 0;
353 stats
->sctp_ss_rexmit_failed
.value
.ui64
= 0;
354 stats
->sctp_reclaim_cnt
.value
.ui64
= 0;
355 stats
->sctp_listen_cnt_drop
.value
.ui64
= 0;
359 * To add counters from the per CPU sctp_kstat_counter_t to the stack
363 sctp_add_kstats2(sctp_kstat_counter_t
*from
, sctp_kstat_t
*to
)
365 to
->sctp_add_faddr
.value
.ui64
+= from
->sctp_add_faddr
;
366 to
->sctp_add_timer
.value
.ui64
+= from
->sctp_add_timer
;
367 to
->sctp_conn_create
.value
.ui64
+= from
->sctp_conn_create
;
368 to
->sctp_find_next_tq
.value
.ui64
+= from
->sctp_find_next_tq
;
369 to
->sctp_fr_add_hdr
.value
.ui64
+= from
->sctp_fr_add_hdr
;
370 to
->sctp_fr_not_found
.value
.ui64
+= from
->sctp_fr_not_found
;
371 to
->sctp_output_failed
.value
.ui64
+= from
->sctp_output_failed
;
372 to
->sctp_rexmit_failed
.value
.ui64
+= from
->sctp_rexmit_failed
;
373 to
->sctp_send_init_failed
.value
.ui64
+= from
->sctp_send_init_failed
;
374 to
->sctp_send_cookie_failed
.value
.ui64
+= from
->sctp_send_cookie_failed
;
375 to
->sctp_send_cookie_ack_failed
.value
.ui64
+=
376 from
->sctp_send_cookie_ack_failed
;
377 to
->sctp_send_err_failed
.value
.ui64
+= from
->sctp_send_err_failed
;
378 to
->sctp_send_sack_failed
.value
.ui64
+= from
->sctp_send_sack_failed
;
379 to
->sctp_send_shutdown_failed
.value
.ui64
+=
380 from
->sctp_send_shutdown_failed
;
381 to
->sctp_send_shutdown_ack_failed
.value
.ui64
+=
382 from
->sctp_send_shutdown_ack_failed
;
383 to
->sctp_send_shutdown_comp_failed
.value
.ui64
+=
384 from
->sctp_send_shutdown_comp_failed
;
385 to
->sctp_send_user_abort_failed
.value
.ui64
+=
386 from
->sctp_send_user_abort_failed
;
387 to
->sctp_send_asconf_failed
.value
.ui64
+= from
->sctp_send_asconf_failed
;
388 to
->sctp_send_asconf_ack_failed
.value
.ui64
+=
389 from
->sctp_send_asconf_ack_failed
;
390 to
->sctp_send_ftsn_failed
.value
.ui64
+= from
->sctp_send_ftsn_failed
;
391 to
->sctp_send_hb_failed
.value
.ui64
+= from
->sctp_send_hb_failed
;
392 to
->sctp_return_hb_failed
.value
.ui64
+= from
->sctp_return_hb_failed
;
393 to
->sctp_ss_rexmit_failed
.value
.ui64
+= from
->sctp_ss_rexmit_failed
;
397 * Sum up all per CPU tcp_stat_t kstat counters.
400 sctp_kstat2_update(kstat_t
*kp
, int rw
)
402 netstackid_t stackid
= (netstackid_t
)(uintptr_t)kp
->ks_private
;
409 if (rw
== KSTAT_WRITE
)
412 ns
= netstack_find_by_stackid(stackid
);
415 sctps
= ns
->netstack_sctp
;
421 stats
= (sctp_kstat_t
*)kp
->ks_data
;
422 sctp_clr_kstats2(stats
);
425 * sctps_sc_cnt may change in the middle of the loop. It is better
426 * to get its value first.
428 cnt
= sctps
->sctps_sc_cnt
;
429 for (i
= 0; i
< cnt
; i
++)
430 sctp_add_kstats2(&sctps
->sctps_sc
[i
]->sctp_sc_stats
, stats
);
437 * The following kstats are for debugging purposes. They keep
438 * track of problems which should not happen normally. But in
439 * those cases which they do happen, these kstats would be handy
440 * for engineers to diagnose the problems. They are not intended
441 * to be consumed by customers.
444 sctp_kstat2_init(netstackid_t stackid
)
448 sctp_kstat_t
template = {
449 { "sctp_add_faddr", KSTAT_DATA_UINT64
},
450 { "sctp_add_timer", KSTAT_DATA_UINT64
},
451 { "sctp_conn_create", KSTAT_DATA_UINT64
},
452 { "sctp_find_next_tq", KSTAT_DATA_UINT64
},
453 { "sctp_fr_add_hdr", KSTAT_DATA_UINT64
},
454 { "sctp_fr_not_found", KSTAT_DATA_UINT64
},
455 { "sctp_output_failed", KSTAT_DATA_UINT64
},
456 { "sctp_rexmit_failed", KSTAT_DATA_UINT64
},
457 { "sctp_send_init_failed", KSTAT_DATA_UINT64
},
458 { "sctp_send_cookie_failed", KSTAT_DATA_UINT64
},
459 { "sctp_send_cookie_ack_failed", KSTAT_DATA_UINT64
},
460 { "sctp_send_err_failed", KSTAT_DATA_UINT64
},
461 { "sctp_send_sack_failed", KSTAT_DATA_UINT64
},
462 { "sctp_send_shutdown_failed", KSTAT_DATA_UINT64
},
463 { "sctp_send_shutdown_ack_failed", KSTAT_DATA_UINT64
},
464 { "sctp_send_shutdown_comp_failed", KSTAT_DATA_UINT64
},
465 { "sctp_send_user_abort_failed", KSTAT_DATA_UINT64
},
466 { "sctp_send_asconf_failed", KSTAT_DATA_UINT64
},
467 { "sctp_send_asconf_ack_failed", KSTAT_DATA_UINT64
},
468 { "sctp_send_ftsn_failed", KSTAT_DATA_UINT64
},
469 { "sctp_send_hb_failed", KSTAT_DATA_UINT64
},
470 { "sctp_return_hb_failed", KSTAT_DATA_UINT64
},
471 { "sctp_ss_rexmit_failed", KSTAT_DATA_UINT64
},
472 { "sctp_reclaim_drop", KSTAT_DATA_UINT64
},
473 { "sctp_listen_cnt_drop", KSTAT_DATA_UINT64
},
476 ksp
= kstat_create_netstack(SCTP_MOD_NAME
, 0, "sctpstat", "net",
477 KSTAT_TYPE_NAMED
, NUM_OF_FIELDS(template), 0, stackid
);
482 bcopy(&template, ksp
->ks_data
, sizeof (template));
483 ksp
->ks_private
= (void *)(uintptr_t)stackid
;
484 ksp
->ks_update
= sctp_kstat2_update
;
491 sctp_kstat_fini(netstackid_t stackid
, kstat_t
*ksp
)
494 ASSERT(stackid
== (netstackid_t
)(uintptr_t)ksp
->ks_private
);
495 kstat_delete_netstack(ksp
, stackid
);
500 sctp_kstat2_fini(netstackid_t stackid
, kstat_t
*ksp
)
503 ASSERT(stackid
== (netstackid_t
)(uintptr_t)ksp
->ks_private
);
504 kstat_delete_netstack(ksp
, stackid
);
509 * Return SNMP global stats in buffer in mpdata.
510 * Return associatiation table in mp_conn_data,
511 * local address table in mp_local_data, and
512 * remote address table in mp_rem_data.
515 sctp_snmp_get_mib2(queue_t
*q
, mblk_t
*mpctl
, sctp_stack_t
*sctps
)
517 mblk_t
*mpdata
, *mp_ret
;
518 mblk_t
*mp_conn_ctl
= NULL
;
519 mblk_t
*mp_conn_data
;
520 mblk_t
*mp_conn_tail
= NULL
;
521 mblk_t
*mp_local_ctl
= NULL
;
522 mblk_t
*mp_local_data
;
523 mblk_t
*mp_local_tail
= NULL
;
524 mblk_t
*mp_rem_ctl
= NULL
;
526 mblk_t
*mp_rem_tail
= NULL
;
528 sctp_t
*sctp
, *sctp_prev
= NULL
;
530 mib2_sctpConnEntry_t sce
;
531 mib2_sctpConnLocalEntry_t scle
;
532 mib2_sctpConnRemoteEntry_t scre
;
536 zoneid_t zoneid
= Q_TO_CONN(q
)->conn_zoneid
;
539 mib2_sctp_t sctp_mib
;
542 * Make copies of the original message.
543 * mpctl will hold SCTP counters,
544 * mp_conn_ctl will hold list of connections.
546 mp_ret
= copymsg(mpctl
);
547 mp_conn_ctl
= copymsg(mpctl
);
548 mp_local_ctl
= copymsg(mpctl
);
549 mp_rem_ctl
= copymsg(mpctl
);
551 mpdata
= mpctl
->b_cont
;
553 if (mp_conn_ctl
== NULL
|| mp_local_ctl
== NULL
||
554 mp_rem_ctl
== NULL
|| mpdata
== NULL
) {
556 freemsg(mp_local_ctl
);
557 freemsg(mp_conn_ctl
);
562 mp_conn_data
= mp_conn_ctl
->b_cont
;
563 mp_local_data
= mp_local_ctl
->b_cont
;
564 mp_rem_data
= mp_rem_ctl
->b_cont
;
566 bzero(&sctp_mib
, sizeof (sctp_mib
));
568 /* hostname address parameters are not supported in Solaris */
569 sce
.sctpAssocRemHostName
.o_length
= 0;
570 sce
.sctpAssocRemHostName
.o_bytes
[0] = 0;
572 /* build table of connections -- need count in fixed part */
575 mutex_enter(&sctps
->sctps_g_lock
);
576 sctp
= list_head(&sctps
->sctps_g_list
);
577 while (sctp
!= NULL
) {
578 mutex_enter(&sctp
->sctp_reflock
);
579 if (sctp
->sctp_condemned
) {
580 mutex_exit(&sctp
->sctp_reflock
);
581 sctp
= list_next(&sctps
->sctps_g_list
, sctp
);
585 mutex_exit(&sctp
->sctp_reflock
);
586 mutex_exit(&sctps
->sctps_g_lock
);
587 if (sctp_prev
!= NULL
)
588 SCTP_REFRELE(sctp_prev
);
589 if (sctp
->sctp_connp
->conn_zoneid
!= zoneid
)
591 if (sctp
->sctp_state
== SCTPS_ESTABLISHED
||
592 sctp
->sctp_state
== SCTPS_SHUTDOWN_PENDING
||
593 sctp
->sctp_state
== SCTPS_SHUTDOWN_RECEIVED
) {
595 * Just bump the local sctp_mib. The number of
596 * existing associations is not kept in kernel.
598 BUMP_MIB(&sctp_mib
, sctpCurrEstab
);
600 SCTPS_UPDATE_MIB(sctps
, sctpOutSCTPPkts
, sctp
->sctp_opkts
);
601 sctp
->sctp_opkts
= 0;
602 SCTPS_UPDATE_MIB(sctps
, sctpOutCtrlChunks
, sctp
->sctp_obchunks
);
603 UPDATE_LOCAL(sctp
->sctp_cum_obchunks
,
604 sctp
->sctp_obchunks
);
605 sctp
->sctp_obchunks
= 0;
606 SCTPS_UPDATE_MIB(sctps
, sctpOutOrderChunks
,
607 sctp
->sctp_odchunks
);
608 UPDATE_LOCAL(sctp
->sctp_cum_odchunks
,
609 sctp
->sctp_odchunks
);
610 sctp
->sctp_odchunks
= 0;
611 SCTPS_UPDATE_MIB(sctps
, sctpOutUnorderChunks
,
612 sctp
->sctp_oudchunks
);
613 UPDATE_LOCAL(sctp
->sctp_cum_oudchunks
,
614 sctp
->sctp_oudchunks
);
615 sctp
->sctp_oudchunks
= 0;
616 SCTPS_UPDATE_MIB(sctps
, sctpRetransChunks
,
617 sctp
->sctp_rxtchunks
);
618 UPDATE_LOCAL(sctp
->sctp_cum_rxtchunks
,
619 sctp
->sctp_rxtchunks
);
620 sctp
->sctp_rxtchunks
= 0;
621 SCTPS_UPDATE_MIB(sctps
, sctpInSCTPPkts
, sctp
->sctp_ipkts
);
622 sctp
->sctp_ipkts
= 0;
623 SCTPS_UPDATE_MIB(sctps
, sctpInCtrlChunks
, sctp
->sctp_ibchunks
);
624 UPDATE_LOCAL(sctp
->sctp_cum_ibchunks
,
625 sctp
->sctp_ibchunks
);
626 sctp
->sctp_ibchunks
= 0;
627 SCTPS_UPDATE_MIB(sctps
, sctpInOrderChunks
, sctp
->sctp_idchunks
);
628 UPDATE_LOCAL(sctp
->sctp_cum_idchunks
,
629 sctp
->sctp_idchunks
);
630 sctp
->sctp_idchunks
= 0;
631 SCTPS_UPDATE_MIB(sctps
, sctpInUnorderChunks
,
632 sctp
->sctp_iudchunks
);
633 UPDATE_LOCAL(sctp
->sctp_cum_iudchunks
,
634 sctp
->sctp_iudchunks
);
635 sctp
->sctp_iudchunks
= 0;
636 SCTPS_UPDATE_MIB(sctps
, sctpFragUsrMsgs
, sctp
->sctp_fragdmsgs
);
637 sctp
->sctp_fragdmsgs
= 0;
638 SCTPS_UPDATE_MIB(sctps
, sctpReasmUsrMsgs
, sctp
->sctp_reassmsgs
);
639 sctp
->sctp_reassmsgs
= 0;
641 sce
.sctpAssocId
= ntohl(sctp
->sctp_lvtag
);
642 sce
.sctpAssocLocalPort
= ntohs(sctp
->sctp_connp
->conn_lport
);
643 sce
.sctpAssocRemPort
= ntohs(sctp
->sctp_connp
->conn_fport
);
646 if (sctp
->sctp_primary
!= NULL
) {
647 fp
= sctp
->sctp_primary
;
649 if (IN6_IS_ADDR_V4MAPPED(&fp
->sf_faddr
)) {
650 sce
.sctpAssocRemPrimAddrType
=
653 sce
.sctpAssocRemPrimAddrType
=
656 sce
.sctpAssocRemPrimAddr
= fp
->sf_faddr
;
657 sce
.sctpAssocLocPrimAddr
= fp
->sf_saddr
;
658 sce
.sctpAssocHeartBeatInterval
= TICK_TO_MSEC(
661 sce
.sctpAssocRemPrimAddrType
= MIB2_SCTP_ADDR_V4
;
662 bzero(&sce
.sctpAssocRemPrimAddr
,
663 sizeof (sce
.sctpAssocRemPrimAddr
));
664 bzero(&sce
.sctpAssocLocPrimAddr
,
665 sizeof (sce
.sctpAssocLocPrimAddr
));
666 sce
.sctpAssocHeartBeatInterval
=
667 sctps
->sctps_heartbeat_interval
;
671 * Table for local addresses
674 for (i
= 0; i
< SCTP_IPIF_HASH
; i
++) {
675 sctp_saddr_ipif_t
*obj
;
677 if (sctp
->sctp_saddrs
[i
].ipif_count
== 0)
679 obj
= list_head(&sctp
->sctp_saddrs
[i
].sctp_ipif_list
);
680 for (l
= 0; l
< sctp
->sctp_saddrs
[i
].ipif_count
; l
++) {
681 sctp_ipif_t
*sctp_ipif
;
684 sctp_ipif
= obj
->saddr_ipifp
;
685 addr
= sctp_ipif
->sctp_ipif_saddr
;
687 scle
.sctpAssocId
= ntohl(sctp
->sctp_lvtag
);
688 if (IN6_IS_ADDR_V4MAPPED(&addr
)) {
689 scle
.sctpAssocLocalAddrType
=
692 scle
.sctpAssocLocalAddrType
=
695 scle
.sctpAssocLocalAddr
= addr
;
696 (void) snmp_append_data2(mp_local_data
,
697 &mp_local_tail
, (char *)&scle
,
699 if (scanned
>= sctp
->sctp_nsaddrs
)
701 obj
= list_next(&sctp
->
702 sctp_saddrs
[i
].sctp_ipif_list
, obj
);
707 * Table for remote addresses
709 for (fp
= sctp
->sctp_faddrs
; fp
; fp
= fp
->sf_next
) {
710 scre
.sctpAssocId
= ntohl(sctp
->sctp_lvtag
);
711 if (IN6_IS_ADDR_V4MAPPED(&fp
->sf_faddr
)) {
712 scre
.sctpAssocRemAddrType
= MIB2_SCTP_ADDR_V4
;
714 scre
.sctpAssocRemAddrType
= MIB2_SCTP_ADDR_V6
;
716 scre
.sctpAssocRemAddr
= fp
->sf_faddr
;
717 if (fp
->sf_state
== SCTP_FADDRS_ALIVE
) {
718 scre
.sctpAssocRemAddrActive
=
719 scre
.sctpAssocRemAddrHBActive
=
722 scre
.sctpAssocRemAddrActive
=
723 scre
.sctpAssocRemAddrHBActive
=
726 scre
.sctpAssocRemAddrRTO
= TICK_TO_MSEC(fp
->sf_rto
);
727 scre
.sctpAssocRemAddrMaxPathRtx
= fp
->sf_max_retr
;
728 scre
.sctpAssocRemAddrRtx
= fp
->sf_T3expire
;
729 (void) snmp_append_data2(mp_rem_data
, &mp_rem_tail
,
730 (char *)&scre
, sizeof (scre
));
732 connp
= sctp
->sctp_connp
;
734 sce
.sctpAssocState
= sctp_snmp_state(sctp
);
735 sce
.sctpAssocInStreams
= sctp
->sctp_num_istr
;
736 sce
.sctpAssocOutStreams
= sctp
->sctp_num_ostr
;
737 sce
.sctpAssocMaxRetr
= sctp
->sctp_pa_max_rxt
;
738 /* A 0 here indicates that no primary process is known */
739 sce
.sctpAssocPrimProcess
= 0;
740 sce
.sctpAssocT1expired
= sctp
->sctp_T1expire
;
741 sce
.sctpAssocT2expired
= sctp
->sctp_T2expire
;
742 sce
.sctpAssocRtxChunks
= sctp
->sctp_T3expire
;
743 sce
.sctpAssocStartTime
= sctp
->sctp_assoc_start_time
;
744 sce
.sctpConnEntryInfo
.ce_sendq
= sctp
->sctp_unacked
+
746 sce
.sctpConnEntryInfo
.ce_recvq
= sctp
->sctp_rxqueued
;
747 sce
.sctpConnEntryInfo
.ce_swnd
= sctp
->sctp_frwnd
;
748 sce
.sctpConnEntryInfo
.ce_rwnd
= sctp
->sctp_rwnd
;
749 sce
.sctpConnEntryInfo
.ce_mss
= sctp
->sctp_mss
;
750 (void) snmp_append_data2(mp_conn_data
, &mp_conn_tail
,
751 (char *)&sce
, sizeof (sce
));
754 mutex_enter(&sctps
->sctps_g_lock
);
755 sctp
= list_next(&sctps
->sctps_g_list
, sctp
);
757 mutex_exit(&sctps
->sctps_g_lock
);
758 if (sctp_prev
!= NULL
)
759 SCTP_REFRELE(sctp_prev
);
761 sctp_sum_mib(sctps
, &sctp_mib
);
763 optp
= (struct opthdr
*)&mpctl
->b_rptr
[sizeof (struct T_optmgmt_ack
)];
764 optp
->level
= MIB2_SCTP
;
766 (void) snmp_append_data(mpdata
, (char *)&sctp_mib
, sizeof (sctp_mib
));
767 optp
->len
= msgdsize(mpdata
);
770 /* table of connections... */
771 optp
= (struct opthdr
*)&mp_conn_ctl
->b_rptr
[
772 sizeof (struct T_optmgmt_ack
)];
773 optp
->level
= MIB2_SCTP
;
774 optp
->name
= MIB2_SCTP_CONN
;
775 optp
->len
= msgdsize(mp_conn_data
);
776 qreply(q
, mp_conn_ctl
);
778 /* assoc local address table */
779 optp
= (struct opthdr
*)&mp_local_ctl
->b_rptr
[
780 sizeof (struct T_optmgmt_ack
)];
781 optp
->level
= MIB2_SCTP
;
782 optp
->name
= MIB2_SCTP_CONN_LOCAL
;
783 optp
->len
= msgdsize(mp_local_data
);
784 qreply(q
, mp_local_ctl
);
786 /* assoc remote address table */
787 optp
= (struct opthdr
*)&mp_rem_ctl
->b_rptr
[
788 sizeof (struct T_optmgmt_ack
)];
789 optp
->level
= MIB2_SCTP
;
790 optp
->name
= MIB2_SCTP_CONN_REMOTE
;
791 optp
->len
= msgdsize(mp_rem_data
);
792 qreply(q
, mp_rem_ctl
);
797 /* Translate SCTP state to MIB2 SCTP state. */
799 sctp_snmp_state(sctp_t
*sctp
)
804 switch (sctp
->sctp_state
) {
807 return (MIB2_SCTP_closed
);
809 return (MIB2_SCTP_listen
);
810 case SCTPS_COOKIE_WAIT
:
811 return (MIB2_SCTP_cookieWait
);
812 case SCTPS_COOKIE_ECHOED
:
813 return (MIB2_SCTP_cookieEchoed
);
814 case SCTPS_ESTABLISHED
:
815 return (MIB2_SCTP_established
);
816 case SCTPS_SHUTDOWN_PENDING
:
817 return (MIB2_SCTP_shutdownPending
);
818 case SCTPS_SHUTDOWN_SENT
:
819 return (MIB2_SCTP_shutdownSent
);
820 case SCTPS_SHUTDOWN_RECEIVED
:
821 return (MIB2_SCTP_shutdownReceived
);
822 case SCTPS_SHUTDOWN_ACK_SENT
:
823 return (MIB2_SCTP_shutdownAckSent
);
830 * To sum up all MIB2 stats for a sctp_stack_t from all per CPU stats. The
831 * caller should initialize the target mib2_sctp_t properly as this function
832 * just adds up all the per CPU stats.
835 sctp_sum_mib(sctp_stack_t
*sctps
, mib2_sctp_t
*sctp_mib
)
840 /* Static componets of mib2_sctp_t. */
841 SET_MIB(sctp_mib
->sctpRtoAlgorithm
, MIB2_SCTP_RTOALGO_VANJ
);
842 SET_MIB(sctp_mib
->sctpRtoMin
, sctps
->sctps_rto_ming
);
843 SET_MIB(sctp_mib
->sctpRtoMax
, sctps
->sctps_rto_maxg
);
844 SET_MIB(sctp_mib
->sctpRtoInitial
, sctps
->sctps_rto_initialg
);
845 SET_MIB(sctp_mib
->sctpMaxAssocs
, -1);
846 SET_MIB(sctp_mib
->sctpValCookieLife
, sctps
->sctps_cookie_life
);
847 SET_MIB(sctp_mib
->sctpMaxInitRetr
, sctps
->sctps_max_init_retr
);
849 /* fixed length structure for IPv4 and IPv6 counters */
850 SET_MIB(sctp_mib
->sctpEntrySize
, sizeof (mib2_sctpConnEntry_t
));
851 SET_MIB(sctp_mib
->sctpLocalEntrySize
,
852 sizeof (mib2_sctpConnLocalEntry_t
));
853 SET_MIB(sctp_mib
->sctpRemoteEntrySize
,
854 sizeof (mib2_sctpConnRemoteEntry_t
));
857 * sctps_sc_cnt may change in the middle of the loop. It is better
858 * to get its value first.
860 cnt
= sctps
->sctps_sc_cnt
;
861 for (i
= 0; i
< cnt
; i
++)
862 sctp_add_mib(&sctps
->sctps_sc
[i
]->sctp_sc_mib
, sctp_mib
);
866 sctp_add_mib(mib2_sctp_t
*from
, mib2_sctp_t
*to
)
868 to
->sctpActiveEstab
+= from
->sctpActiveEstab
;
869 to
->sctpPassiveEstab
+= from
->sctpPassiveEstab
;
870 to
->sctpAborted
+= from
->sctpAborted
;
871 to
->sctpShutdowns
+= from
->sctpShutdowns
;
872 to
->sctpOutOfBlue
+= from
->sctpOutOfBlue
;
873 to
->sctpChecksumError
+= from
->sctpChecksumError
;
874 to
->sctpOutCtrlChunks
+= from
->sctpOutCtrlChunks
;
875 to
->sctpOutOrderChunks
+= from
->sctpOutOrderChunks
;
876 to
->sctpOutUnorderChunks
+= from
->sctpOutUnorderChunks
;
877 to
->sctpRetransChunks
+= from
->sctpRetransChunks
;
878 to
->sctpOutAck
+= from
->sctpOutAck
;
879 to
->sctpOutAckDelayed
+= from
->sctpOutAckDelayed
;
880 to
->sctpOutWinUpdate
+= from
->sctpOutWinUpdate
;
881 to
->sctpOutFastRetrans
+= from
->sctpOutFastRetrans
;
882 to
->sctpOutWinProbe
+= from
->sctpOutWinProbe
;
883 to
->sctpInCtrlChunks
+= from
->sctpInCtrlChunks
;
884 to
->sctpInOrderChunks
+= from
->sctpInOrderChunks
;
885 to
->sctpInUnorderChunks
+= from
->sctpInUnorderChunks
;
886 to
->sctpInAck
+= from
->sctpInAck
;
887 to
->sctpInDupAck
+= from
->sctpInDupAck
;
888 to
->sctpInAckUnsent
+= from
->sctpInAckUnsent
;
889 to
->sctpFragUsrMsgs
+= from
->sctpFragUsrMsgs
;
890 to
->sctpReasmUsrMsgs
+= from
->sctpReasmUsrMsgs
;
891 to
->sctpOutSCTPPkts
+= from
->sctpOutSCTPPkts
;
892 to
->sctpInSCTPPkts
+= from
->sctpInSCTPPkts
;
893 to
->sctpInInvalidCookie
+= from
->sctpInInvalidCookie
;
894 to
->sctpTimRetrans
+= from
->sctpTimRetrans
;
895 to
->sctpTimRetransDrop
+= from
->sctpTimRetransDrop
;
896 to
->sctpTimHeartBeatProbe
+= from
->sctpTimHeartBeatProbe
;
897 to
->sctpTimHeartBeatDrop
+= from
->sctpTimHeartBeatDrop
;
898 to
->sctpListenDrop
+= from
->sctpListenDrop
;
899 to
->sctpInClosed
+= from
->sctpInClosed
;