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) 2010, Oracle and/or its affiliates. All rights reserved. 24 * Copyright (c) 2011, Joyent Inc. All rights reserved. 25 */ 26 27 #include <sys/types.h> 28 #include <sys/tihdr.h> 29 #include <sys/policy.h> 30 #include <sys/tsol/tnet.h> 31 #include <sys/kstat.h> 32 33 #include <sys/strsun.h> 34 #include <sys/stropts.h> 35 #include <sys/strsubr.h> 36 #include <sys/socket.h> 37 #include <sys/socketvar.h> 38 #include <sys/uio.h> 39 40 #include <inet/common.h> 41 #include <inet/ip.h> 42 #include <inet/tcp.h> 43 #include <inet/tcp_impl.h> 44 #include <inet/tcp_stats.h> 45 #include <inet/kstatcom.h> 46 #include <inet/snmpcom.h> 47 48 static int tcp_kstat_update(kstat_t *, int); 49 static int tcp_kstat2_update(kstat_t *, int); 50 static void tcp_sum_mib(tcp_stack_t *, mib2_tcp_t *); 51 52 static void tcp_add_mib(mib2_tcp_t *, mib2_tcp_t *); 53 static void tcp_add_stats(tcp_stat_counter_t *, tcp_stat_t *); 54 static void tcp_clr_stats(tcp_stat_t *); 55 56 tcp_g_stat_t tcp_g_statistics; 57 kstat_t *tcp_g_kstat; 58 59 /* Translate TCP state to MIB2 TCP state. */ 60 static int 61 tcp_snmp_state(tcp_t *tcp) 62 { 63 if (tcp == NULL) 64 return (0); 65 66 switch (tcp->tcp_state) { 67 case TCPS_CLOSED: 68 case TCPS_IDLE: /* RFC1213 doesn't have analogue for IDLE & BOUND */ 69 case TCPS_BOUND: 70 return (MIB2_TCP_closed); 71 case TCPS_LISTEN: 72 return (MIB2_TCP_listen); 73 case TCPS_SYN_SENT: 74 return (MIB2_TCP_synSent); 75 case TCPS_SYN_RCVD: 76 return (MIB2_TCP_synReceived); 77 case TCPS_ESTABLISHED: 78 return (MIB2_TCP_established); 79 case TCPS_CLOSE_WAIT: 80 return (MIB2_TCP_closeWait); 81 case TCPS_FIN_WAIT_1: 82 return (MIB2_TCP_finWait1); 83 case TCPS_CLOSING: 84 return (MIB2_TCP_closing); 85 case TCPS_LAST_ACK: 86 return (MIB2_TCP_lastAck); 87 case TCPS_FIN_WAIT_2: 88 return (MIB2_TCP_finWait2); 89 case TCPS_TIME_WAIT: 90 return (MIB2_TCP_timeWait); 91 default: 92 return (0); 93 } 94 } 95 96 /* 97 * Return SNMP stuff in buffer in mpdata. 98 */ 99 mblk_t * 100 tcp_snmp_get(queue_t *q, mblk_t *mpctl, boolean_t legacy_req) 101 { 102 mblk_t *mpdata; 103 mblk_t *mp_conn_ctl = NULL; 104 mblk_t *mp_conn_tail; 105 mblk_t *mp_attr_ctl = NULL; 106 mblk_t *mp_attr_tail; 107 mblk_t *mp_pidnode_ctl = NULL; 108 mblk_t *mp_pidnode_tail; 109 mblk_t *mp6_conn_ctl = NULL; 110 mblk_t *mp6_conn_tail; 111 mblk_t *mp6_attr_ctl = NULL; 112 mblk_t *mp6_attr_tail; 113 mblk_t *mp6_pidnode_ctl = NULL; 114 mblk_t *mp6_pidnode_tail; 115 struct opthdr *optp; 116 mib2_tcpConnEntry_t tce; 117 mib2_tcp6ConnEntry_t tce6; 118 mib2_transportMLPEntry_t mlp; 119 connf_t *connfp; 120 int i; 121 boolean_t ispriv; 122 zoneid_t zoneid; 123 int v4_conn_idx; 124 int v6_conn_idx; 125 conn_t *connp = Q_TO_CONN(q); 126 tcp_stack_t *tcps; 127 ip_stack_t *ipst; 128 mblk_t *mp2ctl; 129 mib2_tcp_t tcp_mib; 130 size_t tcp_mib_size, tce_size, tce6_size; 131 132 /* 133 * make a copy of the original message 134 */ 135 mp2ctl = copymsg(mpctl); 136 137 if (mpctl == NULL || 138 (mpdata = mpctl->b_cont) == NULL || 139 (mp_conn_ctl = copymsg(mpctl)) == NULL || 140 (mp_attr_ctl = copymsg(mpctl)) == NULL || 141 (mp_pidnode_ctl = copymsg(mpctl)) == NULL || 142 (mp6_conn_ctl = copymsg(mpctl)) == NULL || 143 (mp6_attr_ctl = copymsg(mpctl)) == NULL || 144 (mp6_pidnode_ctl = copymsg(mpctl)) == NULL) { 145 freemsg(mp_conn_ctl); 146 freemsg(mp_attr_ctl); 147 freemsg(mp_pidnode_ctl); 148 freemsg(mp6_conn_ctl); 149 freemsg(mp6_attr_ctl); 150 freemsg(mp6_pidnode_ctl); 151 freemsg(mpctl); 152 freemsg(mp2ctl); 153 return (NULL); 154 } 155 156 ipst = connp->conn_netstack->netstack_ip; 157 tcps = connp->conn_netstack->netstack_tcp; 158 159 if (legacy_req) { 160 tcp_mib_size = LEGACY_MIB_SIZE(&tcp_mib, mib2_tcp_t); 161 tce_size = LEGACY_MIB_SIZE(&tce, mib2_tcpConnEntry_t); 162 tce6_size = LEGACY_MIB_SIZE(&tce6, mib2_tcp6ConnEntry_t); 163 } else { 164 tcp_mib_size = sizeof (mib2_tcp_t); 165 tce_size = sizeof (mib2_tcpConnEntry_t); 166 tce6_size = sizeof (mib2_tcp6ConnEntry_t); 167 } 168 169 bzero(&tcp_mib, sizeof (tcp_mib)); 170 171 /* build table of connections -- need count in fixed part */ 172 SET_MIB(tcp_mib.tcpRtoAlgorithm, 4); /* vanj */ 173 SET_MIB(tcp_mib.tcpRtoMin, tcps->tcps_rexmit_interval_min); 174 SET_MIB(tcp_mib.tcpRtoMax, tcps->tcps_rexmit_interval_max); 175 SET_MIB(tcp_mib.tcpMaxConn, -1); 176 SET_MIB(tcp_mib.tcpCurrEstab, 0); 177 178 ispriv = 179 secpolicy_ip_config((Q_TO_CONN(q))->conn_cred, B_TRUE) == 0; 180 zoneid = Q_TO_CONN(q)->conn_zoneid; 181 182 v4_conn_idx = v6_conn_idx = 0; 183 mp_conn_tail = mp_attr_tail = mp6_conn_tail = mp6_attr_tail = NULL; 184 mp_pidnode_tail = mp6_pidnode_tail = NULL; 185 186 for (i = 0; i < CONN_G_HASH_SIZE; i++) { 187 ipst = tcps->tcps_netstack->netstack_ip; 188 189 connfp = &ipst->ips_ipcl_globalhash_fanout[i]; 190 191 connp = NULL; 192 193 while ((connp = 194 ipcl_get_next_conn(connfp, connp, IPCL_TCPCONN)) != NULL) { 195 tcp_t *tcp; 196 boolean_t needattr; 197 198 if (connp->conn_zoneid != zoneid) 199 continue; /* not in this zone */ 200 201 tcp = connp->conn_tcp; 202 TCPS_UPDATE_MIB(tcps, tcpHCInSegs, tcp->tcp_ibsegs); 203 tcp->tcp_ibsegs = 0; 204 TCPS_UPDATE_MIB(tcps, tcpHCOutSegs, tcp->tcp_obsegs); 205 tcp->tcp_obsegs = 0; 206 207 tce6.tcp6ConnState = tce.tcpConnState = 208 tcp_snmp_state(tcp); 209 if (tce.tcpConnState == MIB2_TCP_established || 210 tce.tcpConnState == MIB2_TCP_closeWait) 211 BUMP_MIB(&tcp_mib, tcpCurrEstab); 212 213 needattr = B_FALSE; 214 bzero(&mlp, sizeof (mlp)); 215 if (connp->conn_mlp_type != mlptSingle) { 216 if (connp->conn_mlp_type == mlptShared || 217 connp->conn_mlp_type == mlptBoth) 218 mlp.tme_flags |= MIB2_TMEF_SHARED; 219 if (connp->conn_mlp_type == mlptPrivate || 220 connp->conn_mlp_type == mlptBoth) 221 mlp.tme_flags |= MIB2_TMEF_PRIVATE; 222 needattr = B_TRUE; 223 } 224 if (connp->conn_anon_mlp) { 225 mlp.tme_flags |= MIB2_TMEF_ANONMLP; 226 needattr = B_TRUE; 227 } 228 switch (connp->conn_mac_mode) { 229 case CONN_MAC_DEFAULT: 230 break; 231 case CONN_MAC_AWARE: 232 mlp.tme_flags |= MIB2_TMEF_MACEXEMPT; 233 needattr = B_TRUE; 234 break; 235 case CONN_MAC_IMPLICIT: 236 mlp.tme_flags |= MIB2_TMEF_MACIMPLICIT; 237 needattr = B_TRUE; 238 break; 239 } 240 if (connp->conn_ixa->ixa_tsl != NULL) { 241 ts_label_t *tsl; 242 243 tsl = connp->conn_ixa->ixa_tsl; 244 mlp.tme_flags |= MIB2_TMEF_IS_LABELED; 245 mlp.tme_doi = label2doi(tsl); 246 mlp.tme_label = *label2bslabel(tsl); 247 needattr = B_TRUE; 248 } 249 250 /* Create a message to report on IPv6 entries */ 251 if (connp->conn_ipversion == IPV6_VERSION) { 252 tce6.tcp6ConnLocalAddress = connp->conn_laddr_v6; 253 tce6.tcp6ConnRemAddress = connp->conn_faddr_v6; 254 tce6.tcp6ConnLocalPort = ntohs(connp->conn_lport); 255 tce6.tcp6ConnRemPort = ntohs(connp->conn_fport); 256 if (connp->conn_ixa->ixa_flags & IXAF_SCOPEID_SET) { 257 tce6.tcp6ConnIfIndex = 258 connp->conn_ixa->ixa_scopeid; 259 } else { 260 tce6.tcp6ConnIfIndex = connp->conn_bound_if; 261 } 262 /* Don't want just anybody seeing these... */ 263 if (ispriv) { 264 tce6.tcp6ConnEntryInfo.ce_snxt = 265 tcp->tcp_snxt; 266 tce6.tcp6ConnEntryInfo.ce_suna = 267 tcp->tcp_suna; 268 tce6.tcp6ConnEntryInfo.ce_rnxt = 269 tcp->tcp_rnxt; 270 tce6.tcp6ConnEntryInfo.ce_rack = 271 tcp->tcp_rack; 272 } else { 273 /* 274 * Netstat, unfortunately, uses this to 275 * get send/receive queue sizes. How to fix? 276 * Why not compute the difference only? 277 */ 278 tce6.tcp6ConnEntryInfo.ce_snxt = 279 tcp->tcp_snxt - tcp->tcp_suna; 280 tce6.tcp6ConnEntryInfo.ce_suna = 0; 281 tce6.tcp6ConnEntryInfo.ce_rnxt = 282 tcp->tcp_rnxt - tcp->tcp_rack; 283 tce6.tcp6ConnEntryInfo.ce_rack = 0; 284 } 285 286 tce6.tcp6ConnEntryInfo.ce_swnd = tcp->tcp_swnd; 287 tce6.tcp6ConnEntryInfo.ce_rwnd = tcp->tcp_rwnd; 288 tce6.tcp6ConnEntryInfo.ce_rto = tcp->tcp_rto; 289 tce6.tcp6ConnEntryInfo.ce_mss = tcp->tcp_mss; 290 tce6.tcp6ConnEntryInfo.ce_state = tcp->tcp_state; 291 292 tce6.tcp6ConnCreationProcess = 293 (connp->conn_cpid < 0) ? MIB2_UNKNOWN_PROCESS : 294 connp->conn_cpid; 295 tce6.tcp6ConnCreationTime = connp->conn_open_time; 296 297 (void) snmp_append_data2(mp6_conn_ctl->b_cont, 298 &mp6_conn_tail, (char *)&tce6, tce6_size); 299 300 (void) snmp_append_data2(mp6_pidnode_ctl->b_cont, 301 &mp6_pidnode_tail, (char *)&tce6, tce6_size); 302 303 (void) snmp_append_mblk2(mp6_pidnode_ctl->b_cont, 304 &mp6_pidnode_tail, conn_get_pid_mblk(connp)); 305 306 mlp.tme_connidx = v6_conn_idx++; 307 if (needattr) 308 (void) snmp_append_data2(mp6_attr_ctl->b_cont, 309 &mp6_attr_tail, (char *)&mlp, sizeof (mlp)); 310 } 311 /* 312 * Create an IPv4 table entry for IPv4 entries and also 313 * for IPv6 entries which are bound to in6addr_any 314 * but don't have IPV6_V6ONLY set. 315 * (i.e. anything an IPv4 peer could connect to) 316 */ 317 if (connp->conn_ipversion == IPV4_VERSION || 318 (tcp->tcp_state <= TCPS_LISTEN && 319 !connp->conn_ipv6_v6only && 320 IN6_IS_ADDR_UNSPECIFIED(&connp->conn_laddr_v6))) { 321 if (connp->conn_ipversion == IPV6_VERSION) { 322 tce.tcpConnRemAddress = INADDR_ANY; 323 tce.tcpConnLocalAddress = INADDR_ANY; 324 } else { 325 tce.tcpConnRemAddress = 326 connp->conn_faddr_v4; 327 tce.tcpConnLocalAddress = 328 connp->conn_laddr_v4; 329 } 330 tce.tcpConnLocalPort = ntohs(connp->conn_lport); 331 tce.tcpConnRemPort = ntohs(connp->conn_fport); 332 /* Don't want just anybody seeing these... */ 333 if (ispriv) { 334 tce.tcpConnEntryInfo.ce_snxt = 335 tcp->tcp_snxt; 336 tce.tcpConnEntryInfo.ce_suna = 337 tcp->tcp_suna; 338 tce.tcpConnEntryInfo.ce_rnxt = 339 tcp->tcp_rnxt; 340 tce.tcpConnEntryInfo.ce_rack = 341 tcp->tcp_rack; 342 } else { 343 /* 344 * Netstat, unfortunately, uses this to 345 * get send/receive queue sizes. How 346 * to fix? 347 * Why not compute the difference only? 348 */ 349 tce.tcpConnEntryInfo.ce_snxt = 350 tcp->tcp_snxt - tcp->tcp_suna; 351 tce.tcpConnEntryInfo.ce_suna = 0; 352 tce.tcpConnEntryInfo.ce_rnxt = 353 tcp->tcp_rnxt - tcp->tcp_rack; 354 tce.tcpConnEntryInfo.ce_rack = 0; 355 } 356 357 tce.tcpConnEntryInfo.ce_swnd = tcp->tcp_swnd; 358 tce.tcpConnEntryInfo.ce_rwnd = tcp->tcp_rwnd; 359 tce.tcpConnEntryInfo.ce_rto = tcp->tcp_rto; 360 tce.tcpConnEntryInfo.ce_mss = tcp->tcp_mss; 361 tce.tcpConnEntryInfo.ce_state = 362 tcp->tcp_state; 363 364 tce.tcpConnCreationProcess = 365 (connp->conn_cpid < 0) ? 366 MIB2_UNKNOWN_PROCESS : 367 connp->conn_cpid; 368 tce.tcpConnCreationTime = connp->conn_open_time; 369 370 (void) snmp_append_data2(mp_conn_ctl->b_cont, 371 &mp_conn_tail, (char *)&tce, tce_size); 372 373 (void) snmp_append_data2(mp_pidnode_ctl->b_cont, 374 &mp_pidnode_tail, (char *)&tce, tce_size); 375 376 (void) snmp_append_mblk2(mp_pidnode_ctl->b_cont, 377 &mp_pidnode_tail, conn_get_pid_mblk(connp)); 378 379 mlp.tme_connidx = v4_conn_idx++; 380 if (needattr) 381 (void) snmp_append_data2( 382 mp_attr_ctl->b_cont, 383 &mp_attr_tail, (char *)&mlp, 384 sizeof (mlp)); 385 } 386 } 387 } 388 389 tcp_sum_mib(tcps, &tcp_mib); 390 391 /* Fixed length structure for IPv4 and IPv6 counters */ 392 SET_MIB(tcp_mib.tcpConnTableSize, tce_size); 393 SET_MIB(tcp_mib.tcp6ConnTableSize, tce6_size); 394 395 /* 396 * Synchronize 32- and 64-bit counters. Note that tcpInSegs and 397 * tcpOutSegs are not updated anywhere in TCP. The new 64 bits 398 * counters are used. Hence the old counters' values in tcp_sc_mib 399 * are always 0. 400 */ 401 SYNC32_MIB(&tcp_mib, tcpInSegs, tcpHCInSegs); 402 SYNC32_MIB(&tcp_mib, tcpOutSegs, tcpHCOutSegs); 403 404 optp = (struct opthdr *)&mpctl->b_rptr[sizeof (struct T_optmgmt_ack)]; 405 optp->level = MIB2_TCP; 406 optp->name = 0; 407 (void) snmp_append_data(mpdata, (char *)&tcp_mib, tcp_mib_size); 408 optp->len = msgdsize(mpdata); 409 qreply(q, mpctl); 410 411 /* table of connections... */ 412 optp = (struct opthdr *)&mp_conn_ctl->b_rptr[ 413 sizeof (struct T_optmgmt_ack)]; 414 optp->level = MIB2_TCP; 415 optp->name = MIB2_TCP_CONN; 416 optp->len = msgdsize(mp_conn_ctl->b_cont); 417 qreply(q, mp_conn_ctl); 418 419 /* table of MLP attributes... */ 420 optp = (struct opthdr *)&mp_attr_ctl->b_rptr[ 421 sizeof (struct T_optmgmt_ack)]; 422 optp->level = MIB2_TCP; 423 optp->name = EXPER_XPORT_MLP; 424 optp->len = msgdsize(mp_attr_ctl->b_cont); 425 if (optp->len == 0) 426 freemsg(mp_attr_ctl); 427 else 428 qreply(q, mp_attr_ctl); 429 430 /* table of IPv6 connections... */ 431 optp = (struct opthdr *)&mp6_conn_ctl->b_rptr[ 432 sizeof (struct T_optmgmt_ack)]; 433 optp->level = MIB2_TCP6; 434 optp->name = MIB2_TCP6_CONN; 435 optp->len = msgdsize(mp6_conn_ctl->b_cont); 436 qreply(q, mp6_conn_ctl); 437 438 /* table of IPv6 MLP attributes... */ 439 optp = (struct opthdr *)&mp6_attr_ctl->b_rptr[ 440 sizeof (struct T_optmgmt_ack)]; 441 optp->level = MIB2_TCP6; 442 optp->name = EXPER_XPORT_MLP; 443 optp->len = msgdsize(mp6_attr_ctl->b_cont); 444 if (optp->len == 0) 445 freemsg(mp6_attr_ctl); 446 else 447 qreply(q, mp6_attr_ctl); 448 449 /* table of EXPER_XPORT_PROC_INFO ipv4 */ 450 optp = (struct opthdr *)&mp_pidnode_ctl->b_rptr[ 451 sizeof (struct T_optmgmt_ack)]; 452 optp->level = MIB2_TCP; 453 optp->name = EXPER_XPORT_PROC_INFO; 454 optp->len = msgdsize(mp_pidnode_ctl->b_cont); 455 if (optp->len == 0) 456 freemsg(mp_pidnode_ctl); 457 else 458 qreply(q, mp_pidnode_ctl); 459 460 /* table of EXPER_XPORT_PROC_INFO ipv6 */ 461 optp = (struct opthdr *)&mp6_pidnode_ctl->b_rptr[ 462 sizeof (struct T_optmgmt_ack)]; 463 optp->level = MIB2_TCP6; 464 optp->name = EXPER_XPORT_PROC_INFO; 465 optp->len = msgdsize(mp6_pidnode_ctl->b_cont); 466 if (optp->len == 0) 467 freemsg(mp6_pidnode_ctl); 468 else 469 qreply(q, mp6_pidnode_ctl); 470 471 return (mp2ctl); 472 } 473 474 /* Return 0 if invalid set request, 1 otherwise, including non-tcp requests */ 475 /* ARGSUSED */ 476 int 477 tcp_snmp_set(queue_t *q, int level, int name, uchar_t *ptr, int len) 478 { 479 mib2_tcpConnEntry_t *tce = (mib2_tcpConnEntry_t *)ptr; 480 481 switch (level) { 482 case MIB2_TCP: 483 switch (name) { 484 case 13: 485 if (tce->tcpConnState != MIB2_TCP_deleteTCB) 486 return (0); 487 /* TODO: delete entry defined by tce */ 488 return (1); 489 default: 490 return (0); 491 } 492 default: 493 return (1); 494 } 495 } 496 497 /* 498 * TCP Kstats implementation 499 */ 500 void * 501 tcp_kstat_init(netstackid_t stackid) 502 { 503 kstat_t *ksp; 504 505 tcp_named_kstat_t template = { 506 { "rtoAlgorithm", KSTAT_DATA_INT32, 0 }, 507 { "rtoMin", KSTAT_DATA_INT32, 0 }, 508 { "rtoMax", KSTAT_DATA_INT32, 0 }, 509 { "maxConn", KSTAT_DATA_INT32, 0 }, 510 { "activeOpens", KSTAT_DATA_UINT32, 0 }, 511 { "passiveOpens", KSTAT_DATA_UINT32, 0 }, 512 { "attemptFails", KSTAT_DATA_UINT32, 0 }, 513 { "estabResets", KSTAT_DATA_UINT32, 0 }, 514 { "currEstab", KSTAT_DATA_UINT32, 0 }, 515 { "inSegs", KSTAT_DATA_UINT64, 0 }, 516 { "outSegs", KSTAT_DATA_UINT64, 0 }, 517 { "retransSegs", KSTAT_DATA_UINT32, 0 }, 518 { "connTableSize", KSTAT_DATA_INT32, 0 }, 519 { "outRsts", KSTAT_DATA_UINT32, 0 }, 520 { "outDataSegs", KSTAT_DATA_UINT32, 0 }, 521 { "outDataBytes", KSTAT_DATA_UINT32, 0 }, 522 { "retransBytes", KSTAT_DATA_UINT32, 0 }, 523 { "outAck", KSTAT_DATA_UINT32, 0 }, 524 { "outAckDelayed", KSTAT_DATA_UINT32, 0 }, 525 { "outUrg", KSTAT_DATA_UINT32, 0 }, 526 { "outWinUpdate", KSTAT_DATA_UINT32, 0 }, 527 { "outWinProbe", KSTAT_DATA_UINT32, 0 }, 528 { "outControl", KSTAT_DATA_UINT32, 0 }, 529 { "outFastRetrans", KSTAT_DATA_UINT32, 0 }, 530 { "inAckSegs", KSTAT_DATA_UINT32, 0 }, 531 { "inAckBytes", KSTAT_DATA_UINT32, 0 }, 532 { "inDupAck", KSTAT_DATA_UINT32, 0 }, 533 { "inAckUnsent", KSTAT_DATA_UINT32, 0 }, 534 { "inDataInorderSegs", KSTAT_DATA_UINT32, 0 }, 535 { "inDataInorderBytes", KSTAT_DATA_UINT32, 0 }, 536 { "inDataUnorderSegs", KSTAT_DATA_UINT32, 0 }, 537 { "inDataUnorderBytes", KSTAT_DATA_UINT32, 0 }, 538 { "inDataDupSegs", KSTAT_DATA_UINT32, 0 }, 539 { "inDataDupBytes", KSTAT_DATA_UINT32, 0 }, 540 { "inDataPartDupSegs", KSTAT_DATA_UINT32, 0 }, 541 { "inDataPartDupBytes", KSTAT_DATA_UINT32, 0 }, 542 { "inDataPastWinSegs", KSTAT_DATA_UINT32, 0 }, 543 { "inDataPastWinBytes", KSTAT_DATA_UINT32, 0 }, 544 { "inWinProbe", KSTAT_DATA_UINT32, 0 }, 545 { "inWinUpdate", KSTAT_DATA_UINT32, 0 }, 546 { "inClosed", KSTAT_DATA_UINT32, 0 }, 547 { "rttUpdate", KSTAT_DATA_UINT32, 0 }, 548 { "rttNoUpdate", KSTAT_DATA_UINT32, 0 }, 549 { "timRetrans", KSTAT_DATA_UINT32, 0 }, 550 { "timRetransDrop", KSTAT_DATA_UINT32, 0 }, 551 { "timKeepalive", KSTAT_DATA_UINT32, 0 }, 552 { "timKeepaliveProbe", KSTAT_DATA_UINT32, 0 }, 553 { "timKeepaliveDrop", KSTAT_DATA_UINT32, 0 }, 554 { "listenDrop", KSTAT_DATA_UINT32, 0 }, 555 { "listenDropQ0", KSTAT_DATA_UINT32, 0 }, 556 { "halfOpenDrop", KSTAT_DATA_UINT32, 0 }, 557 { "outSackRetransSegs", KSTAT_DATA_UINT32, 0 }, 558 { "connTableSize6", KSTAT_DATA_INT32, 0 } 559 }; 560 561 ksp = kstat_create_netstack(TCP_MOD_NAME, stackid, TCP_MOD_NAME, "mib2", 562 KSTAT_TYPE_NAMED, NUM_OF_FIELDS(tcp_named_kstat_t), 0, stackid); 563 564 if (ksp == NULL) 565 return (NULL); 566 567 template.rtoAlgorithm.value.ui32 = 4; 568 template.maxConn.value.i32 = -1; 569 570 bcopy(&template, ksp->ks_data, sizeof (template)); 571 ksp->ks_update = tcp_kstat_update; 572 ksp->ks_private = (void *)(uintptr_t)stackid; 573 574 /* 575 * If this is an exclusive netstack for a local zone, the global zone 576 * should still be able to read the kstat. 577 */ 578 if (stackid != GLOBAL_NETSTACKID) 579 kstat_zone_add(ksp, GLOBAL_ZONEID); 580 581 kstat_install(ksp); 582 return (ksp); 583 } 584 585 void 586 tcp_kstat_fini(netstackid_t stackid, kstat_t *ksp) 587 { 588 if (ksp != NULL) { 589 ASSERT(stackid == (netstackid_t)(uintptr_t)ksp->ks_private); 590 kstat_delete_netstack(ksp, stackid); 591 } 592 } 593 594 static int 595 tcp_kstat_update(kstat_t *kp, int rw) 596 { 597 tcp_named_kstat_t *tcpkp; 598 tcp_t *tcp; 599 connf_t *connfp; 600 conn_t *connp; 601 int i; 602 netstackid_t stackid = (netstackid_t)(uintptr_t)kp->ks_private; 603 netstack_t *ns; 604 tcp_stack_t *tcps; 605 ip_stack_t *ipst; 606 mib2_tcp_t tcp_mib; 607 608 if (rw == KSTAT_WRITE) 609 return (EACCES); 610 611 ns = netstack_find_by_stackid(stackid); 612 if (ns == NULL) 613 return (-1); 614 tcps = ns->netstack_tcp; 615 if (tcps == NULL) { 616 netstack_rele(ns); 617 return (-1); 618 } 619 620 tcpkp = (tcp_named_kstat_t *)kp->ks_data; 621 622 tcpkp->currEstab.value.ui32 = 0; 623 tcpkp->rtoMin.value.ui32 = tcps->tcps_rexmit_interval_min; 624 tcpkp->rtoMax.value.ui32 = tcps->tcps_rexmit_interval_max; 625 626 ipst = ns->netstack_ip; 627 628 for (i = 0; i < CONN_G_HASH_SIZE; i++) { 629 connfp = &ipst->ips_ipcl_globalhash_fanout[i]; 630 connp = NULL; 631 while ((connp = 632 ipcl_get_next_conn(connfp, connp, IPCL_TCPCONN)) != NULL) { 633 tcp = connp->conn_tcp; 634 switch (tcp_snmp_state(tcp)) { 635 case MIB2_TCP_established: 636 case MIB2_TCP_closeWait: 637 tcpkp->currEstab.value.ui32++; 638 break; 639 } 640 } 641 } 642 bzero(&tcp_mib, sizeof (tcp_mib)); 643 tcp_sum_mib(tcps, &tcp_mib); 644 645 /* Fixed length structure for IPv4 and IPv6 counters */ 646 SET_MIB(tcp_mib.tcpConnTableSize, sizeof (mib2_tcpConnEntry_t)); 647 SET_MIB(tcp_mib.tcp6ConnTableSize, sizeof (mib2_tcp6ConnEntry_t)); 648 649 tcpkp->activeOpens.value.ui32 = tcp_mib.tcpActiveOpens; 650 tcpkp->passiveOpens.value.ui32 = tcp_mib.tcpPassiveOpens; 651 tcpkp->attemptFails.value.ui32 = tcp_mib.tcpAttemptFails; 652 tcpkp->estabResets.value.ui32 = tcp_mib.tcpEstabResets; 653 tcpkp->inSegs.value.ui64 = tcp_mib.tcpHCInSegs; 654 tcpkp->outSegs.value.ui64 = tcp_mib.tcpHCOutSegs; 655 tcpkp->retransSegs.value.ui32 = tcp_mib.tcpRetransSegs; 656 tcpkp->connTableSize.value.i32 = tcp_mib.tcpConnTableSize; 657 tcpkp->outRsts.value.ui32 = tcp_mib.tcpOutRsts; 658 tcpkp->outDataSegs.value.ui32 = tcp_mib.tcpOutDataSegs; 659 tcpkp->outDataBytes.value.ui32 = tcp_mib.tcpOutDataBytes; 660 tcpkp->retransBytes.value.ui32 = tcp_mib.tcpRetransBytes; 661 tcpkp->outAck.value.ui32 = tcp_mib.tcpOutAck; 662 tcpkp->outAckDelayed.value.ui32 = tcp_mib.tcpOutAckDelayed; 663 tcpkp->outUrg.value.ui32 = tcp_mib.tcpOutUrg; 664 tcpkp->outWinUpdate.value.ui32 = tcp_mib.tcpOutWinUpdate; 665 tcpkp->outWinProbe.value.ui32 = tcp_mib.tcpOutWinProbe; 666 tcpkp->outControl.value.ui32 = tcp_mib.tcpOutControl; 667 tcpkp->outFastRetrans.value.ui32 = tcp_mib.tcpOutFastRetrans; 668 tcpkp->inAckSegs.value.ui32 = tcp_mib.tcpInAckSegs; 669 tcpkp->inAckBytes.value.ui32 = tcp_mib.tcpInAckBytes; 670 tcpkp->inDupAck.value.ui32 = tcp_mib.tcpInDupAck; 671 tcpkp->inAckUnsent.value.ui32 = tcp_mib.tcpInAckUnsent; 672 tcpkp->inDataInorderSegs.value.ui32 = tcp_mib.tcpInDataInorderSegs; 673 tcpkp->inDataInorderBytes.value.ui32 = tcp_mib.tcpInDataInorderBytes; 674 tcpkp->inDataUnorderSegs.value.ui32 = tcp_mib.tcpInDataUnorderSegs; 675 tcpkp->inDataUnorderBytes.value.ui32 = tcp_mib.tcpInDataUnorderBytes; 676 tcpkp->inDataDupSegs.value.ui32 = tcp_mib.tcpInDataDupSegs; 677 tcpkp->inDataDupBytes.value.ui32 = tcp_mib.tcpInDataDupBytes; 678 tcpkp->inDataPartDupSegs.value.ui32 = tcp_mib.tcpInDataPartDupSegs; 679 tcpkp->inDataPartDupBytes.value.ui32 = tcp_mib.tcpInDataPartDupBytes; 680 tcpkp->inDataPastWinSegs.value.ui32 = tcp_mib.tcpInDataPastWinSegs; 681 tcpkp->inDataPastWinBytes.value.ui32 = tcp_mib.tcpInDataPastWinBytes; 682 tcpkp->inWinProbe.value.ui32 = tcp_mib.tcpInWinProbe; 683 tcpkp->inWinUpdate.value.ui32 = tcp_mib.tcpInWinUpdate; 684 tcpkp->inClosed.value.ui32 = tcp_mib.tcpInClosed; 685 tcpkp->rttNoUpdate.value.ui32 = tcp_mib.tcpRttNoUpdate; 686 tcpkp->rttUpdate.value.ui32 = tcp_mib.tcpRttUpdate; 687 tcpkp->timRetrans.value.ui32 = tcp_mib.tcpTimRetrans; 688 tcpkp->timRetransDrop.value.ui32 = tcp_mib.tcpTimRetransDrop; 689 tcpkp->timKeepalive.value.ui32 = tcp_mib.tcpTimKeepalive; 690 tcpkp->timKeepaliveProbe.value.ui32 = tcp_mib.tcpTimKeepaliveProbe; 691 tcpkp->timKeepaliveDrop.value.ui32 = tcp_mib.tcpTimKeepaliveDrop; 692 tcpkp->listenDrop.value.ui32 = tcp_mib.tcpListenDrop; 693 tcpkp->listenDropQ0.value.ui32 = tcp_mib.tcpListenDropQ0; 694 tcpkp->halfOpenDrop.value.ui32 = tcp_mib.tcpHalfOpenDrop; 695 tcpkp->outSackRetransSegs.value.ui32 = tcp_mib.tcpOutSackRetransSegs; 696 tcpkp->connTableSize6.value.i32 = tcp_mib.tcp6ConnTableSize; 697 698 netstack_rele(ns); 699 return (0); 700 } 701 702 /* 703 * kstats related to squeues i.e. not per IP instance 704 */ 705 void * 706 tcp_g_kstat_init(tcp_g_stat_t *tcp_g_statp) 707 { 708 kstat_t *ksp; 709 710 tcp_g_stat_t template = { 711 { "tcp_timermp_alloced", KSTAT_DATA_UINT64 }, 712 { "tcp_timermp_allocfail", KSTAT_DATA_UINT64 }, 713 { "tcp_timermp_allocdblfail", KSTAT_DATA_UINT64 }, 714 { "tcp_freelist_cleanup", KSTAT_DATA_UINT64 }, 715 }; 716 717 ksp = kstat_create(TCP_MOD_NAME, 0, "tcpstat_g", "net", 718 KSTAT_TYPE_NAMED, sizeof (template) / sizeof (kstat_named_t), 719 KSTAT_FLAG_VIRTUAL); 720 721 if (ksp == NULL) 722 return (NULL); 723 724 bcopy(&template, tcp_g_statp, sizeof (template)); 725 ksp->ks_data = (void *)tcp_g_statp; 726 727 kstat_install(ksp); 728 return (ksp); 729 } 730 731 void 732 tcp_g_kstat_fini(kstat_t *ksp) 733 { 734 if (ksp != NULL) { 735 kstat_delete(ksp); 736 } 737 } 738 739 void * 740 tcp_kstat2_init(netstackid_t stackid) 741 { 742 kstat_t *ksp; 743 744 tcp_stat_t template = { 745 { "tcp_time_wait_syn_success", KSTAT_DATA_UINT64, 0 }, 746 { "tcp_clean_death_nondetached", KSTAT_DATA_UINT64, 0 }, 747 { "tcp_eager_blowoff_q", KSTAT_DATA_UINT64, 0 }, 748 { "tcp_eager_blowoff_q0", KSTAT_DATA_UINT64, 0 }, 749 { "tcp_no_listener", KSTAT_DATA_UINT64, 0 }, 750 { "tcp_listendrop", KSTAT_DATA_UINT64, 0 }, 751 { "tcp_listendropq0", KSTAT_DATA_UINT64, 0 }, 752 { "tcp_wsrv_called", KSTAT_DATA_UINT64, 0 }, 753 { "tcp_flwctl_on", KSTAT_DATA_UINT64, 0 }, 754 { "tcp_timer_fire_early", KSTAT_DATA_UINT64, 0 }, 755 { "tcp_timer_fire_miss", KSTAT_DATA_UINT64, 0 }, 756 { "tcp_zcopy_on", KSTAT_DATA_UINT64, 0 }, 757 { "tcp_zcopy_off", KSTAT_DATA_UINT64, 0 }, 758 { "tcp_zcopy_backoff", KSTAT_DATA_UINT64, 0 }, 759 { "tcp_fusion_flowctl", KSTAT_DATA_UINT64, 0 }, 760 { "tcp_fusion_backenabled", KSTAT_DATA_UINT64, 0 }, 761 { "tcp_fusion_urg", KSTAT_DATA_UINT64, 0 }, 762 { "tcp_fusion_putnext", KSTAT_DATA_UINT64, 0 }, 763 { "tcp_fusion_unfusable", KSTAT_DATA_UINT64, 0 }, 764 { "tcp_fusion_aborted", KSTAT_DATA_UINT64, 0 }, 765 { "tcp_fusion_unqualified", KSTAT_DATA_UINT64, 0 }, 766 { "tcp_fusion_rrw_busy", KSTAT_DATA_UINT64, 0 }, 767 { "tcp_fusion_rrw_msgcnt", KSTAT_DATA_UINT64, 0 }, 768 { "tcp_fusion_rrw_plugged", KSTAT_DATA_UINT64, 0 }, 769 { "tcp_in_ack_unsent_drop", KSTAT_DATA_UINT64, 0 }, 770 { "tcp_sock_fallback", KSTAT_DATA_UINT64, 0 }, 771 { "tcp_lso_enabled", KSTAT_DATA_UINT64, 0 }, 772 { "tcp_lso_disabled", KSTAT_DATA_UINT64, 0 }, 773 { "tcp_lso_times", KSTAT_DATA_UINT64, 0 }, 774 { "tcp_lso_pkt_out", KSTAT_DATA_UINT64, 0 }, 775 { "tcp_listen_cnt_drop", KSTAT_DATA_UINT64, 0 }, 776 { "tcp_listen_mem_drop", KSTAT_DATA_UINT64, 0 }, 777 { "tcp_zwin_mem_drop", KSTAT_DATA_UINT64, 0 }, 778 { "tcp_zwin_ack_syn", KSTAT_DATA_UINT64, 0 }, 779 { "tcp_rst_unsent", KSTAT_DATA_UINT64, 0 }, 780 { "tcp_reclaim_cnt", KSTAT_DATA_UINT64, 0 }, 781 { "tcp_reass_timeout", KSTAT_DATA_UINT64, 0 }, 782 #ifdef TCP_DEBUG_COUNTER 783 { "tcp_time_wait", KSTAT_DATA_UINT64, 0 }, 784 { "tcp_rput_time_wait", KSTAT_DATA_UINT64, 0 }, 785 { "tcp_detach_time_wait", KSTAT_DATA_UINT64, 0 }, 786 { "tcp_timeout_calls", KSTAT_DATA_UINT64, 0 }, 787 { "tcp_timeout_cached_alloc", KSTAT_DATA_UINT64, 0 }, 788 { "tcp_timeout_cancel_reqs", KSTAT_DATA_UINT64, 0 }, 789 { "tcp_timeout_canceled", KSTAT_DATA_UINT64, 0 }, 790 { "tcp_timermp_freed", KSTAT_DATA_UINT64, 0 }, 791 { "tcp_push_timer_cnt", KSTAT_DATA_UINT64, 0 }, 792 { "tcp_ack_timer_cnt", KSTAT_DATA_UINT64, 0 }, 793 #endif 794 }; 795 796 ksp = kstat_create_netstack(TCP_MOD_NAME, stackid, "tcpstat", "net", 797 KSTAT_TYPE_NAMED, sizeof (template) / sizeof (kstat_named_t), 0, 798 stackid); 799 800 if (ksp == NULL) 801 return (NULL); 802 803 bcopy(&template, ksp->ks_data, sizeof (template)); 804 ksp->ks_private = (void *)(uintptr_t)stackid; 805 ksp->ks_update = tcp_kstat2_update; 806 807 /* 808 * If this is an exclusive netstack for a local zone, the global zone 809 * should still be able to read the kstat. 810 */ 811 if (stackid != GLOBAL_NETSTACKID) 812 kstat_zone_add(ksp, GLOBAL_ZONEID); 813 814 kstat_install(ksp); 815 return (ksp); 816 } 817 818 void 819 tcp_kstat2_fini(netstackid_t stackid, kstat_t *ksp) 820 { 821 if (ksp != NULL) { 822 ASSERT(stackid == (netstackid_t)(uintptr_t)ksp->ks_private); 823 kstat_delete_netstack(ksp, stackid); 824 } 825 } 826 827 /* 828 * Sum up all per CPU tcp_stat_t kstat counters. 829 */ 830 static int 831 tcp_kstat2_update(kstat_t *kp, int rw) 832 { 833 netstackid_t stackid = (netstackid_t)(uintptr_t)kp->ks_private; 834 netstack_t *ns; 835 tcp_stack_t *tcps; 836 tcp_stat_t *stats; 837 int i; 838 int cnt; 839 840 if (rw == KSTAT_WRITE) 841 return (EACCES); 842 843 ns = netstack_find_by_stackid(stackid); 844 if (ns == NULL) 845 return (-1); 846 tcps = ns->netstack_tcp; 847 if (tcps == NULL) { 848 netstack_rele(ns); 849 return (-1); 850 } 851 852 stats = (tcp_stat_t *)kp->ks_data; 853 tcp_clr_stats(stats); 854 855 /* 856 * tcps_sc_cnt may change in the middle of the loop. It is better 857 * to get its value first. 858 */ 859 cnt = tcps->tcps_sc_cnt; 860 for (i = 0; i < cnt; i++) 861 tcp_add_stats(&tcps->tcps_sc[i]->tcp_sc_stats, stats); 862 863 netstack_rele(ns); 864 return (0); 865 } 866 867 /* 868 * To add stats from one mib2_tcp_t to another. Static fields are not added. 869 * The caller should set them up propertly. 870 */ 871 static void 872 tcp_add_mib(mib2_tcp_t *from, mib2_tcp_t *to) 873 { 874 to->tcpActiveOpens += from->tcpActiveOpens; 875 to->tcpPassiveOpens += from->tcpPassiveOpens; 876 to->tcpAttemptFails += from->tcpAttemptFails; 877 to->tcpEstabResets += from->tcpEstabResets; 878 to->tcpInSegs += from->tcpInSegs; 879 to->tcpOutSegs += from->tcpOutSegs; 880 to->tcpRetransSegs += from->tcpRetransSegs; 881 to->tcpOutRsts += from->tcpOutRsts; 882 883 to->tcpOutDataSegs += from->tcpOutDataSegs; 884 to->tcpOutDataBytes += from->tcpOutDataBytes; 885 to->tcpRetransBytes += from->tcpRetransBytes; 886 to->tcpOutAck += from->tcpOutAck; 887 to->tcpOutAckDelayed += from->tcpOutAckDelayed; 888 to->tcpOutUrg += from->tcpOutUrg; 889 to->tcpOutWinUpdate += from->tcpOutWinUpdate; 890 to->tcpOutWinProbe += from->tcpOutWinProbe; 891 to->tcpOutControl += from->tcpOutControl; 892 to->tcpOutFastRetrans += from->tcpOutFastRetrans; 893 894 to->tcpInAckBytes += from->tcpInAckBytes; 895 to->tcpInDupAck += from->tcpInDupAck; 896 to->tcpInAckUnsent += from->tcpInAckUnsent; 897 to->tcpInDataInorderSegs += from->tcpInDataInorderSegs; 898 to->tcpInDataInorderBytes += from->tcpInDataInorderBytes; 899 to->tcpInDataUnorderSegs += from->tcpInDataUnorderSegs; 900 to->tcpInDataUnorderBytes += from->tcpInDataUnorderBytes; 901 to->tcpInDataDupSegs += from->tcpInDataDupSegs; 902 to->tcpInDataDupBytes += from->tcpInDataDupBytes; 903 to->tcpInDataPartDupSegs += from->tcpInDataPartDupSegs; 904 to->tcpInDataPartDupBytes += from->tcpInDataPartDupBytes; 905 to->tcpInDataPastWinSegs += from->tcpInDataPastWinSegs; 906 to->tcpInDataPastWinBytes += from->tcpInDataPastWinBytes; 907 to->tcpInWinProbe += from->tcpInWinProbe; 908 to->tcpInWinUpdate += from->tcpInWinUpdate; 909 to->tcpInClosed += from->tcpInClosed; 910 911 to->tcpRttNoUpdate += from->tcpRttNoUpdate; 912 to->tcpRttUpdate += from->tcpRttUpdate; 913 to->tcpTimRetrans += from->tcpTimRetrans; 914 to->tcpTimRetransDrop += from->tcpTimRetransDrop; 915 to->tcpTimKeepalive += from->tcpTimKeepalive; 916 to->tcpTimKeepaliveProbe += from->tcpTimKeepaliveProbe; 917 to->tcpTimKeepaliveDrop += from->tcpTimKeepaliveDrop; 918 to->tcpListenDrop += from->tcpListenDrop; 919 to->tcpListenDropQ0 += from->tcpListenDropQ0; 920 to->tcpHalfOpenDrop += from->tcpHalfOpenDrop; 921 to->tcpOutSackRetransSegs += from->tcpOutSackRetransSegs; 922 to->tcpHCInSegs += from->tcpHCInSegs; 923 to->tcpHCOutSegs += from->tcpHCOutSegs; 924 } 925 926 /* 927 * To sum up all MIB2 stats for a tcp_stack_t from all per CPU stats. The 928 * caller should initialize the target mib2_tcp_t properly as this function 929 * just adds up all the per CPU stats. 930 */ 931 static void 932 tcp_sum_mib(tcp_stack_t *tcps, mib2_tcp_t *tcp_mib) 933 { 934 int i; 935 int cnt; 936 937 /* 938 * tcps_sc_cnt may change in the middle of the loop. It is better 939 * to get its value first. 940 */ 941 cnt = tcps->tcps_sc_cnt; 942 for (i = 0; i < cnt; i++) 943 tcp_add_mib(&tcps->tcps_sc[i]->tcp_sc_mib, tcp_mib); 944 } 945 946 /* 947 * To set all tcp_stat_t counters to 0. 948 */ 949 static void 950 tcp_clr_stats(tcp_stat_t *stats) 951 { 952 stats->tcp_time_wait_syn_success.value.ui64 = 0; 953 stats->tcp_clean_death_nondetached.value.ui64 = 0; 954 stats->tcp_eager_blowoff_q.value.ui64 = 0; 955 stats->tcp_eager_blowoff_q0.value.ui64 = 0; 956 stats->tcp_no_listener.value.ui64 = 0; 957 stats->tcp_listendrop.value.ui64 = 0; 958 stats->tcp_listendropq0.value.ui64 = 0; 959 stats->tcp_wsrv_called.value.ui64 = 0; 960 stats->tcp_flwctl_on.value.ui64 = 0; 961 stats->tcp_timer_fire_early.value.ui64 = 0; 962 stats->tcp_timer_fire_miss.value.ui64 = 0; 963 stats->tcp_zcopy_on.value.ui64 = 0; 964 stats->tcp_zcopy_off.value.ui64 = 0; 965 stats->tcp_zcopy_backoff.value.ui64 = 0; 966 stats->tcp_fusion_flowctl.value.ui64 = 0; 967 stats->tcp_fusion_backenabled.value.ui64 = 0; 968 stats->tcp_fusion_urg.value.ui64 = 0; 969 stats->tcp_fusion_putnext.value.ui64 = 0; 970 stats->tcp_fusion_unfusable.value.ui64 = 0; 971 stats->tcp_fusion_aborted.value.ui64 = 0; 972 stats->tcp_fusion_unqualified.value.ui64 = 0; 973 stats->tcp_fusion_rrw_busy.value.ui64 = 0; 974 stats->tcp_fusion_rrw_msgcnt.value.ui64 = 0; 975 stats->tcp_fusion_rrw_plugged.value.ui64 = 0; 976 stats->tcp_in_ack_unsent_drop.value.ui64 = 0; 977 stats->tcp_sock_fallback.value.ui64 = 0; 978 stats->tcp_lso_enabled.value.ui64 = 0; 979 stats->tcp_lso_disabled.value.ui64 = 0; 980 stats->tcp_lso_times.value.ui64 = 0; 981 stats->tcp_lso_pkt_out.value.ui64 = 0; 982 stats->tcp_listen_cnt_drop.value.ui64 = 0; 983 stats->tcp_listen_mem_drop.value.ui64 = 0; 984 stats->tcp_zwin_mem_drop.value.ui64 = 0; 985 stats->tcp_zwin_ack_syn.value.ui64 = 0; 986 stats->tcp_rst_unsent.value.ui64 = 0; 987 stats->tcp_reclaim_cnt.value.ui64 = 0; 988 stats->tcp_reass_timeout.value.ui64 = 0; 989 990 #ifdef TCP_DEBUG_COUNTER 991 stats->tcp_time_wait.value.ui64 = 0; 992 stats->tcp_rput_time_wait.value.ui64 = 0; 993 stats->tcp_detach_time_wait.value.ui64 = 0; 994 stats->tcp_timeout_calls.value.ui64 = 0; 995 stats->tcp_timeout_cached_alloc.value.ui64 = 0; 996 stats->tcp_timeout_cancel_reqs.value.ui64 = 0; 997 stats->tcp_timeout_canceled.value.ui64 = 0; 998 stats->tcp_timermp_freed.value.ui64 = 0; 999 stats->tcp_push_timer_cnt.value.ui64 = 0; 1000 stats->tcp_ack_timer_cnt.value.ui64 = 0; 1001 #endif 1002 } 1003 1004 /* 1005 * To add counters from the per CPU tcp_stat_counter_t to the stack 1006 * tcp_stat_t. 1007 */ 1008 static void 1009 tcp_add_stats(tcp_stat_counter_t *from, tcp_stat_t *to) 1010 { 1011 to->tcp_time_wait_syn_success.value.ui64 += 1012 from->tcp_time_wait_syn_success; 1013 to->tcp_clean_death_nondetached.value.ui64 += 1014 from->tcp_clean_death_nondetached; 1015 to->tcp_eager_blowoff_q.value.ui64 += 1016 from->tcp_eager_blowoff_q; 1017 to->tcp_eager_blowoff_q0.value.ui64 += 1018 from->tcp_eager_blowoff_q0; 1019 to->tcp_no_listener.value.ui64 += 1020 from->tcp_no_listener; 1021 to->tcp_listendrop.value.ui64 += 1022 from->tcp_listendrop; 1023 to->tcp_listendropq0.value.ui64 += 1024 from->tcp_listendropq0; 1025 to->tcp_wsrv_called.value.ui64 += 1026 from->tcp_wsrv_called; 1027 to->tcp_flwctl_on.value.ui64 += 1028 from->tcp_flwctl_on; 1029 to->tcp_timer_fire_early.value.ui64 += 1030 from->tcp_timer_fire_early; 1031 to->tcp_timer_fire_miss.value.ui64 += 1032 from->tcp_timer_fire_miss; 1033 to->tcp_zcopy_on.value.ui64 += 1034 from->tcp_zcopy_on; 1035 to->tcp_zcopy_off.value.ui64 += 1036 from->tcp_zcopy_off; 1037 to->tcp_zcopy_backoff.value.ui64 += 1038 from->tcp_zcopy_backoff; 1039 to->tcp_fusion_flowctl.value.ui64 += 1040 from->tcp_fusion_flowctl; 1041 to->tcp_fusion_backenabled.value.ui64 += 1042 from->tcp_fusion_backenabled; 1043 to->tcp_fusion_urg.value.ui64 += 1044 from->tcp_fusion_urg; 1045 to->tcp_fusion_putnext.value.ui64 += 1046 from->tcp_fusion_putnext; 1047 to->tcp_fusion_unfusable.value.ui64 += 1048 from->tcp_fusion_unfusable; 1049 to->tcp_fusion_aborted.value.ui64 += 1050 from->tcp_fusion_aborted; 1051 to->tcp_fusion_unqualified.value.ui64 += 1052 from->tcp_fusion_unqualified; 1053 to->tcp_fusion_rrw_busy.value.ui64 += 1054 from->tcp_fusion_rrw_busy; 1055 to->tcp_fusion_rrw_msgcnt.value.ui64 += 1056 from->tcp_fusion_rrw_msgcnt; 1057 to->tcp_fusion_rrw_plugged.value.ui64 += 1058 from->tcp_fusion_rrw_plugged; 1059 to->tcp_in_ack_unsent_drop.value.ui64 += 1060 from->tcp_in_ack_unsent_drop; 1061 to->tcp_sock_fallback.value.ui64 += 1062 from->tcp_sock_fallback; 1063 to->tcp_lso_enabled.value.ui64 += 1064 from->tcp_lso_enabled; 1065 to->tcp_lso_disabled.value.ui64 += 1066 from->tcp_lso_disabled; 1067 to->tcp_lso_times.value.ui64 += 1068 from->tcp_lso_times; 1069 to->tcp_lso_pkt_out.value.ui64 += 1070 from->tcp_lso_pkt_out; 1071 to->tcp_listen_cnt_drop.value.ui64 += 1072 from->tcp_listen_cnt_drop; 1073 to->tcp_listen_mem_drop.value.ui64 += 1074 from->tcp_listen_mem_drop; 1075 to->tcp_zwin_mem_drop.value.ui64 += 1076 from->tcp_zwin_mem_drop; 1077 to->tcp_zwin_ack_syn.value.ui64 += 1078 from->tcp_zwin_ack_syn; 1079 to->tcp_rst_unsent.value.ui64 += 1080 from->tcp_rst_unsent; 1081 to->tcp_reclaim_cnt.value.ui64 += 1082 from->tcp_reclaim_cnt; 1083 to->tcp_reass_timeout.value.ui64 += 1084 from->tcp_reass_timeout; 1085 1086 #ifdef TCP_DEBUG_COUNTER 1087 to->tcp_time_wait.value.ui64 += 1088 from->tcp_time_wait; 1089 to->tcp_rput_time_wait.value.ui64 += 1090 from->tcp_rput_time_wait; 1091 to->tcp_detach_time_wait.value.ui64 += 1092 from->tcp_detach_time_wait; 1093 to->tcp_timeout_calls.value.ui64 += 1094 from->tcp_timeout_calls; 1095 to->tcp_timeout_cached_alloc.value.ui64 += 1096 from->tcp_timeout_cached_alloc; 1097 to->tcp_timeout_cancel_reqs.value.ui64 += 1098 from->tcp_timeout_cancel_reqs; 1099 to->tcp_timeout_canceled.value.ui64 += 1100 from->tcp_timeout_canceled; 1101 to->tcp_timermp_freed.value.ui64 += 1102 from->tcp_timermp_freed; 1103 to->tcp_push_timer_cnt.value.ui64 += 1104 from->tcp_push_timer_cnt; 1105 to->tcp_ack_timer_cnt.value.ui64 += 1106 from->tcp_ack_timer_cnt; 1107 #endif 1108 }