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>
33 #include <sys/tsol/tndb.h>
35 #include <netinet/in.h>
37 #include <inet/common.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"
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
*);
53 sctp_kstat_update(kstat_t
*kp
, int rw
)
55 sctp_named_kstat_t
*sctpkp
;
56 sctp_t
*sctp
, *sctp_prev
;
58 netstackid_t stackid
= (netstackid_t
)(uintptr_t)kp
->ks_private
;
63 if (kp
== NULL
|| kp
->ks_data
== NULL
)
66 if (rw
== KSTAT_WRITE
)
69 ns
= netstack_find_by_stackid(stackid
);
72 sctps
= ns
->netstack_sctp
;
79 * For all exclusive netstacks, the zone ID is always GLOBAL_ZONEID.
81 if (stackid
!= GLOBAL_NETSTACKID
)
82 myzoneid
= GLOBAL_ZONEID
;
84 myzoneid
= curproc
->p_zone
->zone_id
;
86 bzero(&sctp_mib
, sizeof (sctp_mib
));
89 * Get the number of current associations and gather their
90 * individual set of statistics.
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
);
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
)
109 if (sctp
->sctp_state
== SCTPS_ESTABLISHED
||
110 sctp
->sctp_state
== SCTPS_SHUTDOWN_PENDING
||
111 sctp
->sctp_state
== SCTPS_SHUTDOWN_RECEIVED
) {
113 * Just bump the local sctp_mib. The number of
114 * existing associations is not kept in kernel.
116 BUMP_MIB(&sctp_mib
, sctpCurrEstab
);
119 if (sctp
->sctp_opkts
) {
120 SCTPS_UPDATE_MIB(sctps
, sctpOutSCTPPkts
,
122 sctp
->sctp_opkts
= 0;
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;
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;
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;
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;
157 if (sctp
->sctp_ipkts
) {
158 SCTPS_UPDATE_MIB(sctps
, sctpInSCTPPkts
,
160 sctp
->sctp_ipkts
= 0;
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;
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;
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;
187 if (sctp
->sctp_fragdmsgs
) {
188 SCTPS_UPDATE_MIB(sctps
, sctpFragUsrMsgs
,
189 sctp
->sctp_fragdmsgs
);
190 sctp
->sctp_fragdmsgs
= 0;
193 if (sctp
->sctp_reassmsgs
) {
194 SCTPS_UPDATE_MIB(sctps
, sctpReasmUsrMsgs
,
195 sctp
->sctp_reassmsgs
);
196 sctp
->sctp_reassmsgs
= 0;
201 mutex_enter(&sctps
->sctps_g_lock
);
202 sctp
= list_next(&sctps
->sctps_g_list
, sctp
);
204 mutex_exit(&sctps
->sctps_g_lock
);
205 if (sctp_prev
!= NULL
)
206 SCTP_REFRELE(sctp_prev
);
208 sctp_sum_mib(sctps
, &sctp_mib
);
210 /* Copy data from the SCTP MIB */
211 sctpkp
= (sctp_named_kstat_t
*)kp
->ks_data
;
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
;
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
;
261 sctp_kstat_init(netstackid_t stackid
)
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 }
308 ksp
= kstat_create_netstack(SCTP_MOD_NAME
, 0, "sctp", "mib2",
309 KSTAT_TYPE_NAMED
, NUM_OF_FIELDS(sctp_named_kstat_t
), 0, stackid
);
314 /* These won't change. */
315 template.sctpRtoAlgorithm
.value
.i32
= MIB2_SCTP_RTOALGO_VANJ
;
316 template.sctpMaxAssocs
.value
.i32
= -1;
318 bcopy(&template, ksp
->ks_data
, sizeof (template));
319 ksp
->ks_update
= sctp_kstat_update
;
320 ksp
->ks_private
= (void *)(uintptr_t)stackid
;
327 * To set all sctp_stat_t counters to 0.
330 sctp_clr_kstats2(sctp_kstat_t
*stats
)
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;
363 * To add counters from the per CPU sctp_kstat_counter_t to the stack
367 sctp_add_kstats2(sctp_kstat_counter_t
*from
, sctp_kstat_t
*to
)
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
;
404 * Sum up all per CPU tcp_stat_t kstat counters.
407 sctp_kstat2_update(kstat_t
*kp
, int rw
)
409 netstackid_t stackid
= (netstackid_t
)(uintptr_t)kp
->ks_private
;
416 if (rw
== KSTAT_WRITE
)
419 ns
= netstack_find_by_stackid(stackid
);
422 sctps
= ns
->netstack_sctp
;
428 stats
= (sctp_kstat_t
*)kp
->ks_data
;
429 sctp_clr_kstats2(stats
);
432 * sctps_sc_cnt may change in the middle of the loop. It is better
433 * to get its value first.
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
);
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.
451 sctp_kstat2_init(netstackid_t stackid
)
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
},
486 ksp
= kstat_create_netstack(SCTP_MOD_NAME
, 0, "sctpstat", "net",
487 KSTAT_TYPE_NAMED
, NUM_OF_FIELDS(template), 0, stackid
);
492 bcopy(&template, ksp
->ks_data
, sizeof (template));
493 ksp
->ks_private
= (void *)(uintptr_t)stackid
;
494 ksp
->ks_update
= sctp_kstat2_update
;
501 sctp_kstat_fini(netstackid_t stackid
, kstat_t
*ksp
)
504 ASSERT(stackid
== (netstackid_t
)(uintptr_t)ksp
->ks_private
);
505 kstat_delete_netstack(ksp
, stackid
);
510 sctp_kstat2_fini(netstackid_t stackid
, kstat_t
*ksp
)
513 ASSERT(stackid
== (netstackid_t
)(uintptr_t)ksp
->ks_private
);
514 kstat_delete_netstack(ksp
, stackid
);
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.
525 sctp_snmp_get_mib2(queue_t
*q
, mblk_t
*mpctl
, sctp_stack_t
*sctps
)
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
;
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
;
541 sctp_t
*sctp
, *sctp_prev
= NULL
;
543 mib2_sctpConnEntry_t sce
;
544 mib2_sctpConnLocalEntry_t scle
;
545 mib2_sctpConnRemoteEntry_t scre
;
546 mib2_transportMLPEntry_t mlp
;
550 zoneid_t zoneid
= Q_TO_CONN(q
)->conn_zoneid
;
554 mib2_sctp_t sctp_mib
;
557 * Make copies of the original message.
558 * mpctl will hold SCTP counters,
559 * mp_conn_ctl will hold list of connections.
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
);
567 mpdata
= mpctl
->b_cont
;
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
);
573 freemsg(mp_local_ctl
);
574 freemsg(mp_conn_ctl
);
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
;
584 bzero(&sctp_mib
, sizeof (sctp_mib
));
586 /* hostname address parameters are not supported in Solaris */
587 sce
.sctpAssocRemHostName
.o_length
= 0;
588 sce
.sctpAssocRemHostName
.o_bytes
[0] = 0;
590 /* build table of connections -- need count in fixed part */
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
);
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
)
609 if (sctp
->sctp_state
== SCTPS_ESTABLISHED
||
610 sctp
->sctp_state
== SCTPS_SHUTDOWN_PENDING
||
611 sctp
->sctp_state
== SCTPS_SHUTDOWN_RECEIVED
) {
613 * Just bump the local sctp_mib. The number of
614 * existing associations is not kept in kernel.
616 BUMP_MIB(&sctp_mib
, sctpCurrEstab
);
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;
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
);
664 if (sctp
->sctp_primary
!= NULL
) {
665 fp
= sctp
->sctp_primary
;
667 if (IN6_IS_ADDR_V4MAPPED(&fp
->sf_faddr
)) {
668 sce
.sctpAssocRemPrimAddrType
=
671 sce
.sctpAssocRemPrimAddrType
=
674 sce
.sctpAssocRemPrimAddr
= fp
->sf_faddr
;
675 sce
.sctpAssocLocPrimAddr
= fp
->sf_saddr
;
676 sce
.sctpAssocHeartBeatInterval
= TICK_TO_MSEC(
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
;
689 * Table for local addresses
692 for (i
= 0; i
< SCTP_IPIF_HASH
; i
++) {
693 sctp_saddr_ipif_t
*obj
;
695 if (sctp
->sctp_saddrs
[i
].ipif_count
== 0)
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
;
702 sctp_ipif
= obj
->saddr_ipifp
;
703 addr
= sctp_ipif
->sctp_ipif_saddr
;
705 scle
.sctpAssocId
= ntohl(sctp
->sctp_lvtag
);
706 if (IN6_IS_ADDR_V4MAPPED(&addr
)) {
707 scle
.sctpAssocLocalAddrType
=
710 scle
.sctpAssocLocalAddrType
=
713 scle
.sctpAssocLocalAddr
= addr
;
714 (void) snmp_append_data2(mp_local_data
,
715 &mp_local_tail
, (char *)&scle
,
717 if (scanned
>= sctp
->sctp_nsaddrs
)
719 obj
= list_next(&sctp
->
720 sctp_saddrs
[i
].sctp_ipif_list
, obj
);
725 * Table for remote addresses
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
;
732 scre
.sctpAssocRemAddrType
= MIB2_SCTP_ADDR_V6
;
734 scre
.sctpAssocRemAddr
= fp
->sf_faddr
;
735 if (fp
->sf_state
== SCTP_FADDRS_ALIVE
) {
736 scre
.sctpAssocRemAddrActive
=
737 scre
.sctpAssocRemAddrHBActive
=
740 scre
.sctpAssocRemAddrActive
=
741 scre
.sctpAssocRemAddrHBActive
=
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
));
750 connp
= sctp
->sctp_connp
;
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
;
762 if (connp
->conn_anon_mlp
) {
763 mlp
.tme_flags
|= MIB2_TMEF_ANONMLP
;
766 switch (connp
->conn_mac_mode
) {
767 case CONN_MAC_DEFAULT
:
770 mlp
.tme_flags
|= MIB2_TMEF_MACEXEMPT
;
773 case CONN_MAC_IMPLICIT
:
774 mlp
.tme_flags
|= MIB2_TMEF_MACIMPLICIT
;
778 if (sctp
->sctp_connp
->conn_ixa
->ixa_tsl
!= NULL
) {
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
);
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
+
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
++;
808 (void) snmp_append_data2(mp_attr_ctl
->b_cont
,
809 &mp_attr_tail
, (char *)&mlp
, sizeof (mlp
));
812 mutex_enter(&sctps
->sctps_g_lock
);
813 sctp
= list_next(&sctps
->sctps_g_list
, sctp
);
815 mutex_exit(&sctps
->sctps_g_lock
);
816 if (sctp_prev
!= NULL
)
817 SCTP_REFRELE(sctp_prev
);
819 sctp_sum_mib(sctps
, &sctp_mib
);
821 optp
= (struct opthdr
*)&mpctl
->b_rptr
[sizeof (struct T_optmgmt_ack
)];
822 optp
->level
= MIB2_SCTP
;
824 (void) snmp_append_data(mpdata
, (char *)&sctp_mib
, sizeof (sctp_mib
));
825 optp
->len
= msgdsize(mpdata
);
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
);
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
);
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
);
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
);
859 freemsg(mp_attr_ctl
);
861 qreply(q
, mp_attr_ctl
);
866 /* Translate SCTP state to MIB2 SCTP state. */
868 sctp_snmp_state(sctp_t
*sctp
)
873 switch (sctp
->sctp_state
) {
876 return (MIB2_SCTP_closed
);
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
);
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.
904 sctp_sum_mib(sctp_stack_t
*sctps
, mib2_sctp_t
*sctp_mib
)
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
);
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
));
926 * sctps_sc_cnt may change in the middle of the loop. It is better
927 * to get its value first.
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
);
935 sctp_add_mib(mib2_sctp_t
*from
, mib2_sctp_t
*to
)
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
;