]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - cddl/lib/libdtrace/tcp.d
MFC r302474 (By gnn)
[FreeBSD/FreeBSD.git] / cddl / lib / libdtrace / tcp.d
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_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  */
139 typedef struct tcplsinfo {
140         int32_t tcps_state;             /* previous TCP state */
141 } tcplsinfo_t;
142
143 /*
144  * tcpinfo is the TCP header fields.
145  */
146 typedef 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  */
165 typedef 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
179 translator 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
187 translator 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
237 translator 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
256 translator 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
270 translator 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
278 inline int TA_INPUT =   0;
279 #pragma D binding "1.12.1" TA_OUTPUT
280 inline int TA_OUTPUT =  1;
281 #pragma D binding "1.12.1" TA_USER
282 inline int TA_USER =    2;
283 #pragma D binding "1.12.1" TA_RESPOND
284 inline int TA_RESPOND = 3;
285 #pragma D binding "1.12.1" TA_DROP
286 inline int TA_DROP =    4;
287
288 /* direction strings. */
289
290 #pragma D binding "1.12.1" tcpdebug_dir_string
291 inline 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
300 inline 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
312 inline int PRU_ATTACH           = 0;
313 #pragma D binding "1.12.1" PRU_DETACH
314 inline int PRU_DETACH           = 1;
315 #pragma D binding "1.12.1" PRU_BIND
316 inline int PRU_BIND             = 2;
317 #pragma D binding "1.12.1" PRU_LISTEN
318 inline int PRU_LISTEN           = 3;
319 #pragma D binding "1.12.1" PRU_CONNECT
320 inline int PRU_CONNECT          = 4;
321 #pragma D binding "1.12.1" PRU_ACCEPT
322 inline int PRU_ACCEPT    = 5 ;
323 #pragma D binding "1.12.1" PRU_DISCONNECT
324 inline int PRU_DISCONNECT=  6;
325 #pragma D binding "1.12.1" PRU_SHUTDOWN
326 inline int PRU_SHUTDOWN  =  7;
327 #pragma D binding "1.12.1" PRU_RCVD
328 inline int PRU_RCVD      =  8;
329 #pragma D binding "1.12.1" PRU_SEND
330 inline int PRU_SEND      =  9;
331 #pragma D binding "1.12.1" PRU_ABORT
332 inline int PRU_ABORT      = 10;
333 #pragma D binding "1.12.1" PRU_CONTROL
334 inline int PRU_CONTROL    = 11;
335 #pragma D binding "1.12.1" PRU_SENSE
336 inline int PRU_SENSE      = 12;
337 #pragma D binding "1.12.1" PRU_RCVOOB
338 inline int PRU_RCVOOB     = 13;
339 #pragma D binding "1.12.1" PRU_SENDOOB
340 inline int PRU_SENDOOB    = 14;
341 #pragma D binding "1.12.1" PRU_SOCKADDR
342 inline int PRU_SOCKADDR   = 15;
343 #pragma D binding "1.12.1" PRU_PEERADDR
344 inline int PRU_PEERADDR   = 16;
345 #pragma D binding "1.12.1" PRU_CONNECT2
346 inline int PRU_CONNECT2   = 17;
347 #pragma D binding "1.12.1" PRU_FASTTIMO
348 inline int PRU_FASTTIMO   = 18;
349 #pragma D binding "1.12.1" PRU_SLOWTIMO
350 inline int PRU_SLOWTIMO   = 19;
351 #pragma D binding "1.12.1" PRU_PROTORCV
352 inline int PRU_PROTORCV   = 20;
353 #pragma D binding "1.12.1" PRU_PROTOSEND
354 inline int PRU_PROTOSEND  = 21;
355 #pragma D binding "1.12.1" PRU_SEND_EOF
356 inline int PRU_SEND_EOF   = 22;
357 #pragma D binding "1.12.1" PRU_SOSETLABEL
358 inline int PRU_SOSETLABEL = 23;
359 #pragma D binding "1.12.1" PRU_CLOSE
360 inline int PRU_CLOSE      = 24;
361 #pragma D binding "1.12.1" PRU_FLUSH
362 inline int PRU_FLUSH      = 25;
363
364 #pragma D binding "1.12.1" prureq_string
365 inline 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" ;