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