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 /*
  22  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
  23  */
  24 
  25 #pragma D depends_on module unix
  26 #pragma D depends_on provider tcp
  27 
  28 inline int TH_FIN = @TH_FIN@;
  29 #pragma D binding "1.6.3" TH_FIN
  30 inline int TH_SYN = @TH_SYN@;
  31 #pragma D binding "1.6.3" TH_SYN
  32 inline int TH_RST = @TH_RST@;
  33 #pragma D binding "1.6.3" TH_RST
  34 inline int TH_PUSH = @TH_PUSH@;
  35 #pragma D binding "1.6.3" TH_PUSH
  36 inline int TH_ACK = @TH_ACK@;
  37 #pragma D binding "1.6.3" TH_ACK
  38 inline int TH_URG = @TH_URG@;
  39 #pragma D binding "1.6.3" TH_URG
  40 inline int TH_ECE = @TH_ECE@;
  41 #pragma D binding "1.6.3" TH_ECE
  42 inline int TH_CWR = @TH_CWR@;
  43 #pragma D binding "1.6.3" TH_CWR
  44 
  45 inline int32_t TCP_STATE_CLOSED = @TCPS_CLOSED@;
  46 #pragma D binding "1.6.3" TCP_STATE_CLOSED
  47 inline int32_t TCP_STATE_IDLE = @TCPS_IDLE@;
  48 #pragma D binding "1.6.3" TCP_STATE_IDLE
  49 inline int32_t TCP_STATE_BOUND = @TCPS_BOUND@;
  50 #pragma D binding "1.6.3" TCP_STATE_BOUND
  51 inline int32_t TCP_STATE_LISTEN = @TCPS_LISTEN@;
  52 #pragma D binding "1.6.3" TCP_STATE_LISTEN
  53 inline int32_t TCP_STATE_SYN_SENT = @TCPS_SYN_SENT@;
  54 #pragma D binding "1.6.3" TCP_STATE_SYN_SENT
  55 inline int32_t TCP_STATE_SYN_RECEIVED = @TCPS_SYN_RCVD@;
  56 #pragma D binding "1.6.3" TCP_STATE_SYN_RECEIVED
  57 inline int32_t TCP_STATE_ESTABLISHED = @TCPS_ESTABLISHED@;
  58 #pragma D binding "1.6.3" TCP_STATE_ESTABLISHED
  59 inline int32_t TCP_STATE_CLOSE_WAIT = @TCPS_CLOSE_WAIT@;
  60 #pragma D binding "1.6.3" TCP_STATE_CLOSE_WAIT
  61 inline int32_t TCP_STATE_FIN_WAIT_1 = @TCPS_FIN_WAIT_1@;
  62 #pragma D binding "1.6.3" TCP_STATE_FIN_WAIT_1
  63 inline int32_t TCP_STATE_CLOSING = @TCPS_CLOSING@;
  64 #pragma D binding "1.6.3" TCP_STATE_CLOSING
  65 inline int32_t TCP_STATE_LAST_ACK = @TCPS_LAST_ACK@;
  66 #pragma D binding "1.6.3" TCP_STATE_LAST_ACK
  67 inline int32_t TCP_STATE_FIN_WAIT_2 = @TCPS_FIN_WAIT_2@;
  68 #pragma D binding "1.6.3" TCP_STATE_FIN_WAIT_2
  69 inline int32_t TCP_STATE_TIME_WAIT = @TCPS_TIME_WAIT@;
  70 #pragma D binding "1.6.3" TCP_STATE_TIME_WAIT
  71 
  72 /*
  73  * Convert a TCP state value to a string.
  74  */
  75 inline string tcp_state_string[int32_t state] =
  76         state == TCP_STATE_CLOSED ? "state-closed" :
  77         state == TCP_STATE_IDLE ? "state-idle" :
  78         state == TCP_STATE_BOUND ? "state-bound" :
  79         state == TCP_STATE_LISTEN ? "state-listen" :
  80         state == TCP_STATE_SYN_SENT ? "state-syn-sent" :
  81         state == TCP_STATE_SYN_RECEIVED ? "state-syn-received" :
  82         state == TCP_STATE_ESTABLISHED ? "state-established" :
  83         state == TCP_STATE_CLOSE_WAIT ? "state-close-wait" :
  84         state == TCP_STATE_FIN_WAIT_1 ? "state-fin-wait-1" :
  85         state == TCP_STATE_CLOSING ? "state-closing" :
  86         state == TCP_STATE_LAST_ACK ? "state-last-ack" :
  87         state == TCP_STATE_FIN_WAIT_2 ? "state-fin-wait-2" :
  88         state == TCP_STATE_TIME_WAIT ? "state-time-wait" :
  89         "<unknown>";
  90 #pragma D binding "1.6.3" tcp_state_string
  91 
  92 /*
  93  * tcpinfo is the TCP header fields.
  94  */
  95 typedef struct tcpinfo {
  96         uint16_t tcp_sport;             /* source port */
  97         uint16_t tcp_dport;             /* destination port */
  98         uint32_t tcp_seq;               /* sequence number */
  99         uint32_t tcp_ack;               /* acknowledgment number */
 100         uint8_t tcp_offset;             /* data offset, in bytes */
 101         uint8_t tcp_flags;              /* flags */
 102         uint16_t tcp_window;            /* window size */
 103         uint16_t tcp_checksum;          /* checksum */
 104         uint16_t tcp_urgent;            /* urgent data pointer */
 105         tcph_t *tcp_hdr;                /* raw TCP header */
 106 } tcpinfo_t;
 107 
 108 /*
 109  * tcpsinfo contains stable TCP details from tcp_t.
 110  */
 111 typedef struct tcpsinfo {
 112         uintptr_t tcps_addr;
 113         int tcps_local;                 /* is delivered locally, boolean */
 114         int tcps_active;                /* active open (from here), boolean */
 115         uint16_t tcps_lport;            /* local port */
 116         uint16_t tcps_rport;            /* remote port */
 117         string tcps_laddr;              /* local address, as a string */
 118         string tcps_raddr;              /* remote address, as a string */
 119         int32_t tcps_state;             /* TCP state */
 120         uint32_t tcps_iss;              /* Initial sequence # sent */
 121         uint32_t tcps_suna;             /* sequence # sent but unacked */
 122         uint32_t tcps_snxt;             /* next sequence # to send */
 123         uint32_t tcps_rack;             /* sequence # we have acked */
 124         uint32_t tcps_rnxt;             /* next sequence # expected */
 125         uint32_t tcps_swnd;             /* send window size */
 126         int32_t tcps_snd_ws;            /* send window scaling */
 127         uint32_t tcps_rwnd;             /* receive window size */
 128         int32_t tcps_rcv_ws;            /* receive window scaling */
 129         uint32_t tcps_cwnd;             /* congestion window */
 130         uint32_t tcps_cwnd_ssthresh;    /* threshold for congestion avoidance */
 131         uint32_t tcps_sack_fack;        /* SACK sequence # we have acked */
 132         uint32_t tcps_sack_snxt;        /* next SACK seq # for retransmission */
 133         uint32_t tcps_rto;              /* round-trip timeout, msec */
 134         uint32_t tcps_mss;              /* max segment size */
 135         int tcps_retransmit;            /* retransmit send event, boolean */
 136 } tcpsinfo_t;
 137 
 138 /*
 139  * tcplsinfo provides the old tcp state for state changes.
 140  */
 141 typedef struct tcplsinfo {
 142         int32_t tcps_state;             /* previous TCP state */
 143 } tcplsinfo_t;
 144 
 145 /*
 146  * __dtrace_tcp_tcph_t is used by the tcpinfo_t * translator to take either
 147  * the non-NULL tcph_t * passed in or, if it is NULL, uses arg3 (tcp_t *)
 148  * from the tcp:::send and tcp:::receive probes and translates the tcp_t *
 149  * into the tcpinfo_t.  When no headers are available - as is the case for
 150  * TCP fusion tcp:::send and tcp:::receive - this allows us to present the
 151  * consumer with header data based on tcp_t * content and hide TCP fusion
 152  * implementation details.
 153  */
 154 typedef tcph_t * __dtrace_tcp_tcph_t;
 155 
 156 #pragma D binding "1.6.3" translator
 157 translator tcpinfo_t < tcph_t *T > {
 158         tcp_sport = ntohs(*(uint16_t *)T->th_lport);
 159         tcp_dport = ntohs(*(uint16_t *)T->th_fport);
 160         tcp_seq = ntohl(*(uint32_t *)T->th_seq);
 161         tcp_ack = ntohl(*(uint32_t *)T->th_ack);
 162         tcp_offset = (*(uint8_t *)T->th_offset_and_rsrvd & 0xf0) >> 2;
 163         tcp_flags = *(uint8_t *)T->th_flags;
 164         tcp_window = ntohs(*(uint16_t *)T->th_win);
 165         tcp_checksum = ntohs(*(uint16_t *)T->th_sum);
 166         tcp_urgent = ntohs(*(uint16_t *)T->th_urp);
 167         tcp_hdr = T;
 168 };
 169 
 170 #pragma D binding "1.6.3" translator
 171 translator tcpinfo_t < __dtrace_tcp_tcph_t *T > {
 172         tcp_sport =
 173             T != NULL ? ntohs(*(uint16_t *)((tcph_t *)T)->th_lport) :
 174             arg3 != NULL && probename == "send" ?
 175             ntohs(((tcp_t *)arg3)->tcp_connp->u_port.connu_ports.connu_lport) :
 176             arg3 != NULL && probename == "receive" ?
 177             ntohs(((tcp_t *)arg3)->tcp_connp->u_port.connu_ports.connu_fport) :
 178             0;
 179         tcp_dport =
 180             T != NULL ? ntohs(*(uint16_t *)((tcph_t *)T)->th_fport) :
 181             arg3 != NULL && probename == "send" ?
 182             ntohs(((tcp_t *)arg3)->tcp_connp->u_port.connu_ports.connu_fport) :
 183             arg3 != NULL && probename == "receive" ?
 184             ntohs(((tcp_t *)arg3)->tcp_connp->u_port.connu_ports.connu_lport) :
 185             0;
 186         tcp_seq =
 187             T != NULL ? ntohl(*(uint32_t *)((tcph_t *)T)->th_seq) :
 188             arg3 != NULL && probename == "send" ?
 189             ((tcp_t *)arg3)->tcp_snxt - ((tcp_t *)arg3)->tcp_last_sent_len :
 190             arg3 != NULL && probename == "receive" ?
 191             ((tcp_t *)arg3)->tcp_rnxt - ((tcp_t *)arg3)->tcp_last_recv_len :
 192             0;
 193         tcp_ack =
 194             T != NULL ? ntohl(*(uint32_t *)((tcph_t *)T)->th_ack) :
 195             arg3 != NULL && probename == "send" ?
 196             ((tcp_t *)arg3)->tcp_rnxt :
 197             arg3 != NULL && probename == "receive" ?
 198             ((tcp_t *)arg3)->tcp_snxt :
 199             0;
 200         tcp_offset = T != NULL ? 
 201             (*(uint8_t *)((tcph_t *)T)->th_offset_and_rsrvd & 0xf0) >> 2 :
 202             @TCP_MIN_HEADER_LENGTH@;
 203         tcp_flags = T != NULL ? *(uint8_t *)((tcph_t *)T)->th_flags : TH_ACK;
 204         tcp_window = T != NULL ? ntohs(*(uint16_t *)((tcph_t *)T)->th_win) :
 205             arg3 != NULL ? ((tcp_t *)arg3)->tcp_swnd : 0;
 206         tcp_checksum = T != NULL ? ntohs(*(uint16_t *)((tcph_t *)T)->th_sum) :
 207             0;
 208         tcp_urgent = T != NULL ? ntohs(*(uint16_t *)((tcph_t *)T)->th_urp) : 0;
 209         tcp_hdr = NULL;
 210 };
 211 
 212 #pragma D binding "1.6.3" translator
 213 translator tcpsinfo_t < tcp_t *T > {
 214         tcps_addr = (uintptr_t)T;
 215         /*
 216          * The following two members should just use tcp_t->tcp_loopback
 217          * and tcp_t->tcp_active_open, however these are bit fields and
 218          * can't be used until CR 6876830 is fixed.  Meanwhile we source
 219          * them a different way.
 220          */
 221         tcps_local = T ? T->tcp_ipha ?
 222             T->tcp_ipha->ipha_src == T->tcp_ipha->ipha_dst : 1 : 0;
 223         tcps_active = T ? !T->tcp_saved_listener : 0;
 224         tcps_lport = T ?
 225             ntohs(T->tcp_connp->u_port.connu_ports.connu_lport) : 0;
 226         tcps_rport = T ?
 227             ntohs(T->tcp_connp->u_port.connu_ports.connu_fport) : 0;
 228         tcps_laddr = T ?
 229             inet_ntoa6(&T->tcp_connp->connua_v6addr.connua_laddr) : "<unknown>";
 230         tcps_raddr = T ?
 231             inet_ntoa6(&T->tcp_connp->connua_v6addr.connua_faddr) : "<unknown>";
 232         tcps_state = T ? T->tcp_state : TCP_STATE_CLOSED;
 233         tcps_iss = T ? T->tcp_iss : 0;
 234         tcps_suna = T ? T->tcp_suna : 0;
 235         tcps_snxt = T ? T->tcp_snxt : 0;
 236         tcps_rack = T ? T->tcp_rack : 0;
 237         tcps_rnxt = T ? T->tcp_rnxt : 0;
 238         tcps_swnd = T ? T->tcp_swnd : 0;
 239         tcps_snd_ws = T ? T->tcp_snd_ws : 0;
 240         tcps_rwnd = T ? T->tcp_rwnd : 0;
 241         tcps_rcv_ws = T ? T->tcp_rcv_ws : 0;
 242         tcps_cwnd = T ? T->tcp_cwnd : 0;
 243         tcps_cwnd_ssthresh = T ? T->tcp_cwnd_ssthresh : 0;
 244         tcps_sack_fack = T ? T->tcp_sack_info.tcp_fack : 0;
 245         tcps_sack_snxt = T ? T->tcp_sack_info.tcp_sack_snxt : 0;
 246         tcps_rto = T ? T->tcp_rto : 0;
 247         tcps_mss = T ? T->tcp_mss : 0;
 248         /*
 249          * Determine if send is a retransmission by comparing the seq # to
 250          * tcp_rexmit_nxt/tcp_rexmit_max - if the value is >= rexmit_nxt and
 251          * < rexmit_max, this is a retransmission.  Cannot use tcp_rexmit
 252          * bitfield value due to CR 6876830.
 253          */
 254         tcps_retransmit = T && probename == "send" && arg4 != NULL &&
 255             ntohl(*(uint32_t *)((tcph_t *)arg4)->th_seq) >= T->tcp_rexmit_nxt &&
 256             ntohl(*(uint32_t *)((tcph_t *)arg4)->th_seq) <  T->tcp_rexmit_max ?
 257             1 : 0;
 258 };
 259 
 260 /*
 261  * Note: although we specify that the old state argument used as the
 262  * input to the tcplsinfo_t translator is an int32_t, it reaches us as an
 263  * int64_t (since it is a probe argument) so explicitly cast it back to
 264  * interpret the negatively-valued states correctly.
 265  */
 266 #pragma D binding "1.6.3" translator
 267 translator tcplsinfo_t < int64_t I > {
 268         tcps_state = (int32_t) I;
 269 };