aboutsummaryrefslogtreecommitdiff
path: root/cddl/lib/libdtrace/tcp.d
diff options
context:
space:
mode:
Diffstat (limited to 'cddl/lib/libdtrace/tcp.d')
-rw-r--r--cddl/lib/libdtrace/tcp.d419
1 files changed, 419 insertions, 0 deletions
diff --git a/cddl/lib/libdtrace/tcp.d b/cddl/lib/libdtrace/tcp.d
new file mode 100644
index 000000000000..8f51675df305
--- /dev/null
+++ b/cddl/lib/libdtrace/tcp.d
@@ -0,0 +1,419 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013 Mark Johnston <markj@freebsd.org>
+ */
+
+#pragma D depends_on library ip.d
+#pragma D depends_on module kernel
+#pragma D depends_on provider tcp
+
+/*
+ * Convert a TCP state value to a string.
+ */
+#pragma D binding "1.6.3" TCPS_CLOSED
+inline int TCPS_CLOSED = 0;
+#pragma D binding "1.6.3" TCPS_LISTEN
+inline int TCPS_LISTEN = 1;
+#pragma D binding "1.6.3" TCPS_SYN_SENT
+inline int TCPS_SYN_SENT = 2;
+#pragma D binding "1.6.3" TCPS_SYN_RECEIVED
+inline int TCPS_SYN_RECEIVED = 3;
+#pragma D binding "1.6.3" TCPS_ESTABLISHED
+inline int TCPS_ESTABLISHED = 4;
+#pragma D binding "1.6.3" TCPS_CLOSE_WAIT
+inline int TCPS_CLOSE_WAIT = 5;
+#pragma D binding "1.6.3" TCPS_FIN_WAIT_1
+inline int TCPS_FIN_WAIT_1 = 6;
+#pragma D binding "1.6.3" TCPS_CLOSING
+inline int TCPS_CLOSING = 7;
+#pragma D binding "1.6.3" TCPS_LAST_ACK
+inline int TCPS_LAST_ACK = 8;
+#pragma D binding "1.6.3" TCPS_FIN_WAIT_2
+inline int TCPS_FIN_WAIT_2 = 9;
+#pragma D binding "1.6.3" TCPS_TIME_WAIT
+inline int TCPS_TIME_WAIT = 10;
+
+/*
+ * For compatibility also provide the names used by Solaris.
+ */
+#pragma D binding "1.13" TCP_STATE_CLOSED
+inline int TCP_STATE_CLOSED = TCPS_CLOSED;
+#pragma D binding "1.13" TCP_STATE_LISTEN
+inline int TCP_STATE_LISTEN = TCPS_LISTEN;
+#pragma D binding "1.13" TCP_STATE_SYN_SENT
+inline int TCP_STATE_SYN_SENT = TCPS_SYN_SENT;
+#pragma D binding "1.13" TCP_STATE_SYN_RECEIVED
+inline int TCP_STATE_SYN_RECEIVED = TCPS_SYN_RECEIVED;
+#pragma D binding "1.13" TCP_STATE_ESTABLISHED
+inline int TCP_STATE_ESTABLISHED = TCPS_ESTABLISHED;
+#pragma D binding "1.13" TCP_STATE_CLOSE_WAIT
+inline int TCP_STATE_CLOSE_WAIT = TCPS_CLOSE_WAIT;
+#pragma D binding "1.13" TCP_STATE_FIN_WAIT_1
+inline int TCP_STATE_FIN_WAIT_1 = TCPS_FIN_WAIT_1;
+#pragma D binding "1.13" TCP_STATE_CLOSING
+inline int TCP_STATE_CLOSING = TCPS_CLOSING;
+#pragma D binding "1.13" TCP_STATE_LAST_ACK
+inline int TCP_STATE_LAST_ACK = TCPS_LAST_ACK;
+#pragma D binding "1.13" TCP_STATE_FIN_WAIT_2
+inline int TCP_STATE_FIN_WAIT_2 = TCPS_FIN_WAIT_2;
+#pragma D binding "1.13" TCP_STATE_TIME_WAIT
+inline int TCP_STATE_TIME_WAIT = TCPS_TIME_WAIT;
+
+/* TCP segment flags. */
+#pragma D binding "1.6.3" TH_FIN
+inline uint16_t TH_FIN = 0x01;
+#pragma D binding "1.6.3" TH_SYN
+inline uint16_t TH_SYN = 0x02;
+#pragma D binding "1.6.3" TH_RST
+inline uint16_t TH_RST = 0x04;
+#pragma D binding "1.6.3" TH_PUSH
+inline uint16_t TH_PUSH = 0x08;
+#pragma D binding "1.6.3" TH_ACK
+inline uint16_t TH_ACK = 0x10;
+#pragma D binding "1.6.3" TH_URG
+inline uint16_t TH_URG = 0x20;
+#pragma D binding "1.6.3" TH_ECE
+inline uint16_t TH_ECE = 0x40;
+#pragma D binding "1.6.3" TH_CWR
+inline uint16_t TH_CWR = 0x80;
+#pragma D binding "1.6.3" TH_AE
+inline uint16_t TH_AE = 0x100;
+
+/* TCP connection state strings. */
+#pragma D binding "1.6.3" tcp_state_string
+inline string tcp_state_string[int32_t state] =
+ state == TCPS_CLOSED ? "state-closed" :
+ state == TCPS_LISTEN ? "state-listen" :
+ state == TCPS_SYN_SENT ? "state-syn-sent" :
+ state == TCPS_SYN_RECEIVED ? "state-syn-received" :
+ state == TCPS_ESTABLISHED ? "state-established" :
+ state == TCPS_CLOSE_WAIT ? "state-close-wait" :
+ state == TCPS_FIN_WAIT_1 ? "state-fin-wait-1" :
+ state == TCPS_CLOSING ? "state-closing" :
+ state == TCPS_LAST_ACK ? "state-last-ack" :
+ state == TCPS_FIN_WAIT_2 ? "state-fin-wait-2" :
+ state == TCPS_TIME_WAIT ? "state-time-wait" :
+ "<unknown>";
+
+/*
+ * tcpsinfo contains stable TCP details from tcp_t.
+ */
+typedef struct tcpsinfo {
+ uintptr_t tcps_addr;
+ int tcps_local; /* is delivered locally, boolean */
+ int tcps_active; /* active open (from here), boolean */
+ uint16_t tcps_lport; /* local port */
+ uint16_t tcps_rport; /* remote port */
+ string tcps_laddr; /* local address, as a string */
+ string tcps_raddr; /* remote address, as a string */
+ int32_t tcps_state; /* TCP state */
+ uint32_t tcps_iss; /* Initial sequence # sent */
+ uint32_t tcps_irs; /* Initial sequence # received */
+ uint32_t tcps_suna; /* sequence # sent but unacked */
+ uint32_t tcps_smax; /* highest sequence number sent */
+ uint32_t tcps_snxt; /* next sequence # to send */
+ uint32_t tcps_rack; /* sequence # we have acked */
+ uint32_t tcps_rnxt; /* next sequence # expected */
+ u_long tcps_swnd; /* send window size */
+ int32_t tcps_snd_ws; /* send window scaling */
+ uint32_t tcps_swl1; /* window update seg seq number */
+ uint32_t tcps_swl2; /* window update seg ack number */
+ uint32_t tcps_rup; /* receive urgent pointer */
+ uint32_t tcps_radv; /* advertised window */
+ u_long tcps_rwnd; /* receive window size */
+ int32_t tcps_rcv_ws; /* receive window scaling */
+ u_long tcps_cwnd; /* congestion window */
+ u_long tcps_cwnd_ssthresh; /* threshold for congestion avoidance */
+ uint32_t tcps_srecover; /* for use in NewReno Fast Recovery */
+ uint32_t tcps_sack_fack; /* SACK sequence # we have acked */
+ uint32_t tcps_sack_snxt; /* next SACK seq # for retransmission */
+ uint32_t tcps_rto; /* round-trip timeout, msec */
+ uint32_t tcps_mss; /* max segment size */
+ int tcps_retransmit; /* retransmit send event, boolean */
+ int tcps_srtt; /* smoothed RTT in units of (TCP_RTT_SCALE*hz) */
+ int tcps_debug; /* socket has SO_DEBUG set */
+ int tcps_cookie; /* expose the socket's SO_USER_COOKIE */
+ int32_t tcps_dupacks; /* consecutive dup acks received */
+ uint32_t tcps_rtttime; /* RTT measurement start time */
+ uint32_t tcps_rtseq; /* sequence # being timed */
+ uint32_t tcps_ts_recent; /* timestamp echo data */
+} tcpsinfo_t;
+
+/*
+ * tcplsinfo provides the old tcp state for state changes.
+ */
+typedef struct tcplsinfo {
+ int32_t tcps_state; /* previous TCP state */
+} tcplsinfo_t;
+
+/*
+ * tcpinfo is the TCP header fields.
+ */
+typedef struct tcpinfo {
+ uint16_t tcp_sport; /* source port */
+ uint16_t tcp_dport; /* destination port */
+ uint32_t tcp_seq; /* sequence number */
+ uint32_t tcp_ack; /* acknowledgment number */
+ uint8_t tcp_offset; /* data offset, in bytes */
+ uint16_t tcp_flags; /* flags */
+ uint16_t tcp_window; /* window size */
+ uint16_t tcp_checksum; /* checksum */
+ uint16_t tcp_urgent; /* urgent data pointer */
+ struct tcphdr *tcp_hdr; /* raw TCP header */
+} tcpinfo_t;
+
+/*
+ * A clone of tcpinfo_t used to handle the fact that the TCP input path
+ * overwrites some fields of the TCP header with their host-order equivalents.
+ * Unfortunately, DTrace doesn't let us simply typedef a new name for struct
+ * tcpinfo and define a separate translator for it.
+ */
+typedef struct tcpinfoh {
+ uint16_t tcp_sport; /* source port */
+ uint16_t tcp_dport; /* destination port */
+ uint32_t tcp_seq; /* sequence number */
+ uint32_t tcp_ack; /* acknowledgment number */
+ uint8_t tcp_offset; /* data offset, in bytes */
+ uint16_t tcp_flags; /* flags */
+ uint16_t tcp_window; /* window size */
+ uint16_t tcp_checksum; /* checksum */
+ uint16_t tcp_urgent; /* urgent data pointer */
+ struct tcphdr *tcp_hdr; /* raw TCP header */
+} tcpinfoh_t;
+
+#pragma D binding "1.6.3" translator
+translator csinfo_t < struct tcpcb *p > {
+ cs_addr = NULL;
+ cs_cid = (uint64_t)(p == NULL ? 0 : &p->t_inpcb);
+ cs_pid = 0;
+ cs_zoneid = 0;
+};
+
+#pragma D binding "1.6.3" translator
+translator tcpsinfo_t < struct tcpcb *p > {
+ tcps_addr = (uintptr_t)p;
+ tcps_local = -1; /* XXX */
+ tcps_active = -1; /* XXX */
+ tcps_lport = p == NULL ? 0 : ntohs(p->t_inpcb.inp_inc.inc_ie.ie_lport);
+ tcps_rport = p == NULL ? 0 : ntohs(p->t_inpcb.inp_inc.inc_ie.ie_fport);
+ tcps_laddr = p == NULL ? "<unknown>" :
+ p->t_inpcb.inp_vflag == INP_IPV4 ?
+ inet_ntoa(&p->t_inpcb.inp_inc.inc_ie.ie_dependladdr.id46_addr.ia46_addr4.s_addr) :
+ inet_ntoa6(&p->t_inpcb.inp_inc.inc_ie.ie_dependladdr.id6_addr);
+ tcps_raddr = p == NULL ? "<unknown>" :
+ p->t_inpcb.inp_vflag == INP_IPV4 ?
+ inet_ntoa(&p->t_inpcb.inp_inc.inc_ie.ie_dependfaddr.id46_addr.ia46_addr4.s_addr) :
+ inet_ntoa6(&p->t_inpcb.inp_inc.inc_ie.ie_dependfaddr.id6_addr);
+ tcps_state = p == NULL ? -1 : p->t_state;
+ tcps_iss = p == NULL ? 0 : p->iss;
+ tcps_irs = p == NULL ? 0 : p->irs;
+ tcps_suna = p == NULL ? 0 : p->snd_una;
+ tcps_smax = p == NULL ? 0 : p->snd_max;
+ tcps_snxt = p == NULL ? 0 : p->snd_nxt;
+ tcps_rack = p == NULL ? 0 : p->last_ack_sent;
+ tcps_rnxt = p == NULL ? 0 : p->rcv_nxt;
+ tcps_swnd = p == NULL ? -1 : p->snd_wnd;
+ tcps_snd_ws = p == NULL ? -1 : p->snd_scale;
+ tcps_swl1 = p == NULL ? -1 : p->snd_wl1;
+ tcps_swl2 = p == NULL ? -1 : p->snd_wl2;
+ tcps_radv = p == NULL ? -1 : p->rcv_adv;
+ tcps_rwnd = p == NULL ? -1 : p->rcv_wnd;
+ tcps_rup = p == NULL ? -1 : p->rcv_up;
+ tcps_rcv_ws = p == NULL ? -1 : p->rcv_scale;
+ tcps_cwnd = p == NULL ? -1 : p->snd_cwnd;
+ tcps_cwnd_ssthresh = p == NULL ? -1 : p->snd_ssthresh;
+ tcps_srecover = p == NULL ? -1 : p->snd_recover;
+ tcps_sack_fack = p == NULL ? 0 : p->snd_fack;
+ tcps_sack_snxt = p == NULL ? 0 : p->snd_recover;
+ tcps_rto = p == NULL ? -1 : (p->t_rxtcur * 1000) / `hz;
+ tcps_mss = p == NULL ? -1 : p->t_maxseg;
+ tcps_retransmit = p == NULL ? -1 : p->t_rxtshift > 0 ? 1 : 0;
+ tcps_srtt = p == NULL ? -1 : p->t_srtt; /* smoothed RTT in units of (TCP_RTT_SCALE*hz) */
+ tcps_debug = p == NULL ? 0 :
+ p->t_inpcb.inp_socket->so_options & 1;
+ tcps_cookie = p == NULL ? -1 :
+ p->t_inpcb.inp_socket->so_user_cookie;
+ tcps_dupacks = p == NULL ? -1 : p->t_dupacks;
+ tcps_rtttime = p == NULL ? -1 : p->t_rtttime;
+ tcps_rtseq = p == NULL ? -1 : p->t_rtseq;
+ tcps_ts_recent = p == NULL ? -1 : p->ts_recent;
+};
+
+#pragma D binding "1.6.3" translator
+translator tcpinfo_t < struct tcphdr *p > {
+ tcp_sport = p == NULL ? 0 : ntohs(p->th_sport);
+ tcp_dport = p == NULL ? 0 : ntohs(p->th_dport);
+ tcp_seq = p == NULL ? -1 : ntohl(p->th_seq);
+ tcp_ack = p == NULL ? -1 : ntohl(p->th_ack);
+ tcp_offset = p == NULL ? -1 : (p->th_off << 2);
+ tcp_flags = p == NULL ? 0 : ((p->th_x2 << 8) | p->th_flags);
+ tcp_window = p == NULL ? 0 : ntohs(p->th_win);
+ tcp_checksum = p == NULL ? 0 : ntohs(p->th_sum);
+ tcp_urgent = p == NULL ? 0 : ntohs(p->th_urp);
+ tcp_hdr = (struct tcphdr *)p;
+};
+
+/*
+ * This translator differs from the one for tcpinfo_t in that the sequence
+ * number, acknowledgement number, window size and urgent pointer are already
+ * in host order and thus don't need to be converted.
+ */
+#pragma D binding "1.6.3" translator
+translator tcpinfoh_t < struct tcphdr *p > {
+ tcp_sport = p == NULL ? 0 : ntohs(p->th_sport);
+ tcp_dport = p == NULL ? 0 : ntohs(p->th_dport);
+ tcp_seq = p == NULL ? -1 : p->th_seq;
+ tcp_ack = p == NULL ? -1 : p->th_ack;
+ tcp_offset = p == NULL ? -1 : (p->th_off << 2);
+ tcp_flags = p == NULL ? 0 : ((p->th_x2 << 8) | p->th_flags);
+ tcp_window = p == NULL ? 0 : p->th_win;
+ tcp_checksum = p == NULL ? 0 : ntohs(p->th_sum);
+ tcp_urgent = p == NULL ? 0 : p->th_urp;
+ tcp_hdr = (struct tcphdr *)p;
+};
+
+#pragma D binding "1.6.3" translator
+translator tcplsinfo_t < int s > {
+ tcps_state = s;
+};
+
+
+/* Support for TCP debug */
+
+#pragma D binding "1.12.1" TA_INPUT
+inline int TA_INPUT = 0;
+#pragma D binding "1.12.1" TA_OUTPUT
+inline int TA_OUTPUT = 1;
+#pragma D binding "1.12.1" TA_USER
+inline int TA_USER = 2;
+#pragma D binding "1.12.1" TA_RESPOND
+inline int TA_RESPOND = 3;
+#pragma D binding "1.12.1" TA_DROP
+inline int TA_DROP = 4;
+
+/* direction strings. */
+
+#pragma D binding "1.13" tcpdebug_dir_string
+inline string tcpdebug_dir_string[uint8_t direction] =
+ direction == TA_INPUT ? "input" :
+ direction == TA_OUTPUT ? "output" :
+ direction == TA_USER ? "user" :
+ direction == TA_RESPOND ? "respond" :
+ direction == TA_DROP ? "drop" :
+ "unknown" ;
+
+#pragma D binding "1.13" tcpflag_string
+inline string tcpflag_string[uint16_t flags] =
+ flags & TH_FIN ? "FIN" :
+ flags & TH_SYN ? "SYN" :
+ flags & TH_RST ? "RST" :
+ flags & TH_PUSH ? "PUSH" :
+ flags & TH_ACK ? "ACK" :
+ flags & TH_URG ? "URG" :
+ flags & TH_ECE ? "ECE" :
+ flags & TH_CWR ? "CWR" :
+ flags & TH_AE ? "AE" :
+ "unknown" ;
+
+#pragma D binding "1.12.1" PRU_ATTACH
+inline int PRU_ATTACH = 0;
+#pragma D binding "1.12.1" PRU_DETACH
+inline int PRU_DETACH = 1;
+#pragma D binding "1.12.1" PRU_BIND
+inline int PRU_BIND = 2;
+#pragma D binding "1.12.1" PRU_LISTEN
+inline int PRU_LISTEN = 3;
+#pragma D binding "1.12.1" PRU_CONNECT
+inline int PRU_CONNECT = 4;
+#pragma D binding "1.12.1" PRU_ACCEPT
+inline int PRU_ACCEPT = 5 ;
+#pragma D binding "1.12.1" PRU_DISCONNECT
+inline int PRU_DISCONNECT = 6;
+#pragma D binding "1.12.1" PRU_SHUTDOWN
+inline int PRU_SHUTDOWN = 7;
+#pragma D binding "1.12.1" PRU_RCVD
+inline int PRU_RCVD = 8;
+#pragma D binding "1.12.1" PRU_SEND
+inline int PRU_SEND = 9;
+#pragma D binding "1.12.1" PRU_ABORT
+inline int PRU_ABORT = 10;
+#pragma D binding "1.12.1" PRU_CONTROL
+inline int PRU_CONTROL = 11;
+#pragma D binding "1.12.1" PRU_SENSE
+inline int PRU_SENSE = 12;
+#pragma D binding "1.12.1" PRU_RCVOOB
+inline int PRU_RCVOOB = 13;
+#pragma D binding "1.12.1" PRU_SENDOOB
+inline int PRU_SENDOOB = 14;
+#pragma D binding "1.12.1" PRU_SOCKADDR
+inline int PRU_SOCKADDR = 15;
+#pragma D binding "1.12.1" PRU_PEERADDR
+inline int PRU_PEERADDR = 16;
+#pragma D binding "1.12.1" PRU_CONNECT2
+inline int PRU_CONNECT2 = 17;
+#pragma D binding "1.12.1" PRU_FASTTIMO
+inline int PRU_FASTTIMO = 18;
+#pragma D binding "1.12.1" PRU_SLOWTIMO
+inline int PRU_SLOWTIMO = 19;
+#pragma D binding "1.12.1" PRU_PROTORCV
+inline int PRU_PROTORCV = 20;
+#pragma D binding "1.12.1" PRU_PROTOSEND
+inline int PRU_PROTOSEND = 21;
+#pragma D binding "1.12.1" PRU_SEND_EOF
+inline int PRU_SEND_EOF = 22;
+#pragma D binding "1.12.1" PRU_SOSETLABEL
+inline int PRU_SOSETLABEL = 23;
+#pragma D binding "1.12.1" PRU_CLOSE
+inline int PRU_CLOSE = 24;
+#pragma D binding "1.12.1" PRU_FLUSH
+inline int PRU_FLUSH = 25;
+
+#pragma D binding "1.12.1" prureq_string
+inline string prureq_string[uint8_t req] =
+ req == PRU_ATTACH ? "ATTACH" :
+ req == PRU_DETACH ? "DETACH" :
+ req == PRU_BIND ? "BIND" :
+ req == PRU_LISTEN ? "LISTEN" :
+ req == PRU_CONNECT ? "CONNECT" :
+ req == PRU_ACCEPT ? "ACCEPT" :
+ req == PRU_DISCONNECT ? "DISCONNECT" :
+ req == PRU_SHUTDOWN ? "SHUTDOWN" :
+ req == PRU_RCVD ? "RCVD" :
+ req == PRU_SEND ? "SEND" :
+ req == PRU_ABORT ? "ABORT" :
+ req == PRU_CONTROL ? "CONTROL" :
+ req == PRU_SENSE ? "SENSE" :
+ req == PRU_RCVOOB ? "RCVOOB" :
+ req == PRU_SENDOOB ? "SENDOOB" :
+ req == PRU_SOCKADDR ? "SOCKADDR" :
+ req == PRU_PEERADDR ? "PEERADDR" :
+ req == PRU_CONNECT2 ? "CONNECT2" :
+ req == PRU_FASTTIMO ? "FASTTIMO" :
+ req == PRU_SLOWTIMO ? "SLOWTIMO" :
+ req == PRU_PROTORCV ? "PROTORCV" :
+ req == PRU_PROTOSEND ? "PROTOSEND" :
+ req == PRU_SEND ? "SEND_EOF" :
+ req == PRU_SOSETLABEL ? "SOSETLABEL" :
+ req == PRU_CLOSE ? "CLOSE" :
+ req == PRU_FLUSH ? "FLUSE" :
+ "unknown" ;