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