1721fffe3SKacheong Poon /* 2721fffe3SKacheong Poon * CDDL HEADER START 3721fffe3SKacheong Poon * 4721fffe3SKacheong Poon * The contents of this file are subject to the terms of the 5721fffe3SKacheong Poon * Common Development and Distribution License (the "License"). 6721fffe3SKacheong Poon * You may not use this file except in compliance with the License. 7721fffe3SKacheong Poon * 8721fffe3SKacheong Poon * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9721fffe3SKacheong Poon * or http://www.opensolaris.org/os/licensing. 10721fffe3SKacheong Poon * See the License for the specific language governing permissions 11721fffe3SKacheong Poon * and limitations under the License. 12721fffe3SKacheong Poon * 13721fffe3SKacheong Poon * When distributing Covered Code, include this CDDL HEADER in each 14721fffe3SKacheong Poon * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15721fffe3SKacheong Poon * If applicable, add the following below this CDDL HEADER, with the 16721fffe3SKacheong Poon * fields enclosed by brackets "[]" replaced with your own identifying 17721fffe3SKacheong Poon * information: Portions Copyright [yyyy] [name of copyright owner] 18721fffe3SKacheong Poon * 19721fffe3SKacheong Poon * CDDL HEADER END 20721fffe3SKacheong Poon */ 21721fffe3SKacheong Poon 22721fffe3SKacheong Poon /* 235dd46ab5SKacheong Poon * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 24*4a0bd071SBill Pijewski * Copyright (c) 2011, Joyent Inc. All rights reserved. 25721fffe3SKacheong Poon */ 26721fffe3SKacheong Poon 27721fffe3SKacheong Poon #include <sys/types.h> 28721fffe3SKacheong Poon #include <sys/tihdr.h> 29721fffe3SKacheong Poon #include <sys/policy.h> 30721fffe3SKacheong Poon #include <sys/tsol/tnet.h> 31*4a0bd071SBill Pijewski #include <sys/kstat.h> 32721fffe3SKacheong Poon 33721fffe3SKacheong Poon #include <inet/common.h> 34721fffe3SKacheong Poon #include <inet/ip.h> 35721fffe3SKacheong Poon #include <inet/tcp.h> 36721fffe3SKacheong Poon #include <inet/tcp_impl.h> 37721fffe3SKacheong Poon #include <inet/tcp_stats.h> 38721fffe3SKacheong Poon #include <inet/kstatcom.h> 39721fffe3SKacheong Poon #include <inet/snmpcom.h> 40721fffe3SKacheong Poon 41ca3c8f41SDavid Höppner static int tcp_kstat_update(kstat_t *, int); 42ca3c8f41SDavid Höppner static int tcp_kstat2_update(kstat_t *, int); 43721fffe3SKacheong Poon static void tcp_sum_mib(tcp_stack_t *, mib2_tcp_t *); 44721fffe3SKacheong Poon 455dd46ab5SKacheong Poon static void tcp_add_mib(mib2_tcp_t *, mib2_tcp_t *); 465dd46ab5SKacheong Poon static void tcp_add_stats(tcp_stat_counter_t *, tcp_stat_t *); 47721fffe3SKacheong Poon static void tcp_clr_stats(tcp_stat_t *); 48721fffe3SKacheong Poon 49721fffe3SKacheong Poon tcp_g_stat_t tcp_g_statistics; 50721fffe3SKacheong Poon kstat_t *tcp_g_kstat; 51721fffe3SKacheong Poon 52721fffe3SKacheong Poon /* Translate TCP state to MIB2 TCP state. */ 53721fffe3SKacheong Poon static int 54721fffe3SKacheong Poon tcp_snmp_state(tcp_t *tcp) 55721fffe3SKacheong Poon { 56721fffe3SKacheong Poon if (tcp == NULL) 57721fffe3SKacheong Poon return (0); 58721fffe3SKacheong Poon 59721fffe3SKacheong Poon switch (tcp->tcp_state) { 60721fffe3SKacheong Poon case TCPS_CLOSED: 61721fffe3SKacheong Poon case TCPS_IDLE: /* RFC1213 doesn't have analogue for IDLE & BOUND */ 62721fffe3SKacheong Poon case TCPS_BOUND: 63721fffe3SKacheong Poon return (MIB2_TCP_closed); 64721fffe3SKacheong Poon case TCPS_LISTEN: 65721fffe3SKacheong Poon return (MIB2_TCP_listen); 66721fffe3SKacheong Poon case TCPS_SYN_SENT: 67721fffe3SKacheong Poon return (MIB2_TCP_synSent); 68721fffe3SKacheong Poon case TCPS_SYN_RCVD: 69721fffe3SKacheong Poon return (MIB2_TCP_synReceived); 70721fffe3SKacheong Poon case TCPS_ESTABLISHED: 71721fffe3SKacheong Poon return (MIB2_TCP_established); 72721fffe3SKacheong Poon case TCPS_CLOSE_WAIT: 73721fffe3SKacheong Poon return (MIB2_TCP_closeWait); 74721fffe3SKacheong Poon case TCPS_FIN_WAIT_1: 75721fffe3SKacheong Poon return (MIB2_TCP_finWait1); 76721fffe3SKacheong Poon case TCPS_CLOSING: 77721fffe3SKacheong Poon return (MIB2_TCP_closing); 78721fffe3SKacheong Poon case TCPS_LAST_ACK: 79721fffe3SKacheong Poon return (MIB2_TCP_lastAck); 80721fffe3SKacheong Poon case TCPS_FIN_WAIT_2: 81721fffe3SKacheong Poon return (MIB2_TCP_finWait2); 82721fffe3SKacheong Poon case TCPS_TIME_WAIT: 83721fffe3SKacheong Poon return (MIB2_TCP_timeWait); 84721fffe3SKacheong Poon default: 85721fffe3SKacheong Poon return (0); 86721fffe3SKacheong Poon } 87721fffe3SKacheong Poon } 88721fffe3SKacheong Poon 89721fffe3SKacheong Poon /* 90721fffe3SKacheong Poon * Return SNMP stuff in buffer in mpdata. 91721fffe3SKacheong Poon */ 92721fffe3SKacheong Poon mblk_t * 936f773e29SBaban Kenkre tcp_snmp_get(queue_t *q, mblk_t *mpctl, boolean_t legacy_req) 94721fffe3SKacheong Poon { 95721fffe3SKacheong Poon mblk_t *mpdata; 96721fffe3SKacheong Poon mblk_t *mp_conn_ctl = NULL; 97721fffe3SKacheong Poon mblk_t *mp_conn_tail; 98721fffe3SKacheong Poon mblk_t *mp_attr_ctl = NULL; 99721fffe3SKacheong Poon mblk_t *mp_attr_tail; 100721fffe3SKacheong Poon mblk_t *mp6_conn_ctl = NULL; 101721fffe3SKacheong Poon mblk_t *mp6_conn_tail; 102721fffe3SKacheong Poon mblk_t *mp6_attr_ctl = NULL; 103721fffe3SKacheong Poon mblk_t *mp6_attr_tail; 104721fffe3SKacheong Poon struct opthdr *optp; 105721fffe3SKacheong Poon mib2_tcpConnEntry_t tce; 106721fffe3SKacheong Poon mib2_tcp6ConnEntry_t tce6; 107721fffe3SKacheong Poon mib2_transportMLPEntry_t mlp; 108721fffe3SKacheong Poon connf_t *connfp; 109721fffe3SKacheong Poon int i; 110721fffe3SKacheong Poon boolean_t ispriv; 111721fffe3SKacheong Poon zoneid_t zoneid; 112721fffe3SKacheong Poon int v4_conn_idx; 113721fffe3SKacheong Poon int v6_conn_idx; 114721fffe3SKacheong Poon conn_t *connp = Q_TO_CONN(q); 115721fffe3SKacheong Poon tcp_stack_t *tcps; 116721fffe3SKacheong Poon ip_stack_t *ipst; 117721fffe3SKacheong Poon mblk_t *mp2ctl; 118721fffe3SKacheong Poon mib2_tcp_t tcp_mib; 1196f773e29SBaban Kenkre size_t tcp_mib_size, tce_size, tce6_size; 120721fffe3SKacheong Poon 121721fffe3SKacheong Poon /* 122721fffe3SKacheong Poon * make a copy of the original message 123721fffe3SKacheong Poon */ 124721fffe3SKacheong Poon mp2ctl = copymsg(mpctl); 125721fffe3SKacheong Poon 126721fffe3SKacheong Poon if (mpctl == NULL || 127721fffe3SKacheong Poon (mpdata = mpctl->b_cont) == NULL || 128721fffe3SKacheong Poon (mp_conn_ctl = copymsg(mpctl)) == NULL || 129721fffe3SKacheong Poon (mp_attr_ctl = copymsg(mpctl)) == NULL || 130721fffe3SKacheong Poon (mp6_conn_ctl = copymsg(mpctl)) == NULL || 131721fffe3SKacheong Poon (mp6_attr_ctl = copymsg(mpctl)) == NULL) { 132721fffe3SKacheong Poon freemsg(mp_conn_ctl); 133721fffe3SKacheong Poon freemsg(mp_attr_ctl); 134721fffe3SKacheong Poon freemsg(mp6_conn_ctl); 135721fffe3SKacheong Poon freemsg(mp6_attr_ctl); 136721fffe3SKacheong Poon freemsg(mpctl); 137721fffe3SKacheong Poon freemsg(mp2ctl); 138721fffe3SKacheong Poon return (NULL); 139721fffe3SKacheong Poon } 140721fffe3SKacheong Poon 141721fffe3SKacheong Poon ipst = connp->conn_netstack->netstack_ip; 142721fffe3SKacheong Poon tcps = connp->conn_netstack->netstack_tcp; 143721fffe3SKacheong Poon 1446f773e29SBaban Kenkre if (legacy_req) { 1456f773e29SBaban Kenkre tcp_mib_size = LEGACY_MIB_SIZE(&tcp_mib, mib2_tcp_t); 1466f773e29SBaban Kenkre tce_size = LEGACY_MIB_SIZE(&tce, mib2_tcpConnEntry_t); 1476f773e29SBaban Kenkre tce6_size = LEGACY_MIB_SIZE(&tce6, mib2_tcp6ConnEntry_t); 1486f773e29SBaban Kenkre } else { 1496f773e29SBaban Kenkre tcp_mib_size = sizeof (mib2_tcp_t); 1506f773e29SBaban Kenkre tce_size = sizeof (mib2_tcpConnEntry_t); 1516f773e29SBaban Kenkre tce6_size = sizeof (mib2_tcp6ConnEntry_t); 1526f773e29SBaban Kenkre } 1536f773e29SBaban Kenkre 154721fffe3SKacheong Poon bzero(&tcp_mib, sizeof (tcp_mib)); 155721fffe3SKacheong Poon 156721fffe3SKacheong Poon /* build table of connections -- need count in fixed part */ 157721fffe3SKacheong Poon SET_MIB(tcp_mib.tcpRtoAlgorithm, 4); /* vanj */ 158721fffe3SKacheong Poon SET_MIB(tcp_mib.tcpRtoMin, tcps->tcps_rexmit_interval_min); 159721fffe3SKacheong Poon SET_MIB(tcp_mib.tcpRtoMax, tcps->tcps_rexmit_interval_max); 160721fffe3SKacheong Poon SET_MIB(tcp_mib.tcpMaxConn, -1); 161721fffe3SKacheong Poon SET_MIB(tcp_mib.tcpCurrEstab, 0); 162721fffe3SKacheong Poon 163721fffe3SKacheong Poon ispriv = 164721fffe3SKacheong Poon secpolicy_ip_config((Q_TO_CONN(q))->conn_cred, B_TRUE) == 0; 165721fffe3SKacheong Poon zoneid = Q_TO_CONN(q)->conn_zoneid; 166721fffe3SKacheong Poon 167721fffe3SKacheong Poon v4_conn_idx = v6_conn_idx = 0; 168721fffe3SKacheong Poon mp_conn_tail = mp_attr_tail = mp6_conn_tail = mp6_attr_tail = NULL; 169721fffe3SKacheong Poon 170721fffe3SKacheong Poon for (i = 0; i < CONN_G_HASH_SIZE; i++) { 171721fffe3SKacheong Poon ipst = tcps->tcps_netstack->netstack_ip; 172721fffe3SKacheong Poon 173721fffe3SKacheong Poon connfp = &ipst->ips_ipcl_globalhash_fanout[i]; 174721fffe3SKacheong Poon 175721fffe3SKacheong Poon connp = NULL; 176721fffe3SKacheong Poon 177721fffe3SKacheong Poon while ((connp = 178721fffe3SKacheong Poon ipcl_get_next_conn(connfp, connp, IPCL_TCPCONN)) != NULL) { 179721fffe3SKacheong Poon tcp_t *tcp; 180721fffe3SKacheong Poon boolean_t needattr; 181721fffe3SKacheong Poon 182721fffe3SKacheong Poon if (connp->conn_zoneid != zoneid) 183721fffe3SKacheong Poon continue; /* not in this zone */ 184721fffe3SKacheong Poon 185721fffe3SKacheong Poon tcp = connp->conn_tcp; 186721fffe3SKacheong Poon TCPS_UPDATE_MIB(tcps, tcpHCInSegs, tcp->tcp_ibsegs); 187721fffe3SKacheong Poon tcp->tcp_ibsegs = 0; 188721fffe3SKacheong Poon TCPS_UPDATE_MIB(tcps, tcpHCOutSegs, tcp->tcp_obsegs); 189721fffe3SKacheong Poon tcp->tcp_obsegs = 0; 190721fffe3SKacheong Poon 191721fffe3SKacheong Poon tce6.tcp6ConnState = tce.tcpConnState = 192721fffe3SKacheong Poon tcp_snmp_state(tcp); 193721fffe3SKacheong Poon if (tce.tcpConnState == MIB2_TCP_established || 194721fffe3SKacheong Poon tce.tcpConnState == MIB2_TCP_closeWait) 19547b75f87SKacheong Poon BUMP_MIB(&tcp_mib, tcpCurrEstab); 196721fffe3SKacheong Poon 197721fffe3SKacheong Poon needattr = B_FALSE; 198721fffe3SKacheong Poon bzero(&mlp, sizeof (mlp)); 199721fffe3SKacheong Poon if (connp->conn_mlp_type != mlptSingle) { 200721fffe3SKacheong Poon if (connp->conn_mlp_type == mlptShared || 201721fffe3SKacheong Poon connp->conn_mlp_type == mlptBoth) 202721fffe3SKacheong Poon mlp.tme_flags |= MIB2_TMEF_SHARED; 203721fffe3SKacheong Poon if (connp->conn_mlp_type == mlptPrivate || 204721fffe3SKacheong Poon connp->conn_mlp_type == mlptBoth) 205721fffe3SKacheong Poon mlp.tme_flags |= MIB2_TMEF_PRIVATE; 206721fffe3SKacheong Poon needattr = B_TRUE; 207721fffe3SKacheong Poon } 208721fffe3SKacheong Poon if (connp->conn_anon_mlp) { 209721fffe3SKacheong Poon mlp.tme_flags |= MIB2_TMEF_ANONMLP; 210721fffe3SKacheong Poon needattr = B_TRUE; 211721fffe3SKacheong Poon } 212721fffe3SKacheong Poon switch (connp->conn_mac_mode) { 213721fffe3SKacheong Poon case CONN_MAC_DEFAULT: 214721fffe3SKacheong Poon break; 215721fffe3SKacheong Poon case CONN_MAC_AWARE: 216721fffe3SKacheong Poon mlp.tme_flags |= MIB2_TMEF_MACEXEMPT; 217721fffe3SKacheong Poon needattr = B_TRUE; 218721fffe3SKacheong Poon break; 219721fffe3SKacheong Poon case CONN_MAC_IMPLICIT: 220721fffe3SKacheong Poon mlp.tme_flags |= MIB2_TMEF_MACIMPLICIT; 221721fffe3SKacheong Poon needattr = B_TRUE; 222721fffe3SKacheong Poon break; 223721fffe3SKacheong Poon } 224721fffe3SKacheong Poon if (connp->conn_ixa->ixa_tsl != NULL) { 225721fffe3SKacheong Poon ts_label_t *tsl; 226721fffe3SKacheong Poon 227721fffe3SKacheong Poon tsl = connp->conn_ixa->ixa_tsl; 228721fffe3SKacheong Poon mlp.tme_flags |= MIB2_TMEF_IS_LABELED; 229721fffe3SKacheong Poon mlp.tme_doi = label2doi(tsl); 230721fffe3SKacheong Poon mlp.tme_label = *label2bslabel(tsl); 231721fffe3SKacheong Poon needattr = B_TRUE; 232721fffe3SKacheong Poon } 233721fffe3SKacheong Poon 234721fffe3SKacheong Poon /* Create a message to report on IPv6 entries */ 235721fffe3SKacheong Poon if (connp->conn_ipversion == IPV6_VERSION) { 236721fffe3SKacheong Poon tce6.tcp6ConnLocalAddress = connp->conn_laddr_v6; 237721fffe3SKacheong Poon tce6.tcp6ConnRemAddress = connp->conn_faddr_v6; 238721fffe3SKacheong Poon tce6.tcp6ConnLocalPort = ntohs(connp->conn_lport); 239721fffe3SKacheong Poon tce6.tcp6ConnRemPort = ntohs(connp->conn_fport); 240721fffe3SKacheong Poon if (connp->conn_ixa->ixa_flags & IXAF_SCOPEID_SET) { 241721fffe3SKacheong Poon tce6.tcp6ConnIfIndex = 242721fffe3SKacheong Poon connp->conn_ixa->ixa_scopeid; 243721fffe3SKacheong Poon } else { 244721fffe3SKacheong Poon tce6.tcp6ConnIfIndex = connp->conn_bound_if; 245721fffe3SKacheong Poon } 246721fffe3SKacheong Poon /* Don't want just anybody seeing these... */ 247721fffe3SKacheong Poon if (ispriv) { 248721fffe3SKacheong Poon tce6.tcp6ConnEntryInfo.ce_snxt = 249721fffe3SKacheong Poon tcp->tcp_snxt; 250721fffe3SKacheong Poon tce6.tcp6ConnEntryInfo.ce_suna = 251721fffe3SKacheong Poon tcp->tcp_suna; 252721fffe3SKacheong Poon tce6.tcp6ConnEntryInfo.ce_rnxt = 253721fffe3SKacheong Poon tcp->tcp_rnxt; 254721fffe3SKacheong Poon tce6.tcp6ConnEntryInfo.ce_rack = 255721fffe3SKacheong Poon tcp->tcp_rack; 256721fffe3SKacheong Poon } else { 257721fffe3SKacheong Poon /* 258721fffe3SKacheong Poon * Netstat, unfortunately, uses this to 259721fffe3SKacheong Poon * get send/receive queue sizes. How to fix? 260721fffe3SKacheong Poon * Why not compute the difference only? 261721fffe3SKacheong Poon */ 262721fffe3SKacheong Poon tce6.tcp6ConnEntryInfo.ce_snxt = 263721fffe3SKacheong Poon tcp->tcp_snxt - tcp->tcp_suna; 264721fffe3SKacheong Poon tce6.tcp6ConnEntryInfo.ce_suna = 0; 265721fffe3SKacheong Poon tce6.tcp6ConnEntryInfo.ce_rnxt = 266721fffe3SKacheong Poon tcp->tcp_rnxt - tcp->tcp_rack; 267721fffe3SKacheong Poon tce6.tcp6ConnEntryInfo.ce_rack = 0; 268721fffe3SKacheong Poon } 269721fffe3SKacheong Poon 270721fffe3SKacheong Poon tce6.tcp6ConnEntryInfo.ce_swnd = tcp->tcp_swnd; 271721fffe3SKacheong Poon tce6.tcp6ConnEntryInfo.ce_rwnd = tcp->tcp_rwnd; 272721fffe3SKacheong Poon tce6.tcp6ConnEntryInfo.ce_rto = tcp->tcp_rto; 273721fffe3SKacheong Poon tce6.tcp6ConnEntryInfo.ce_mss = tcp->tcp_mss; 274721fffe3SKacheong Poon tce6.tcp6ConnEntryInfo.ce_state = tcp->tcp_state; 275721fffe3SKacheong Poon 276721fffe3SKacheong Poon tce6.tcp6ConnCreationProcess = 277721fffe3SKacheong Poon (connp->conn_cpid < 0) ? MIB2_UNKNOWN_PROCESS : 278721fffe3SKacheong Poon connp->conn_cpid; 279721fffe3SKacheong Poon tce6.tcp6ConnCreationTime = connp->conn_open_time; 280721fffe3SKacheong Poon 281721fffe3SKacheong Poon (void) snmp_append_data2(mp6_conn_ctl->b_cont, 2826f773e29SBaban Kenkre &mp6_conn_tail, (char *)&tce6, tce6_size); 283721fffe3SKacheong Poon 284721fffe3SKacheong Poon mlp.tme_connidx = v6_conn_idx++; 285721fffe3SKacheong Poon if (needattr) 286721fffe3SKacheong Poon (void) snmp_append_data2(mp6_attr_ctl->b_cont, 287721fffe3SKacheong Poon &mp6_attr_tail, (char *)&mlp, sizeof (mlp)); 288721fffe3SKacheong Poon } 289721fffe3SKacheong Poon /* 290721fffe3SKacheong Poon * Create an IPv4 table entry for IPv4 entries and also 291721fffe3SKacheong Poon * for IPv6 entries which are bound to in6addr_any 292721fffe3SKacheong Poon * but don't have IPV6_V6ONLY set. 293721fffe3SKacheong Poon * (i.e. anything an IPv4 peer could connect to) 294721fffe3SKacheong Poon */ 295721fffe3SKacheong Poon if (connp->conn_ipversion == IPV4_VERSION || 296721fffe3SKacheong Poon (tcp->tcp_state <= TCPS_LISTEN && 297721fffe3SKacheong Poon !connp->conn_ipv6_v6only && 298721fffe3SKacheong Poon IN6_IS_ADDR_UNSPECIFIED(&connp->conn_laddr_v6))) { 299721fffe3SKacheong Poon if (connp->conn_ipversion == IPV6_VERSION) { 300721fffe3SKacheong Poon tce.tcpConnRemAddress = INADDR_ANY; 301721fffe3SKacheong Poon tce.tcpConnLocalAddress = INADDR_ANY; 302721fffe3SKacheong Poon } else { 303721fffe3SKacheong Poon tce.tcpConnRemAddress = 304721fffe3SKacheong Poon connp->conn_faddr_v4; 305721fffe3SKacheong Poon tce.tcpConnLocalAddress = 306721fffe3SKacheong Poon connp->conn_laddr_v4; 307721fffe3SKacheong Poon } 308721fffe3SKacheong Poon tce.tcpConnLocalPort = ntohs(connp->conn_lport); 309721fffe3SKacheong Poon tce.tcpConnRemPort = ntohs(connp->conn_fport); 310721fffe3SKacheong Poon /* Don't want just anybody seeing these... */ 311721fffe3SKacheong Poon if (ispriv) { 312721fffe3SKacheong Poon tce.tcpConnEntryInfo.ce_snxt = 313721fffe3SKacheong Poon tcp->tcp_snxt; 314721fffe3SKacheong Poon tce.tcpConnEntryInfo.ce_suna = 315721fffe3SKacheong Poon tcp->tcp_suna; 316721fffe3SKacheong Poon tce.tcpConnEntryInfo.ce_rnxt = 317721fffe3SKacheong Poon tcp->tcp_rnxt; 318721fffe3SKacheong Poon tce.tcpConnEntryInfo.ce_rack = 319721fffe3SKacheong Poon tcp->tcp_rack; 320721fffe3SKacheong Poon } else { 321721fffe3SKacheong Poon /* 322721fffe3SKacheong Poon * Netstat, unfortunately, uses this to 323721fffe3SKacheong Poon * get send/receive queue sizes. How 324721fffe3SKacheong Poon * to fix? 325721fffe3SKacheong Poon * Why not compute the difference only? 326721fffe3SKacheong Poon */ 327721fffe3SKacheong Poon tce.tcpConnEntryInfo.ce_snxt = 328721fffe3SKacheong Poon tcp->tcp_snxt - tcp->tcp_suna; 329721fffe3SKacheong Poon tce.tcpConnEntryInfo.ce_suna = 0; 330721fffe3SKacheong Poon tce.tcpConnEntryInfo.ce_rnxt = 331721fffe3SKacheong Poon tcp->tcp_rnxt - tcp->tcp_rack; 332721fffe3SKacheong Poon tce.tcpConnEntryInfo.ce_rack = 0; 333721fffe3SKacheong Poon } 334721fffe3SKacheong Poon 335721fffe3SKacheong Poon tce.tcpConnEntryInfo.ce_swnd = tcp->tcp_swnd; 336721fffe3SKacheong Poon tce.tcpConnEntryInfo.ce_rwnd = tcp->tcp_rwnd; 337721fffe3SKacheong Poon tce.tcpConnEntryInfo.ce_rto = tcp->tcp_rto; 338721fffe3SKacheong Poon tce.tcpConnEntryInfo.ce_mss = tcp->tcp_mss; 339721fffe3SKacheong Poon tce.tcpConnEntryInfo.ce_state = 340721fffe3SKacheong Poon tcp->tcp_state; 341721fffe3SKacheong Poon 342721fffe3SKacheong Poon tce.tcpConnCreationProcess = 343721fffe3SKacheong Poon (connp->conn_cpid < 0) ? 344721fffe3SKacheong Poon MIB2_UNKNOWN_PROCESS : 345721fffe3SKacheong Poon connp->conn_cpid; 346721fffe3SKacheong Poon tce.tcpConnCreationTime = connp->conn_open_time; 347721fffe3SKacheong Poon 348721fffe3SKacheong Poon (void) snmp_append_data2(mp_conn_ctl->b_cont, 3496f773e29SBaban Kenkre &mp_conn_tail, (char *)&tce, tce_size); 350721fffe3SKacheong Poon 351721fffe3SKacheong Poon mlp.tme_connidx = v4_conn_idx++; 352721fffe3SKacheong Poon if (needattr) 353721fffe3SKacheong Poon (void) snmp_append_data2( 354721fffe3SKacheong Poon mp_attr_ctl->b_cont, 355721fffe3SKacheong Poon &mp_attr_tail, (char *)&mlp, 356721fffe3SKacheong Poon sizeof (mlp)); 357721fffe3SKacheong Poon } 358721fffe3SKacheong Poon } 359721fffe3SKacheong Poon } 360721fffe3SKacheong Poon 36147b75f87SKacheong Poon tcp_sum_mib(tcps, &tcp_mib); 362721fffe3SKacheong Poon 3636f773e29SBaban Kenkre /* Fixed length structure for IPv4 and IPv6 counters */ 3646f773e29SBaban Kenkre SET_MIB(tcp_mib.tcpConnTableSize, tce_size); 3656f773e29SBaban Kenkre SET_MIB(tcp_mib.tcp6ConnTableSize, tce6_size); 3666f773e29SBaban Kenkre 36747b75f87SKacheong Poon /* 36847b75f87SKacheong Poon * Synchronize 32- and 64-bit counters. Note that tcpInSegs and 36947b75f87SKacheong Poon * tcpOutSegs are not updated anywhere in TCP. The new 64 bits 37047b75f87SKacheong Poon * counters are used. Hence the old counters' values in tcp_sc_mib 37147b75f87SKacheong Poon * are always 0. 37247b75f87SKacheong Poon */ 373721fffe3SKacheong Poon SYNC32_MIB(&tcp_mib, tcpInSegs, tcpHCInSegs); 374721fffe3SKacheong Poon SYNC32_MIB(&tcp_mib, tcpOutSegs, tcpHCOutSegs); 375721fffe3SKacheong Poon 376721fffe3SKacheong Poon optp = (struct opthdr *)&mpctl->b_rptr[sizeof (struct T_optmgmt_ack)]; 377721fffe3SKacheong Poon optp->level = MIB2_TCP; 378721fffe3SKacheong Poon optp->name = 0; 3796f773e29SBaban Kenkre (void) snmp_append_data(mpdata, (char *)&tcp_mib, tcp_mib_size); 380721fffe3SKacheong Poon optp->len = msgdsize(mpdata); 381721fffe3SKacheong Poon qreply(q, mpctl); 382721fffe3SKacheong Poon 383721fffe3SKacheong Poon /* table of connections... */ 384721fffe3SKacheong Poon optp = (struct opthdr *)&mp_conn_ctl->b_rptr[ 385721fffe3SKacheong Poon sizeof (struct T_optmgmt_ack)]; 386721fffe3SKacheong Poon optp->level = MIB2_TCP; 387721fffe3SKacheong Poon optp->name = MIB2_TCP_CONN; 388721fffe3SKacheong Poon optp->len = msgdsize(mp_conn_ctl->b_cont); 389721fffe3SKacheong Poon qreply(q, mp_conn_ctl); 390721fffe3SKacheong Poon 391721fffe3SKacheong Poon /* table of MLP attributes... */ 392721fffe3SKacheong Poon optp = (struct opthdr *)&mp_attr_ctl->b_rptr[ 393721fffe3SKacheong Poon sizeof (struct T_optmgmt_ack)]; 394721fffe3SKacheong Poon optp->level = MIB2_TCP; 395721fffe3SKacheong Poon optp->name = EXPER_XPORT_MLP; 396721fffe3SKacheong Poon optp->len = msgdsize(mp_attr_ctl->b_cont); 397721fffe3SKacheong Poon if (optp->len == 0) 398721fffe3SKacheong Poon freemsg(mp_attr_ctl); 399721fffe3SKacheong Poon else 400721fffe3SKacheong Poon qreply(q, mp_attr_ctl); 401721fffe3SKacheong Poon 402721fffe3SKacheong Poon /* table of IPv6 connections... */ 403721fffe3SKacheong Poon optp = (struct opthdr *)&mp6_conn_ctl->b_rptr[ 404721fffe3SKacheong Poon sizeof (struct T_optmgmt_ack)]; 405721fffe3SKacheong Poon optp->level = MIB2_TCP6; 406721fffe3SKacheong Poon optp->name = MIB2_TCP6_CONN; 407721fffe3SKacheong Poon optp->len = msgdsize(mp6_conn_ctl->b_cont); 408721fffe3SKacheong Poon qreply(q, mp6_conn_ctl); 409721fffe3SKacheong Poon 410721fffe3SKacheong Poon /* table of IPv6 MLP attributes... */ 411721fffe3SKacheong Poon optp = (struct opthdr *)&mp6_attr_ctl->b_rptr[ 412721fffe3SKacheong Poon sizeof (struct T_optmgmt_ack)]; 413721fffe3SKacheong Poon optp->level = MIB2_TCP6; 414721fffe3SKacheong Poon optp->name = EXPER_XPORT_MLP; 415721fffe3SKacheong Poon optp->len = msgdsize(mp6_attr_ctl->b_cont); 416721fffe3SKacheong Poon if (optp->len == 0) 417721fffe3SKacheong Poon freemsg(mp6_attr_ctl); 418721fffe3SKacheong Poon else 419721fffe3SKacheong Poon qreply(q, mp6_attr_ctl); 420721fffe3SKacheong Poon return (mp2ctl); 421721fffe3SKacheong Poon } 422721fffe3SKacheong Poon 423721fffe3SKacheong Poon /* Return 0 if invalid set request, 1 otherwise, including non-tcp requests */ 424721fffe3SKacheong Poon /* ARGSUSED */ 425721fffe3SKacheong Poon int 426721fffe3SKacheong Poon tcp_snmp_set(queue_t *q, int level, int name, uchar_t *ptr, int len) 427721fffe3SKacheong Poon { 428721fffe3SKacheong Poon mib2_tcpConnEntry_t *tce = (mib2_tcpConnEntry_t *)ptr; 429721fffe3SKacheong Poon 430721fffe3SKacheong Poon switch (level) { 431721fffe3SKacheong Poon case MIB2_TCP: 432721fffe3SKacheong Poon switch (name) { 433721fffe3SKacheong Poon case 13: 434721fffe3SKacheong Poon if (tce->tcpConnState != MIB2_TCP_deleteTCB) 435721fffe3SKacheong Poon return (0); 436721fffe3SKacheong Poon /* TODO: delete entry defined by tce */ 437721fffe3SKacheong Poon return (1); 438721fffe3SKacheong Poon default: 439721fffe3SKacheong Poon return (0); 440721fffe3SKacheong Poon } 441721fffe3SKacheong Poon default: 442721fffe3SKacheong Poon return (1); 443721fffe3SKacheong Poon } 444721fffe3SKacheong Poon } 445721fffe3SKacheong Poon 446721fffe3SKacheong Poon /* 447721fffe3SKacheong Poon * TCP Kstats implementation 448721fffe3SKacheong Poon */ 449721fffe3SKacheong Poon void * 450721fffe3SKacheong Poon tcp_kstat_init(netstackid_t stackid) 451721fffe3SKacheong Poon { 452721fffe3SKacheong Poon kstat_t *ksp; 453721fffe3SKacheong Poon 454721fffe3SKacheong Poon tcp_named_kstat_t template = { 455721fffe3SKacheong Poon { "rtoAlgorithm", KSTAT_DATA_INT32, 0 }, 456721fffe3SKacheong Poon { "rtoMin", KSTAT_DATA_INT32, 0 }, 457721fffe3SKacheong Poon { "rtoMax", KSTAT_DATA_INT32, 0 }, 458721fffe3SKacheong Poon { "maxConn", KSTAT_DATA_INT32, 0 }, 459721fffe3SKacheong Poon { "activeOpens", KSTAT_DATA_UINT32, 0 }, 460721fffe3SKacheong Poon { "passiveOpens", KSTAT_DATA_UINT32, 0 }, 461721fffe3SKacheong Poon { "attemptFails", KSTAT_DATA_UINT32, 0 }, 462721fffe3SKacheong Poon { "estabResets", KSTAT_DATA_UINT32, 0 }, 463721fffe3SKacheong Poon { "currEstab", KSTAT_DATA_UINT32, 0 }, 464721fffe3SKacheong Poon { "inSegs", KSTAT_DATA_UINT64, 0 }, 465721fffe3SKacheong Poon { "outSegs", KSTAT_DATA_UINT64, 0 }, 466721fffe3SKacheong Poon { "retransSegs", KSTAT_DATA_UINT32, 0 }, 467721fffe3SKacheong Poon { "connTableSize", KSTAT_DATA_INT32, 0 }, 468721fffe3SKacheong Poon { "outRsts", KSTAT_DATA_UINT32, 0 }, 469721fffe3SKacheong Poon { "outDataSegs", KSTAT_DATA_UINT32, 0 }, 470721fffe3SKacheong Poon { "outDataBytes", KSTAT_DATA_UINT32, 0 }, 471721fffe3SKacheong Poon { "retransBytes", KSTAT_DATA_UINT32, 0 }, 472721fffe3SKacheong Poon { "outAck", KSTAT_DATA_UINT32, 0 }, 473721fffe3SKacheong Poon { "outAckDelayed", KSTAT_DATA_UINT32, 0 }, 474721fffe3SKacheong Poon { "outUrg", KSTAT_DATA_UINT32, 0 }, 475721fffe3SKacheong Poon { "outWinUpdate", KSTAT_DATA_UINT32, 0 }, 476721fffe3SKacheong Poon { "outWinProbe", KSTAT_DATA_UINT32, 0 }, 477721fffe3SKacheong Poon { "outControl", KSTAT_DATA_UINT32, 0 }, 478721fffe3SKacheong Poon { "outFastRetrans", KSTAT_DATA_UINT32, 0 }, 479721fffe3SKacheong Poon { "inAckSegs", KSTAT_DATA_UINT32, 0 }, 480721fffe3SKacheong Poon { "inAckBytes", KSTAT_DATA_UINT32, 0 }, 481721fffe3SKacheong Poon { "inDupAck", KSTAT_DATA_UINT32, 0 }, 482721fffe3SKacheong Poon { "inAckUnsent", KSTAT_DATA_UINT32, 0 }, 483721fffe3SKacheong Poon { "inDataInorderSegs", KSTAT_DATA_UINT32, 0 }, 484721fffe3SKacheong Poon { "inDataInorderBytes", KSTAT_DATA_UINT32, 0 }, 485721fffe3SKacheong Poon { "inDataUnorderSegs", KSTAT_DATA_UINT32, 0 }, 486721fffe3SKacheong Poon { "inDataUnorderBytes", KSTAT_DATA_UINT32, 0 }, 487721fffe3SKacheong Poon { "inDataDupSegs", KSTAT_DATA_UINT32, 0 }, 488721fffe3SKacheong Poon { "inDataDupBytes", KSTAT_DATA_UINT32, 0 }, 489721fffe3SKacheong Poon { "inDataPartDupSegs", KSTAT_DATA_UINT32, 0 }, 490721fffe3SKacheong Poon { "inDataPartDupBytes", KSTAT_DATA_UINT32, 0 }, 491721fffe3SKacheong Poon { "inDataPastWinSegs", KSTAT_DATA_UINT32, 0 }, 492721fffe3SKacheong Poon { "inDataPastWinBytes", KSTAT_DATA_UINT32, 0 }, 493721fffe3SKacheong Poon { "inWinProbe", KSTAT_DATA_UINT32, 0 }, 494721fffe3SKacheong Poon { "inWinUpdate", KSTAT_DATA_UINT32, 0 }, 495721fffe3SKacheong Poon { "inClosed", KSTAT_DATA_UINT32, 0 }, 496721fffe3SKacheong Poon { "rttUpdate", KSTAT_DATA_UINT32, 0 }, 497721fffe3SKacheong Poon { "rttNoUpdate", KSTAT_DATA_UINT32, 0 }, 498721fffe3SKacheong Poon { "timRetrans", KSTAT_DATA_UINT32, 0 }, 499721fffe3SKacheong Poon { "timRetransDrop", KSTAT_DATA_UINT32, 0 }, 500721fffe3SKacheong Poon { "timKeepalive", KSTAT_DATA_UINT32, 0 }, 501721fffe3SKacheong Poon { "timKeepaliveProbe", KSTAT_DATA_UINT32, 0 }, 502721fffe3SKacheong Poon { "timKeepaliveDrop", KSTAT_DATA_UINT32, 0 }, 503721fffe3SKacheong Poon { "listenDrop", KSTAT_DATA_UINT32, 0 }, 504721fffe3SKacheong Poon { "listenDropQ0", KSTAT_DATA_UINT32, 0 }, 505721fffe3SKacheong Poon { "halfOpenDrop", KSTAT_DATA_UINT32, 0 }, 506721fffe3SKacheong Poon { "outSackRetransSegs", KSTAT_DATA_UINT32, 0 }, 507721fffe3SKacheong Poon { "connTableSize6", KSTAT_DATA_INT32, 0 } 508721fffe3SKacheong Poon }; 509721fffe3SKacheong Poon 510*4a0bd071SBill Pijewski ksp = kstat_create_netstack(TCP_MOD_NAME, stackid, TCP_MOD_NAME, "mib2", 511721fffe3SKacheong Poon KSTAT_TYPE_NAMED, NUM_OF_FIELDS(tcp_named_kstat_t), 0, stackid); 512721fffe3SKacheong Poon 513721fffe3SKacheong Poon if (ksp == NULL) 514721fffe3SKacheong Poon return (NULL); 515721fffe3SKacheong Poon 516721fffe3SKacheong Poon template.rtoAlgorithm.value.ui32 = 4; 517721fffe3SKacheong Poon template.maxConn.value.i32 = -1; 518721fffe3SKacheong Poon 519721fffe3SKacheong Poon bcopy(&template, ksp->ks_data, sizeof (template)); 520721fffe3SKacheong Poon ksp->ks_update = tcp_kstat_update; 521721fffe3SKacheong Poon ksp->ks_private = (void *)(uintptr_t)stackid; 522721fffe3SKacheong Poon 523*4a0bd071SBill Pijewski /* 524*4a0bd071SBill Pijewski * If this is an exclusive netstack for a local zone, the global zone 525*4a0bd071SBill Pijewski * should still be able to read the kstat. 526*4a0bd071SBill Pijewski */ 527*4a0bd071SBill Pijewski if (stackid != GLOBAL_NETSTACKID) 528*4a0bd071SBill Pijewski kstat_zone_add(ksp, GLOBAL_ZONEID); 529*4a0bd071SBill Pijewski 530721fffe3SKacheong Poon kstat_install(ksp); 531721fffe3SKacheong Poon return (ksp); 532721fffe3SKacheong Poon } 533721fffe3SKacheong Poon 534721fffe3SKacheong Poon void 535721fffe3SKacheong Poon tcp_kstat_fini(netstackid_t stackid, kstat_t *ksp) 536721fffe3SKacheong Poon { 537721fffe3SKacheong Poon if (ksp != NULL) { 538721fffe3SKacheong Poon ASSERT(stackid == (netstackid_t)(uintptr_t)ksp->ks_private); 539721fffe3SKacheong Poon kstat_delete_netstack(ksp, stackid); 540721fffe3SKacheong Poon } 541721fffe3SKacheong Poon } 542721fffe3SKacheong Poon 543721fffe3SKacheong Poon static int 544721fffe3SKacheong Poon tcp_kstat_update(kstat_t *kp, int rw) 545721fffe3SKacheong Poon { 546721fffe3SKacheong Poon tcp_named_kstat_t *tcpkp; 547721fffe3SKacheong Poon tcp_t *tcp; 548721fffe3SKacheong Poon connf_t *connfp; 549721fffe3SKacheong Poon conn_t *connp; 550721fffe3SKacheong Poon int i; 551721fffe3SKacheong Poon netstackid_t stackid = (netstackid_t)(uintptr_t)kp->ks_private; 552721fffe3SKacheong Poon netstack_t *ns; 553721fffe3SKacheong Poon tcp_stack_t *tcps; 554721fffe3SKacheong Poon ip_stack_t *ipst; 555721fffe3SKacheong Poon mib2_tcp_t tcp_mib; 556721fffe3SKacheong Poon 557721fffe3SKacheong Poon if (rw == KSTAT_WRITE) 558721fffe3SKacheong Poon return (EACCES); 559721fffe3SKacheong Poon 560721fffe3SKacheong Poon ns = netstack_find_by_stackid(stackid); 561721fffe3SKacheong Poon if (ns == NULL) 562721fffe3SKacheong Poon return (-1); 563721fffe3SKacheong Poon tcps = ns->netstack_tcp; 564721fffe3SKacheong Poon if (tcps == NULL) { 565721fffe3SKacheong Poon netstack_rele(ns); 566721fffe3SKacheong Poon return (-1); 567721fffe3SKacheong Poon } 568721fffe3SKacheong Poon 569721fffe3SKacheong Poon tcpkp = (tcp_named_kstat_t *)kp->ks_data; 570721fffe3SKacheong Poon 571721fffe3SKacheong Poon tcpkp->currEstab.value.ui32 = 0; 572721fffe3SKacheong Poon tcpkp->rtoMin.value.ui32 = tcps->tcps_rexmit_interval_min; 573721fffe3SKacheong Poon tcpkp->rtoMax.value.ui32 = tcps->tcps_rexmit_interval_max; 574721fffe3SKacheong Poon 575721fffe3SKacheong Poon ipst = ns->netstack_ip; 576721fffe3SKacheong Poon 577721fffe3SKacheong Poon for (i = 0; i < CONN_G_HASH_SIZE; i++) { 578721fffe3SKacheong Poon connfp = &ipst->ips_ipcl_globalhash_fanout[i]; 579721fffe3SKacheong Poon connp = NULL; 580721fffe3SKacheong Poon while ((connp = 581721fffe3SKacheong Poon ipcl_get_next_conn(connfp, connp, IPCL_TCPCONN)) != NULL) { 582721fffe3SKacheong Poon tcp = connp->conn_tcp; 583721fffe3SKacheong Poon switch (tcp_snmp_state(tcp)) { 584721fffe3SKacheong Poon case MIB2_TCP_established: 585721fffe3SKacheong Poon case MIB2_TCP_closeWait: 586721fffe3SKacheong Poon tcpkp->currEstab.value.ui32++; 587721fffe3SKacheong Poon break; 588721fffe3SKacheong Poon } 589721fffe3SKacheong Poon } 590721fffe3SKacheong Poon } 591721fffe3SKacheong Poon bzero(&tcp_mib, sizeof (tcp_mib)); 592721fffe3SKacheong Poon tcp_sum_mib(tcps, &tcp_mib); 593721fffe3SKacheong Poon 5946f773e29SBaban Kenkre /* Fixed length structure for IPv4 and IPv6 counters */ 5956f773e29SBaban Kenkre SET_MIB(tcp_mib.tcpConnTableSize, sizeof (mib2_tcpConnEntry_t)); 5966f773e29SBaban Kenkre SET_MIB(tcp_mib.tcp6ConnTableSize, sizeof (mib2_tcp6ConnEntry_t)); 5976f773e29SBaban Kenkre 598721fffe3SKacheong Poon tcpkp->activeOpens.value.ui32 = tcp_mib.tcpActiveOpens; 599721fffe3SKacheong Poon tcpkp->passiveOpens.value.ui32 = tcp_mib.tcpPassiveOpens; 600721fffe3SKacheong Poon tcpkp->attemptFails.value.ui32 = tcp_mib.tcpAttemptFails; 601721fffe3SKacheong Poon tcpkp->estabResets.value.ui32 = tcp_mib.tcpEstabResets; 602721fffe3SKacheong Poon tcpkp->inSegs.value.ui64 = tcp_mib.tcpHCInSegs; 603721fffe3SKacheong Poon tcpkp->outSegs.value.ui64 = tcp_mib.tcpHCOutSegs; 604721fffe3SKacheong Poon tcpkp->retransSegs.value.ui32 = tcp_mib.tcpRetransSegs; 605721fffe3SKacheong Poon tcpkp->connTableSize.value.i32 = tcp_mib.tcpConnTableSize; 606721fffe3SKacheong Poon tcpkp->outRsts.value.ui32 = tcp_mib.tcpOutRsts; 607721fffe3SKacheong Poon tcpkp->outDataSegs.value.ui32 = tcp_mib.tcpOutDataSegs; 608721fffe3SKacheong Poon tcpkp->outDataBytes.value.ui32 = tcp_mib.tcpOutDataBytes; 609721fffe3SKacheong Poon tcpkp->retransBytes.value.ui32 = tcp_mib.tcpRetransBytes; 610721fffe3SKacheong Poon tcpkp->outAck.value.ui32 = tcp_mib.tcpOutAck; 611721fffe3SKacheong Poon tcpkp->outAckDelayed.value.ui32 = tcp_mib.tcpOutAckDelayed; 612721fffe3SKacheong Poon tcpkp->outUrg.value.ui32 = tcp_mib.tcpOutUrg; 613721fffe3SKacheong Poon tcpkp->outWinUpdate.value.ui32 = tcp_mib.tcpOutWinUpdate; 614721fffe3SKacheong Poon tcpkp->outWinProbe.value.ui32 = tcp_mib.tcpOutWinProbe; 615721fffe3SKacheong Poon tcpkp->outControl.value.ui32 = tcp_mib.tcpOutControl; 616721fffe3SKacheong Poon tcpkp->outFastRetrans.value.ui32 = tcp_mib.tcpOutFastRetrans; 617721fffe3SKacheong Poon tcpkp->inAckSegs.value.ui32 = tcp_mib.tcpInAckSegs; 618721fffe3SKacheong Poon tcpkp->inAckBytes.value.ui32 = tcp_mib.tcpInAckBytes; 619721fffe3SKacheong Poon tcpkp->inDupAck.value.ui32 = tcp_mib.tcpInDupAck; 620721fffe3SKacheong Poon tcpkp->inAckUnsent.value.ui32 = tcp_mib.tcpInAckUnsent; 621721fffe3SKacheong Poon tcpkp->inDataInorderSegs.value.ui32 = tcp_mib.tcpInDataInorderSegs; 622721fffe3SKacheong Poon tcpkp->inDataInorderBytes.value.ui32 = tcp_mib.tcpInDataInorderBytes; 623721fffe3SKacheong Poon tcpkp->inDataUnorderSegs.value.ui32 = tcp_mib.tcpInDataUnorderSegs; 624721fffe3SKacheong Poon tcpkp->inDataUnorderBytes.value.ui32 = tcp_mib.tcpInDataUnorderBytes; 625721fffe3SKacheong Poon tcpkp->inDataDupSegs.value.ui32 = tcp_mib.tcpInDataDupSegs; 626721fffe3SKacheong Poon tcpkp->inDataDupBytes.value.ui32 = tcp_mib.tcpInDataDupBytes; 627721fffe3SKacheong Poon tcpkp->inDataPartDupSegs.value.ui32 = tcp_mib.tcpInDataPartDupSegs; 628721fffe3SKacheong Poon tcpkp->inDataPartDupBytes.value.ui32 = tcp_mib.tcpInDataPartDupBytes; 629721fffe3SKacheong Poon tcpkp->inDataPastWinSegs.value.ui32 = tcp_mib.tcpInDataPastWinSegs; 630721fffe3SKacheong Poon tcpkp->inDataPastWinBytes.value.ui32 = tcp_mib.tcpInDataPastWinBytes; 631721fffe3SKacheong Poon tcpkp->inWinProbe.value.ui32 = tcp_mib.tcpInWinProbe; 632721fffe3SKacheong Poon tcpkp->inWinUpdate.value.ui32 = tcp_mib.tcpInWinUpdate; 633721fffe3SKacheong Poon tcpkp->inClosed.value.ui32 = tcp_mib.tcpInClosed; 634721fffe3SKacheong Poon tcpkp->rttNoUpdate.value.ui32 = tcp_mib.tcpRttNoUpdate; 635721fffe3SKacheong Poon tcpkp->rttUpdate.value.ui32 = tcp_mib.tcpRttUpdate; 636721fffe3SKacheong Poon tcpkp->timRetrans.value.ui32 = tcp_mib.tcpTimRetrans; 637721fffe3SKacheong Poon tcpkp->timRetransDrop.value.ui32 = tcp_mib.tcpTimRetransDrop; 638721fffe3SKacheong Poon tcpkp->timKeepalive.value.ui32 = tcp_mib.tcpTimKeepalive; 639721fffe3SKacheong Poon tcpkp->timKeepaliveProbe.value.ui32 = tcp_mib.tcpTimKeepaliveProbe; 640721fffe3SKacheong Poon tcpkp->timKeepaliveDrop.value.ui32 = tcp_mib.tcpTimKeepaliveDrop; 641721fffe3SKacheong Poon tcpkp->listenDrop.value.ui32 = tcp_mib.tcpListenDrop; 642721fffe3SKacheong Poon tcpkp->listenDropQ0.value.ui32 = tcp_mib.tcpListenDropQ0; 643721fffe3SKacheong Poon tcpkp->halfOpenDrop.value.ui32 = tcp_mib.tcpHalfOpenDrop; 644721fffe3SKacheong Poon tcpkp->outSackRetransSegs.value.ui32 = tcp_mib.tcpOutSackRetransSegs; 645721fffe3SKacheong Poon tcpkp->connTableSize6.value.i32 = tcp_mib.tcp6ConnTableSize; 646721fffe3SKacheong Poon 647721fffe3SKacheong Poon netstack_rele(ns); 648721fffe3SKacheong Poon return (0); 649721fffe3SKacheong Poon } 650721fffe3SKacheong Poon 651721fffe3SKacheong Poon /* 652721fffe3SKacheong Poon * kstats related to squeues i.e. not per IP instance 653721fffe3SKacheong Poon */ 654721fffe3SKacheong Poon void * 655721fffe3SKacheong Poon tcp_g_kstat_init(tcp_g_stat_t *tcp_g_statp) 656721fffe3SKacheong Poon { 657721fffe3SKacheong Poon kstat_t *ksp; 658721fffe3SKacheong Poon 659721fffe3SKacheong Poon tcp_g_stat_t template = { 660721fffe3SKacheong Poon { "tcp_timermp_alloced", KSTAT_DATA_UINT64 }, 661721fffe3SKacheong Poon { "tcp_timermp_allocfail", KSTAT_DATA_UINT64 }, 662721fffe3SKacheong Poon { "tcp_timermp_allocdblfail", KSTAT_DATA_UINT64 }, 663721fffe3SKacheong Poon { "tcp_freelist_cleanup", KSTAT_DATA_UINT64 }, 664721fffe3SKacheong Poon }; 665721fffe3SKacheong Poon 666721fffe3SKacheong Poon ksp = kstat_create(TCP_MOD_NAME, 0, "tcpstat_g", "net", 667721fffe3SKacheong Poon KSTAT_TYPE_NAMED, sizeof (template) / sizeof (kstat_named_t), 668721fffe3SKacheong Poon KSTAT_FLAG_VIRTUAL); 669721fffe3SKacheong Poon 670721fffe3SKacheong Poon if (ksp == NULL) 671721fffe3SKacheong Poon return (NULL); 672721fffe3SKacheong Poon 673721fffe3SKacheong Poon bcopy(&template, tcp_g_statp, sizeof (template)); 674721fffe3SKacheong Poon ksp->ks_data = (void *)tcp_g_statp; 675721fffe3SKacheong Poon 676721fffe3SKacheong Poon kstat_install(ksp); 677721fffe3SKacheong Poon return (ksp); 678721fffe3SKacheong Poon } 679721fffe3SKacheong Poon 680721fffe3SKacheong Poon void 681721fffe3SKacheong Poon tcp_g_kstat_fini(kstat_t *ksp) 682721fffe3SKacheong Poon { 683721fffe3SKacheong Poon if (ksp != NULL) { 684721fffe3SKacheong Poon kstat_delete(ksp); 685721fffe3SKacheong Poon } 686721fffe3SKacheong Poon } 687721fffe3SKacheong Poon 688721fffe3SKacheong Poon void * 689721fffe3SKacheong Poon tcp_kstat2_init(netstackid_t stackid) 690721fffe3SKacheong Poon { 691721fffe3SKacheong Poon kstat_t *ksp; 692721fffe3SKacheong Poon 693721fffe3SKacheong Poon tcp_stat_t template = { 694721fffe3SKacheong Poon { "tcp_time_wait_syn_success", KSTAT_DATA_UINT64, 0 }, 695721fffe3SKacheong Poon { "tcp_clean_death_nondetached", KSTAT_DATA_UINT64, 0 }, 696721fffe3SKacheong Poon { "tcp_eager_blowoff_q", KSTAT_DATA_UINT64, 0 }, 697721fffe3SKacheong Poon { "tcp_eager_blowoff_q0", KSTAT_DATA_UINT64, 0 }, 698721fffe3SKacheong Poon { "tcp_no_listener", KSTAT_DATA_UINT64, 0 }, 699721fffe3SKacheong Poon { "tcp_listendrop", KSTAT_DATA_UINT64, 0 }, 700721fffe3SKacheong Poon { "tcp_listendropq0", KSTAT_DATA_UINT64, 0 }, 701721fffe3SKacheong Poon { "tcp_wsrv_called", KSTAT_DATA_UINT64, 0 }, 702721fffe3SKacheong Poon { "tcp_flwctl_on", KSTAT_DATA_UINT64, 0 }, 703721fffe3SKacheong Poon { "tcp_timer_fire_early", KSTAT_DATA_UINT64, 0 }, 704721fffe3SKacheong Poon { "tcp_timer_fire_miss", KSTAT_DATA_UINT64, 0 }, 705721fffe3SKacheong Poon { "tcp_zcopy_on", KSTAT_DATA_UINT64, 0 }, 706721fffe3SKacheong Poon { "tcp_zcopy_off", KSTAT_DATA_UINT64, 0 }, 707721fffe3SKacheong Poon { "tcp_zcopy_backoff", KSTAT_DATA_UINT64, 0 }, 708721fffe3SKacheong Poon { "tcp_fusion_flowctl", KSTAT_DATA_UINT64, 0 }, 709721fffe3SKacheong Poon { "tcp_fusion_backenabled", KSTAT_DATA_UINT64, 0 }, 710721fffe3SKacheong Poon { "tcp_fusion_urg", KSTAT_DATA_UINT64, 0 }, 711721fffe3SKacheong Poon { "tcp_fusion_putnext", KSTAT_DATA_UINT64, 0 }, 712721fffe3SKacheong Poon { "tcp_fusion_unfusable", KSTAT_DATA_UINT64, 0 }, 713721fffe3SKacheong Poon { "tcp_fusion_aborted", KSTAT_DATA_UINT64, 0 }, 714721fffe3SKacheong Poon { "tcp_fusion_unqualified", KSTAT_DATA_UINT64, 0 }, 715721fffe3SKacheong Poon { "tcp_fusion_rrw_busy", KSTAT_DATA_UINT64, 0 }, 716721fffe3SKacheong Poon { "tcp_fusion_rrw_msgcnt", KSTAT_DATA_UINT64, 0 }, 717721fffe3SKacheong Poon { "tcp_fusion_rrw_plugged", KSTAT_DATA_UINT64, 0 }, 718721fffe3SKacheong Poon { "tcp_in_ack_unsent_drop", KSTAT_DATA_UINT64, 0 }, 719721fffe3SKacheong Poon { "tcp_sock_fallback", KSTAT_DATA_UINT64, 0 }, 720721fffe3SKacheong Poon { "tcp_lso_enabled", KSTAT_DATA_UINT64, 0 }, 721721fffe3SKacheong Poon { "tcp_lso_disabled", KSTAT_DATA_UINT64, 0 }, 722721fffe3SKacheong Poon { "tcp_lso_times", KSTAT_DATA_UINT64, 0 }, 723721fffe3SKacheong Poon { "tcp_lso_pkt_out", KSTAT_DATA_UINT64, 0 }, 724721fffe3SKacheong Poon { "tcp_listen_cnt_drop", KSTAT_DATA_UINT64, 0 }, 725721fffe3SKacheong Poon { "tcp_listen_mem_drop", KSTAT_DATA_UINT64, 0 }, 726721fffe3SKacheong Poon { "tcp_zwin_mem_drop", KSTAT_DATA_UINT64, 0 }, 727721fffe3SKacheong Poon { "tcp_zwin_ack_syn", KSTAT_DATA_UINT64, 0 }, 728721fffe3SKacheong Poon { "tcp_rst_unsent", KSTAT_DATA_UINT64, 0 }, 729721fffe3SKacheong Poon { "tcp_reclaim_cnt", KSTAT_DATA_UINT64, 0 }, 730721fffe3SKacheong Poon { "tcp_reass_timeout", KSTAT_DATA_UINT64, 0 }, 731721fffe3SKacheong Poon #ifdef TCP_DEBUG_COUNTER 732721fffe3SKacheong Poon { "tcp_time_wait", KSTAT_DATA_UINT64, 0 }, 733721fffe3SKacheong Poon { "tcp_rput_time_wait", KSTAT_DATA_UINT64, 0 }, 734721fffe3SKacheong Poon { "tcp_detach_time_wait", KSTAT_DATA_UINT64, 0 }, 735721fffe3SKacheong Poon { "tcp_timeout_calls", KSTAT_DATA_UINT64, 0 }, 736721fffe3SKacheong Poon { "tcp_timeout_cached_alloc", KSTAT_DATA_UINT64, 0 }, 737721fffe3SKacheong Poon { "tcp_timeout_cancel_reqs", KSTAT_DATA_UINT64, 0 }, 738721fffe3SKacheong Poon { "tcp_timeout_canceled", KSTAT_DATA_UINT64, 0 }, 739721fffe3SKacheong Poon { "tcp_timermp_freed", KSTAT_DATA_UINT64, 0 }, 740721fffe3SKacheong Poon { "tcp_push_timer_cnt", KSTAT_DATA_UINT64, 0 }, 741721fffe3SKacheong Poon { "tcp_ack_timer_cnt", KSTAT_DATA_UINT64, 0 }, 742721fffe3SKacheong Poon #endif 743721fffe3SKacheong Poon }; 744721fffe3SKacheong Poon 745*4a0bd071SBill Pijewski ksp = kstat_create_netstack(TCP_MOD_NAME, stackid, "tcpstat", "net", 746721fffe3SKacheong Poon KSTAT_TYPE_NAMED, sizeof (template) / sizeof (kstat_named_t), 0, 747721fffe3SKacheong Poon stackid); 748721fffe3SKacheong Poon 749721fffe3SKacheong Poon if (ksp == NULL) 750721fffe3SKacheong Poon return (NULL); 751721fffe3SKacheong Poon 752721fffe3SKacheong Poon bcopy(&template, ksp->ks_data, sizeof (template)); 753721fffe3SKacheong Poon ksp->ks_private = (void *)(uintptr_t)stackid; 754721fffe3SKacheong Poon ksp->ks_update = tcp_kstat2_update; 755721fffe3SKacheong Poon 756*4a0bd071SBill Pijewski /* 757*4a0bd071SBill Pijewski * If this is an exclusive netstack for a local zone, the global zone 758*4a0bd071SBill Pijewski * should still be able to read the kstat. 759*4a0bd071SBill Pijewski */ 760*4a0bd071SBill Pijewski if (stackid != GLOBAL_NETSTACKID) 761*4a0bd071SBill Pijewski kstat_zone_add(ksp, GLOBAL_ZONEID); 762*4a0bd071SBill Pijewski 763721fffe3SKacheong Poon kstat_install(ksp); 764721fffe3SKacheong Poon return (ksp); 765721fffe3SKacheong Poon } 766721fffe3SKacheong Poon 767721fffe3SKacheong Poon void 768721fffe3SKacheong Poon tcp_kstat2_fini(netstackid_t stackid, kstat_t *ksp) 769721fffe3SKacheong Poon { 770721fffe3SKacheong Poon if (ksp != NULL) { 771721fffe3SKacheong Poon ASSERT(stackid == (netstackid_t)(uintptr_t)ksp->ks_private); 772721fffe3SKacheong Poon kstat_delete_netstack(ksp, stackid); 773721fffe3SKacheong Poon } 774721fffe3SKacheong Poon } 775721fffe3SKacheong Poon 776721fffe3SKacheong Poon /* 777721fffe3SKacheong Poon * Sum up all per CPU tcp_stat_t kstat counters. 778721fffe3SKacheong Poon */ 779721fffe3SKacheong Poon static int 780721fffe3SKacheong Poon tcp_kstat2_update(kstat_t *kp, int rw) 781721fffe3SKacheong Poon { 782721fffe3SKacheong Poon netstackid_t stackid = (netstackid_t)(uintptr_t)kp->ks_private; 783721fffe3SKacheong Poon netstack_t *ns; 784721fffe3SKacheong Poon tcp_stack_t *tcps; 785721fffe3SKacheong Poon tcp_stat_t *stats; 786721fffe3SKacheong Poon int i; 787721fffe3SKacheong Poon int cnt; 788721fffe3SKacheong Poon 789721fffe3SKacheong Poon if (rw == KSTAT_WRITE) 790721fffe3SKacheong Poon return (EACCES); 791721fffe3SKacheong Poon 792721fffe3SKacheong Poon ns = netstack_find_by_stackid(stackid); 793721fffe3SKacheong Poon if (ns == NULL) 794721fffe3SKacheong Poon return (-1); 795721fffe3SKacheong Poon tcps = ns->netstack_tcp; 796721fffe3SKacheong Poon if (tcps == NULL) { 797721fffe3SKacheong Poon netstack_rele(ns); 798721fffe3SKacheong Poon return (-1); 799721fffe3SKacheong Poon } 800721fffe3SKacheong Poon 801721fffe3SKacheong Poon stats = (tcp_stat_t *)kp->ks_data; 802721fffe3SKacheong Poon tcp_clr_stats(stats); 803721fffe3SKacheong Poon 804721fffe3SKacheong Poon /* 805721fffe3SKacheong Poon * tcps_sc_cnt may change in the middle of the loop. It is better 806721fffe3SKacheong Poon * to get its value first. 807721fffe3SKacheong Poon */ 808721fffe3SKacheong Poon cnt = tcps->tcps_sc_cnt; 809721fffe3SKacheong Poon for (i = 0; i < cnt; i++) 8105dd46ab5SKacheong Poon tcp_add_stats(&tcps->tcps_sc[i]->tcp_sc_stats, stats); 811721fffe3SKacheong Poon 812721fffe3SKacheong Poon netstack_rele(ns); 813721fffe3SKacheong Poon return (0); 814721fffe3SKacheong Poon } 815721fffe3SKacheong Poon 816721fffe3SKacheong Poon /* 8175dd46ab5SKacheong Poon * To add stats from one mib2_tcp_t to another. Static fields are not added. 818721fffe3SKacheong Poon * The caller should set them up propertly. 819721fffe3SKacheong Poon */ 820ca3c8f41SDavid Höppner static void 8215dd46ab5SKacheong Poon tcp_add_mib(mib2_tcp_t *from, mib2_tcp_t *to) 822721fffe3SKacheong Poon { 823721fffe3SKacheong Poon to->tcpActiveOpens += from->tcpActiveOpens; 824721fffe3SKacheong Poon to->tcpPassiveOpens += from->tcpPassiveOpens; 825721fffe3SKacheong Poon to->tcpAttemptFails += from->tcpAttemptFails; 826721fffe3SKacheong Poon to->tcpEstabResets += from->tcpEstabResets; 827721fffe3SKacheong Poon to->tcpInSegs += from->tcpInSegs; 828721fffe3SKacheong Poon to->tcpOutSegs += from->tcpOutSegs; 829721fffe3SKacheong Poon to->tcpRetransSegs += from->tcpRetransSegs; 830721fffe3SKacheong Poon to->tcpOutRsts += from->tcpOutRsts; 831721fffe3SKacheong Poon 832721fffe3SKacheong Poon to->tcpOutDataSegs += from->tcpOutDataSegs; 833721fffe3SKacheong Poon to->tcpOutDataBytes += from->tcpOutDataBytes; 834721fffe3SKacheong Poon to->tcpRetransBytes += from->tcpRetransBytes; 835721fffe3SKacheong Poon to->tcpOutAck += from->tcpOutAck; 836721fffe3SKacheong Poon to->tcpOutAckDelayed += from->tcpOutAckDelayed; 837721fffe3SKacheong Poon to->tcpOutUrg += from->tcpOutUrg; 838721fffe3SKacheong Poon to->tcpOutWinUpdate += from->tcpOutWinUpdate; 839721fffe3SKacheong Poon to->tcpOutWinProbe += from->tcpOutWinProbe; 840721fffe3SKacheong Poon to->tcpOutControl += from->tcpOutControl; 841721fffe3SKacheong Poon to->tcpOutFastRetrans += from->tcpOutFastRetrans; 842721fffe3SKacheong Poon 843721fffe3SKacheong Poon to->tcpInAckBytes += from->tcpInAckBytes; 844721fffe3SKacheong Poon to->tcpInDupAck += from->tcpInDupAck; 845721fffe3SKacheong Poon to->tcpInAckUnsent += from->tcpInAckUnsent; 846721fffe3SKacheong Poon to->tcpInDataInorderSegs += from->tcpInDataInorderSegs; 847721fffe3SKacheong Poon to->tcpInDataInorderBytes += from->tcpInDataInorderBytes; 848721fffe3SKacheong Poon to->tcpInDataUnorderSegs += from->tcpInDataUnorderSegs; 849721fffe3SKacheong Poon to->tcpInDataUnorderBytes += from->tcpInDataUnorderBytes; 850721fffe3SKacheong Poon to->tcpInDataDupSegs += from->tcpInDataDupSegs; 851721fffe3SKacheong Poon to->tcpInDataDupBytes += from->tcpInDataDupBytes; 852721fffe3SKacheong Poon to->tcpInDataPartDupSegs += from->tcpInDataPartDupSegs; 853721fffe3SKacheong Poon to->tcpInDataPartDupBytes += from->tcpInDataPartDupBytes; 854721fffe3SKacheong Poon to->tcpInDataPastWinSegs += from->tcpInDataPastWinSegs; 855721fffe3SKacheong Poon to->tcpInDataPastWinBytes += from->tcpInDataPastWinBytes; 856721fffe3SKacheong Poon to->tcpInWinProbe += from->tcpInWinProbe; 857721fffe3SKacheong Poon to->tcpInWinUpdate += from->tcpInWinUpdate; 858721fffe3SKacheong Poon to->tcpInClosed += from->tcpInClosed; 859721fffe3SKacheong Poon 860721fffe3SKacheong Poon to->tcpRttNoUpdate += from->tcpRttNoUpdate; 861721fffe3SKacheong Poon to->tcpRttUpdate += from->tcpRttUpdate; 862721fffe3SKacheong Poon to->tcpTimRetrans += from->tcpTimRetrans; 863721fffe3SKacheong Poon to->tcpTimRetransDrop += from->tcpTimRetransDrop; 864721fffe3SKacheong Poon to->tcpTimKeepalive += from->tcpTimKeepalive; 865721fffe3SKacheong Poon to->tcpTimKeepaliveProbe += from->tcpTimKeepaliveProbe; 866721fffe3SKacheong Poon to->tcpTimKeepaliveDrop += from->tcpTimKeepaliveDrop; 867721fffe3SKacheong Poon to->tcpListenDrop += from->tcpListenDrop; 868721fffe3SKacheong Poon to->tcpListenDropQ0 += from->tcpListenDropQ0; 869721fffe3SKacheong Poon to->tcpHalfOpenDrop += from->tcpHalfOpenDrop; 870721fffe3SKacheong Poon to->tcpOutSackRetransSegs += from->tcpOutSackRetransSegs; 871721fffe3SKacheong Poon to->tcpHCInSegs += from->tcpHCInSegs; 872721fffe3SKacheong Poon to->tcpHCOutSegs += from->tcpHCOutSegs; 873721fffe3SKacheong Poon } 874721fffe3SKacheong Poon 875721fffe3SKacheong Poon /* 876721fffe3SKacheong Poon * To sum up all MIB2 stats for a tcp_stack_t from all per CPU stats. The 877721fffe3SKacheong Poon * caller should initialize the target mib2_tcp_t properly as this function 878721fffe3SKacheong Poon * just adds up all the per CPU stats. 879721fffe3SKacheong Poon */ 880721fffe3SKacheong Poon static void 881721fffe3SKacheong Poon tcp_sum_mib(tcp_stack_t *tcps, mib2_tcp_t *tcp_mib) 882721fffe3SKacheong Poon { 883721fffe3SKacheong Poon int i; 884721fffe3SKacheong Poon int cnt; 885721fffe3SKacheong Poon 886721fffe3SKacheong Poon /* 887721fffe3SKacheong Poon * tcps_sc_cnt may change in the middle of the loop. It is better 888721fffe3SKacheong Poon * to get its value first. 889721fffe3SKacheong Poon */ 890721fffe3SKacheong Poon cnt = tcps->tcps_sc_cnt; 891721fffe3SKacheong Poon for (i = 0; i < cnt; i++) 8925dd46ab5SKacheong Poon tcp_add_mib(&tcps->tcps_sc[i]->tcp_sc_mib, tcp_mib); 893721fffe3SKacheong Poon } 894721fffe3SKacheong Poon 895721fffe3SKacheong Poon /* 896721fffe3SKacheong Poon * To set all tcp_stat_t counters to 0. 897721fffe3SKacheong Poon */ 8985dd46ab5SKacheong Poon static void 899721fffe3SKacheong Poon tcp_clr_stats(tcp_stat_t *stats) 900721fffe3SKacheong Poon { 901721fffe3SKacheong Poon stats->tcp_time_wait_syn_success.value.ui64 = 0; 902721fffe3SKacheong Poon stats->tcp_clean_death_nondetached.value.ui64 = 0; 903721fffe3SKacheong Poon stats->tcp_eager_blowoff_q.value.ui64 = 0; 904721fffe3SKacheong Poon stats->tcp_eager_blowoff_q0.value.ui64 = 0; 905721fffe3SKacheong Poon stats->tcp_no_listener.value.ui64 = 0; 906721fffe3SKacheong Poon stats->tcp_listendrop.value.ui64 = 0; 907721fffe3SKacheong Poon stats->tcp_listendropq0.value.ui64 = 0; 908721fffe3SKacheong Poon stats->tcp_wsrv_called.value.ui64 = 0; 909721fffe3SKacheong Poon stats->tcp_flwctl_on.value.ui64 = 0; 910721fffe3SKacheong Poon stats->tcp_timer_fire_early.value.ui64 = 0; 911721fffe3SKacheong Poon stats->tcp_timer_fire_miss.value.ui64 = 0; 912721fffe3SKacheong Poon stats->tcp_zcopy_on.value.ui64 = 0; 913721fffe3SKacheong Poon stats->tcp_zcopy_off.value.ui64 = 0; 914721fffe3SKacheong Poon stats->tcp_zcopy_backoff.value.ui64 = 0; 915721fffe3SKacheong Poon stats->tcp_fusion_flowctl.value.ui64 = 0; 916721fffe3SKacheong Poon stats->tcp_fusion_backenabled.value.ui64 = 0; 917721fffe3SKacheong Poon stats->tcp_fusion_urg.value.ui64 = 0; 918721fffe3SKacheong Poon stats->tcp_fusion_putnext.value.ui64 = 0; 919721fffe3SKacheong Poon stats->tcp_fusion_unfusable.value.ui64 = 0; 920721fffe3SKacheong Poon stats->tcp_fusion_aborted.value.ui64 = 0; 921721fffe3SKacheong Poon stats->tcp_fusion_unqualified.value.ui64 = 0; 922721fffe3SKacheong Poon stats->tcp_fusion_rrw_busy.value.ui64 = 0; 923721fffe3SKacheong Poon stats->tcp_fusion_rrw_msgcnt.value.ui64 = 0; 924721fffe3SKacheong Poon stats->tcp_fusion_rrw_plugged.value.ui64 = 0; 925721fffe3SKacheong Poon stats->tcp_in_ack_unsent_drop.value.ui64 = 0; 926721fffe3SKacheong Poon stats->tcp_sock_fallback.value.ui64 = 0; 927721fffe3SKacheong Poon stats->tcp_lso_enabled.value.ui64 = 0; 928721fffe3SKacheong Poon stats->tcp_lso_disabled.value.ui64 = 0; 929721fffe3SKacheong Poon stats->tcp_lso_times.value.ui64 = 0; 930721fffe3SKacheong Poon stats->tcp_lso_pkt_out.value.ui64 = 0; 931721fffe3SKacheong Poon stats->tcp_listen_cnt_drop.value.ui64 = 0; 932721fffe3SKacheong Poon stats->tcp_listen_mem_drop.value.ui64 = 0; 933721fffe3SKacheong Poon stats->tcp_zwin_mem_drop.value.ui64 = 0; 934721fffe3SKacheong Poon stats->tcp_zwin_ack_syn.value.ui64 = 0; 935721fffe3SKacheong Poon stats->tcp_rst_unsent.value.ui64 = 0; 936721fffe3SKacheong Poon stats->tcp_reclaim_cnt.value.ui64 = 0; 937721fffe3SKacheong Poon stats->tcp_reass_timeout.value.ui64 = 0; 938721fffe3SKacheong Poon 939721fffe3SKacheong Poon #ifdef TCP_DEBUG_COUNTER 940721fffe3SKacheong Poon stats->tcp_time_wait.value.ui64 = 0; 941721fffe3SKacheong Poon stats->tcp_rput_time_wait.value.ui64 = 0; 942721fffe3SKacheong Poon stats->tcp_detach_time_wait.value.ui64 = 0; 943721fffe3SKacheong Poon stats->tcp_timeout_calls.value.ui64 = 0; 944721fffe3SKacheong Poon stats->tcp_timeout_cached_alloc.value.ui64 = 0; 945721fffe3SKacheong Poon stats->tcp_timeout_cancel_reqs.value.ui64 = 0; 946721fffe3SKacheong Poon stats->tcp_timeout_canceled.value.ui64 = 0; 947721fffe3SKacheong Poon stats->tcp_timermp_freed.value.ui64 = 0; 948721fffe3SKacheong Poon stats->tcp_push_timer_cnt.value.ui64 = 0; 949721fffe3SKacheong Poon stats->tcp_ack_timer_cnt.value.ui64 = 0; 950721fffe3SKacheong Poon #endif 951721fffe3SKacheong Poon } 952721fffe3SKacheong Poon 953721fffe3SKacheong Poon /* 9545dd46ab5SKacheong Poon * To add counters from the per CPU tcp_stat_counter_t to the stack 9555dd46ab5SKacheong Poon * tcp_stat_t. 956721fffe3SKacheong Poon */ 9575dd46ab5SKacheong Poon static void 9585dd46ab5SKacheong Poon tcp_add_stats(tcp_stat_counter_t *from, tcp_stat_t *to) 959721fffe3SKacheong Poon { 960721fffe3SKacheong Poon to->tcp_time_wait_syn_success.value.ui64 += 9615dd46ab5SKacheong Poon from->tcp_time_wait_syn_success; 962721fffe3SKacheong Poon to->tcp_clean_death_nondetached.value.ui64 += 9635dd46ab5SKacheong Poon from->tcp_clean_death_nondetached; 964721fffe3SKacheong Poon to->tcp_eager_blowoff_q.value.ui64 += 9655dd46ab5SKacheong Poon from->tcp_eager_blowoff_q; 966721fffe3SKacheong Poon to->tcp_eager_blowoff_q0.value.ui64 += 9675dd46ab5SKacheong Poon from->tcp_eager_blowoff_q0; 968721fffe3SKacheong Poon to->tcp_no_listener.value.ui64 += 9695dd46ab5SKacheong Poon from->tcp_no_listener; 970721fffe3SKacheong Poon to->tcp_listendrop.value.ui64 += 9715dd46ab5SKacheong Poon from->tcp_listendrop; 972721fffe3SKacheong Poon to->tcp_listendropq0.value.ui64 += 9735dd46ab5SKacheong Poon from->tcp_listendropq0; 974721fffe3SKacheong Poon to->tcp_wsrv_called.value.ui64 += 9755dd46ab5SKacheong Poon from->tcp_wsrv_called; 976721fffe3SKacheong Poon to->tcp_flwctl_on.value.ui64 += 9775dd46ab5SKacheong Poon from->tcp_flwctl_on; 978721fffe3SKacheong Poon to->tcp_timer_fire_early.value.ui64 += 9795dd46ab5SKacheong Poon from->tcp_timer_fire_early; 980721fffe3SKacheong Poon to->tcp_timer_fire_miss.value.ui64 += 9815dd46ab5SKacheong Poon from->tcp_timer_fire_miss; 982721fffe3SKacheong Poon to->tcp_zcopy_on.value.ui64 += 9835dd46ab5SKacheong Poon from->tcp_zcopy_on; 984721fffe3SKacheong Poon to->tcp_zcopy_off.value.ui64 += 9855dd46ab5SKacheong Poon from->tcp_zcopy_off; 986721fffe3SKacheong Poon to->tcp_zcopy_backoff.value.ui64 += 9875dd46ab5SKacheong Poon from->tcp_zcopy_backoff; 988721fffe3SKacheong Poon to->tcp_fusion_flowctl.value.ui64 += 9895dd46ab5SKacheong Poon from->tcp_fusion_flowctl; 990721fffe3SKacheong Poon to->tcp_fusion_backenabled.value.ui64 += 9915dd46ab5SKacheong Poon from->tcp_fusion_backenabled; 992721fffe3SKacheong Poon to->tcp_fusion_urg.value.ui64 += 9935dd46ab5SKacheong Poon from->tcp_fusion_urg; 994721fffe3SKacheong Poon to->tcp_fusion_putnext.value.ui64 += 9955dd46ab5SKacheong Poon from->tcp_fusion_putnext; 996721fffe3SKacheong Poon to->tcp_fusion_unfusable.value.ui64 += 9975dd46ab5SKacheong Poon from->tcp_fusion_unfusable; 998721fffe3SKacheong Poon to->tcp_fusion_aborted.value.ui64 += 9995dd46ab5SKacheong Poon from->tcp_fusion_aborted; 1000721fffe3SKacheong Poon to->tcp_fusion_unqualified.value.ui64 += 10015dd46ab5SKacheong Poon from->tcp_fusion_unqualified; 1002721fffe3SKacheong Poon to->tcp_fusion_rrw_busy.value.ui64 += 10035dd46ab5SKacheong Poon from->tcp_fusion_rrw_busy; 1004721fffe3SKacheong Poon to->tcp_fusion_rrw_msgcnt.value.ui64 += 10055dd46ab5SKacheong Poon from->tcp_fusion_rrw_msgcnt; 1006721fffe3SKacheong Poon to->tcp_fusion_rrw_plugged.value.ui64 += 10075dd46ab5SKacheong Poon from->tcp_fusion_rrw_plugged; 1008721fffe3SKacheong Poon to->tcp_in_ack_unsent_drop.value.ui64 += 10095dd46ab5SKacheong Poon from->tcp_in_ack_unsent_drop; 1010721fffe3SKacheong Poon to->tcp_sock_fallback.value.ui64 += 10115dd46ab5SKacheong Poon from->tcp_sock_fallback; 1012721fffe3SKacheong Poon to->tcp_lso_enabled.value.ui64 += 10135dd46ab5SKacheong Poon from->tcp_lso_enabled; 1014721fffe3SKacheong Poon to->tcp_lso_disabled.value.ui64 += 10155dd46ab5SKacheong Poon from->tcp_lso_disabled; 1016721fffe3SKacheong Poon to->tcp_lso_times.value.ui64 += 10175dd46ab5SKacheong Poon from->tcp_lso_times; 1018721fffe3SKacheong Poon to->tcp_lso_pkt_out.value.ui64 += 10195dd46ab5SKacheong Poon from->tcp_lso_pkt_out; 1020721fffe3SKacheong Poon to->tcp_listen_cnt_drop.value.ui64 += 10215dd46ab5SKacheong Poon from->tcp_listen_cnt_drop; 1022721fffe3SKacheong Poon to->tcp_listen_mem_drop.value.ui64 += 10235dd46ab5SKacheong Poon from->tcp_listen_mem_drop; 1024721fffe3SKacheong Poon to->tcp_zwin_mem_drop.value.ui64 += 10255dd46ab5SKacheong Poon from->tcp_zwin_mem_drop; 1026721fffe3SKacheong Poon to->tcp_zwin_ack_syn.value.ui64 += 10275dd46ab5SKacheong Poon from->tcp_zwin_ack_syn; 1028721fffe3SKacheong Poon to->tcp_rst_unsent.value.ui64 += 10295dd46ab5SKacheong Poon from->tcp_rst_unsent; 1030721fffe3SKacheong Poon to->tcp_reclaim_cnt.value.ui64 += 10315dd46ab5SKacheong Poon from->tcp_reclaim_cnt; 1032721fffe3SKacheong Poon to->tcp_reass_timeout.value.ui64 += 10335dd46ab5SKacheong Poon from->tcp_reass_timeout; 1034721fffe3SKacheong Poon 1035721fffe3SKacheong Poon #ifdef TCP_DEBUG_COUNTER 1036721fffe3SKacheong Poon to->tcp_time_wait.value.ui64 += 10375dd46ab5SKacheong Poon from->tcp_time_wait; 1038721fffe3SKacheong Poon to->tcp_rput_time_wait.value.ui64 += 10395dd46ab5SKacheong Poon from->tcp_rput_time_wait; 1040721fffe3SKacheong Poon to->tcp_detach_time_wait.value.ui64 += 10415dd46ab5SKacheong Poon from->tcp_detach_time_wait; 1042721fffe3SKacheong Poon to->tcp_timeout_calls.value.ui64 += 10435dd46ab5SKacheong Poon from->tcp_timeout_calls; 1044721fffe3SKacheong Poon to->tcp_timeout_cached_alloc.value.ui64 += 10455dd46ab5SKacheong Poon from->tcp_timeout_cached_alloc; 1046721fffe3SKacheong Poon to->tcp_timeout_cancel_reqs.value.ui64 += 10475dd46ab5SKacheong Poon from->tcp_timeout_cancel_reqs; 1048721fffe3SKacheong Poon to->tcp_timeout_canceled.value.ui64 += 10495dd46ab5SKacheong Poon from->tcp_timeout_canceled; 1050721fffe3SKacheong Poon to->tcp_timermp_freed.value.ui64 += 10515dd46ab5SKacheong Poon from->tcp_timermp_freed; 1052721fffe3SKacheong Poon to->tcp_push_timer_cnt.value.ui64 += 10535dd46ab5SKacheong Poon from->tcp_push_timer_cnt; 1054721fffe3SKacheong Poon to->tcp_ack_timer_cnt.value.ui64 += 10555dd46ab5SKacheong Poon from->tcp_ack_timer_cnt; 1056721fffe3SKacheong Poon #endif 1057721fffe3SKacheong Poon } 1058