xref: /freebsd/cddl/lib/libdtrace/tcp.d (revision 2f28ceeb34d0de48ec59674099ac4ecbc1d15d8c)
157f60867SMark Johnston /*
257f60867SMark Johnston  * CDDL HEADER START
357f60867SMark Johnston  *
457f60867SMark Johnston  * The contents of this file are subject to the terms of the
557f60867SMark Johnston  * Common Development and Distribution License (the "License").
657f60867SMark Johnston  * You may not use this file except in compliance with the License.
757f60867SMark Johnston  *
857f60867SMark Johnston  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
957f60867SMark Johnston  * or http://www.opensolaris.org/os/licensing.
1057f60867SMark Johnston  * See the License for the specific language governing permissions
1157f60867SMark Johnston  * and limitations under the License.
1257f60867SMark Johnston  *
1357f60867SMark Johnston  * When distributing Covered Code, include this CDDL HEADER in each
1457f60867SMark Johnston  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1557f60867SMark Johnston  * If applicable, add the following below this CDDL HEADER, with the
1657f60867SMark Johnston  * fields enclosed by brackets "[]" replaced with your own identifying
1757f60867SMark Johnston  * information: Portions Copyright [yyyy] [name of copyright owner]
1857f60867SMark Johnston  *
1957f60867SMark Johnston  * CDDL HEADER END
2057f60867SMark Johnston  *
2157f60867SMark Johnston  * $FreeBSD$
2257f60867SMark Johnston  */
2357f60867SMark Johnston /*
2457f60867SMark Johnston  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
2557f60867SMark Johnston  * Copyright (c) 2013 Mark Johnston <markj@freebsd.org>
2657f60867SMark Johnston  */
2757f60867SMark Johnston 
2857f60867SMark Johnston #pragma D depends_on library ip.d
2957f60867SMark Johnston #pragma D depends_on provider tcp
3057f60867SMark Johnston 
3157f60867SMark Johnston /*
3257f60867SMark Johnston  * Convert a TCP state value to a string.
3357f60867SMark Johnston  */
34*2f28ceebSMark Johnston #pragma D binding "1.6.3" TCPS_CLOSED
3557f60867SMark Johnston inline int TCPS_CLOSED =	0;
36*2f28ceebSMark Johnston #pragma D binding "1.6.3" TCPS_LISTEN
3757f60867SMark Johnston inline int TCPS_LISTEN =	1;
38*2f28ceebSMark Johnston #pragma D binding "1.6.3" TCPS_SYN_SENT
3957f60867SMark Johnston inline int TCPS_SYN_SENT =	2;
40*2f28ceebSMark Johnston #pragma D binding "1.6.3" TCPS_SYN_RECEIVED
4157f60867SMark Johnston inline int TCPS_SYN_RECEIVED =	3;
42*2f28ceebSMark Johnston #pragma D binding "1.6.3" TCPS_ESTABLISHED
4357f60867SMark Johnston inline int TCPS_ESTABLISHED =	4;
44*2f28ceebSMark Johnston #pragma D binding "1.6.3" TCPS_CLOSE_WAIT
4557f60867SMark Johnston inline int TCPS_CLOSE_WAIT =	5;
46*2f28ceebSMark Johnston #pragma D binding "1.6.3" TCPS_FIN_WAIT_1
4757f60867SMark Johnston inline int TCPS_FIN_WAIT_1 =	6;
48*2f28ceebSMark Johnston #pragma D binding "1.6.3" TCPS_CLOSING
4957f60867SMark Johnston inline int TCPS_CLOSING =	7;
50*2f28ceebSMark Johnston #pragma D binding "1.6.3" TCPS_LAST_ACK
5157f60867SMark Johnston inline int TCPS_LAST_ACK =	8;
52*2f28ceebSMark Johnston #pragma D binding "1.6.3" TCPS_FIN_WAIT_2
5357f60867SMark Johnston inline int TCPS_FIN_WAIT_2 =	9;
54*2f28ceebSMark Johnston #pragma D binding "1.6.3" TCPS_TIME_WAIT
5557f60867SMark Johnston inline int TCPS_TIME_WAIT =	10;
5657f60867SMark Johnston 
5757f60867SMark Johnston /* TCP segment flags. */
58*2f28ceebSMark Johnston #pragma D binding "1.6.3" TH_FIN
5957f60867SMark Johnston inline uint8_t TH_FIN =		0x01;
60*2f28ceebSMark Johnston #pragma D binding "1.6.3" TH_SYN
6157f60867SMark Johnston inline uint8_t TH_SYN =		0x02;
62*2f28ceebSMark Johnston #pragma D binding "1.6.3" TH_RST
6357f60867SMark Johnston inline uint8_t TH_RST =		0x04;
64*2f28ceebSMark Johnston #pragma D binding "1.6.3" TH_PUSH
6557f60867SMark Johnston inline uint8_t TH_PUSH =	0x08;
66*2f28ceebSMark Johnston #pragma D binding "1.6.3" TH_ACK
6757f60867SMark Johnston inline uint8_t TH_ACK =		0x10;
68*2f28ceebSMark Johnston #pragma D binding "1.6.3" TH_URG
6957f60867SMark Johnston inline uint8_t TH_URG =		0x20;
70*2f28ceebSMark Johnston #pragma D binding "1.6.3" TH_ECE
7157f60867SMark Johnston inline uint8_t TH_ECE =		0x40;
72*2f28ceebSMark Johnston #pragma D binding "1.6.3" TH_CWR
7357f60867SMark Johnston inline uint8_t TH_CWR =		0x80;
7457f60867SMark Johnston 
7557f60867SMark Johnston /* TCP connection state strings. */
76*2f28ceebSMark Johnston #pragma D binding "1.6.3" tcp_state_string
7757f60867SMark Johnston inline string tcp_state_string[int32_t state] =
7857f60867SMark Johnston 	state == TCPS_CLOSED ?		"state-closed" :
7957f60867SMark Johnston 	state == TCPS_LISTEN ?		"state-listen" :
8057f60867SMark Johnston 	state == TCPS_SYN_SENT ?	"state-syn-sent" :
8157f60867SMark Johnston 	state == TCPS_SYN_RECEIVED ?	"state-syn-received" :
8257f60867SMark Johnston 	state == TCPS_ESTABLISHED ?	"state-established" :
8357f60867SMark Johnston 	state == TCPS_CLOSE_WAIT ?	"state-close-wait" :
8457f60867SMark Johnston 	state == TCPS_FIN_WAIT_1 ?	"state-fin-wait-1" :
8557f60867SMark Johnston 	state == TCPS_CLOSING ?		"state-closing" :
8657f60867SMark Johnston 	state == TCPS_LAST_ACK ?	"state-last-ack" :
8757f60867SMark Johnston 	state == TCPS_FIN_WAIT_2 ?	"state-fin-wait-2" :
8857f60867SMark Johnston 	state == TCPS_TIME_WAIT ?	"state-time-wait" :
8957f60867SMark Johnston 	"<unknown>";
9057f60867SMark Johnston 
9157f60867SMark Johnston /*
9257f60867SMark Johnston  * tcpsinfo contains stable TCP details from tcp_t.
9357f60867SMark Johnston  */
9457f60867SMark Johnston typedef struct tcpsinfo {
9557f60867SMark Johnston 	uintptr_t tcps_addr;
9657f60867SMark Johnston 	int tcps_local;			/* is delivered locally, boolean */
9757f60867SMark Johnston 	int tcps_active;		/* active open (from here), boolean */
9857f60867SMark Johnston 	uint16_t tcps_lport;		/* local port */
9957f60867SMark Johnston 	uint16_t tcps_rport;		/* remote port */
10057f60867SMark Johnston 	string tcps_laddr;		/* local address, as a string */
10157f60867SMark Johnston 	string tcps_raddr;		/* remote address, as a string */
10257f60867SMark Johnston 	int32_t tcps_state;		/* TCP state */
10357f60867SMark Johnston 	uint32_t tcps_iss;		/* Initial sequence # sent */
10457f60867SMark Johnston 	uint32_t tcps_suna;		/* sequence # sent but unacked */
10557f60867SMark Johnston 	uint32_t tcps_snxt;		/* next sequence # to send */
10657f60867SMark Johnston 	uint32_t tcps_rack;		/* sequence # we have acked */
10757f60867SMark Johnston 	uint32_t tcps_rnxt;		/* next sequence # expected */
10857f60867SMark Johnston 	uint32_t tcps_swnd;		/* send window size */
10957f60867SMark Johnston 	int32_t tcps_snd_ws;		/* send window scaling */
11057f60867SMark Johnston 	uint32_t tcps_rwnd;		/* receive window size */
11157f60867SMark Johnston 	int32_t tcps_rcv_ws;		/* receive window scaling */
11257f60867SMark Johnston 	uint32_t tcps_cwnd;		/* congestion window */
11357f60867SMark Johnston 	uint32_t tcps_cwnd_ssthresh;	/* threshold for congestion avoidance */
11457f60867SMark Johnston 	uint32_t tcps_sack_fack;	/* SACK sequence # we have acked */
11557f60867SMark Johnston 	uint32_t tcps_sack_snxt;	/* next SACK seq # for retransmission */
11657f60867SMark Johnston 	uint32_t tcps_rto;		/* round-trip timeout, msec */
11757f60867SMark Johnston 	uint32_t tcps_mss;		/* max segment size */
11857f60867SMark Johnston 	int tcps_retransmit;		/* retransmit send event, boolean */
11957f60867SMark Johnston } tcpsinfo_t;
12057f60867SMark Johnston 
12157f60867SMark Johnston /*
12257f60867SMark Johnston  * tcplsinfo provides the old tcp state for state changes.
12357f60867SMark Johnston  */
12457f60867SMark Johnston typedef struct tcplsinfo {
12557f60867SMark Johnston 	int32_t tcps_state;		/* previous TCP state */
12657f60867SMark Johnston } tcplsinfo_t;
12757f60867SMark Johnston 
12857f60867SMark Johnston /*
12957f60867SMark Johnston  * tcpinfo is the TCP header fields.
13057f60867SMark Johnston  */
13157f60867SMark Johnston typedef struct tcpinfo {
13257f60867SMark Johnston 	uint16_t tcp_sport;		/* source port */
13357f60867SMark Johnston 	uint16_t tcp_dport;		/* destination port */
13457f60867SMark Johnston 	uint32_t tcp_seq;		/* sequence number */
13557f60867SMark Johnston 	uint32_t tcp_ack;		/* acknowledgment number */
13657f60867SMark Johnston 	uint8_t tcp_offset;		/* data offset, in bytes */
13757f60867SMark Johnston 	uint8_t tcp_flags;		/* flags */
13857f60867SMark Johnston 	uint16_t tcp_window;		/* window size */
13957f60867SMark Johnston 	uint16_t tcp_checksum;		/* checksum */
14057f60867SMark Johnston 	uint16_t tcp_urgent;		/* urgent data pointer */
14157f60867SMark Johnston 	struct tcphdr *tcp_hdr;		/* raw TCP header */
14257f60867SMark Johnston } tcpinfo_t;
14357f60867SMark Johnston 
1448298c17cSMark Johnston /*
1458298c17cSMark Johnston  * A clone of tcpinfo_t used to handle the fact that the TCP input path
1468298c17cSMark Johnston  * overwrites some fields of the TCP header with their host-order equivalents.
1478298c17cSMark Johnston  * Unfortunately, DTrace doesn't let us simply typedef a new name for struct
1488298c17cSMark Johnston  * tcpinfo and define a separate translator for it.
1498298c17cSMark Johnston  */
1508298c17cSMark Johnston typedef struct tcpinfoh {
1518298c17cSMark Johnston 	uint16_t tcp_sport;		/* source port */
1528298c17cSMark Johnston 	uint16_t tcp_dport;		/* destination port */
1538298c17cSMark Johnston 	uint32_t tcp_seq;		/* sequence number */
1548298c17cSMark Johnston 	uint32_t tcp_ack;		/* acknowledgment number */
1558298c17cSMark Johnston 	uint8_t tcp_offset;		/* data offset, in bytes */
1568298c17cSMark Johnston 	uint8_t tcp_flags;		/* flags */
1578298c17cSMark Johnston 	uint16_t tcp_window;		/* window size */
1588298c17cSMark Johnston 	uint16_t tcp_checksum;		/* checksum */
1598298c17cSMark Johnston 	uint16_t tcp_urgent;		/* urgent data pointer */
1608298c17cSMark Johnston 	struct tcphdr *tcp_hdr;		/* raw TCP header */
1618298c17cSMark Johnston } tcpinfoh_t;
1628298c17cSMark Johnston 
163*2f28ceebSMark Johnston #pragma D binding "1.6.3" translator
16457f60867SMark Johnston translator csinfo_t < struct tcpcb *p > {
16557f60867SMark Johnston 	cs_addr =	NULL;
1669feec372SMark Johnston 	cs_cid =	(uint64_t)(p == NULL ? 0 : p->t_inpcb);
16757f60867SMark Johnston 	cs_pid =	0;
16857f60867SMark Johnston 	cs_zoneid =	0;
16957f60867SMark Johnston };
17057f60867SMark Johnston 
171*2f28ceebSMark Johnston #pragma D binding "1.6.3" translator
17257f60867SMark Johnston translator tcpsinfo_t < struct tcpcb *p > {
17357f60867SMark Johnston 	tcps_addr =		(uintptr_t)p;
17457f60867SMark Johnston 	tcps_local =		-1; /* XXX */
17557f60867SMark Johnston 	tcps_active =		-1; /* XXX */
17657f60867SMark Johnston 	tcps_lport =		p == NULL ? 0 : ntohs(p->t_inpcb->inp_inc.inc_ie.ie_lport);
17757f60867SMark Johnston 	tcps_rport =		p == NULL ? 0 : ntohs(p->t_inpcb->inp_inc.inc_ie.ie_fport);
17857f60867SMark Johnston 	tcps_laddr =		p == NULL ? 0 :
17957f60867SMark Johnston 	    p->t_inpcb->inp_vflag == INP_IPV4 ?
18057f60867SMark Johnston 	    inet_ntoa(&p->t_inpcb->inp_inc.inc_ie.ie_dependladdr.ie46_local.ia46_addr4.s_addr) :
18157f60867SMark Johnston 	    inet_ntoa6(&p->t_inpcb->inp_inc.inc_ie.ie_dependladdr.ie6_local);
18257f60867SMark Johnston 	tcps_raddr =		p == NULL ? 0 :
18357f60867SMark Johnston 	    p->t_inpcb->inp_vflag == INP_IPV4 ?
18457f60867SMark Johnston 	    inet_ntoa(&p->t_inpcb->inp_inc.inc_ie.ie_dependfaddr.ie46_foreign.ia46_addr4.s_addr) :
18557f60867SMark Johnston 	    inet_ntoa6(&p->t_inpcb->inp_inc.inc_ie.ie_dependfaddr.ie6_foreign);
18657f60867SMark Johnston 	tcps_state =		p == NULL ? -1 : p->t_state;
18757f60867SMark Johnston 	tcps_iss =		p == NULL ? 0  : p->iss;
18857f60867SMark Johnston 	tcps_suna =		p == NULL ? 0  : p->snd_una;
18957f60867SMark Johnston 	tcps_snxt =		p == NULL ? 0  : p->snd_nxt;
19057f60867SMark Johnston 	tcps_rack =		p == NULL ? 0  : p->last_ack_sent;
19157f60867SMark Johnston 	tcps_rnxt =		p == NULL ? 0  : p->rcv_nxt;
19257f60867SMark Johnston 	tcps_swnd =		p == NULL ? -1  : p->snd_wnd;
19357f60867SMark Johnston 	tcps_snd_ws =		p == NULL ? -1  : p->snd_scale;
19457f60867SMark Johnston 	tcps_rwnd =		p == NULL ? -1  : p->rcv_wnd;
19557f60867SMark Johnston 	tcps_rcv_ws =		p == NULL ? -1  : p->rcv_scale;
19657f60867SMark Johnston 	tcps_cwnd =		p == NULL ? -1  : p->snd_cwnd;
19757f60867SMark Johnston 	tcps_cwnd_ssthresh =	p == NULL ? -1  : p->snd_ssthresh;
19857f60867SMark Johnston 	tcps_sack_fack =	p == NULL ? 0  : p->snd_fack;
19957f60867SMark Johnston 	tcps_sack_snxt =	p == NULL ? 0  : p->sack_newdata;
20057f60867SMark Johnston 	tcps_rto =		p == NULL ? -1  : p->t_rxtcur / 1000; /* XXX */
20157f60867SMark Johnston 	tcps_mss =		p == NULL ? -1  : p->t_maxseg;
2028298c17cSMark Johnston 	tcps_retransmit =	p == NULL ? -1 : p->t_rxtshift > 0 ? 1 : 0;
20357f60867SMark Johnston };
20457f60867SMark Johnston 
205*2f28ceebSMark Johnston #pragma D binding "1.6.3" translator
20657f60867SMark Johnston translator tcpinfo_t < struct tcphdr *p > {
20757f60867SMark Johnston 	tcp_sport =	p == NULL ? 0  : ntohs(p->th_sport);
20857f60867SMark Johnston 	tcp_dport =	p == NULL ? 0  : ntohs(p->th_dport);
20957f60867SMark Johnston 	tcp_seq =	p == NULL ? -1 : ntohl(p->th_seq);
21057f60867SMark Johnston 	tcp_ack =	p == NULL ? -1 : ntohl(p->th_ack);
21157f60867SMark Johnston 	tcp_offset =	p == NULL ? -1 : (p->th_off >> 2);
21257f60867SMark Johnston 	tcp_flags =	p == NULL ? 0  : p->th_flags;
21357f60867SMark Johnston 	tcp_window =	p == NULL ? 0  : ntohs(p->th_win);
21457f60867SMark Johnston 	tcp_checksum =	p == NULL ? 0  : ntohs(p->th_sum);
21557f60867SMark Johnston 	tcp_urgent =	p == NULL ? 0  : ntohs(p->th_urp);
21657f60867SMark Johnston 	tcp_hdr =	(struct tcphdr *)p;
21757f60867SMark Johnston };
21857f60867SMark Johnston 
2198298c17cSMark Johnston /*
2208298c17cSMark Johnston  * This translator differs from the one for tcpinfo_t in that the sequence
2218298c17cSMark Johnston  * number, acknowledgement number, window size and urgent pointer are already
2228298c17cSMark Johnston  * in host order and thus don't need to be converted.
2238298c17cSMark Johnston  */
224*2f28ceebSMark Johnston #pragma D binding "1.6.3" translator
2258298c17cSMark Johnston translator tcpinfoh_t < struct tcphdr *p > {
2268298c17cSMark Johnston 	tcp_sport =	p == NULL ? 0  : ntohs(p->th_sport);
2278298c17cSMark Johnston 	tcp_dport =	p == NULL ? 0  : ntohs(p->th_dport);
2288298c17cSMark Johnston 	tcp_seq =	p == NULL ? -1 : p->th_seq;
2298298c17cSMark Johnston 	tcp_ack =	p == NULL ? -1 : p->th_ack;
2308298c17cSMark Johnston 	tcp_offset =	p == NULL ? -1 : (p->th_off >> 2);
2318298c17cSMark Johnston 	tcp_flags =	p == NULL ? 0  : p->th_flags;
2328298c17cSMark Johnston 	tcp_window =	p == NULL ? 0  : (p->th_win);
2338298c17cSMark Johnston 	tcp_checksum =	p == NULL ? 0  : ntohs(p->th_sum);
2348298c17cSMark Johnston 	tcp_urgent =	p == NULL ? 0  : p->th_urp;
2358298c17cSMark Johnston 	tcp_hdr =	(struct tcphdr *)p;
2368298c17cSMark Johnston };
2378298c17cSMark Johnston 
238*2f28ceebSMark Johnston #pragma D binding "1.6.3" translator
23957f60867SMark Johnston translator tcplsinfo_t < int s > {
24057f60867SMark Johnston 	tcps_state =	s;
24157f60867SMark Johnston };
242