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.
244a0bd071SBill Pijewski  * Copyright (c) 2011, Joyent Inc. All rights reserved.
25a2f04351SSebastien Roy  * Copyright (c) 2015, 2016 by Delphix. All rights reserved.
26*78a2e113SAndy Fiddaman  * Copyright 2019 OmniOS Community Edition (OmniOSce) Association.
27721fffe3SKacheong Poon  */
28721fffe3SKacheong Poon 
29721fffe3SKacheong Poon #include <sys/types.h>
30721fffe3SKacheong Poon #include <sys/tihdr.h>
31721fffe3SKacheong Poon #include <sys/policy.h>
32721fffe3SKacheong Poon #include <sys/tsol/tnet.h>
334a0bd071SBill Pijewski #include <sys/kstat.h>
34*78a2e113SAndy Fiddaman #include <sys/stropts.h>
35*78a2e113SAndy Fiddaman #include <sys/strsubr.h>
36*78a2e113SAndy Fiddaman #include <sys/socket.h>
37*78a2e113SAndy Fiddaman #include <sys/socketvar.h>
38721fffe3SKacheong Poon 
39721fffe3SKacheong Poon #include <inet/common.h>
40721fffe3SKacheong Poon #include <inet/ip.h>
41721fffe3SKacheong Poon #include <inet/tcp.h>
42721fffe3SKacheong Poon #include <inet/tcp_impl.h>
43721fffe3SKacheong Poon #include <inet/tcp_stats.h>
44721fffe3SKacheong Poon #include <inet/kstatcom.h>
45721fffe3SKacheong Poon #include <inet/snmpcom.h>
46721fffe3SKacheong Poon 
47ca3c8f41SDavid Höppner static int	tcp_kstat_update(kstat_t *, int);
48ca3c8f41SDavid Höppner static int	tcp_kstat2_update(kstat_t *, int);
49721fffe3SKacheong Poon static void	tcp_sum_mib(tcp_stack_t *, mib2_tcp_t *);
50721fffe3SKacheong Poon 
515dd46ab5SKacheong Poon static void	tcp_add_mib(mib2_tcp_t *, mib2_tcp_t *);
525dd46ab5SKacheong Poon static void	tcp_add_stats(tcp_stat_counter_t *, tcp_stat_t *);
53721fffe3SKacheong Poon static void	tcp_clr_stats(tcp_stat_t *);
54721fffe3SKacheong Poon 
55721fffe3SKacheong Poon tcp_g_stat_t	tcp_g_statistics;
56721fffe3SKacheong Poon kstat_t		*tcp_g_kstat;
57721fffe3SKacheong Poon 
58721fffe3SKacheong Poon /* Translate TCP state to MIB2 TCP state. */
59721fffe3SKacheong Poon static int
tcp_snmp_state(tcp_t * tcp)60721fffe3SKacheong Poon tcp_snmp_state(tcp_t *tcp)
61721fffe3SKacheong Poon {
62721fffe3SKacheong Poon 	if (tcp == NULL)
63721fffe3SKacheong Poon 		return (0);
64721fffe3SKacheong Poon 
65721fffe3SKacheong Poon 	switch (tcp->tcp_state) {
66721fffe3SKacheong Poon 	case TCPS_CLOSED:
67721fffe3SKacheong Poon 	case TCPS_IDLE:	/* RFC1213 doesn't have analogue for IDLE & BOUND */
68721fffe3SKacheong Poon 	case TCPS_BOUND:
69721fffe3SKacheong Poon 		return (MIB2_TCP_closed);
70721fffe3SKacheong Poon 	case TCPS_LISTEN:
71721fffe3SKacheong Poon 		return (MIB2_TCP_listen);
72721fffe3SKacheong Poon 	case TCPS_SYN_SENT:
73721fffe3SKacheong Poon 		return (MIB2_TCP_synSent);
74721fffe3SKacheong Poon 	case TCPS_SYN_RCVD:
75721fffe3SKacheong Poon 		return (MIB2_TCP_synReceived);
76721fffe3SKacheong Poon 	case TCPS_ESTABLISHED:
77721fffe3SKacheong Poon 		return (MIB2_TCP_established);
78721fffe3SKacheong Poon 	case TCPS_CLOSE_WAIT:
79721fffe3SKacheong Poon 		return (MIB2_TCP_closeWait);
80721fffe3SKacheong Poon 	case TCPS_FIN_WAIT_1:
81721fffe3SKacheong Poon 		return (MIB2_TCP_finWait1);
82721fffe3SKacheong Poon 	case TCPS_CLOSING:
83721fffe3SKacheong Poon 		return (MIB2_TCP_closing);
84721fffe3SKacheong Poon 	case TCPS_LAST_ACK:
85721fffe3SKacheong Poon 		return (MIB2_TCP_lastAck);
86721fffe3SKacheong Poon 	case TCPS_FIN_WAIT_2:
87721fffe3SKacheong Poon 		return (MIB2_TCP_finWait2);
88721fffe3SKacheong Poon 	case TCPS_TIME_WAIT:
89721fffe3SKacheong Poon 		return (MIB2_TCP_timeWait);
90721fffe3SKacheong Poon 	default:
91721fffe3SKacheong Poon 		return (0);
92721fffe3SKacheong Poon 	}
93721fffe3SKacheong Poon }
94721fffe3SKacheong Poon 
95a2f04351SSebastien Roy static void
tcp_set_conninfo(tcp_t * tcp,struct tcpConnEntryInfo_s * tcei,boolean_t ispriv)96a2f04351SSebastien Roy tcp_set_conninfo(tcp_t *tcp, struct tcpConnEntryInfo_s *tcei, boolean_t ispriv)
97a2f04351SSebastien Roy {
98a2f04351SSebastien Roy 	/* Don't want just anybody seeing these... */
99a2f04351SSebastien Roy 	if (ispriv) {
100a2f04351SSebastien Roy 		tcei->ce_snxt = tcp->tcp_snxt;
101a2f04351SSebastien Roy 		tcei->ce_suna = tcp->tcp_suna;
102a2f04351SSebastien Roy 		tcei->ce_rnxt = tcp->tcp_rnxt;
103a2f04351SSebastien Roy 		tcei->ce_rack = tcp->tcp_rack;
104a2f04351SSebastien Roy 	} else {
105a2f04351SSebastien Roy 		/*
106a2f04351SSebastien Roy 		 * Netstat, unfortunately, uses this to get send/receive queue
107a2f04351SSebastien Roy 		 * sizes.  How to fix? Why not compute the difference only?
108a2f04351SSebastien Roy 		 */
109a2f04351SSebastien Roy 		tcei->ce_snxt = tcp->tcp_snxt - tcp->tcp_suna;
110a2f04351SSebastien Roy 		tcei->ce_suna = 0;
111a2f04351SSebastien Roy 		tcei->ce_rnxt = tcp->tcp_rnxt - tcp->tcp_rack;
112a2f04351SSebastien Roy 		tcei->ce_rack = 0;
113a2f04351SSebastien Roy 	}
114a2f04351SSebastien Roy 
115a2f04351SSebastien Roy 	tcei->ce_in_data_inorder_bytes = tcp->tcp_cs.tcp_in_data_inorder_bytes;
116a2f04351SSebastien Roy 	tcei->ce_in_data_inorder_segs = tcp->tcp_cs.tcp_in_data_inorder_segs;
117a2f04351SSebastien Roy 	tcei->ce_in_data_unorder_bytes = tcp->tcp_cs.tcp_in_data_unorder_bytes;
118a2f04351SSebastien Roy 	tcei->ce_in_data_unorder_segs = tcp->tcp_cs.tcp_in_data_unorder_segs;
119a2f04351SSebastien Roy 	tcei->ce_in_zwnd_probes = tcp->tcp_cs.tcp_in_zwnd_probes;
120a2f04351SSebastien Roy 
121a2f04351SSebastien Roy 	tcei->ce_out_data_bytes = tcp->tcp_cs.tcp_out_data_bytes;
122a2f04351SSebastien Roy 	tcei->ce_out_data_segs = tcp->tcp_cs.tcp_out_data_segs;
123a2f04351SSebastien Roy 	tcei->ce_out_retrans_bytes = tcp->tcp_cs.tcp_out_retrans_bytes;
124a2f04351SSebastien Roy 	tcei->ce_out_retrans_segs = tcp->tcp_cs.tcp_out_retrans_segs;
125a2f04351SSebastien Roy 	tcei->ce_out_zwnd_probes = tcp->tcp_cs.tcp_out_zwnd_probes;
126a2f04351SSebastien Roy 
127a2f04351SSebastien Roy 	tcei->ce_unsent = tcp->tcp_unsent;
128a2f04351SSebastien Roy 	tcei->ce_swnd = tcp->tcp_swnd;
129a2f04351SSebastien Roy 	tcei->ce_cwnd = tcp->tcp_cwnd;
130a2f04351SSebastien Roy 	tcei->ce_rwnd = tcp->tcp_rwnd;
131a2f04351SSebastien Roy 	tcei->ce_rto =  tcp->tcp_rto;
132a2f04351SSebastien Roy 	tcei->ce_mss =  tcp->tcp_mss;
133a2f04351SSebastien Roy 	tcei->ce_state = tcp->tcp_state;
134a2f04351SSebastien Roy 	tcei->ce_rtt_sa = NSEC2USEC(tcp->tcp_rtt_sa >> 3);
135a2f04351SSebastien Roy 	tcei->ce_rtt_sum = NSEC2USEC(tcp->tcp_rtt_sum);
136a2f04351SSebastien Roy 	tcei->ce_rtt_cnt = tcp->tcp_rtt_cnt;
137a2f04351SSebastien Roy }
138a2f04351SSebastien Roy 
139721fffe3SKacheong Poon /*
140721fffe3SKacheong Poon  * Return SNMP stuff in buffer in mpdata.
141721fffe3SKacheong Poon  */
142721fffe3SKacheong Poon mblk_t *
tcp_snmp_get(queue_t * q,mblk_t * mpctl,boolean_t legacy_req)1436f773e29SBaban Kenkre tcp_snmp_get(queue_t *q, mblk_t *mpctl, boolean_t legacy_req)
144721fffe3SKacheong Poon {
145721fffe3SKacheong Poon 	mblk_t			*mpdata;
146721fffe3SKacheong Poon 	mblk_t			*mp_conn_ctl = NULL;
147721fffe3SKacheong Poon 	mblk_t			*mp_conn_tail;
148721fffe3SKacheong Poon 	mblk_t			*mp_attr_ctl = NULL;
149721fffe3SKacheong Poon 	mblk_t			*mp_attr_tail;
150*78a2e113SAndy Fiddaman 	mblk_t			*mp_info_ctl = NULL;
151*78a2e113SAndy Fiddaman 	mblk_t			*mp_info_tail;
152721fffe3SKacheong Poon 	mblk_t			*mp6_conn_ctl = NULL;
153721fffe3SKacheong Poon 	mblk_t			*mp6_conn_tail;
154721fffe3SKacheong Poon 	mblk_t			*mp6_attr_ctl = NULL;
155721fffe3SKacheong Poon 	mblk_t			*mp6_attr_tail;
156*78a2e113SAndy Fiddaman 	mblk_t			*mp6_info_ctl = NULL;
157*78a2e113SAndy Fiddaman 	mblk_t			*mp6_info_tail;
158721fffe3SKacheong Poon 	struct opthdr		*optp;
159721fffe3SKacheong Poon 	mib2_tcpConnEntry_t	tce;
160721fffe3SKacheong Poon 	mib2_tcp6ConnEntry_t	tce6;
161721fffe3SKacheong Poon 	mib2_transportMLPEntry_t mlp;
162*78a2e113SAndy Fiddaman 	mib2_socketInfoEntry_t	*sie, psie;
163721fffe3SKacheong Poon 	connf_t			*connfp;
164721fffe3SKacheong Poon 	int			i;
165*78a2e113SAndy Fiddaman 	boolean_t		ispriv;
166*78a2e113SAndy Fiddaman 	zoneid_t		zoneid;
167721fffe3SKacheong Poon 	int			v4_conn_idx;
168721fffe3SKacheong Poon 	int			v6_conn_idx;
169721fffe3SKacheong Poon 	conn_t			*connp = Q_TO_CONN(q);
170721fffe3SKacheong Poon 	tcp_stack_t		*tcps;
171721fffe3SKacheong Poon 	ip_stack_t		*ipst;
172721fffe3SKacheong Poon 	mblk_t			*mp2ctl;
173721fffe3SKacheong Poon 	mib2_tcp_t		tcp_mib;
1746f773e29SBaban Kenkre 	size_t			tcp_mib_size, tce_size, tce6_size;
175721fffe3SKacheong Poon 
176721fffe3SKacheong Poon 	/*
177721fffe3SKacheong Poon 	 * make a copy of the original message
178721fffe3SKacheong Poon 	 */
179721fffe3SKacheong Poon 	mp2ctl = copymsg(mpctl);
180721fffe3SKacheong Poon 
181721fffe3SKacheong Poon 	if (mpctl == NULL ||
182721fffe3SKacheong Poon 	    (mpdata = mpctl->b_cont) == NULL ||
183721fffe3SKacheong Poon 	    (mp_conn_ctl = copymsg(mpctl)) == NULL ||
184721fffe3SKacheong Poon 	    (mp_attr_ctl = copymsg(mpctl)) == NULL ||
185*78a2e113SAndy Fiddaman 	    (mp_info_ctl = copymsg(mpctl)) == NULL ||
186721fffe3SKacheong Poon 	    (mp6_conn_ctl = copymsg(mpctl)) == NULL ||
187*78a2e113SAndy Fiddaman 	    (mp6_attr_ctl = copymsg(mpctl)) == NULL ||
188*78a2e113SAndy Fiddaman 	    (mp6_info_ctl = copymsg(mpctl)) == NULL) {
189721fffe3SKacheong Poon 		freemsg(mp_conn_ctl);
190721fffe3SKacheong Poon 		freemsg(mp_attr_ctl);
191*78a2e113SAndy Fiddaman 		freemsg(mp_info_ctl);
192721fffe3SKacheong Poon 		freemsg(mp6_conn_ctl);
193721fffe3SKacheong Poon 		freemsg(mp6_attr_ctl);
194*78a2e113SAndy Fiddaman 		freemsg(mp6_info_ctl);
195721fffe3SKacheong Poon 		freemsg(mpctl);
196721fffe3SKacheong Poon 		freemsg(mp2ctl);
197721fffe3SKacheong Poon 		return (NULL);
198721fffe3SKacheong Poon 	}
199721fffe3SKacheong Poon 
200721fffe3SKacheong Poon 	ipst = connp->conn_netstack->netstack_ip;
201721fffe3SKacheong Poon 	tcps = connp->conn_netstack->netstack_tcp;
202721fffe3SKacheong Poon 
2036f773e29SBaban Kenkre 	if (legacy_req) {
2046f773e29SBaban Kenkre 		tcp_mib_size = LEGACY_MIB_SIZE(&tcp_mib, mib2_tcp_t);
2056f773e29SBaban Kenkre 		tce_size = LEGACY_MIB_SIZE(&tce, mib2_tcpConnEntry_t);
2066f773e29SBaban Kenkre 		tce6_size = LEGACY_MIB_SIZE(&tce6, mib2_tcp6ConnEntry_t);
2076f773e29SBaban Kenkre 	} else {
2086f773e29SBaban Kenkre 		tcp_mib_size = sizeof (mib2_tcp_t);
2096f773e29SBaban Kenkre 		tce_size = sizeof (mib2_tcpConnEntry_t);
2106f773e29SBaban Kenkre 		tce6_size = sizeof (mib2_tcp6ConnEntry_t);
2116f773e29SBaban Kenkre 	}
2126f773e29SBaban Kenkre 
213721fffe3SKacheong Poon 	bzero(&tcp_mib, sizeof (tcp_mib));
214721fffe3SKacheong Poon 
215721fffe3SKacheong Poon 	/* build table of connections -- need count in fixed part */
216721fffe3SKacheong Poon 	SET_MIB(tcp_mib.tcpRtoAlgorithm, 4);   /* vanj */
217721fffe3SKacheong Poon 	SET_MIB(tcp_mib.tcpRtoMin, tcps->tcps_rexmit_interval_min);
218721fffe3SKacheong Poon 	SET_MIB(tcp_mib.tcpRtoMax, tcps->tcps_rexmit_interval_max);
219721fffe3SKacheong Poon 	SET_MIB(tcp_mib.tcpMaxConn, -1);
220721fffe3SKacheong Poon 	SET_MIB(tcp_mib.tcpCurrEstab, 0);
221721fffe3SKacheong Poon 
222721fffe3SKacheong Poon 	ispriv =
223721fffe3SKacheong Poon 	    secpolicy_ip_config((Q_TO_CONN(q))->conn_cred, B_TRUE) == 0;
224721fffe3SKacheong Poon 	zoneid = Q_TO_CONN(q)->conn_zoneid;
225721fffe3SKacheong Poon 
226721fffe3SKacheong Poon 	v4_conn_idx = v6_conn_idx = 0;
227721fffe3SKacheong Poon 	mp_conn_tail = mp_attr_tail = mp6_conn_tail = mp6_attr_tail = NULL;
228*78a2e113SAndy Fiddaman 	mp_info_tail = mp6_info_tail = NULL;
229721fffe3SKacheong Poon 
230721fffe3SKacheong Poon 	for (i = 0; i < CONN_G_HASH_SIZE; i++) {
231721fffe3SKacheong Poon 		ipst = tcps->tcps_netstack->netstack_ip;
232721fffe3SKacheong Poon 
233721fffe3SKacheong Poon 		connfp = &ipst->ips_ipcl_globalhash_fanout[i];
234721fffe3SKacheong Poon 
235721fffe3SKacheong Poon 		connp = NULL;
236721fffe3SKacheong Poon 
237721fffe3SKacheong Poon 		while ((connp =
238721fffe3SKacheong Poon 		    ipcl_get_next_conn(connfp, connp, IPCL_TCPCONN)) != NULL) {
239721fffe3SKacheong Poon 			tcp_t *tcp;
240721fffe3SKacheong Poon 			boolean_t needattr;
241721fffe3SKacheong Poon 
242721fffe3SKacheong Poon 			if (connp->conn_zoneid != zoneid)
243721fffe3SKacheong Poon 				continue;	/* not in this zone */
244721fffe3SKacheong Poon 
245721fffe3SKacheong Poon 			tcp = connp->conn_tcp;
246721fffe3SKacheong Poon 			tce6.tcp6ConnState = tce.tcpConnState =
247721fffe3SKacheong Poon 			    tcp_snmp_state(tcp);
248721fffe3SKacheong Poon 			if (tce.tcpConnState == MIB2_TCP_established ||
249721fffe3SKacheong Poon 			    tce.tcpConnState == MIB2_TCP_closeWait)
25047b75f87SKacheong Poon 				BUMP_MIB(&tcp_mib, tcpCurrEstab);
251721fffe3SKacheong Poon 
252721fffe3SKacheong Poon 			needattr = B_FALSE;
253721fffe3SKacheong Poon 			bzero(&mlp, sizeof (mlp));
254721fffe3SKacheong Poon 			if (connp->conn_mlp_type != mlptSingle) {
255721fffe3SKacheong Poon 				if (connp->conn_mlp_type == mlptShared ||
256721fffe3SKacheong Poon 				    connp->conn_mlp_type == mlptBoth)
257721fffe3SKacheong Poon 					mlp.tme_flags |= MIB2_TMEF_SHARED;
258721fffe3SKacheong Poon 				if (connp->conn_mlp_type == mlptPrivate ||
259721fffe3SKacheong Poon 				    connp->conn_mlp_type == mlptBoth)
260721fffe3SKacheong Poon 					mlp.tme_flags |= MIB2_TMEF_PRIVATE;
261721fffe3SKacheong Poon 				needattr = B_TRUE;
262721fffe3SKacheong Poon 			}
263721fffe3SKacheong Poon 			if (connp->conn_anon_mlp) {
264721fffe3SKacheong Poon 				mlp.tme_flags |= MIB2_TMEF_ANONMLP;
265721fffe3SKacheong Poon 				needattr = B_TRUE;
266721fffe3SKacheong Poon 			}
267721fffe3SKacheong Poon 			switch (connp->conn_mac_mode) {
268721fffe3SKacheong Poon 			case CONN_MAC_DEFAULT:
269721fffe3SKacheong Poon 				break;
270721fffe3SKacheong Poon 			case CONN_MAC_AWARE:
271721fffe3SKacheong Poon 				mlp.tme_flags |= MIB2_TMEF_MACEXEMPT;
272721fffe3SKacheong Poon 				needattr = B_TRUE;
273721fffe3SKacheong Poon 				break;
274721fffe3SKacheong Poon 			case CONN_MAC_IMPLICIT:
275721fffe3SKacheong Poon 				mlp.tme_flags |= MIB2_TMEF_MACIMPLICIT;
276721fffe3SKacheong Poon 				needattr = B_TRUE;
277721fffe3SKacheong Poon 				break;
278721fffe3SKacheong Poon 			}
279721fffe3SKacheong Poon 			if (connp->conn_ixa->ixa_tsl != NULL) {
280721fffe3SKacheong Poon 				ts_label_t *tsl;
281721fffe3SKacheong Poon 
282721fffe3SKacheong Poon 				tsl = connp->conn_ixa->ixa_tsl;
283721fffe3SKacheong Poon 				mlp.tme_flags |= MIB2_TMEF_IS_LABELED;
284721fffe3SKacheong Poon 				mlp.tme_doi = label2doi(tsl);
285721fffe3SKacheong Poon 				mlp.tme_label = *label2bslabel(tsl);
286721fffe3SKacheong Poon 				needattr = B_TRUE;
287721fffe3SKacheong Poon 			}
288721fffe3SKacheong Poon 
289721fffe3SKacheong Poon 			/* Create a message to report on IPv6 entries */
290721fffe3SKacheong Poon 			if (connp->conn_ipversion == IPV6_VERSION) {
291*78a2e113SAndy Fiddaman 				tce6.tcp6ConnLocalAddress =
292*78a2e113SAndy Fiddaman 				    connp->conn_laddr_v6;
293*78a2e113SAndy Fiddaman 				tce6.tcp6ConnRemAddress =
294*78a2e113SAndy Fiddaman 				    connp->conn_faddr_v6;
295*78a2e113SAndy Fiddaman 				tce6.tcp6ConnLocalPort =
296*78a2e113SAndy Fiddaman 				    ntohs(connp->conn_lport);
297*78a2e113SAndy Fiddaman 				tce6.tcp6ConnRemPort =
298*78a2e113SAndy Fiddaman 				    ntohs(connp->conn_fport);
299*78a2e113SAndy Fiddaman 				if (connp->conn_ixa->ixa_flags &
300*78a2e113SAndy Fiddaman 				    IXAF_SCOPEID_SET) {
301*78a2e113SAndy Fiddaman 					tce6.tcp6ConnIfIndex =
302*78a2e113SAndy Fiddaman 					    connp->conn_ixa->ixa_scopeid;
303*78a2e113SAndy Fiddaman 				} else {
304*78a2e113SAndy Fiddaman 					tce6.tcp6ConnIfIndex =
305*78a2e113SAndy Fiddaman 					    connp->conn_bound_if;
306*78a2e113SAndy Fiddaman 				}
307*78a2e113SAndy Fiddaman 
308*78a2e113SAndy Fiddaman 				tcp_set_conninfo(tcp, &tce6.tcp6ConnEntryInfo,
309*78a2e113SAndy Fiddaman 				    ispriv);
310*78a2e113SAndy Fiddaman 
311*78a2e113SAndy Fiddaman 				tce6.tcp6ConnCreationProcess =
312*78a2e113SAndy Fiddaman 				    (connp->conn_cpid < 0) ?
313*78a2e113SAndy Fiddaman 				    MIB2_UNKNOWN_PROCESS : connp->conn_cpid;
314*78a2e113SAndy Fiddaman 				tce6.tcp6ConnCreationTime =
315*78a2e113SAndy Fiddaman 				    connp->conn_open_time;
316721fffe3SKacheong Poon 
317*78a2e113SAndy Fiddaman 				(void) snmp_append_data2(mp6_conn_ctl->b_cont,
318*78a2e113SAndy Fiddaman 				    &mp6_conn_tail, (char *)&tce6, tce6_size);
319721fffe3SKacheong Poon 
320*78a2e113SAndy Fiddaman 				if (needattr) {
321*78a2e113SAndy Fiddaman 					mlp.tme_connidx = v6_conn_idx;
322*78a2e113SAndy Fiddaman 					(void) snmp_append_data2(
323*78a2e113SAndy Fiddaman 					    mp6_attr_ctl->b_cont,
324*78a2e113SAndy Fiddaman 					    &mp6_attr_tail,
325*78a2e113SAndy Fiddaman 					    (char *)&mlp, sizeof (mlp));
326*78a2e113SAndy Fiddaman 				}
327721fffe3SKacheong Poon 
328*78a2e113SAndy Fiddaman 				if ((sie = conn_get_socket_info(connp,
329*78a2e113SAndy Fiddaman 				    &psie)) != NULL) {
330*78a2e113SAndy Fiddaman 					sie->sie_connidx = v6_conn_idx;
331*78a2e113SAndy Fiddaman 					(void) snmp_append_data2(
332*78a2e113SAndy Fiddaman 					    mp6_info_ctl->b_cont,
333*78a2e113SAndy Fiddaman 					    &mp6_info_tail,
334*78a2e113SAndy Fiddaman 					    (char *)sie, sizeof (*sie));
335*78a2e113SAndy Fiddaman 				}
336721fffe3SKacheong Poon 
337*78a2e113SAndy Fiddaman 				v6_conn_idx++;
338721fffe3SKacheong Poon 			}
339*78a2e113SAndy Fiddaman 
340721fffe3SKacheong Poon 			/*
341721fffe3SKacheong Poon 			 * Create an IPv4 table entry for IPv4 entries and also
342721fffe3SKacheong Poon 			 * for IPv6 entries which are bound to in6addr_any
343721fffe3SKacheong Poon 			 * but don't have IPV6_V6ONLY set.
344721fffe3SKacheong Poon 			 * (i.e. anything an IPv4 peer could connect to)
345721fffe3SKacheong Poon 			 */
346721fffe3SKacheong Poon 			if (connp->conn_ipversion == IPV4_VERSION ||
347721fffe3SKacheong Poon 			    (tcp->tcp_state <= TCPS_LISTEN &&
348721fffe3SKacheong Poon 			    !connp->conn_ipv6_v6only &&
349721fffe3SKacheong Poon 			    IN6_IS_ADDR_UNSPECIFIED(&connp->conn_laddr_v6))) {
350721fffe3SKacheong Poon 				if (connp->conn_ipversion == IPV6_VERSION) {
351721fffe3SKacheong Poon 					tce.tcpConnRemAddress = INADDR_ANY;
352721fffe3SKacheong Poon 					tce.tcpConnLocalAddress = INADDR_ANY;
353721fffe3SKacheong Poon 				} else {
354721fffe3SKacheong Poon 					tce.tcpConnRemAddress =
355721fffe3SKacheong Poon 					    connp->conn_faddr_v4;
356721fffe3SKacheong Poon 					tce.tcpConnLocalAddress =
357721fffe3SKacheong Poon 					    connp->conn_laddr_v4;
358721fffe3SKacheong Poon 				}
359721fffe3SKacheong Poon 				tce.tcpConnLocalPort = ntohs(connp->conn_lport);
360721fffe3SKacheong Poon 				tce.tcpConnRemPort = ntohs(connp->conn_fport);
361721fffe3SKacheong Poon 
362a2f04351SSebastien Roy 				tcp_set_conninfo(tcp, &tce.tcpConnEntryInfo,
363a2f04351SSebastien Roy 				    ispriv);
364721fffe3SKacheong Poon 
365721fffe3SKacheong Poon 				tce.tcpConnCreationProcess =
366721fffe3SKacheong Poon 				    (connp->conn_cpid < 0) ?
367721fffe3SKacheong Poon 				    MIB2_UNKNOWN_PROCESS :
368721fffe3SKacheong Poon 				    connp->conn_cpid;
369721fffe3SKacheong Poon 				tce.tcpConnCreationTime = connp->conn_open_time;
370721fffe3SKacheong Poon 
371721fffe3SKacheong Poon 				(void) snmp_append_data2(mp_conn_ctl->b_cont,
3726f773e29SBaban Kenkre 				    &mp_conn_tail, (char *)&tce, tce_size);
373721fffe3SKacheong Poon 
374*78a2e113SAndy Fiddaman 				if (needattr) {
375*78a2e113SAndy Fiddaman 					mlp.tme_connidx = v4_conn_idx;
376721fffe3SKacheong Poon 					(void) snmp_append_data2(
377721fffe3SKacheong Poon 					    mp_attr_ctl->b_cont,
378721fffe3SKacheong Poon 					    &mp_attr_tail, (char *)&mlp,
379721fffe3SKacheong Poon 					    sizeof (mlp));
380*78a2e113SAndy Fiddaman 				}
381*78a2e113SAndy Fiddaman 
382*78a2e113SAndy Fiddaman 				if ((sie = conn_get_socket_info(connp, &psie))
383*78a2e113SAndy Fiddaman 				    != NULL) {
384*78a2e113SAndy Fiddaman 					sie->sie_connidx = v4_conn_idx;
385*78a2e113SAndy Fiddaman 					if (connp->conn_ipversion ==
386*78a2e113SAndy Fiddaman 					    IPV6_VERSION)
387*78a2e113SAndy Fiddaman 						sie->sie_flags |=
388*78a2e113SAndy Fiddaman 						    MIB2_SOCKINFO_IPV6;
389*78a2e113SAndy Fiddaman 					(void) snmp_append_data2(
390*78a2e113SAndy Fiddaman 					    mp_info_ctl->b_cont, &mp_info_tail,
391*78a2e113SAndy Fiddaman 					    (char *)sie, sizeof (*sie));
392*78a2e113SAndy Fiddaman 				}
393*78a2e113SAndy Fiddaman 
394*78a2e113SAndy Fiddaman 				v4_conn_idx++;
395721fffe3SKacheong Poon 			}
396721fffe3SKacheong Poon 		}
397721fffe3SKacheong Poon 	}
398721fffe3SKacheong Poon 
39947b75f87SKacheong Poon 	tcp_sum_mib(tcps, &tcp_mib);
400721fffe3SKacheong Poon 
4016f773e29SBaban Kenkre 	/* Fixed length structure for IPv4 and IPv6 counters */
4026f773e29SBaban Kenkre 	SET_MIB(tcp_mib.tcpConnTableSize, tce_size);
4036f773e29SBaban Kenkre 	SET_MIB(tcp_mib.tcp6ConnTableSize, tce6_size);
4046f773e29SBaban Kenkre 
40547b75f87SKacheong Poon 	/*
40647b75f87SKacheong Poon 	 * Synchronize 32- and 64-bit counters.  Note that tcpInSegs and
40747b75f87SKacheong Poon 	 * tcpOutSegs are not updated anywhere in TCP.  The new 64 bits
40847b75f87SKacheong Poon 	 * counters are used.  Hence the old counters' values in tcp_sc_mib
40947b75f87SKacheong Poon 	 * are always 0.
41047b75f87SKacheong Poon 	 */
411721fffe3SKacheong Poon 	SYNC32_MIB(&tcp_mib, tcpInSegs, tcpHCInSegs);
412721fffe3SKacheong Poon 	SYNC32_MIB(&tcp_mib, tcpOutSegs, tcpHCOutSegs);
413721fffe3SKacheong Poon 
414721fffe3SKacheong Poon 	optp = (struct opthdr *)&mpctl->b_rptr[sizeof (struct T_optmgmt_ack)];
415721fffe3SKacheong Poon 	optp->level = MIB2_TCP;
416721fffe3SKacheong Poon 	optp->name = 0;
4176f773e29SBaban Kenkre 	(void) snmp_append_data(mpdata, (char *)&tcp_mib, tcp_mib_size);
418721fffe3SKacheong Poon 	optp->len = msgdsize(mpdata);
419721fffe3SKacheong Poon 	qreply(q, mpctl);
420721fffe3SKacheong Poon 
421721fffe3SKacheong Poon 	/* table of connections... */
422721fffe3SKacheong Poon 	optp = (struct opthdr *)&mp_conn_ctl->b_rptr[
423721fffe3SKacheong Poon 	    sizeof (struct T_optmgmt_ack)];
424721fffe3SKacheong Poon 	optp->level = MIB2_TCP;
425721fffe3SKacheong Poon 	optp->name = MIB2_TCP_CONN;
426721fffe3SKacheong Poon 	optp->len = msgdsize(mp_conn_ctl->b_cont);
427721fffe3SKacheong Poon 	qreply(q, mp_conn_ctl);
428721fffe3SKacheong Poon 
429721fffe3SKacheong Poon 	/* table of MLP attributes... */
430721fffe3SKacheong Poon 	optp = (struct opthdr *)&mp_attr_ctl->b_rptr[
431721fffe3SKacheong Poon 	    sizeof (struct T_optmgmt_ack)];
432721fffe3SKacheong Poon 	optp->level = MIB2_TCP;
433721fffe3SKacheong Poon 	optp->name = EXPER_XPORT_MLP;
434721fffe3SKacheong Poon 	optp->len = msgdsize(mp_attr_ctl->b_cont);
435721fffe3SKacheong Poon 	if (optp->len == 0)
436721fffe3SKacheong Poon 		freemsg(mp_attr_ctl);
437721fffe3SKacheong Poon 	else
438721fffe3SKacheong Poon 		qreply(q, mp_attr_ctl);
439721fffe3SKacheong Poon 
440*78a2e113SAndy Fiddaman 	/* table of socket info... */
441*78a2e113SAndy Fiddaman 	optp = (struct opthdr *)&mp_info_ctl->b_rptr[
442*78a2e113SAndy Fiddaman 	    sizeof (struct T_optmgmt_ack)];
443*78a2e113SAndy Fiddaman 	optp->level = MIB2_TCP;
444*78a2e113SAndy Fiddaman 	optp->name = EXPER_SOCK_INFO;
445*78a2e113SAndy Fiddaman 	optp->len = msgdsize(mp_info_ctl->b_cont);
446*78a2e113SAndy Fiddaman 	if (optp->len == 0)
447*78a2e113SAndy Fiddaman 		freemsg(mp_info_ctl);
448*78a2e113SAndy Fiddaman 	else
449*78a2e113SAndy Fiddaman 		qreply(q, mp_info_ctl);
450*78a2e113SAndy Fiddaman 
451721fffe3SKacheong Poon 	/* table of IPv6 connections... */
452721fffe3SKacheong Poon 	optp = (struct opthdr *)&mp6_conn_ctl->b_rptr[
453721fffe3SKacheong Poon 	    sizeof (struct T_optmgmt_ack)];
454721fffe3SKacheong Poon 	optp->level = MIB2_TCP6;
455721fffe3SKacheong Poon 	optp->name = MIB2_TCP6_CONN;
456721fffe3SKacheong Poon 	optp->len = msgdsize(mp6_conn_ctl->b_cont);
457721fffe3SKacheong Poon 	qreply(q, mp6_conn_ctl);
458721fffe3SKacheong Poon 
459721fffe3SKacheong Poon 	/* table of IPv6 MLP attributes... */
460721fffe3SKacheong Poon 	optp = (struct opthdr *)&mp6_attr_ctl->b_rptr[
461721fffe3SKacheong Poon 	    sizeof (struct T_optmgmt_ack)];
462721fffe3SKacheong Poon 	optp->level = MIB2_TCP6;
463721fffe3SKacheong Poon 	optp->name = EXPER_XPORT_MLP;
464721fffe3SKacheong Poon 	optp->len = msgdsize(mp6_attr_ctl->b_cont);
465721fffe3SKacheong Poon 	if (optp->len == 0)
466721fffe3SKacheong Poon 		freemsg(mp6_attr_ctl);
467721fffe3SKacheong Poon 	else
468721fffe3SKacheong Poon 		qreply(q, mp6_attr_ctl);
469*78a2e113SAndy Fiddaman 
470*78a2e113SAndy Fiddaman 	/* table of IPv6 socket info.. */
471*78a2e113SAndy Fiddaman 	optp = (struct opthdr *)&mp6_info_ctl->b_rptr[
472*78a2e113SAndy Fiddaman 	    sizeof (struct T_optmgmt_ack)];
473*78a2e113SAndy Fiddaman 	optp->level = MIB2_TCP6;
474*78a2e113SAndy Fiddaman 	optp->name = EXPER_SOCK_INFO;
475*78a2e113SAndy Fiddaman 	optp->len = msgdsize(mp6_info_ctl->b_cont);
476*78a2e113SAndy Fiddaman 	if (optp->len == 0)
477*78a2e113SAndy Fiddaman 		freemsg(mp6_info_ctl);
478*78a2e113SAndy Fiddaman 	else
479*78a2e113SAndy Fiddaman 		qreply(q, mp6_info_ctl);
480*78a2e113SAndy Fiddaman 
481721fffe3SKacheong Poon 	return (mp2ctl);
482721fffe3SKacheong Poon }
483721fffe3SKacheong Poon 
484721fffe3SKacheong Poon /* Return 0 if invalid set request, 1 otherwise, including non-tcp requests  */
485721fffe3SKacheong Poon /* ARGSUSED */
486721fffe3SKacheong Poon int
tcp_snmp_set(queue_t * q,int level,int name,uchar_t * ptr,int len)487721fffe3SKacheong Poon tcp_snmp_set(queue_t *q, int level, int name, uchar_t *ptr, int len)
488721fffe3SKacheong Poon {
489721fffe3SKacheong Poon 	mib2_tcpConnEntry_t	*tce = (mib2_tcpConnEntry_t *)ptr;
490721fffe3SKacheong Poon 
491721fffe3SKacheong Poon 	switch (level) {
492721fffe3SKacheong Poon 	case MIB2_TCP:
493721fffe3SKacheong Poon 		switch (name) {
494721fffe3SKacheong Poon 		case 13:
495721fffe3SKacheong Poon 			if (tce->tcpConnState != MIB2_TCP_deleteTCB)
496721fffe3SKacheong Poon 				return (0);
497721fffe3SKacheong Poon 			/* TODO: delete entry defined by tce */
498721fffe3SKacheong Poon 			return (1);
499721fffe3SKacheong Poon 		default:
500721fffe3SKacheong Poon 			return (0);
501721fffe3SKacheong Poon 		}
502721fffe3SKacheong Poon 	default:
503721fffe3SKacheong Poon 		return (1);
504721fffe3SKacheong Poon 	}
505721fffe3SKacheong Poon }
506721fffe3SKacheong Poon 
507721fffe3SKacheong Poon /*
508721fffe3SKacheong Poon  * TCP Kstats implementation
509721fffe3SKacheong Poon  */
510721fffe3SKacheong Poon void *
tcp_kstat_init(netstackid_t stackid)511721fffe3SKacheong Poon tcp_kstat_init(netstackid_t stackid)
512721fffe3SKacheong Poon {
513721fffe3SKacheong Poon 	kstat_t	*ksp;
514721fffe3SKacheong Poon 
515721fffe3SKacheong Poon 	tcp_named_kstat_t template = {
516721fffe3SKacheong Poon 		{ "rtoAlgorithm",	KSTAT_DATA_INT32, 0 },
517721fffe3SKacheong Poon 		{ "rtoMin",		KSTAT_DATA_INT32, 0 },
518721fffe3SKacheong Poon 		{ "rtoMax",		KSTAT_DATA_INT32, 0 },
519721fffe3SKacheong Poon 		{ "maxConn",		KSTAT_DATA_INT32, 0 },
520721fffe3SKacheong Poon 		{ "activeOpens",	KSTAT_DATA_UINT32, 0 },
521721fffe3SKacheong Poon 		{ "passiveOpens",	KSTAT_DATA_UINT32, 0 },
522721fffe3SKacheong Poon 		{ "attemptFails",	KSTAT_DATA_UINT32, 0 },
523721fffe3SKacheong Poon 		{ "estabResets",	KSTAT_DATA_UINT32, 0 },
524721fffe3SKacheong Poon 		{ "currEstab",		KSTAT_DATA_UINT32, 0 },
525721fffe3SKacheong Poon 		{ "inSegs",		KSTAT_DATA_UINT64, 0 },
526721fffe3SKacheong Poon 		{ "outSegs",		KSTAT_DATA_UINT64, 0 },
527721fffe3SKacheong Poon 		{ "retransSegs",	KSTAT_DATA_UINT32, 0 },
528721fffe3SKacheong Poon 		{ "connTableSize",	KSTAT_DATA_INT32, 0 },
529721fffe3SKacheong Poon 		{ "outRsts",		KSTAT_DATA_UINT32, 0 },
530721fffe3SKacheong Poon 		{ "outDataSegs",	KSTAT_DATA_UINT32, 0 },
531721fffe3SKacheong Poon 		{ "outDataBytes",	KSTAT_DATA_UINT32, 0 },
532721fffe3SKacheong Poon 		{ "retransBytes",	KSTAT_DATA_UINT32, 0 },
533721fffe3SKacheong Poon 		{ "outAck",		KSTAT_DATA_UINT32, 0 },
534721fffe3SKacheong Poon 		{ "outAckDelayed",	KSTAT_DATA_UINT32, 0 },
535721fffe3SKacheong Poon 		{ "outUrg",		KSTAT_DATA_UINT32, 0 },
536721fffe3SKacheong Poon 		{ "outWinUpdate",	KSTAT_DATA_UINT32, 0 },
537721fffe3SKacheong Poon 		{ "outWinProbe",	KSTAT_DATA_UINT32, 0 },
538721fffe3SKacheong Poon 		{ "outControl",		KSTAT_DATA_UINT32, 0 },
539721fffe3SKacheong Poon 		{ "outFastRetrans",	KSTAT_DATA_UINT32, 0 },
540721fffe3SKacheong Poon 		{ "inAckSegs",		KSTAT_DATA_UINT32, 0 },
541721fffe3SKacheong Poon 		{ "inAckBytes",		KSTAT_DATA_UINT32, 0 },
542721fffe3SKacheong Poon 		{ "inDupAck",		KSTAT_DATA_UINT32, 0 },
543721fffe3SKacheong Poon 		{ "inAckUnsent",	KSTAT_DATA_UINT32, 0 },
544721fffe3SKacheong Poon 		{ "inDataInorderSegs",	KSTAT_DATA_UINT32, 0 },
545721fffe3SKacheong Poon 		{ "inDataInorderBytes",	KSTAT_DATA_UINT32, 0 },
546721fffe3SKacheong Poon 		{ "inDataUnorderSegs",	KSTAT_DATA_UINT32, 0 },
547721fffe3SKacheong Poon 		{ "inDataUnorderBytes",	KSTAT_DATA_UINT32, 0 },
548721fffe3SKacheong Poon 		{ "inDataDupSegs",	KSTAT_DATA_UINT32, 0 },
549721fffe3SKacheong Poon 		{ "inDataDupBytes",	KSTAT_DATA_UINT32, 0 },
550721fffe3SKacheong Poon 		{ "inDataPartDupSegs",	KSTAT_DATA_UINT32, 0 },
551721fffe3SKacheong Poon 		{ "inDataPartDupBytes",	KSTAT_DATA_UINT32, 0 },
552721fffe3SKacheong Poon 		{ "inDataPastWinSegs",	KSTAT_DATA_UINT32, 0 },
553721fffe3SKacheong Poon 		{ "inDataPastWinBytes",	KSTAT_DATA_UINT32, 0 },
554721fffe3SKacheong Poon 		{ "inWinProbe",		KSTAT_DATA_UINT32, 0 },
555721fffe3SKacheong Poon 		{ "inWinUpdate",	KSTAT_DATA_UINT32, 0 },
556721fffe3SKacheong Poon 		{ "inClosed",		KSTAT_DATA_UINT32, 0 },
557721fffe3SKacheong Poon 		{ "rttUpdate",		KSTAT_DATA_UINT32, 0 },
558721fffe3SKacheong Poon 		{ "rttNoUpdate",	KSTAT_DATA_UINT32, 0 },
559721fffe3SKacheong Poon 		{ "timRetrans",		KSTAT_DATA_UINT32, 0 },
560721fffe3SKacheong Poon 		{ "timRetransDrop",	KSTAT_DATA_UINT32, 0 },
561721fffe3SKacheong Poon 		{ "timKeepalive",	KSTAT_DATA_UINT32, 0 },
562721fffe3SKacheong Poon 		{ "timKeepaliveProbe",	KSTAT_DATA_UINT32, 0 },
563721fffe3SKacheong Poon 		{ "timKeepaliveDrop",	KSTAT_DATA_UINT32, 0 },
564721fffe3SKacheong Poon 		{ "listenDrop",		KSTAT_DATA_UINT32, 0 },
565721fffe3SKacheong Poon 		{ "listenDropQ0",	KSTAT_DATA_UINT32, 0 },
566721fffe3SKacheong Poon 		{ "halfOpenDrop",	KSTAT_DATA_UINT32, 0 },
567721fffe3SKacheong Poon 		{ "outSackRetransSegs",	KSTAT_DATA_UINT32, 0 },
568721fffe3SKacheong Poon 		{ "connTableSize6",	KSTAT_DATA_INT32, 0 }
569721fffe3SKacheong Poon 	};
570721fffe3SKacheong Poon 
5714a0bd071SBill Pijewski 	ksp = kstat_create_netstack(TCP_MOD_NAME, stackid, TCP_MOD_NAME, "mib2",
572721fffe3SKacheong Poon 	    KSTAT_TYPE_NAMED, NUM_OF_FIELDS(tcp_named_kstat_t), 0, stackid);
573721fffe3SKacheong Poon 
574721fffe3SKacheong Poon 	if (ksp == NULL)
575721fffe3SKacheong Poon 		return (NULL);
576721fffe3SKacheong Poon 
577721fffe3SKacheong Poon 	template.rtoAlgorithm.value.ui32 = 4;
578721fffe3SKacheong Poon 	template.maxConn.value.i32 = -1;
579721fffe3SKacheong Poon 
580721fffe3SKacheong Poon 	bcopy(&template, ksp->ks_data, sizeof (template));
581721fffe3SKacheong Poon 	ksp->ks_update = tcp_kstat_update;
582721fffe3SKacheong Poon 	ksp->ks_private = (void *)(uintptr_t)stackid;
583721fffe3SKacheong Poon 
5844a0bd071SBill Pijewski 	/*
5854a0bd071SBill Pijewski 	 * If this is an exclusive netstack for a local zone, the global zone
5864a0bd071SBill Pijewski 	 * should still be able to read the kstat.
5874a0bd071SBill Pijewski 	 */
5884a0bd071SBill Pijewski 	if (stackid != GLOBAL_NETSTACKID)
5894a0bd071SBill Pijewski 		kstat_zone_add(ksp, GLOBAL_ZONEID);
5904a0bd071SBill Pijewski 
591721fffe3SKacheong Poon 	kstat_install(ksp);
592721fffe3SKacheong Poon 	return (ksp);
593721fffe3SKacheong Poon }
594721fffe3SKacheong Poon 
595721fffe3SKacheong Poon void
tcp_kstat_fini(netstackid_t stackid,kstat_t * ksp)596721fffe3SKacheong Poon tcp_kstat_fini(netstackid_t stackid, kstat_t *ksp)
597721fffe3SKacheong Poon {
598721fffe3SKacheong Poon 	if (ksp != NULL) {
599721fffe3SKacheong Poon 		ASSERT(stackid == (netstackid_t)(uintptr_t)ksp->ks_private);
600721fffe3SKacheong Poon 		kstat_delete_netstack(ksp, stackid);
601721fffe3SKacheong Poon 	}
602721fffe3SKacheong Poon }
603721fffe3SKacheong Poon 
604721fffe3SKacheong Poon static int
tcp_kstat_update(kstat_t * kp,int rw)605721fffe3SKacheong Poon tcp_kstat_update(kstat_t *kp, int rw)
606721fffe3SKacheong Poon {
607721fffe3SKacheong Poon 	tcp_named_kstat_t *tcpkp;
608721fffe3SKacheong Poon 	tcp_t		*tcp;
609721fffe3SKacheong Poon 	connf_t		*connfp;
610721fffe3SKacheong Poon 	conn_t		*connp;
611*78a2e113SAndy Fiddaman 	int		i;
612721fffe3SKacheong Poon 	netstackid_t	stackid = (netstackid_t)(uintptr_t)kp->ks_private;
613721fffe3SKacheong Poon 	netstack_t	*ns;
614721fffe3SKacheong Poon 	tcp_stack_t	*tcps;
615721fffe3SKacheong Poon 	ip_stack_t	*ipst;
616721fffe3SKacheong Poon 	mib2_tcp_t	tcp_mib;
617721fffe3SKacheong Poon 
618721fffe3SKacheong Poon 	if (rw == KSTAT_WRITE)
619721fffe3SKacheong Poon 		return (EACCES);
620721fffe3SKacheong Poon 
621721fffe3SKacheong Poon 	ns = netstack_find_by_stackid(stackid);
622721fffe3SKacheong Poon 	if (ns == NULL)
623721fffe3SKacheong Poon 		return (-1);
624721fffe3SKacheong Poon 	tcps = ns->netstack_tcp;
625721fffe3SKacheong Poon 	if (tcps == NULL) {
626721fffe3SKacheong Poon 		netstack_rele(ns);
627721fffe3SKacheong Poon 		return (-1);
628721fffe3SKacheong Poon 	}
629721fffe3SKacheong Poon 
630721fffe3SKacheong Poon 	tcpkp = (tcp_named_kstat_t *)kp->ks_data;
631721fffe3SKacheong Poon 
632721fffe3SKacheong Poon 	tcpkp->currEstab.value.ui32 = 0;
633721fffe3SKacheong Poon 	tcpkp->rtoMin.value.ui32 = tcps->tcps_rexmit_interval_min;
634721fffe3SKacheong Poon 	tcpkp->rtoMax.value.ui32 = tcps->tcps_rexmit_interval_max;
635721fffe3SKacheong Poon 
636721fffe3SKacheong Poon 	ipst = ns->netstack_ip;
637721fffe3SKacheong Poon 
638721fffe3SKacheong Poon 	for (i = 0; i < CONN_G_HASH_SIZE; i++) {
639721fffe3SKacheong Poon 		connfp = &ipst->ips_ipcl_globalhash_fanout[i];
640721fffe3SKacheong Poon 		connp = NULL;
641721fffe3SKacheong Poon 		while ((connp =
642721fffe3SKacheong Poon 		    ipcl_get_next_conn(connfp, connp, IPCL_TCPCONN)) != NULL) {
643721fffe3SKacheong Poon 			tcp = connp->conn_tcp;
644721fffe3SKacheong Poon 			switch (tcp_snmp_state(tcp)) {
645721fffe3SKacheong Poon 			case MIB2_TCP_established:
646721fffe3SKacheong Poon 			case MIB2_TCP_closeWait:
647721fffe3SKacheong Poon 				tcpkp->currEstab.value.ui32++;
648721fffe3SKacheong Poon 				break;
649721fffe3SKacheong Poon 			}
650721fffe3SKacheong Poon 		}
651721fffe3SKacheong Poon 	}
652721fffe3SKacheong Poon 	bzero(&tcp_mib, sizeof (tcp_mib));
653721fffe3SKacheong Poon 	tcp_sum_mib(tcps, &tcp_mib);
654721fffe3SKacheong Poon 
6556f773e29SBaban Kenkre 	/* Fixed length structure for IPv4 and IPv6 counters */
6566f773e29SBaban Kenkre 	SET_MIB(tcp_mib.tcpConnTableSize, sizeof (mib2_tcpConnEntry_t));
6576f773e29SBaban Kenkre 	SET_MIB(tcp_mib.tcp6ConnTableSize, sizeof (mib2_tcp6ConnEntry_t));
6586f773e29SBaban Kenkre 
659721fffe3SKacheong Poon 	tcpkp->activeOpens.value.ui32 = tcp_mib.tcpActiveOpens;
660721fffe3SKacheong Poon 	tcpkp->passiveOpens.value.ui32 = tcp_mib.tcpPassiveOpens;
661721fffe3SKacheong Poon 	tcpkp->attemptFails.value.ui32 = tcp_mib.tcpAttemptFails;
662721fffe3SKacheong Poon 	tcpkp->estabResets.value.ui32 = tcp_mib.tcpEstabResets;
663721fffe3SKacheong Poon 	tcpkp->inSegs.value.ui64 = tcp_mib.tcpHCInSegs;
664721fffe3SKacheong Poon 	tcpkp->outSegs.value.ui64 = tcp_mib.tcpHCOutSegs;
665721fffe3SKacheong Poon 	tcpkp->retransSegs.value.ui32 =	tcp_mib.tcpRetransSegs;
666721fffe3SKacheong Poon 	tcpkp->connTableSize.value.i32 = tcp_mib.tcpConnTableSize;
667721fffe3SKacheong Poon 	tcpkp->outRsts.value.ui32 = tcp_mib.tcpOutRsts;
668721fffe3SKacheong Poon 	tcpkp->outDataSegs.value.ui32 = tcp_mib.tcpOutDataSegs;
669721fffe3SKacheong Poon 	tcpkp->outDataBytes.value.ui32 = tcp_mib.tcpOutDataBytes;
670721fffe3SKacheong Poon 	tcpkp->retransBytes.value.ui32 = tcp_mib.tcpRetransBytes;
671721fffe3SKacheong Poon 	tcpkp->outAck.value.ui32 = tcp_mib.tcpOutAck;
672721fffe3SKacheong Poon 	tcpkp->outAckDelayed.value.ui32 = tcp_mib.tcpOutAckDelayed;
673721fffe3SKacheong Poon 	tcpkp->outUrg.value.ui32 = tcp_mib.tcpOutUrg;
674721fffe3SKacheong Poon 	tcpkp->outWinUpdate.value.ui32 = tcp_mib.tcpOutWinUpdate;
675721fffe3SKacheong Poon 	tcpkp->outWinProbe.value.ui32 = tcp_mib.tcpOutWinProbe;
676721fffe3SKacheong Poon 	tcpkp->outControl.value.ui32 = tcp_mib.tcpOutControl;
677721fffe3SKacheong Poon 	tcpkp->outFastRetrans.value.ui32 = tcp_mib.tcpOutFastRetrans;
678721fffe3SKacheong Poon 	tcpkp->inAckSegs.value.ui32 = tcp_mib.tcpInAckSegs;
679721fffe3SKacheong Poon 	tcpkp->inAckBytes.value.ui32 = tcp_mib.tcpInAckBytes;
680721fffe3SKacheong Poon 	tcpkp->inDupAck.value.ui32 = tcp_mib.tcpInDupAck;
681721fffe3SKacheong Poon 	tcpkp->inAckUnsent.value.ui32 = tcp_mib.tcpInAckUnsent;
682721fffe3SKacheong Poon 	tcpkp->inDataInorderSegs.value.ui32 = tcp_mib.tcpInDataInorderSegs;
683721fffe3SKacheong Poon 	tcpkp->inDataInorderBytes.value.ui32 = tcp_mib.tcpInDataInorderBytes;
684721fffe3SKacheong Poon 	tcpkp->inDataUnorderSegs.value.ui32 = tcp_mib.tcpInDataUnorderSegs;
685721fffe3SKacheong Poon 	tcpkp->inDataUnorderBytes.value.ui32 = tcp_mib.tcpInDataUnorderBytes;
686721fffe3SKacheong Poon 	tcpkp->inDataDupSegs.value.ui32 = tcp_mib.tcpInDataDupSegs;
687721fffe3SKacheong Poon 	tcpkp->inDataDupBytes.value.ui32 = tcp_mib.tcpInDataDupBytes;
688721fffe3SKacheong Poon 	tcpkp->inDataPartDupSegs.value.ui32 = tcp_mib.tcpInDataPartDupSegs;
689721fffe3SKacheong Poon 	tcpkp->inDataPartDupBytes.value.ui32 = tcp_mib.tcpInDataPartDupBytes;
690721fffe3SKacheong Poon 	tcpkp->inDataPastWinSegs.value.ui32 = tcp_mib.tcpInDataPastWinSegs;
691721fffe3SKacheong Poon 	tcpkp->inDataPastWinBytes.value.ui32 = tcp_mib.tcpInDataPastWinBytes;
692721fffe3SKacheong Poon 	tcpkp->inWinProbe.value.ui32 = tcp_mib.tcpInWinProbe;
693721fffe3SKacheong Poon 	tcpkp->inWinUpdate.value.ui32 = tcp_mib.tcpInWinUpdate;
694721fffe3SKacheong Poon 	tcpkp->inClosed.value.ui32 = tcp_mib.tcpInClosed;
695721fffe3SKacheong Poon 	tcpkp->rttNoUpdate.value.ui32 = tcp_mib.tcpRttNoUpdate;
696721fffe3SKacheong Poon 	tcpkp->rttUpdate.value.ui32 = tcp_mib.tcpRttUpdate;
697721fffe3SKacheong Poon 	tcpkp->timRetrans.value.ui32 = tcp_mib.tcpTimRetrans;
698721fffe3SKacheong Poon 	tcpkp->timRetransDrop.value.ui32 = tcp_mib.tcpTimRetransDrop;
699721fffe3SKacheong Poon 	tcpkp->timKeepalive.value.ui32 = tcp_mib.tcpTimKeepalive;
700721fffe3SKacheong Poon 	tcpkp->timKeepaliveProbe.value.ui32 = tcp_mib.tcpTimKeepaliveProbe;
701721fffe3SKacheong Poon 	tcpkp->timKeepaliveDrop.value.ui32 = tcp_mib.tcpTimKeepaliveDrop;
702721fffe3SKacheong Poon 	tcpkp->listenDrop.value.ui32 = tcp_mib.tcpListenDrop;
703721fffe3SKacheong Poon 	tcpkp->listenDropQ0.value.ui32 = tcp_mib.tcpListenDropQ0;
704721fffe3SKacheong Poon 	tcpkp->halfOpenDrop.value.ui32 = tcp_mib.tcpHalfOpenDrop;
705721fffe3SKacheong Poon 	tcpkp->outSackRetransSegs.value.ui32 = tcp_mib.tcpOutSackRetransSegs;
706721fffe3SKacheong Poon 	tcpkp->connTableSize6.value.i32 = tcp_mib.tcp6ConnTableSize;
707721fffe3SKacheong Poon 
708721fffe3SKacheong Poon 	netstack_rele(ns);
709721fffe3SKacheong Poon 	return (0);
710721fffe3SKacheong Poon }
711721fffe3SKacheong Poon 
712721fffe3SKacheong Poon /*
713721fffe3SKacheong Poon  * kstats related to squeues i.e. not per IP instance
714721fffe3SKacheong Poon  */
715721fffe3SKacheong Poon void *
tcp_g_kstat_init(tcp_g_stat_t * tcp_g_statp)716721fffe3SKacheong Poon tcp_g_kstat_init(tcp_g_stat_t *tcp_g_statp)
717721fffe3SKacheong Poon {
718721fffe3SKacheong Poon 	kstat_t *ksp;
719721fffe3SKacheong Poon 
720721fffe3SKacheong Poon 	tcp_g_stat_t template = {
721721fffe3SKacheong Poon 		{ "tcp_timermp_alloced",	KSTAT_DATA_UINT64 },
722721fffe3SKacheong Poon 		{ "tcp_timermp_allocfail",	KSTAT_DATA_UINT64 },
723721fffe3SKacheong Poon 		{ "tcp_timermp_allocdblfail",	KSTAT_DATA_UINT64 },
724721fffe3SKacheong Poon 		{ "tcp_freelist_cleanup",	KSTAT_DATA_UINT64 },
725721fffe3SKacheong Poon 	};
726721fffe3SKacheong Poon 
727721fffe3SKacheong Poon 	ksp = kstat_create(TCP_MOD_NAME, 0, "tcpstat_g", "net",
728721fffe3SKacheong Poon 	    KSTAT_TYPE_NAMED, sizeof (template) / sizeof (kstat_named_t),
729721fffe3SKacheong Poon 	    KSTAT_FLAG_VIRTUAL);
730721fffe3SKacheong Poon 
731721fffe3SKacheong Poon 	if (ksp == NULL)
732721fffe3SKacheong Poon 		return (NULL);
733721fffe3SKacheong Poon 
734721fffe3SKacheong Poon 	bcopy(&template, tcp_g_statp, sizeof (template));
735721fffe3SKacheong Poon 	ksp->ks_data = (void *)tcp_g_statp;
736721fffe3SKacheong Poon 
737721fffe3SKacheong Poon 	kstat_install(ksp);
738721fffe3SKacheong Poon 	return (ksp);
739721fffe3SKacheong Poon }
740721fffe3SKacheong Poon 
741721fffe3SKacheong Poon void
tcp_g_kstat_fini(kstat_t * ksp)742721fffe3SKacheong Poon tcp_g_kstat_fini(kstat_t *ksp)
743721fffe3SKacheong Poon {
744721fffe3SKacheong Poon 	if (ksp != NULL) {
745721fffe3SKacheong Poon 		kstat_delete(ksp);
746721fffe3SKacheong Poon 	}
747721fffe3SKacheong Poon }
748721fffe3SKacheong Poon 
749721fffe3SKacheong Poon void *
tcp_kstat2_init(netstackid_t stackid)750721fffe3SKacheong Poon tcp_kstat2_init(netstackid_t stackid)
751721fffe3SKacheong Poon {
752721fffe3SKacheong Poon 	kstat_t *ksp;
753721fffe3SKacheong Poon 
754721fffe3SKacheong Poon 	tcp_stat_t template = {
755721fffe3SKacheong Poon 		{ "tcp_time_wait_syn_success",	KSTAT_DATA_UINT64, 0 },
756721fffe3SKacheong Poon 		{ "tcp_clean_death_nondetached",	KSTAT_DATA_UINT64, 0 },
757721fffe3SKacheong Poon 		{ "tcp_eager_blowoff_q",	KSTAT_DATA_UINT64, 0 },
758721fffe3SKacheong Poon 		{ "tcp_eager_blowoff_q0",	KSTAT_DATA_UINT64, 0 },
759721fffe3SKacheong Poon 		{ "tcp_no_listener",		KSTAT_DATA_UINT64, 0 },
760721fffe3SKacheong Poon 		{ "tcp_listendrop",		KSTAT_DATA_UINT64, 0 },
761721fffe3SKacheong Poon 		{ "tcp_listendropq0",		KSTAT_DATA_UINT64, 0 },
762721fffe3SKacheong Poon 		{ "tcp_wsrv_called",		KSTAT_DATA_UINT64, 0 },
763721fffe3SKacheong Poon 		{ "tcp_flwctl_on",		KSTAT_DATA_UINT64, 0 },
764721fffe3SKacheong Poon 		{ "tcp_timer_fire_early",	KSTAT_DATA_UINT64, 0 },
765721fffe3SKacheong Poon 		{ "tcp_timer_fire_miss",	KSTAT_DATA_UINT64, 0 },
766721fffe3SKacheong Poon 		{ "tcp_zcopy_on",		KSTAT_DATA_UINT64, 0 },
767721fffe3SKacheong Poon 		{ "tcp_zcopy_off",		KSTAT_DATA_UINT64, 0 },
768721fffe3SKacheong Poon 		{ "tcp_zcopy_backoff",		KSTAT_DATA_UINT64, 0 },
769721fffe3SKacheong Poon 		{ "tcp_fusion_flowctl",		KSTAT_DATA_UINT64, 0 },
770721fffe3SKacheong Poon 		{ "tcp_fusion_backenabled",	KSTAT_DATA_UINT64, 0 },
771721fffe3SKacheong Poon 		{ "tcp_fusion_urg",		KSTAT_DATA_UINT64, 0 },
772721fffe3SKacheong Poon 		{ "tcp_fusion_putnext",		KSTAT_DATA_UINT64, 0 },
773721fffe3SKacheong Poon 		{ "tcp_fusion_unfusable",	KSTAT_DATA_UINT64, 0 },
774721fffe3SKacheong Poon 		{ "tcp_fusion_aborted",		KSTAT_DATA_UINT64, 0 },
775721fffe3SKacheong Poon 		{ "tcp_fusion_unqualified",	KSTAT_DATA_UINT64, 0 },
776721fffe3SKacheong Poon 		{ "tcp_fusion_rrw_busy",	KSTAT_DATA_UINT64, 0 },
777721fffe3SKacheong Poon 		{ "tcp_fusion_rrw_msgcnt",	KSTAT_DATA_UINT64, 0 },
778721fffe3SKacheong Poon 		{ "tcp_fusion_rrw_plugged",	KSTAT_DATA_UINT64, 0 },
779721fffe3SKacheong Poon 		{ "tcp_in_ack_unsent_drop",	KSTAT_DATA_UINT64, 0 },
780721fffe3SKacheong Poon 		{ "tcp_sock_fallback",		KSTAT_DATA_UINT64, 0 },
781721fffe3SKacheong Poon 		{ "tcp_lso_enabled",		KSTAT_DATA_UINT64, 0 },
782721fffe3SKacheong Poon 		{ "tcp_lso_disabled",		KSTAT_DATA_UINT64, 0 },
783721fffe3SKacheong Poon 		{ "tcp_lso_times",		KSTAT_DATA_UINT64, 0 },
784721fffe3SKacheong Poon 		{ "tcp_lso_pkt_out",		KSTAT_DATA_UINT64, 0 },
785721fffe3SKacheong Poon 		{ "tcp_listen_cnt_drop",	KSTAT_DATA_UINT64, 0 },
786721fffe3SKacheong Poon 		{ "tcp_listen_mem_drop",	KSTAT_DATA_UINT64, 0 },
787721fffe3SKacheong Poon 		{ "tcp_zwin_mem_drop",		KSTAT_DATA_UINT64, 0 },
788721fffe3SKacheong Poon 		{ "tcp_zwin_ack_syn",		KSTAT_DATA_UINT64, 0 },
789721fffe3SKacheong Poon 		{ "tcp_rst_unsent",		KSTAT_DATA_UINT64, 0 },
790721fffe3SKacheong Poon 		{ "tcp_reclaim_cnt",		KSTAT_DATA_UINT64, 0 },
791721fffe3SKacheong Poon 		{ "tcp_reass_timeout",		KSTAT_DATA_UINT64, 0 },
792721fffe3SKacheong Poon #ifdef TCP_DEBUG_COUNTER
793721fffe3SKacheong Poon 		{ "tcp_time_wait",		KSTAT_DATA_UINT64, 0 },
794721fffe3SKacheong Poon 		{ "tcp_rput_time_wait",		KSTAT_DATA_UINT64, 0 },
795721fffe3SKacheong Poon 		{ "tcp_detach_time_wait",	KSTAT_DATA_UINT64, 0 },
796721fffe3SKacheong Poon 		{ "tcp_timeout_calls",		KSTAT_DATA_UINT64, 0 },
797721fffe3SKacheong Poon 		{ "tcp_timeout_cached_alloc",	KSTAT_DATA_UINT64, 0 },
798721fffe3SKacheong Poon 		{ "tcp_timeout_cancel_reqs",	KSTAT_DATA_UINT64, 0 },
799721fffe3SKacheong Poon 		{ "tcp_timeout_canceled",	KSTAT_DATA_UINT64, 0 },
800721fffe3SKacheong Poon 		{ "tcp_timermp_freed",		KSTAT_DATA_UINT64, 0 },
801721fffe3SKacheong Poon 		{ "tcp_push_timer_cnt",		KSTAT_DATA_UINT64, 0 },
802721fffe3SKacheong Poon 		{ "tcp_ack_timer_cnt",		KSTAT_DATA_UINT64, 0 },
803721fffe3SKacheong Poon #endif
804721fffe3SKacheong Poon 	};
805721fffe3SKacheong Poon 
8064a0bd071SBill Pijewski 	ksp = kstat_create_netstack(TCP_MOD_NAME, stackid, "tcpstat", "net",
807721fffe3SKacheong Poon 	    KSTAT_TYPE_NAMED, sizeof (template) / sizeof (kstat_named_t), 0,
808721fffe3SKacheong Poon 	    stackid);
809721fffe3SKacheong Poon 
810721fffe3SKacheong Poon 	if (ksp == NULL)
811721fffe3SKacheong Poon 		return (NULL);
812721fffe3SKacheong Poon 
813721fffe3SKacheong Poon 	bcopy(&template, ksp->ks_data, sizeof (template));
814721fffe3SKacheong Poon 	ksp->ks_private = (void *)(uintptr_t)stackid;
815721fffe3SKacheong Poon 	ksp->ks_update = tcp_kstat2_update;
816721fffe3SKacheong Poon 
8174a0bd071SBill Pijewski 	/*
8184a0bd071SBill Pijewski 	 * If this is an exclusive netstack for a local zone, the global zone
8194a0bd071SBill Pijewski 	 * should still be able to read the kstat.
8204a0bd071SBill Pijewski 	 */
8214a0bd071SBill Pijewski 	if (stackid != GLOBAL_NETSTACKID)
8224a0bd071SBill Pijewski 		kstat_zone_add(ksp, GLOBAL_ZONEID);
8234a0bd071SBill Pijewski 
824721fffe3SKacheong Poon 	kstat_install(ksp);
825721fffe3SKacheong Poon 	return (ksp);
826721fffe3SKacheong Poon }
827721fffe3SKacheong Poon 
828721fffe3SKacheong Poon void
tcp_kstat2_fini(netstackid_t stackid,kstat_t * ksp)829721fffe3SKacheong Poon tcp_kstat2_fini(netstackid_t stackid, kstat_t *ksp)
830721fffe3SKacheong Poon {
831721fffe3SKacheong Poon 	if (ksp != NULL) {
832721fffe3SKacheong Poon 		ASSERT(stackid == (netstackid_t)(uintptr_t)ksp->ks_private);
833721fffe3SKacheong Poon 		kstat_delete_netstack(ksp, stackid);
834721fffe3SKacheong Poon 	}
835721fffe3SKacheong Poon }
836721fffe3SKacheong Poon 
837721fffe3SKacheong Poon /*
838721fffe3SKacheong Poon  * Sum up all per CPU tcp_stat_t kstat counters.
839721fffe3SKacheong Poon  */
840721fffe3SKacheong Poon static int
tcp_kstat2_update(kstat_t * kp,int rw)841721fffe3SKacheong Poon tcp_kstat2_update(kstat_t *kp, int rw)
842721fffe3SKacheong Poon {
843721fffe3SKacheong Poon 	netstackid_t	stackid = (netstackid_t)(uintptr_t)kp->ks_private;
844721fffe3SKacheong Poon 	netstack_t	*ns;
845721fffe3SKacheong Poon 	tcp_stack_t	*tcps;
846721fffe3SKacheong Poon 	tcp_stat_t	*stats;
847721fffe3SKacheong Poon 	int		i;
848721fffe3SKacheong Poon 	int		cnt;
849721fffe3SKacheong Poon 
850721fffe3SKacheong Poon 	if (rw == KSTAT_WRITE)
851721fffe3SKacheong Poon 		return (EACCES);
852721fffe3SKacheong Poon 
853721fffe3SKacheong Poon 	ns = netstack_find_by_stackid(stackid);
854721fffe3SKacheong Poon 	if (ns == NULL)
855721fffe3SKacheong Poon 		return (-1);
856721fffe3SKacheong Poon 	tcps = ns->netstack_tcp;
857721fffe3SKacheong Poon 	if (tcps == NULL) {
858721fffe3SKacheong Poon 		netstack_rele(ns);
859721fffe3SKacheong Poon 		return (-1);
860721fffe3SKacheong Poon 	}
861721fffe3SKacheong Poon 
862721fffe3SKacheong Poon 	stats = (tcp_stat_t *)kp->ks_data;
863721fffe3SKacheong Poon 	tcp_clr_stats(stats);
864721fffe3SKacheong Poon 
865721fffe3SKacheong Poon 	/*
866721fffe3SKacheong Poon 	 * tcps_sc_cnt may change in the middle of the loop.  It is better
867721fffe3SKacheong Poon 	 * to get its value first.
868721fffe3SKacheong Poon 	 */
869721fffe3SKacheong Poon 	cnt = tcps->tcps_sc_cnt;
870721fffe3SKacheong Poon 	for (i = 0; i < cnt; i++)
8715dd46ab5SKacheong Poon 		tcp_add_stats(&tcps->tcps_sc[i]->tcp_sc_stats, stats);
872721fffe3SKacheong Poon 
873721fffe3SKacheong Poon 	netstack_rele(ns);
874721fffe3SKacheong Poon 	return (0);
875721fffe3SKacheong Poon }
876721fffe3SKacheong Poon 
877721fffe3SKacheong Poon /*
8785dd46ab5SKacheong Poon  * To add stats from one mib2_tcp_t to another.  Static fields are not added.
879721fffe3SKacheong Poon  * The caller should set them up propertly.
880721fffe3SKacheong Poon  */
881ca3c8f41SDavid Höppner static void
tcp_add_mib(mib2_tcp_t * from,mib2_tcp_t * to)8825dd46ab5SKacheong Poon tcp_add_mib(mib2_tcp_t *from, mib2_tcp_t *to)
883721fffe3SKacheong Poon {
884721fffe3SKacheong Poon 	to->tcpActiveOpens += from->tcpActiveOpens;
885721fffe3SKacheong Poon 	to->tcpPassiveOpens += from->tcpPassiveOpens;
886721fffe3SKacheong Poon 	to->tcpAttemptFails += from->tcpAttemptFails;
887721fffe3SKacheong Poon 	to->tcpEstabResets += from->tcpEstabResets;
888721fffe3SKacheong Poon 	to->tcpInSegs += from->tcpInSegs;
889721fffe3SKacheong Poon 	to->tcpOutSegs += from->tcpOutSegs;
890721fffe3SKacheong Poon 	to->tcpRetransSegs += from->tcpRetransSegs;
891721fffe3SKacheong Poon 	to->tcpOutRsts += from->tcpOutRsts;
892721fffe3SKacheong Poon 
893721fffe3SKacheong Poon 	to->tcpOutDataSegs += from->tcpOutDataSegs;
894721fffe3SKacheong Poon 	to->tcpOutDataBytes += from->tcpOutDataBytes;
895721fffe3SKacheong Poon 	to->tcpRetransBytes += from->tcpRetransBytes;
896721fffe3SKacheong Poon 	to->tcpOutAck += from->tcpOutAck;
897721fffe3SKacheong Poon 	to->tcpOutAckDelayed += from->tcpOutAckDelayed;
898721fffe3SKacheong Poon 	to->tcpOutUrg += from->tcpOutUrg;
899721fffe3SKacheong Poon 	to->tcpOutWinUpdate += from->tcpOutWinUpdate;
900721fffe3SKacheong Poon 	to->tcpOutWinProbe += from->tcpOutWinProbe;
901721fffe3SKacheong Poon 	to->tcpOutControl += from->tcpOutControl;
902721fffe3SKacheong Poon 	to->tcpOutFastRetrans += from->tcpOutFastRetrans;
903721fffe3SKacheong Poon 
904721fffe3SKacheong Poon 	to->tcpInAckBytes += from->tcpInAckBytes;
905721fffe3SKacheong Poon 	to->tcpInDupAck += from->tcpInDupAck;
906721fffe3SKacheong Poon 	to->tcpInAckUnsent += from->tcpInAckUnsent;
907721fffe3SKacheong Poon 	to->tcpInDataInorderSegs += from->tcpInDataInorderSegs;
908721fffe3SKacheong Poon 	to->tcpInDataInorderBytes += from->tcpInDataInorderBytes;
909721fffe3SKacheong Poon 	to->tcpInDataUnorderSegs += from->tcpInDataUnorderSegs;
910721fffe3SKacheong Poon 	to->tcpInDataUnorderBytes += from->tcpInDataUnorderBytes;
911721fffe3SKacheong Poon 	to->tcpInDataDupSegs += from->tcpInDataDupSegs;
912721fffe3SKacheong Poon 	to->tcpInDataDupBytes += from->tcpInDataDupBytes;
913721fffe3SKacheong Poon 	to->tcpInDataPartDupSegs += from->tcpInDataPartDupSegs;
914721fffe3SKacheong Poon 	to->tcpInDataPartDupBytes += from->tcpInDataPartDupBytes;
915721fffe3SKacheong Poon 	to->tcpInDataPastWinSegs += from->tcpInDataPastWinSegs;
916721fffe3SKacheong Poon 	to->tcpInDataPastWinBytes += from->tcpInDataPastWinBytes;
917721fffe3SKacheong Poon 	to->tcpInWinProbe += from->tcpInWinProbe;
918721fffe3SKacheong Poon 	to->tcpInWinUpdate += from->tcpInWinUpdate;
919721fffe3SKacheong Poon 	to->tcpInClosed += from->tcpInClosed;
920721fffe3SKacheong Poon 
921721fffe3SKacheong Poon 	to->tcpRttNoUpdate += from->tcpRttNoUpdate;
922721fffe3SKacheong Poon 	to->tcpRttUpdate += from->tcpRttUpdate;
923721fffe3SKacheong Poon 	to->tcpTimRetrans += from->tcpTimRetrans;
924721fffe3SKacheong Poon 	to->tcpTimRetransDrop += from->tcpTimRetransDrop;
925721fffe3SKacheong Poon 	to->tcpTimKeepalive += from->tcpTimKeepalive;
926721fffe3SKacheong Poon 	to->tcpTimKeepaliveProbe += from->tcpTimKeepaliveProbe;
927721fffe3SKacheong Poon 	to->tcpTimKeepaliveDrop += from->tcpTimKeepaliveDrop;
928721fffe3SKacheong Poon 	to->tcpListenDrop += from->tcpListenDrop;
929721fffe3SKacheong Poon 	to->tcpListenDropQ0 += from->tcpListenDropQ0;
930721fffe3SKacheong Poon 	to->tcpHalfOpenDrop += from->tcpHalfOpenDrop;
931721fffe3SKacheong Poon 	to->tcpOutSackRetransSegs += from->tcpOutSackRetransSegs;
932721fffe3SKacheong Poon 	to->tcpHCInSegs += from->tcpHCInSegs;
933721fffe3SKacheong Poon 	to->tcpHCOutSegs += from->tcpHCOutSegs;
934721fffe3SKacheong Poon }
935721fffe3SKacheong Poon 
936721fffe3SKacheong Poon /*
937721fffe3SKacheong Poon  * To sum up all MIB2 stats for a tcp_stack_t from all per CPU stats.  The
938721fffe3SKacheong Poon  * caller should initialize the target mib2_tcp_t properly as this function
939721fffe3SKacheong Poon  * just adds up all the per CPU stats.
940721fffe3SKacheong Poon  */
941721fffe3SKacheong Poon static void
tcp_sum_mib(tcp_stack_t * tcps,mib2_tcp_t * tcp_mib)942721fffe3SKacheong Poon tcp_sum_mib(tcp_stack_t *tcps, mib2_tcp_t *tcp_mib)
943721fffe3SKacheong Poon {
944721fffe3SKacheong Poon 	int i;
945721fffe3SKacheong Poon 	int cnt;
946721fffe3SKacheong Poon 
947721fffe3SKacheong Poon 	/*
948721fffe3SKacheong Poon 	 * tcps_sc_cnt may change in the middle of the loop.  It is better
949721fffe3SKacheong Poon 	 * to get its value first.
950721fffe3SKacheong Poon 	 */
951721fffe3SKacheong Poon 	cnt = tcps->tcps_sc_cnt;
952721fffe3SKacheong Poon 	for (i = 0; i < cnt; i++)
9535dd46ab5SKacheong Poon 		tcp_add_mib(&tcps->tcps_sc[i]->tcp_sc_mib, tcp_mib);
954721fffe3SKacheong Poon }
955721fffe3SKacheong Poon 
956721fffe3SKacheong Poon /*
957721fffe3SKacheong Poon  * To set all tcp_stat_t counters to 0.
958721fffe3SKacheong Poon  */
9595dd46ab5SKacheong Poon static void
tcp_clr_stats(tcp_stat_t * stats)960721fffe3SKacheong Poon tcp_clr_stats(tcp_stat_t *stats)
961721fffe3SKacheong Poon {
962721fffe3SKacheong Poon 	stats->tcp_time_wait_syn_success.value.ui64 = 0;
963721fffe3SKacheong Poon 	stats->tcp_clean_death_nondetached.value.ui64 = 0;
964721fffe3SKacheong Poon 	stats->tcp_eager_blowoff_q.value.ui64 = 0;
965721fffe3SKacheong Poon 	stats->tcp_eager_blowoff_q0.value.ui64 = 0;
966721fffe3SKacheong Poon 	stats->tcp_no_listener.value.ui64 = 0;
967721fffe3SKacheong Poon 	stats->tcp_listendrop.value.ui64 = 0;
968721fffe3SKacheong Poon 	stats->tcp_listendropq0.value.ui64 = 0;
969721fffe3SKacheong Poon 	stats->tcp_wsrv_called.value.ui64 = 0;
970721fffe3SKacheong Poon 	stats->tcp_flwctl_on.value.ui64 = 0;
971721fffe3SKacheong Poon 	stats->tcp_timer_fire_early.value.ui64 = 0;
972721fffe3SKacheong Poon 	stats->tcp_timer_fire_miss.value.ui64 = 0;
973721fffe3SKacheong Poon 	stats->tcp_zcopy_on.value.ui64 = 0;
974721fffe3SKacheong Poon 	stats->tcp_zcopy_off.value.ui64 = 0;
975721fffe3SKacheong Poon 	stats->tcp_zcopy_backoff.value.ui64 = 0;
976721fffe3SKacheong Poon 	stats->tcp_fusion_flowctl.value.ui64 = 0;
977721fffe3SKacheong Poon 	stats->tcp_fusion_backenabled.value.ui64 = 0;
978721fffe3SKacheong Poon 	stats->tcp_fusion_urg.value.ui64 = 0;
979721fffe3SKacheong Poon 	stats->tcp_fusion_putnext.value.ui64 = 0;
980721fffe3SKacheong Poon 	stats->tcp_fusion_unfusable.value.ui64 = 0;
981721fffe3SKacheong Poon 	stats->tcp_fusion_aborted.value.ui64 = 0;
982721fffe3SKacheong Poon 	stats->tcp_fusion_unqualified.value.ui64 = 0;
983721fffe3SKacheong Poon 	stats->tcp_fusion_rrw_busy.value.ui64 = 0;
984721fffe3SKacheong Poon 	stats->tcp_fusion_rrw_msgcnt.value.ui64 = 0;
985721fffe3SKacheong Poon 	stats->tcp_fusion_rrw_plugged.value.ui64 = 0;
986721fffe3SKacheong Poon 	stats->tcp_in_ack_unsent_drop.value.ui64 = 0;
987721fffe3SKacheong Poon 	stats->tcp_sock_fallback.value.ui64 = 0;
988721fffe3SKacheong Poon 	stats->tcp_lso_enabled.value.ui64 = 0;
989721fffe3SKacheong Poon 	stats->tcp_lso_disabled.value.ui64 = 0;
990721fffe3SKacheong Poon 	stats->tcp_lso_times.value.ui64 = 0;
991721fffe3SKacheong Poon 	stats->tcp_lso_pkt_out.value.ui64 = 0;
992721fffe3SKacheong Poon 	stats->tcp_listen_cnt_drop.value.ui64 = 0;
993721fffe3SKacheong Poon 	stats->tcp_listen_mem_drop.value.ui64 = 0;
994721fffe3SKacheong Poon 	stats->tcp_zwin_mem_drop.value.ui64 = 0;
995721fffe3SKacheong Poon 	stats->tcp_zwin_ack_syn.value.ui64 = 0;
996721fffe3SKacheong Poon 	stats->tcp_rst_unsent.value.ui64 = 0;
997721fffe3SKacheong Poon 	stats->tcp_reclaim_cnt.value.ui64 = 0;
998721fffe3SKacheong Poon 	stats->tcp_reass_timeout.value.ui64 = 0;
999721fffe3SKacheong Poon 
1000721fffe3SKacheong Poon #ifdef TCP_DEBUG_COUNTER
1001721fffe3SKacheong Poon 	stats->tcp_time_wait.value.ui64 = 0;
1002721fffe3SKacheong Poon 	stats->tcp_rput_time_wait.value.ui64 = 0;
1003721fffe3SKacheong Poon 	stats->tcp_detach_time_wait.value.ui64 = 0;
1004721fffe3SKacheong Poon 	stats->tcp_timeout_calls.value.ui64 = 0;
1005721fffe3SKacheong Poon 	stats->tcp_timeout_cached_alloc.value.ui64 = 0;
1006721fffe3SKacheong Poon 	stats->tcp_timeout_cancel_reqs.value.ui64 = 0;
1007721fffe3SKacheong Poon 	stats->tcp_timeout_canceled.value.ui64 = 0;
1008721fffe3SKacheong Poon 	stats->tcp_timermp_freed.value.ui64 = 0;
1009721fffe3SKacheong Poon 	stats->tcp_push_timer_cnt.value.ui64 = 0;
1010721fffe3SKacheong Poon 	stats->tcp_ack_timer_cnt.value.ui64 = 0;
1011721fffe3SKacheong Poon #endif
1012721fffe3SKacheong Poon }
1013721fffe3SKacheong Poon 
1014721fffe3SKacheong Poon /*
10155dd46ab5SKacheong Poon  * To add counters from the per CPU tcp_stat_counter_t to the stack
10165dd46ab5SKacheong Poon  * tcp_stat_t.
1017721fffe3SKacheong Poon  */
10185dd46ab5SKacheong Poon static void
tcp_add_stats(tcp_stat_counter_t * from,tcp_stat_t * to)10195dd46ab5SKacheong Poon tcp_add_stats(tcp_stat_counter_t *from, tcp_stat_t *to)
1020721fffe3SKacheong Poon {
1021721fffe3SKacheong Poon 	to->tcp_time_wait_syn_success.value.ui64 +=
10225dd46ab5SKacheong Poon 	    from->tcp_time_wait_syn_success;
1023721fffe3SKacheong Poon 	to->tcp_clean_death_nondetached.value.ui64 +=
10245dd46ab5SKacheong Poon 	    from->tcp_clean_death_nondetached;
1025721fffe3SKacheong Poon 	to->tcp_eager_blowoff_q.value.ui64 +=
10265dd46ab5SKacheong Poon 	    from->tcp_eager_blowoff_q;
1027721fffe3SKacheong Poon 	to->tcp_eager_blowoff_q0.value.ui64 +=
10285dd46ab5SKacheong Poon 	    from->tcp_eager_blowoff_q0;
1029721fffe3SKacheong Poon 	to->tcp_no_listener.value.ui64 +=
10305dd46ab5SKacheong Poon 	    from->tcp_no_listener;
1031721fffe3SKacheong Poon 	to->tcp_listendrop.value.ui64 +=
10325dd46ab5SKacheong Poon 	    from->tcp_listendrop;
1033721fffe3SKacheong Poon 	to->tcp_listendropq0.value.ui64 +=
10345dd46ab5SKacheong Poon 	    from->tcp_listendropq0;
1035721fffe3SKacheong Poon 	to->tcp_wsrv_called.value.ui64 +=
10365dd46ab5SKacheong Poon 	    from->tcp_wsrv_called;
1037721fffe3SKacheong Poon 	to->tcp_flwctl_on.value.ui64 +=
10385dd46ab5SKacheong Poon 	    from->tcp_flwctl_on;
1039721fffe3SKacheong Poon 	to->tcp_timer_fire_early.value.ui64 +=
10405dd46ab5SKacheong Poon 	    from->tcp_timer_fire_early;
1041721fffe3SKacheong Poon 	to->tcp_timer_fire_miss.value.ui64 +=
10425dd46ab5SKacheong Poon 	    from->tcp_timer_fire_miss;
1043721fffe3SKacheong Poon 	to->tcp_zcopy_on.value.ui64 +=
10445dd46ab5SKacheong Poon 	    from->tcp_zcopy_on;
1045721fffe3SKacheong Poon 	to->tcp_zcopy_off.value.ui64 +=
10465dd46ab5SKacheong Poon 	    from->tcp_zcopy_off;
1047721fffe3SKacheong Poon 	to->tcp_zcopy_backoff.value.ui64 +=
10485dd46ab5SKacheong Poon 	    from->tcp_zcopy_backoff;
1049721fffe3SKacheong Poon 	to->tcp_fusion_flowctl.value.ui64 +=
10505dd46ab5SKacheong Poon 	    from->tcp_fusion_flowctl;
1051721fffe3SKacheong Poon 	to->tcp_fusion_backenabled.value.ui64 +=
10525dd46ab5SKacheong Poon 	    from->tcp_fusion_backenabled;
1053721fffe3SKacheong Poon 	to->tcp_fusion_urg.value.ui64 +=
10545dd46ab5SKacheong Poon 	    from->tcp_fusion_urg;
1055721fffe3SKacheong Poon 	to->tcp_fusion_putnext.value.ui64 +=
10565dd46ab5SKacheong Poon 	    from->tcp_fusion_putnext;
1057721fffe3SKacheong Poon 	to->tcp_fusion_unfusable.value.ui64 +=
10585dd46ab5SKacheong Poon 	    from->tcp_fusion_unfusable;
1059721fffe3SKacheong Poon 	to->tcp_fusion_aborted.value.ui64 +=
10605dd46ab5SKacheong Poon 	    from->tcp_fusion_aborted;
1061721fffe3SKacheong Poon 	to->tcp_fusion_unqualified.value.ui64 +=
10625dd46ab5SKacheong Poon 	    from->tcp_fusion_unqualified;
1063721fffe3SKacheong Poon 	to->tcp_fusion_rrw_busy.value.ui64 +=
10645dd46ab5SKacheong Poon 	    from->tcp_fusion_rrw_busy;
1065721fffe3SKacheong Poon 	to->tcp_fusion_rrw_msgcnt.value.ui64 +=
10665dd46ab5SKacheong Poon 	    from->tcp_fusion_rrw_msgcnt;
1067721fffe3SKacheong Poon 	to->tcp_fusion_rrw_plugged.value.ui64 +=
10685dd46ab5SKacheong Poon 	    from->tcp_fusion_rrw_plugged;
1069721fffe3SKacheong Poon 	to->tcp_in_ack_unsent_drop.value.ui64 +=
10705dd46ab5SKacheong Poon 	    from->tcp_in_ack_unsent_drop;
1071721fffe3SKacheong Poon 	to->tcp_sock_fallback.value.ui64 +=
10725dd46ab5SKacheong Poon 	    from->tcp_sock_fallback;
1073721fffe3SKacheong Poon 	to->tcp_lso_enabled.value.ui64 +=
10745dd46ab5SKacheong Poon 	    from->tcp_lso_enabled;
1075721fffe3SKacheong Poon 	to->tcp_lso_disabled.value.ui64 +=
10765dd46ab5SKacheong Poon 	    from->tcp_lso_disabled;
1077721fffe3SKacheong Poon 	to->tcp_lso_times.value.ui64 +=
10785dd46ab5SKacheong Poon 	    from->tcp_lso_times;
1079721fffe3SKacheong Poon 	to->tcp_lso_pkt_out.value.ui64 +=
10805dd46ab5SKacheong Poon 	    from->tcp_lso_pkt_out;
1081721fffe3SKacheong Poon 	to->tcp_listen_cnt_drop.value.ui64 +=
10825dd46ab5SKacheong Poon 	    from->tcp_listen_cnt_drop;
1083721fffe3SKacheong Poon 	to->tcp_listen_mem_drop.value.ui64 +=
10845dd46ab5SKacheong Poon 	    from->tcp_listen_mem_drop;
1085721fffe3SKacheong Poon 	to->tcp_zwin_mem_drop.value.ui64 +=
10865dd46ab5SKacheong Poon 	    from->tcp_zwin_mem_drop;
1087721fffe3SKacheong Poon 	to->tcp_zwin_ack_syn.value.ui64 +=
10885dd46ab5SKacheong Poon 	    from->tcp_zwin_ack_syn;
1089721fffe3SKacheong Poon 	to->tcp_rst_unsent.value.ui64 +=
10905dd46ab5SKacheong Poon 	    from->tcp_rst_unsent;
1091721fffe3SKacheong Poon 	to->tcp_reclaim_cnt.value.ui64 +=
10925dd46ab5SKacheong Poon 	    from->tcp_reclaim_cnt;
1093721fffe3SKacheong Poon 	to->tcp_reass_timeout.value.ui64 +=
10945dd46ab5SKacheong Poon 	    from->tcp_reass_timeout;
1095721fffe3SKacheong Poon 
1096721fffe3SKacheong Poon #ifdef TCP_DEBUG_COUNTER
1097721fffe3SKacheong Poon 	to->tcp_time_wait.value.ui64 +=
10985dd46ab5SKacheong Poon 	    from->tcp_time_wait;
1099721fffe3SKacheong Poon 	to->tcp_rput_time_wait.value.ui64 +=
11005dd46ab5SKacheong Poon 	    from->tcp_rput_time_wait;
1101721fffe3SKacheong Poon 	to->tcp_detach_time_wait.value.ui64 +=
11025dd46ab5SKacheong Poon 	    from->tcp_detach_time_wait;
1103721fffe3SKacheong Poon 	to->tcp_timeout_calls.value.ui64 +=
11045dd46ab5SKacheong Poon 	    from->tcp_timeout_calls;
1105721fffe3SKacheong Poon 	to->tcp_timeout_cached_alloc.value.ui64 +=
11065dd46ab5SKacheong Poon 	    from->tcp_timeout_cached_alloc;
1107721fffe3SKacheong Poon 	to->tcp_timeout_cancel_reqs.value.ui64 +=
11085dd46ab5SKacheong Poon 	    from->tcp_timeout_cancel_reqs;
1109721fffe3SKacheong Poon 	to->tcp_timeout_canceled.value.ui64 +=
11105dd46ab5SKacheong Poon 	    from->tcp_timeout_canceled;
1111721fffe3SKacheong Poon 	to->tcp_timermp_freed.value.ui64 +=
11125dd46ab5SKacheong Poon 	    from->tcp_timermp_freed;
1113721fffe3SKacheong Poon 	to->tcp_push_timer_cnt.value.ui64 +=
11145dd46ab5SKacheong Poon 	    from->tcp_push_timer_cnt;
1115721fffe3SKacheong Poon 	to->tcp_ack_timer_cnt.value.ui64 +=
11165dd46ab5SKacheong Poon 	    from->tcp_ack_timer_cnt;
1117721fffe3SKacheong Poon #endif
1118721fffe3SKacheong Poon }
1119