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