tcp.d revision 273765
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 *
21 * $FreeBSD: stable/10/cddl/lib/libdtrace/tcp.d 273765 2014-10-28 06:17:25Z markj $
22 */
23/*
24 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
25 * Copyright (c) 2013 Mark Johnston <markj@freebsd.org>
26 */
27
28#pragma D depends_on library ip.d
29#pragma D depends_on provider tcp
30
31/*
32 * Convert a TCP state value to a string.
33 */
34#pragma D binding "1.0" TCPS_CLOSED
35inline int TCPS_CLOSED =	0;
36#pragma D binding "1.0" TCPS_LISTEN
37inline int TCPS_LISTEN =	1;
38#pragma D binding "1.0" TCPS_SYN_SENT
39inline int TCPS_SYN_SENT =	2;
40#pragma D binding "1.0" TCPS_SYN_RECEIVED
41inline int TCPS_SYN_RECEIVED =	3;
42#pragma D binding "1.0" TCPS_ESTABLISHED
43inline int TCPS_ESTABLISHED =	4;
44#pragma D binding "1.0" TCPS_CLOSE_WAIT
45inline int TCPS_CLOSE_WAIT =	5;
46#pragma D binding "1.0" TCPS_FIN_WAIT_1
47inline int TCPS_FIN_WAIT_1 =	6;
48#pragma D binding "1.0" TCPS_CLOSING
49inline int TCPS_CLOSING =	7;
50#pragma D binding "1.0" TCPS_LAST_ACK
51inline int TCPS_LAST_ACK =	8;
52#pragma D binding "1.0" TCPS_FIN_WAIT_2
53inline int TCPS_FIN_WAIT_2 =	9;
54#pragma D binding "1.0" TCPS_TIME_WAIT
55inline int TCPS_TIME_WAIT =	10;
56
57/* TCP segment flags. */
58#pragma D binding "1.0" TH_FIN
59inline uint8_t TH_FIN =		0x01;
60#pragma D binding "1.0" TH_SYN
61inline uint8_t TH_SYN =		0x02;
62#pragma D binding "1.0" TH_RST
63inline uint8_t TH_RST =		0x04;
64#pragma D binding "1.0" TH_PUSH
65inline uint8_t TH_PUSH =	0x08;
66#pragma D binding "1.0" TH_ACK
67inline uint8_t TH_ACK =		0x10;
68#pragma D binding "1.0" TH_URG
69inline uint8_t TH_URG =		0x20;
70#pragma D binding "1.0" TH_ECE
71inline uint8_t TH_ECE =		0x40;
72#pragma D binding "1.0" TH_CWR
73inline uint8_t TH_CWR =		0x80;
74
75/* TCP connection state strings. */
76#pragma D binding "1.0" tcp_state_string
77inline string tcp_state_string[int32_t state] =
78	state == TCPS_CLOSED ?		"state-closed" :
79	state == TCPS_LISTEN ?		"state-listen" :
80	state == TCPS_SYN_SENT ?	"state-syn-sent" :
81	state == TCPS_SYN_RECEIVED ?	"state-syn-received" :
82	state == TCPS_ESTABLISHED ?	"state-established" :
83	state == TCPS_CLOSE_WAIT ?	"state-close-wait" :
84	state == TCPS_FIN_WAIT_1 ?	"state-fin-wait-1" :
85	state == TCPS_CLOSING ?		"state-closing" :
86	state == TCPS_LAST_ACK ?	"state-last-ack" :
87	state == TCPS_FIN_WAIT_2 ?	"state-fin-wait-2" :
88	state == TCPS_TIME_WAIT ?	"state-time-wait" :
89	"<unknown>";
90
91/*
92 * tcpsinfo contains stable TCP details from tcp_t.
93 */
94typedef struct tcpsinfo {
95	uintptr_t tcps_addr;
96	int tcps_local;			/* is delivered locally, boolean */
97	int tcps_active;		/* active open (from here), boolean */
98	uint16_t tcps_lport;		/* local port */
99	uint16_t tcps_rport;		/* remote port */
100	string tcps_laddr;		/* local address, as a string */
101	string tcps_raddr;		/* remote address, as a string */
102	int32_t tcps_state;		/* TCP state */
103	uint32_t tcps_iss;		/* Initial sequence # sent */
104	uint32_t tcps_suna;		/* sequence # sent but unacked */
105	uint32_t tcps_snxt;		/* next sequence # to send */
106	uint32_t tcps_rack;		/* sequence # we have acked */
107	uint32_t tcps_rnxt;		/* next sequence # expected */
108	uint32_t tcps_swnd;		/* send window size */
109	int32_t tcps_snd_ws;		/* send window scaling */
110	uint32_t tcps_rwnd;		/* receive window size */
111	int32_t tcps_rcv_ws;		/* receive window scaling */
112	uint32_t tcps_cwnd;		/* congestion window */
113	uint32_t tcps_cwnd_ssthresh;	/* threshold for congestion avoidance */
114	uint32_t tcps_sack_fack;	/* SACK sequence # we have acked */
115	uint32_t tcps_sack_snxt;	/* next SACK seq # for retransmission */
116	uint32_t tcps_rto;		/* round-trip timeout, msec */
117	uint32_t tcps_mss;		/* max segment size */
118	int tcps_retransmit;		/* retransmit send event, boolean */
119} tcpsinfo_t;
120
121/*
122 * tcplsinfo provides the old tcp state for state changes.
123 */
124typedef struct tcplsinfo {
125	int32_t tcps_state;		/* previous TCP state */
126} tcplsinfo_t;
127
128/*
129 * tcpinfo is the TCP header fields.
130 */
131typedef struct tcpinfo {
132	uint16_t tcp_sport;		/* source port */
133	uint16_t tcp_dport;		/* destination port */
134	uint32_t tcp_seq;		/* sequence number */
135	uint32_t tcp_ack;		/* acknowledgment number */
136	uint8_t tcp_offset;		/* data offset, in bytes */
137	uint8_t tcp_flags;		/* flags */
138	uint16_t tcp_window;		/* window size */
139	uint16_t tcp_checksum;		/* checksum */
140	uint16_t tcp_urgent;		/* urgent data pointer */
141	struct tcphdr *tcp_hdr;		/* raw TCP header */
142} tcpinfo_t;
143
144/*
145 * A clone of tcpinfo_t used to handle the fact that the TCP input path
146 * overwrites some fields of the TCP header with their host-order equivalents.
147 * Unfortunately, DTrace doesn't let us simply typedef a new name for struct
148 * tcpinfo and define a separate translator for it.
149 */
150typedef struct tcpinfoh {
151	uint16_t tcp_sport;		/* source port */
152	uint16_t tcp_dport;		/* destination port */
153	uint32_t tcp_seq;		/* sequence number */
154	uint32_t tcp_ack;		/* acknowledgment number */
155	uint8_t tcp_offset;		/* data offset, in bytes */
156	uint8_t tcp_flags;		/* flags */
157	uint16_t tcp_window;		/* window size */
158	uint16_t tcp_checksum;		/* checksum */
159	uint16_t tcp_urgent;		/* urgent data pointer */
160	struct tcphdr *tcp_hdr;		/* raw TCP header */
161} tcpinfoh_t;
162
163#pragma D binding "1.0" translator
164translator csinfo_t < struct tcpcb *p > {
165	cs_addr =	NULL;
166	cs_cid =	(uint64_t)(p == NULL ? 0 : p->t_inpcb);
167	cs_pid =	0;
168	cs_zoneid =	0;
169};
170
171#pragma D binding "1.0" translator
172translator tcpsinfo_t < struct tcpcb *p > {
173	tcps_addr =		(uintptr_t)p;
174	tcps_local =		-1; /* XXX */
175	tcps_active =		-1; /* XXX */
176	tcps_lport =		p == NULL ? 0 : ntohs(p->t_inpcb->inp_inc.inc_ie.ie_lport);
177	tcps_rport =		p == NULL ? 0 : ntohs(p->t_inpcb->inp_inc.inc_ie.ie_fport);
178	tcps_laddr =		p == NULL ? 0 :
179	    p->t_inpcb->inp_vflag == INP_IPV4 ?
180	    inet_ntoa(&p->t_inpcb->inp_inc.inc_ie.ie_dependladdr.ie46_local.ia46_addr4.s_addr) :
181	    inet_ntoa6(&p->t_inpcb->inp_inc.inc_ie.ie_dependladdr.ie6_local);
182	tcps_raddr =		p == NULL ? 0 :
183	    p->t_inpcb->inp_vflag == INP_IPV4 ?
184	    inet_ntoa(&p->t_inpcb->inp_inc.inc_ie.ie_dependfaddr.ie46_foreign.ia46_addr4.s_addr) :
185	    inet_ntoa6(&p->t_inpcb->inp_inc.inc_ie.ie_dependfaddr.ie6_foreign);
186	tcps_state =		p == NULL ? -1 : p->t_state;
187	tcps_iss =		p == NULL ? 0  : p->iss;
188	tcps_suna =		p == NULL ? 0  : p->snd_una;
189	tcps_snxt =		p == NULL ? 0  : p->snd_nxt;
190	tcps_rack =		p == NULL ? 0  : p->last_ack_sent;
191	tcps_rnxt =		p == NULL ? 0  : p->rcv_nxt;
192	tcps_swnd =		p == NULL ? -1  : p->snd_wnd;
193	tcps_snd_ws =		p == NULL ? -1  : p->snd_scale;
194	tcps_rwnd =		p == NULL ? -1  : p->rcv_wnd;
195	tcps_rcv_ws =		p == NULL ? -1  : p->rcv_scale;
196	tcps_cwnd =		p == NULL ? -1  : p->snd_cwnd;
197	tcps_cwnd_ssthresh =	p == NULL ? -1  : p->snd_ssthresh;
198	tcps_sack_fack =	p == NULL ? 0  : p->snd_fack;
199	tcps_sack_snxt =	p == NULL ? 0  : p->sack_newdata;
200	tcps_rto =		p == NULL ? -1 : (p->t_rxtcur * 1000) / `hz;
201	tcps_mss =		p == NULL ? -1  : p->t_maxseg;
202	tcps_retransmit =	p == NULL ? -1 : p->t_rxtshift > 0 ? 1 : 0;
203};
204
205#pragma D binding "1.0" translator
206translator tcpinfo_t < struct tcphdr *p > {
207	tcp_sport =	p == NULL ? 0  : ntohs(p->th_sport);
208	tcp_dport =	p == NULL ? 0  : ntohs(p->th_dport);
209	tcp_seq =	p == NULL ? -1 : ntohl(p->th_seq);
210	tcp_ack =	p == NULL ? -1 : ntohl(p->th_ack);
211	tcp_offset =	p == NULL ? -1 : (p->th_off >> 2);
212	tcp_flags =	p == NULL ? 0  : p->th_flags;
213	tcp_window =	p == NULL ? 0  : ntohs(p->th_win);
214	tcp_checksum =	p == NULL ? 0  : ntohs(p->th_sum);
215	tcp_urgent =	p == NULL ? 0  : ntohs(p->th_urp);
216	tcp_hdr =	(struct tcphdr *)p;
217};
218
219/*
220 * This translator differs from the one for tcpinfo_t in that the sequence
221 * number, acknowledgement number, window size and urgent pointer are already
222 * in host order and thus don't need to be converted.
223 */
224#pragma D binding "1.0" translator
225translator tcpinfoh_t < struct tcphdr *p > {
226	tcp_sport =	p == NULL ? 0  : ntohs(p->th_sport);
227	tcp_dport =	p == NULL ? 0  : ntohs(p->th_dport);
228	tcp_seq =	p == NULL ? -1 : p->th_seq;
229	tcp_ack =	p == NULL ? -1 : p->th_ack;
230	tcp_offset =	p == NULL ? -1 : (p->th_off >> 2);
231	tcp_flags =	p == NULL ? 0  : p->th_flags;
232	tcp_window =	p == NULL ? 0  : (p->th_win);
233	tcp_checksum =	p == NULL ? 0  : ntohs(p->th_sum);
234	tcp_urgent =	p == NULL ? 0  : p->th_urp;
235	tcp_hdr =	(struct tcphdr *)p;
236};
237
238#pragma D binding "1.0" translator
239translator tcplsinfo_t < int s > {
240	tcps_state =	s;
241};
242