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 }