xref: /freebsd/cddl/lib/libdtrace/tcp.d (revision 49b49cda41feabe3439f7318e8bf40e3896c7bf4)
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$
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 module kernel
30 #pragma D depends_on provider tcp
31 
32 /*
33  * Convert a TCP state value to a string.
34  */
35 #pragma D binding "1.6.3" TCPS_CLOSED
36 inline int TCPS_CLOSED =	0;
37 #pragma D binding "1.6.3" TCPS_LISTEN
38 inline int TCPS_LISTEN =	1;
39 #pragma D binding "1.6.3" TCPS_SYN_SENT
40 inline int TCPS_SYN_SENT =	2;
41 #pragma D binding "1.6.3" TCPS_SYN_RECEIVED
42 inline int TCPS_SYN_RECEIVED =	3;
43 #pragma D binding "1.6.3" TCPS_ESTABLISHED
44 inline int TCPS_ESTABLISHED =	4;
45 #pragma D binding "1.6.3" TCPS_CLOSE_WAIT
46 inline int TCPS_CLOSE_WAIT =	5;
47 #pragma D binding "1.6.3" TCPS_FIN_WAIT_1
48 inline int TCPS_FIN_WAIT_1 =	6;
49 #pragma D binding "1.6.3" TCPS_CLOSING
50 inline int TCPS_CLOSING =	7;
51 #pragma D binding "1.6.3" TCPS_LAST_ACK
52 inline int TCPS_LAST_ACK =	8;
53 #pragma D binding "1.6.3" TCPS_FIN_WAIT_2
54 inline int TCPS_FIN_WAIT_2 =	9;
55 #pragma D binding "1.6.3" TCPS_TIME_WAIT
56 inline int TCPS_TIME_WAIT =	10;
57 
58 /* TCP segment flags. */
59 #pragma D binding "1.6.3" TH_FIN
60 inline uint8_t TH_FIN =		0x01;
61 #pragma D binding "1.6.3" TH_SYN
62 inline uint8_t TH_SYN =		0x02;
63 #pragma D binding "1.6.3" TH_RST
64 inline uint8_t TH_RST =		0x04;
65 #pragma D binding "1.6.3" TH_PUSH
66 inline uint8_t TH_PUSH =	0x08;
67 #pragma D binding "1.6.3" TH_ACK
68 inline uint8_t TH_ACK =		0x10;
69 #pragma D binding "1.6.3" TH_URG
70 inline uint8_t TH_URG =		0x20;
71 #pragma D binding "1.6.3" TH_ECE
72 inline uint8_t TH_ECE =		0x40;
73 #pragma D binding "1.6.3" TH_CWR
74 inline uint8_t TH_CWR =		0x80;
75 
76 /* TCP connection state strings. */
77 #pragma D binding "1.6.3" tcp_state_string
78 inline string tcp_state_string[int32_t state] =
79 	state == TCPS_CLOSED ?		"state-closed" :
80 	state == TCPS_LISTEN ?		"state-listen" :
81 	state == TCPS_SYN_SENT ?	"state-syn-sent" :
82 	state == TCPS_SYN_RECEIVED ?	"state-syn-received" :
83 	state == TCPS_ESTABLISHED ?	"state-established" :
84 	state == TCPS_CLOSE_WAIT ?	"state-close-wait" :
85 	state == TCPS_FIN_WAIT_1 ?	"state-fin-wait-1" :
86 	state == TCPS_CLOSING ?		"state-closing" :
87 	state == TCPS_LAST_ACK ?	"state-last-ack" :
88 	state == TCPS_FIN_WAIT_2 ?	"state-fin-wait-2" :
89 	state == TCPS_TIME_WAIT ?	"state-time-wait" :
90 	"<unknown>";
91 
92 /*
93  * tcpsinfo contains stable TCP details from tcp_t.
94  */
95 typedef struct tcpsinfo {
96 	uintptr_t tcps_addr;
97 	int tcps_local;			/* is delivered locally, boolean */
98 	int tcps_active;		/* active open (from here), boolean */
99 	uint16_t tcps_lport;		/* local port */
100 	uint16_t tcps_rport;		/* remote port */
101 	string tcps_laddr;		/* local address, as a string */
102 	string tcps_raddr;		/* remote address, as a string */
103 	int32_t tcps_state;		/* TCP state */
104 	uint32_t tcps_iss;		/* Initial sequence # sent */
105 	uint32_t tcps_suna;		/* sequence # sent but unacked */
106 	uint32_t tcps_smax;		/* highest sequence number sent */
107 	uint32_t tcps_snxt;		/* next sequence # to send */
108 	uint32_t tcps_rack;		/* sequence # we have acked */
109 	uint32_t tcps_rnxt;		/* next sequence # expected */
110 	uint32_t tcps_swnd;		/* send window size */
111 	int32_t tcps_snd_ws;		/* send window scaling */
112 	uint32_t tcps_swl1;		/* window update seg seq number */
113 	uint32_t tcps_swl2;		/* window update seg ack number */
114 	uint32_t tcps_rup;		/* receive urgent pointer */
115 	uint32_t tcps_rwnd;		/* receive window size */
116 	int32_t tcps_rcv_ws;		/* receive window scaling */
117 	uint32_t tcps_cwnd;		/* congestion window */
118 	uint32_t tcps_cwnd_ssthresh;	/* threshold for congestion avoidance */
119 	uint32_t tcps_sack_fack;	/* SACK sequence # we have acked */
120 	uint32_t tcps_sack_snxt;	/* next SACK seq # for retransmission */
121 	uint32_t tcps_rto;		/* round-trip timeout, msec */
122 	uint32_t tcps_mss;		/* max segment size */
123 	int tcps_retransmit;		/* retransmit send event, boolean */
124 	int tcps_srtt;			/* smoothed RTT in units of (TCP_RTT_SCALE*hz) */
125 	int tcps_debug;		/* socket has SO_DEBUG set */
126 } tcpsinfo_t;
127 
128 /*
129  * tcplsinfo provides the old tcp state for state changes.
130  */
131 typedef struct tcplsinfo {
132 	int32_t tcps_state;		/* previous TCP state */
133 } tcplsinfo_t;
134 
135 /*
136  * tcpinfo is the TCP header fields.
137  */
138 typedef struct tcpinfo {
139 	uint16_t tcp_sport;		/* source port */
140 	uint16_t tcp_dport;		/* destination port */
141 	uint32_t tcp_seq;		/* sequence number */
142 	uint32_t tcp_ack;		/* acknowledgment number */
143 	uint8_t tcp_offset;		/* data offset, in bytes */
144 	uint8_t tcp_flags;		/* flags */
145 	uint16_t tcp_window;		/* window size */
146 	uint16_t tcp_checksum;		/* checksum */
147 	uint16_t tcp_urgent;		/* urgent data pointer */
148 	struct tcphdr *tcp_hdr;		/* raw TCP header */
149 } tcpinfo_t;
150 
151 /*
152  * A clone of tcpinfo_t used to handle the fact that the TCP input path
153  * overwrites some fields of the TCP header with their host-order equivalents.
154  * Unfortunately, DTrace doesn't let us simply typedef a new name for struct
155  * tcpinfo and define a separate translator for it.
156  */
157 typedef struct tcpinfoh {
158 	uint16_t tcp_sport;		/* source port */
159 	uint16_t tcp_dport;		/* destination port */
160 	uint32_t tcp_seq;		/* sequence number */
161 	uint32_t tcp_ack;		/* acknowledgment number */
162 	uint8_t tcp_offset;		/* data offset, in bytes */
163 	uint8_t tcp_flags;		/* flags */
164 	uint16_t tcp_window;		/* window size */
165 	uint16_t tcp_checksum;		/* checksum */
166 	uint16_t tcp_urgent;		/* urgent data pointer */
167 	struct tcphdr *tcp_hdr;		/* raw TCP header */
168 } tcpinfoh_t;
169 
170 #pragma D binding "1.6.3" translator
171 translator csinfo_t < struct tcpcb *p > {
172 	cs_addr =	NULL;
173 	cs_cid =	(uint64_t)(p == NULL ? 0 : p->t_inpcb);
174 	cs_pid =	0;
175 	cs_zoneid =	0;
176 };
177 
178 #pragma D binding "1.6.3" translator
179 translator tcpsinfo_t < struct tcpcb *p > {
180 	tcps_addr =		(uintptr_t)p;
181 	tcps_local =		-1; /* XXX */
182 	tcps_active =		-1; /* XXX */
183 	tcps_lport =		p == NULL ? 0 : ntohs(p->t_inpcb->inp_inc.inc_ie.ie_lport);
184 	tcps_rport =		p == NULL ? 0 : ntohs(p->t_inpcb->inp_inc.inc_ie.ie_fport);
185 	tcps_laddr =		p == NULL ? 0 :
186 	    p->t_inpcb->inp_vflag == INP_IPV4 ?
187 	    inet_ntoa(&p->t_inpcb->inp_inc.inc_ie.ie_dependladdr.ie46_local.ia46_addr4.s_addr) :
188 	    inet_ntoa6(&p->t_inpcb->inp_inc.inc_ie.ie_dependladdr.ie6_local);
189 	tcps_raddr =		p == NULL ? 0 :
190 	    p->t_inpcb->inp_vflag == INP_IPV4 ?
191 	    inet_ntoa(&p->t_inpcb->inp_inc.inc_ie.ie_dependfaddr.ie46_foreign.ia46_addr4.s_addr) :
192 	    inet_ntoa6(&p->t_inpcb->inp_inc.inc_ie.ie_dependfaddr.ie6_foreign);
193 	tcps_state =		p == NULL ? -1 : p->t_state;
194 	tcps_iss =		p == NULL ? 0  : p->iss;
195 	tcps_suna =		p == NULL ? 0  : p->snd_una;
196 	tcps_smax =		p == NULL ? 0  : p->snd_max;
197 	tcps_snxt =		p == NULL ? 0  : p->snd_nxt;
198 	tcps_rack =		p == NULL ? 0  : p->last_ack_sent;
199 	tcps_rnxt =		p == NULL ? 0  : p->rcv_nxt;
200 	tcps_swnd =		p == NULL ? -1  : p->snd_wnd;
201 	tcps_snd_ws =		p == NULL ? -1  : p->snd_scale;
202 	tcps_swl1 =		p == NULL ? -1  : p->snd_wl1;
203 	tcps_swl2 = 		p == NULL ? -1  : p->snd_wl2;
204 	tcps_rwnd =		p == NULL ? -1  : p->rcv_wnd;
205 	tcps_rup =		p == NULL ? -1  : p->rcv_up;
206 	tcps_rcv_ws =		p == NULL ? -1  : p->rcv_scale;
207 	tcps_cwnd =		p == NULL ? -1  : p->snd_cwnd;
208 	tcps_cwnd_ssthresh =	p == NULL ? -1  : p->snd_ssthresh;
209 	tcps_sack_fack =	p == NULL ? 0  : p->snd_fack;
210 	tcps_sack_snxt =	p == NULL ? 0  : p->sack_newdata;
211 	tcps_rto =		p == NULL ? -1 : (p->t_rxtcur * 1000) / `hz;
212 	tcps_mss =		p == NULL ? -1  : p->t_maxseg;
213 	tcps_retransmit =	p == NULL ? -1 : p->t_rxtshift > 0 ? 1 : 0;
214 	tcps_srtt =             p == NULL ? -1  : p->t_srtt;   /* smoothed RTT in units of (TCP_RTT_SCALE*hz) */
215 	tcps_debug =		p == NULL ? 0 :
216 	    p->t_inpcb->inp_socket->so_options & 1;
217 };
218 
219 #pragma D binding "1.6.3" translator
220 translator tcpinfo_t < struct tcphdr *p > {
221 	tcp_sport =	p == NULL ? 0  : ntohs(p->th_sport);
222 	tcp_dport =	p == NULL ? 0  : ntohs(p->th_dport);
223 	tcp_seq =	p == NULL ? -1 : ntohl(p->th_seq);
224 	tcp_ack =	p == NULL ? -1 : ntohl(p->th_ack);
225 	tcp_offset =	p == NULL ? -1 : (p->th_off >> 2);
226 	tcp_flags =	p == NULL ? 0  : p->th_flags;
227 	tcp_window =	p == NULL ? 0  : ntohs(p->th_win);
228 	tcp_checksum =	p == NULL ? 0  : ntohs(p->th_sum);
229 	tcp_urgent =	p == NULL ? 0  : ntohs(p->th_urp);
230 	tcp_hdr =	(struct tcphdr *)p;
231 };
232 
233 /*
234  * This translator differs from the one for tcpinfo_t in that the sequence
235  * number, acknowledgement number, window size and urgent pointer are already
236  * in host order and thus don't need to be converted.
237  */
238 #pragma D binding "1.6.3" translator
239 translator tcpinfoh_t < struct tcphdr *p > {
240 	tcp_sport =	p == NULL ? 0  : ntohs(p->th_sport);
241 	tcp_dport =	p == NULL ? 0  : ntohs(p->th_dport);
242 	tcp_seq =	p == NULL ? -1 : p->th_seq;
243 	tcp_ack =	p == NULL ? -1 : p->th_ack;
244 	tcp_offset =	p == NULL ? -1 : (p->th_off >> 2);
245 	tcp_flags =	p == NULL ? 0  : p->th_flags;
246 	tcp_window =	p == NULL ? 0  : (p->th_win);
247 	tcp_checksum =	p == NULL ? 0  : ntohs(p->th_sum);
248 	tcp_urgent =	p == NULL ? 0  : p->th_urp;
249 	tcp_hdr =	(struct tcphdr *)p;
250 };
251 
252 #pragma D binding "1.6.3" translator
253 translator tcplsinfo_t < int s > {
254 	tcps_state =	s;
255 };
256 
257 
258 /* Support for TCP debug */
259 
260 #pragma D binding "1.12.1" TA_INPUT
261 inline int TA_INPUT =	0;
262 #pragma D binding "1.12.1" TA_OUTPUT
263 inline int TA_OUTPUT =	1;
264 #pragma D binding "1.12.1" TA_USER
265 inline int TA_USER =	2;
266 #pragma D binding "1.12.1" TA_RESPOND
267 inline int TA_RESPOND =	3;
268 #pragma D binding "1.12.1" TA_DROP
269 inline int TA_DROP =	4;
270 
271 /* direction strings. */
272 
273 #pragma D binding "1.12.1" tcpdebug_dir_string
274 inline string tcpdebug_dir_string[uint8_t direction] =
275 	direction == TA_INPUT ?	"input" :
276 	direction == TA_OUTPUT ? "output" :
277 	direction == TA_USER ? "user" :
278 	direction == TA_RESPOND ? "respond" :
279 	direction == TA_OUTPUT ? "drop" :
280 	"unknown" ;
281 
282 #pragma D binding "1.12.1" tcpflag_string
283 inline string tcpflag_string[uint8_t flags] =
284 	flags & TH_FIN ?	"FIN" :
285 	flags & TH_SYN ?	"SYN" :
286 	flags & TH_RST ?	"RST" :
287 	flags & TH_PUSH ?	"PUSH" :
288 	flags & TH_ACK ?	"ACK" :
289 	flags & TH_URG ?	"URG" :
290 	flags & TH_ECE ?	"ECE" :
291 	flags & TH_CWR ?	"CWR" :
292 	"unknown" ;
293 
294 #pragma D binding "1.12.1" PRU_ATTACH
295 inline int PRU_ATTACH		= 0;
296 #pragma D binding "1.12.1" PRU_DETACH
297 inline int PRU_DETACH		= 1;
298 #pragma D binding "1.12.1" PRU_BIND
299 inline int PRU_BIND		= 2;
300 #pragma D binding "1.12.1" PRU_LISTEN
301 inline int PRU_LISTEN		= 3;
302 #pragma D binding "1.12.1" PRU_CONNECT
303 inline int PRU_CONNECT		= 4;
304 #pragma D binding "1.12.1" PRU_ACCEPT
305 inline int PRU_ACCEPT	 = 5 ;
306 #pragma D binding "1.12.1" PRU_DISCONNECT
307 inline int PRU_DISCONNECT=  6;
308 #pragma D binding "1.12.1" PRU_SHUTDOWN
309 inline int PRU_SHUTDOWN	 =  7;
310 #pragma D binding "1.12.1" PRU_RCVD
311 inline int PRU_RCVD	 =  8;
312 #pragma D binding "1.12.1" PRU_SEND
313 inline int PRU_SEND	 =  9;
314 #pragma D binding "1.12.1" PRU_ABORT
315 inline int PRU_ABORT	  = 10;
316 #pragma D binding "1.12.1" PRU_CONTROL
317 inline int PRU_CONTROL	  = 11;
318 #pragma D binding "1.12.1" PRU_SENSE
319 inline int PRU_SENSE	  = 12;
320 #pragma D binding "1.12.1" PRU_RCVOOB
321 inline int PRU_RCVOOB	  = 13;
322 #pragma D binding "1.12.1" PRU_SENDOOB
323 inline int PRU_SENDOOB	  = 14;
324 #pragma D binding "1.12.1" PRU_SOCKADDR
325 inline int PRU_SOCKADDR	  = 15;
326 #pragma D binding "1.12.1" PRU_PEERADDR
327 inline int PRU_PEERADDR	  = 16;
328 #pragma D binding "1.12.1" PRU_CONNECT2
329 inline int PRU_CONNECT2	  = 17;
330 #pragma D binding "1.12.1" PRU_FASTTIMO
331 inline int PRU_FASTTIMO	  = 18;
332 #pragma D binding "1.12.1" PRU_SLOWTIMO
333 inline int PRU_SLOWTIMO	  = 19;
334 #pragma D binding "1.12.1" PRU_PROTORCV
335 inline int PRU_PROTORCV	  = 20;
336 #pragma D binding "1.12.1" PRU_PROTOSEND
337 inline int PRU_PROTOSEND  = 21;
338 #pragma D binding "1.12.1" PRU_SEND_EOF
339 inline int PRU_SEND_EOF	  = 22;
340 #pragma D binding "1.12.1" PRU_SOSETLABEL
341 inline int PRU_SOSETLABEL = 23;
342 #pragma D binding "1.12.1" PRU_CLOSE
343 inline int PRU_CLOSE	  = 24;
344 #pragma D binding "1.12.1" PRU_FLUSH
345 inline int PRU_FLUSH	  = 25;
346 
347 #pragma D binding "1.12.1" prureq_string
348 inline string prureq_string[uint8_t req] =
349 	req == PRU_ATTACH ? "ATTACH" :
350 	req == PRU_DETACH ? "DETACH" :
351 	req == PRU_BIND ? "BIND" :
352 	req == PRU_LISTEN ? "LISTEN" :
353 	req == PRU_CONNECT ? "CONNECT" :
354 	req == PRU_ACCEPT ? "ACCEPT" :
355 	req == PRU_DISCONNECT ? "DISCONNECT" :
356 	req == PRU_SHUTDOWN ? "SHUTDOWN" :
357 	req == PRU_RCVD ? "RCVD" :
358 	req == PRU_SEND ? "SEND" :
359 	req == PRU_ABORT ? "ABORT" :
360 	req == PRU_CONTROL ? "CONTROL" :
361 	req == PRU_SENSE ? "SENSE" :
362 	req == PRU_RCVOOB ? "RCVOOB" :
363 	req == PRU_SENDOOB ? "SENDOOB" :
364 	req == PRU_SOCKADDR ? "SOCKADDR" :
365 	req == PRU_PEERADDR ? "PEERADDR" :
366 	req == PRU_CONNECT2 ? "CONNECT2" :
367 	req == PRU_FASTTIMO ? "FASTTIMO" :
368 	req == PRU_SLOWTIMO ? "SLOWTIMO" :
369 	req == PRU_PROTORCV ? "PROTORCV" :
370 	req == PRU_PROTOSEND ? "PROTOSEND" :
371 	req == PRU_SEND ? "SEND_EOF" :
372 	req == PRU_SOSETLABEL ? "SOSETLABEL" :
373 	req == PRU_CLOSE ? "CLOSE" :
374 	req == PRU_FLUSH ? "FLUSE" :
375 	"unknown" ;
376