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 dccp
27
28 inline int32_t DCCP_STATE_CLOSED = @DCCPS_CLOSED@;
29 #pragma D binding "1.10" DCCP_STATE_CLOSED
30 inline int32_t DCCP_STATE_BOUND = @DCCPS_BOUND@;
31 #pragma D binding "1.10" DCCP_STATE_BOUND
32 inline int32_t DCCP_STATE_REQUEST = @DCCPS_REQUEST@;
33 #pragma D binding "1.10" DCCP_STATE_REQUEST
34 inline int32_t DCCP_STATE_LISTEN = @DCCPS_LISTEN@;
35 #pragma D binding "1.10" DCCP_STATE_LISTEN
36 inline int32_t DCCP_STATE_PARTOPEN = @DCCPS_PARTOPEN@;
37 #pragma D binding "1.10" DCCP_STATE_PARTOPEN
38 inline int32_t DCCP_STATE_RESPOND = @DCCPS_RESPOND@;
39 #pragma D binding "1.10" DCCP_STATE_RESPOND
40 inline int32_t DCCP_STATE_OPEN = @DCCPS_OPEN@;
41 #pragma D binding "1.10" DCCP_STATE_OPEN
42 inline int32_t DCCP_STATE_CLOSING = @DCCPS_CLOSING@;
43 #pragma D binding "1.10" DCCP_STATE_CLOSING
44 inline int32_t DCCP_STATE_CLOSEREQ = @DCCPS_CLOSEREQ@;
45 #pragma D binding "1.10" DCCP_STATE_CLOSEREQ
46 inline int32_t DCCP_STATE_TIMEWAIT = @DCCPS_TIMEWAIT@;
47 #pragma D binding "1.10" DCCP_STATE_TIMEWAIT
48
49 /*
50 * Convert a DCCP state value to a string.
51 */
52 inline string dccp_state_string[int32_t state] =
53 state == DCCP_STATE_CLOSED ? "state-closed" :
54 state == DCCP_STATE_BOUND ? "state-bound" :
55 state == DCCP_STATE_REQUEST ? "state-request" :
56 state == DCCP_STATE_LISTEN ? "state-listen" :
57 state == DCCP_STATE_PARTOPEN ? "state-partopen" :
58 state == DCCP_STATE_RESPOND ? "state-respond" :
59 state == DCCP_STATE_OPEN ? "state-open" :
60 state == DCCP_STATE_CLOSING ? "state-closing" :
61 state == DCCP_STATE_CLOSEREQ ? "state-closereq" :
62 state == DCCP_STATE_TIMEWAIT ? "state-timewait" :
63 "<unknown>";
64 #pragma D binding "1.10" dccp_state_string
65
66 /*
67 * dccpinfo is the DCCP header fields.
68 */
69 typedef struct dccpinfo {
70 uint16_t dccp_sport; /* source port */
71 uint16_t dccp_dport; /* destination port */
72 uint32_t dccp_seq; /* sequence number */
73 uint8_t dccp_offset; /* data offset, in bytes */
74 uint16_t dccp_checksum; /* checksum */
75 dccph_t *dccp_hdr; /* raw DCCP header */
76 } dccpinfo_t;
77
78 /*
79 * dccpsinfo contains stable DCCP details from dccp_t.
80 */
81 typedef struct dccpsinfo {
82 uintptr_t dccps_addr;
83 int dccps_local; /* Is delivered locally, boolean */
84 int dccps_active; /* Active open (from here), boolean */
85 uint16_t dccps_lport; /* Local port */
86 uint16_t dccps_rport; /* Remote port */
87 string dccps_laddr; /* Local address, as a string */
88 string dccps_raddr; /* Remote address, as a string */
89 int32_t dccps_state; /* DCCP state */
90 uint32_t dccps_iss; /* Initial sequence # sent */
91 } dccpsinfo_t;
92
93 /*
94 * dccplsinfo provides the old dccp state for state changes.
95 */
96 typedef struct dccplsinfo {
97 int32_t dccps_state; /* Previous DCCP state */
98 } dccplsinfo_t;
99
100 /*
101 * __dtrace_tcp_tcph_t is used by the tcpinfo_t * translator to take either
102 * the non-NULL tcph_t * passed in or, if it is NULL, uses arg3 (tcp_t *)
103 * from the tcp:::send and tcp:::recieve probes and translates the tcp_t *
104 * into the tcpinfo_t. When no headers are available - as is the case for
105 * TCP fusion tcp:::send and tcp:::receive - this allows us to present the
106 * consumer with header data based on tcp_t * content and hide TCP fusion
107 * implementation details.
108 */
109 typedef dccph_t * __dtrace_dccp_dccph_t;
110
111 #pragma D binding "1.10" translator
112 translator dccpinfo_t < dccph_t *T > {
113 dccp_sport = ntohs(*(uint16_t *)T->dh_lport);
114 dccp_dport = ntohs(*(uint16_t *)T->dh_fport);
115 dccp_seq = ntohl(*(uint32_t *)T->dh_seq); /* XXX */
116 dccp_offset = (*(uint8_t *)T->dh_offset & 0xf0) >> 2;
117 dccp_checksum = ntohs(*(uint16_t *)T->dh_sum);
118 dccp_hdr = T;
119 };
120
121 #pragma D binding "1.10" translator
122 translator dccpinfo_t < __dtrace_dccp_dccph_t *T > {
123 dccp_sport =
124 T != NULL ? ntohs(*(uint16_t *)((dccph_t *)T)->dh_lport) :
125 arg3 != NULL && probename == "send" ?
126 ntohs(((dccp_t *)arg3)->dccp_connp->u_port.connu_ports.connu_lport) :
127 arg3 != NULL && probename == "receive" ?
128 ntohs(((dccp_t *)arg3)->dccp_connp->u_port.connu_ports.connu_fport) :
129 0;
130 dccp_dport =
131 T != NULL ? ntohs(*(uint16_t *)((dccph_t *)T)->dh_fport) :
132 arg3 != NULL && probename == "send" ?
133 ntohs(((dccp_t *)arg3)->dccp_connp->u_port.connu_ports.connu_fport) :
134 arg3 != NULL && probename == "receive" ?
135 ntohs(((dccp_t *)arg3)->dccp_connp->u_port.connu_ports.connu_lport) :
136 0;
137 dccp_seq =
138 T != NULL ? ntohl(*(uint32_t *)((dccph_t *)T)->dh_seq) :
139 0;
140 dccp_offset = T != NULL ?
141 (*(uint8_t *)((dccph_t *)T)->dh_offset & 0xf0) >> 2 :
142 @DCCP_MIN_HEADER_LENGTH@;
143 dccp_checksum = T != NULL ? ntohs(*(uint16_t *)((dccph_t *)T)->dh_sum) :
144 0;
145 dccp_hdr = NULL;
146 };
147
148 #pragma D binding "1.10" translator
149 translator dccpsinfo_t < dccp_t *T > {
150 dccps_addr = (uintptr_t)T;
151 /*
152 * The following two members should just use tcp_t->tcp_loopback
153 * and tcp_t->tcp_active_open, however these are bit fields and
154 * can't be used until CR 6876830 is fixed. Meanwhile we source
155 * them a different way.
156 */
157 dccps_local = T ? T->dccp_ipha ?
158 T->dccp_ipha->ipha_src == T->dccp_ipha->ipha_dst : 1 : 0;
159 dccps_active = T ? !T->dccp_saved_listener : 0;
160 dccps_lport = T ?
161 ntohs(T->dccp_connp->u_port.connu_ports.connu_lport) : 0;
162 dccps_rport = T ?
163 ntohs(T->dccp_connp->u_port.connu_ports.connu_fport) : 0;
164 dccps_laddr = T ?
165 inet_ntoa6(&T->dccp_connp->connua_v6addr.connua_laddr) : "<unknown>";
166 dccps_raddr = T ?
167 inet_ntoa6(&T->dccp_connp->connua_v6addr.connua_faddr) : "<unknown>";
168 dccps_state = T ? T->dccp_state : DCCP_STATE_CLOSED;
169 dccps_iss = T ? T->dccp_iss : 0;
170 };
171
172 /*
173 * Note: although we specify that the old state argument used as the
174 * input to the tcplsinfo_t translator is an int32_t, it reaches us as an
175 * int64_t (since it is a probe argument) so explicitly cast it back to
176 * interpret the negatively-valued states correctly.
177 */
178 #pragma D binding "1.10" translator
179 translator dccplsinfo_t < int64_t I > {
180 dccps_state = (int32_t) I;
181 };