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