tcp.c revision 200462
1178253Sdelphij/*-
21573Srgrimes * Copyright (c) 1980, 1992, 1993
31573Srgrimes *	The Regents of the University of California.  All rights reserved.
41573Srgrimes *
51573Srgrimes * Redistribution and use in source and binary forms, with or without
61573Srgrimes * modification, are permitted provided that the following conditions
71573Srgrimes * are met:
81573Srgrimes * 1. Redistributions of source code must retain the above copyright
91573Srgrimes *    notice, this list of conditions and the following disclaimer.
101573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111573Srgrimes *    notice, this list of conditions and the following disclaimer in the
121573Srgrimes *    documentation and/or other materials provided with the distribution.
131573Srgrimes * 3. All advertising materials mentioning features or use of this software
141573Srgrimes *    must display the following acknowledgement:
151573Srgrimes *	This product includes software developed by the University of
161573Srgrimes *	California, Berkeley and its contributors.
171573Srgrimes * 4. Neither the name of the University nor the names of its contributors
181573Srgrimes *    may be used to endorse or promote products derived from this software
191573Srgrimes *    without specific prior written permission.
201573Srgrimes *
211573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
221573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241573Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
251573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
301573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3123668Speter * SUCH DAMAGE.
321573Srgrimes */
3390039Sobrien
3490039Sobrien#if 0
351573Srgrimes#ifndef lint
3671579Sdeischen/* From: */
371573Srgrimesstatic char sccsid[] = "@(#)mbufs.c	8.1 (Berkeley) 6/6/93";
3823768Sbdestatic const char rcsid[] =
397978Sbde	"Id: mbufs.c,v 1.5 1997/02/24 20:59:03 wollman Exp";
401573Srgrimes#endif /* not lint */
411573Srgrimes#endif
427978Sbde
431573Srgrimes#include <sys/cdefs.h>
441573Srgrimes__FBSDID("$FreeBSD: head/usr.bin/systat/tcp.c 200462 2009-12-13 03:14:06Z delphij $");
45108631Stjr
461573Srgrimes#include <sys/param.h>
4771579Sdeischen#include <sys/types.h>
481573Srgrimes#include <sys/socket.h>
4969841Sdeischen#include <sys/sysctl.h>
50178256Sdelphij
51178256Sdelphij#include <netinet/in.h>
52178256Sdelphij#include <netinet/in_systm.h>
531573Srgrimes#include <netinet/ip.h>
5423668Speter#include <netinet/tcp.h>
551573Srgrimes#include <netinet/tcp_seq.h>
561573Srgrimes#include <netinet/tcp_fsm.h>
57178253Sdelphij#include <netinet/tcp_timer.h>
581573Srgrimes#include <netinet/tcp_var.h>
5973632Sobrien
6023668Speter#include <stdlib.h>
6123668Speter#include <string.h>
621573Srgrimes#include <paths.h>
63178256Sdelphij
64178256Sdelphij#include "systat.h"
65178256Sdelphij#include "extern.h"
6623668Speter#include "mode.h"
67178256Sdelphij
68178256Sdelphijstatic struct tcpstat curstat, initstat, oldstat;
69249401Sjilles
70178256Sdelphij/*-
71249401Sjilles--0         1         2         3         4         5         6         7
72249401Sjilles--0123456789012345678901234567890123456789012345678901234567890123456789012345
73249401Sjilles00             TCP Connections                       TCP Packets
74249401Sjilles01999999999999 connections initiated    999999999999 total packets sent
75249401Sjilles02999999999999 connections accepted     999999999999 - data
76249401Sjilles03999999999999 connections established  999999999999 - data (retransmit by dupack)
77249401Sjilles04999999999999 connections dropped      999999999999 - data (retransmit by sack)
78249401Sjilles05999999999999 - in embryonic state     999999999999 - ack-only
79249401Sjilles06999999999999 - on retransmit timeout  999999999999 - window probes
80178256Sdelphij07999999999999 - by keepalive           999999999999 - window updates
81178256Sdelphij08999999999999 - from listen queue      999999999999 - urgent data only
82178256Sdelphij09                                      999999999999 - control
83178256Sdelphij10                                      999999999999 - resends by PMTU discovery
84178253Sdelphij11             TCP Timers               999999999999 total packets received
8523668Speter12999999999999 potential rtt updates    999999999999 - in sequence
8623668Speter13999999999999 - successful             999999999999 - completely duplicate
8723668Speter14999999999999 delayed acks sent        999999999999 - with some duplicate data
88249401Sjilles15999999999999 retransmit timeouts      999999999999 - out-of-order
89249401Sjilles16999999999999 persist timeouts         999999999999 - duplicate acks
9023768Sbde17999999999999 keepalive probes         999999999999 - acks
91178256Sdelphij18999999999999 - timeouts               999999999999 - window probes
92178256Sdelphij19                                      999999999999 - window updates
93178256Sdelphij20                                      999999999999 - bad checksum
94178256Sdelphij--0123456789012345678901234567890123456789012345678901234567890123456789012345
95201604Skib--0         1         2         3         4         5         6         7
96202679Sache*/
97201604Skib
98201604SkibWINDOW *
99202572Sacheopentcp(void)
100201604Skib{
101201604Skib	return (subwin(stdscr, LINES-3-1, 0, MAINWIN_ROW, 0));
102201604Skib}
103201604Skib
104178256Sdelphijvoid
105178256Sdelphijclosetcp(WINDOW *w)
106178256Sdelphij{
107178256Sdelphij	if (w == NULL)
108178256Sdelphij		return;
109178256Sdelphij	wclear(w);
110178256Sdelphij	wrefresh(w);
111178256Sdelphij	delwin(w);
112178256Sdelphij}
113178256Sdelphij
114249401Sjillesvoid
115249401Sjilleslabeltcp(void)
11623668Speter{
117133723Sstefanf	wmove(wnd, 0, 0); wclrtoeol(wnd);
11869841Sdeischen#define L(row, str) mvwprintw(wnd, row, 13, str)
11969841Sdeischen#define R(row, str) mvwprintw(wnd, row, 51, str);
12069841Sdeischen	L(0, "TCP Connections");		R(0, "TCP Packets");
1211573Srgrimes	L(1, "connections initiated");		R(1, "total packets sent");
12223768Sbde	L(2, "connections accepted");		R(2, "- data");
12323668Speter	L(3, "connections established");	R(3, "- data (retransmit by dupack)");
12471579Sdeischen	L(4, "connections dropped");		R(4, "- data (retransmit by sack)");
1251573Srgrimes	L(5, "- in embryonic state");		R(5, "- ack-only");
12623668Speter	L(6, "- on retransmit timeout");	R(6, "- window probes");
12723668Speter	L(7, "- by keepalive");			R(7, "- window updates");
12823668Speter	L(8, "- from listen queue");		R(8, "- urgent data only");
12923668Speter						R(9, "- control");
13023668Speter						R(10, "- resends by PMTU discovery");
13123668Speter	L(11, "TCP Timers");			R(11, "total packets received");
13223668Speter	L(12, "potential rtt updates");		R(12, "- in sequence");
13323668Speter	L(13, "- successful");			R(13, "- completely duplicate");
13423668Speter	L(14, "delayed acks sent");		R(14, "- with some duplicate data");
13523668Speter	L(15, "retransmit timeouts");		R(15, "- out-of-order");
13671579Sdeischen	L(16, "persist timeouts");		R(16, "- duplicate acks");
13723768Sbde	L(17, "keepalive probes");		R(17, "- acks");
138115047Stjr	L(18, "- timeouts");			R(18, "- window probes");
13975860Sjoerg						R(19, "- window updates");
14023668Speter						R(20, "- bad checksum");
14123668Speter#undef L
14223668Speter#undef R
14323668Speter}
14423668Speter
14523668Speterstatic void
14623668Speterdomode(struct tcpstat *ret)
14723668Speter{
14823668Speter	const struct tcpstat *sub;
14923668Speter	int divisor = 1;
15023668Speter
15123668Speter	switch(currentmode) {
15223668Speter	case display_RATE:
15323668Speter		sub = &oldstat;
15423668Speter		divisor = naptime;
15523668Speter		break;
15623668Speter	case display_DELTA:
15723668Speter		sub = &oldstat;
15823668Speter		break;
15923668Speter	case display_SINCE:
16023668Speter		sub = &initstat;
16123668Speter		break;
16223668Speter	default:
16371579Sdeischen		*ret = curstat;
16423668Speter		return;
16523668Speter	}
16623668Speter#define DO(stat) ret->stat = (curstat.stat - sub->stat) / divisor
16723668Speter	DO(tcps_connattempt);
16839327Simp	DO(tcps_accepts);
16923768Sbde	DO(tcps_connects);
17023768Sbde	DO(tcps_drops);
17123668Speter	DO(tcps_conndrops);
17223668Speter	DO(tcps_closed);
17323668Speter	DO(tcps_segstimed);
17471579Sdeischen	DO(tcps_rttupdated);
17523668Speter	DO(tcps_delack);
17623668Speter	DO(tcps_timeoutdrop);
17723668Speter	DO(tcps_rexmttimeo);
17823668Speter	DO(tcps_persisttimeo);
17923668Speter	DO(tcps_keeptimeo);
18023668Speter	DO(tcps_keepprobe);
18123668Speter	DO(tcps_keepdrops);
18223668Speter
18323668Speter	DO(tcps_sndtotal);
18423668Speter	DO(tcps_sndpack);
18523668Speter	DO(tcps_sndbyte);
18623668Speter	DO(tcps_sndrexmitpack);
18723668Speter	DO(tcps_sack_rexmits);
18823668Speter	DO(tcps_sndacks);
18923668Speter	DO(tcps_sndprobe);
19023668Speter	DO(tcps_sndurg);
19123668Speter	DO(tcps_sndwinup);
19256698Sjasone	DO(tcps_sndctrl);
193261813Sjilles
194261813Sjilles	DO(tcps_rcvtotal);
19523768Sbde	DO(tcps_rcvpack);
19623668Speter	DO(tcps_rcvbyte);
19723668Speter	DO(tcps_rcvbadsum);
19823768Sbde	DO(tcps_rcvbadoff);
19923668Speter	DO(tcps_rcvshort);
20023668Speter	DO(tcps_rcvduppack);
20123668Speter	DO(tcps_rcvdupbyte);
20223668Speter	DO(tcps_rcvpartduppack);
20323668Speter	DO(tcps_rcvpartdupbyte);
20423668Speter	DO(tcps_rcvoopack);
20523668Speter	DO(tcps_rcvoobyte);
20623668Speter	DO(tcps_rcvpackafterwin);
20723668Speter	DO(tcps_rcvbyteafterwin);
20823668Speter	DO(tcps_rcvafterclose);
20923668Speter	DO(tcps_rcvwinprobe);
21023668Speter	DO(tcps_rcvdupack);
21123668Speter	DO(tcps_rcvacktoomuch);
21223668Speter	DO(tcps_rcvackpack);
21323668Speter	DO(tcps_rcvackbyte);
21423668Speter	DO(tcps_rcvwinupd);
21523668Speter	DO(tcps_pawsdrop);
21623668Speter	DO(tcps_predack);
21723668Speter	DO(tcps_preddat);
21823668Speter	DO(tcps_pcbcachemiss);
21923668Speter	DO(tcps_cachedrtt);
22023668Speter	DO(tcps_cachedrttvar);
22123668Speter	DO(tcps_cachedssthresh);
22223668Speter	DO(tcps_usedrtt);
22334357Sjb	DO(tcps_usedrttvar);
22423668Speter	DO(tcps_usedssthresh);
22523668Speter	DO(tcps_persistdrop);
22623668Speter	DO(tcps_badsyn);
22723668Speter	DO(tcps_mturesent);
22823668Speter	DO(tcps_listendrop);
22923668Speter#undef DO
23023668Speter}
23123668Speter
23223668Spetervoid
23323668Spetershowtcp(void)
23423668Speter{
23523668Speter	struct tcpstat stats;
23623668Speter
23723668Speter	memset(&stats, 0, sizeof stats);
23823668Speter	domode(&stats);
23923668Speter
24023668Speter#define DO(stat, row, col) \
24123668Speter	mvwprintw(wnd, row, col, "%12lu", stats.stat)
242201604Skib#define	L(row, stat) DO(stat, row, 0)
243202679Sache#define	R(row, stat) DO(stat, row, 38)
24423668Speter	L(1, tcps_connattempt);		R(1, tcps_sndtotal);
24523668Speter	L(2, tcps_accepts);		R(2, tcps_sndpack);
24623668Speter	L(3, tcps_connects);		R(3, tcps_sndrexmitpack);
24723668Speter	L(4, tcps_drops);		R(4, tcps_sack_rexmits);
24823668Speter	L(5, tcps_conndrops);		R(5, tcps_sndacks);
24923668Speter	L(6, tcps_timeoutdrop);		R(6, tcps_sndprobe);
25023668Speter	L(7, tcps_keepdrops);		R(7, tcps_sndwinup);
25123668Speter	L(8, tcps_listendrop);		R(8, tcps_sndurg);
25223668Speter					R(9, tcps_sndctrl);
25323668Speter					R(10, tcps_mturesent);
25423668Speter					R(11, tcps_rcvtotal);
25523668Speter	L(12, tcps_segstimed);		R(12, tcps_rcvpack);
25623668Speter	L(13, tcps_rttupdated);		R(13, tcps_rcvduppack);
25723668Speter	L(14, tcps_delack);		R(14, tcps_rcvpartduppack);
25823668Speter	L(15, tcps_rexmttimeo);		R(15, tcps_rcvoopack);
25923668Speter	L(16, tcps_persisttimeo);	R(16, tcps_rcvdupack);
26023668Speter	L(17, tcps_keepprobe);		R(17, tcps_rcvackpack);
26123668Speter	L(18, tcps_keeptimeo);		R(18, tcps_rcvwinprobe);
26223668Speter					R(19, tcps_rcvwinupd);
26323668Speter					R(20, tcps_rcvbadsum);
26423668Speter#undef DO
26523668Speter#undef L
26623668Speter#undef R
26723668Speter}
26823668Speter
26923668Speterint
27023668Speterinittcp(void)
27123668Speter{
27223668Speter	size_t len;
27323668Speter	int name[4];
27423668Speter
27523668Speter	name[0] = CTL_NET;
27623668Speter	name[1] = PF_INET;
27723668Speter	name[2] = IPPROTO_TCP;
27823668Speter	name[3] = TCPCTL_STATS;
27923668Speter
280123861Sdfr	len = 0;
28123668Speter	if (sysctl(name, 4, 0, &len, 0, 0) < 0) {
28223768Sbde		error("sysctl getting tcpstat size failed");
28323768Sbde		return 0;
28423668Speter	}
28523668Speter	if (len > sizeof curstat) {
28623668Speter		error("tcpstat structure has grown--recompile systat!");
28723668Speter		return 0;
28823668Speter	}
2891573Srgrimes	if (sysctl(name, 4, &initstat, &len, 0, 0) < 0) {
29023668Speter		error("sysctl getting tcpstat failed");
29171579Sdeischen		return 0;
29223668Speter	}
2931573Srgrimes	oldstat = initstat;
2941573Srgrimes	return 1;
2951573Srgrimes}
2961573Srgrimes
2977978Sbdevoid
29823668Speterresettcp(void)
29923768Sbde{
30023768Sbde	size_t len;
30123768Sbde	int name[4];
30223768Sbde
30356698Sjasone	name[0] = CTL_NET;
30423768Sbde	name[1] = PF_INET;
30523768Sbde	name[2] = IPPROTO_TCP;
3061573Srgrimes	name[3] = TCPCTL_STATS;
307
308	len = sizeof initstat;
309	if (sysctl(name, 4, &initstat, &len, 0, 0) < 0) {
310		error("sysctl getting tcpstat failed");
311	}
312	oldstat = initstat;
313}
314
315void
316fetchtcp(void)
317{
318	int name[4];
319	size_t len;
320
321	oldstat = curstat;
322	name[0] = CTL_NET;
323	name[1] = PF_INET;
324	name[2] = IPPROTO_TCP;
325	name[3] = TCPCTL_STATS;
326	len = sizeof curstat;
327
328	if (sysctl(name, 4, &curstat, &len, 0, 0) < 0)
329		return;
330}
331
332