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