1 #!/usr/sbin/dtrace -Cqs 2 /* 3 * CDDL HEADER START 4 * 5 * The contents of this file are subject to the terms of the 6 * Common Development and Distribution License (the "License"). 7 * You may not use this file except in compliance with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma D option dynvarsize=64m 28 29 #define TH_RST 0x04 30 #define MAX_RECORDS 10 31 #define M_CTL 0x0d 32 33 #define PRINT_MAIN_HEADER() \ 34 (printf("\n%-25s %-6s %-25s %-6s %-10s %-10s %8s %8s\n", \ 35 "LADDR", "LPORT", "RADDR", "RPORT", "ISS", "IRS", \ 36 "SND_CNT", "RCV_CNT")) 37 38 #define PRINT_RECORD_HEADER() \ 39 (printf("%-20s %-20s %-3s %15s %15s %8s %8s %5s\n", \ 40 "PROBENAME", "TIME", "S/R", "SEQ", "ACK", "DATALEN", \ 41 "WND", "FLAGS")) 42 43 #define PRINT_MAIN_HEADER_VALUES() \ 44 (printf("%-25s %-6d %-25s %-6d %-10d %-10d %8d %8d\n", \ 45 laddr[self->conn_id], lport[self->conn_id], \ 46 faddr[self->conn_id], fport[self->conn_id], \ 47 iss[self->conn_id], irs[self->conn_id], \ 48 send_count[self->conn_id], recv_count[self->conn_id])) 49 50 #define PRINT_HEADER() \ 51 PRINT_MAIN_HEADER(); PRINT_MAIN_HEADER_VALUES(); \ 52 PRINT_RECORD_HEADER() 53 54 #define PRINT_RECORD(i) \ 55 (printf("%-20s %-20Y %-3s %15d %15d %8d %8d %2x\n", \ 56 probe_name[self->conn_id, i], \ 57 conn_time[self->conn_id, i], \ 58 send_recv[self->conn_id, i], \ 59 seqno[self->conn_id, i], \ 60 ack[self->conn_id, i], \ 61 datalen[self->conn_id, i], \ 62 wnd[self->conn_id, i], \ 63 flags[self->conn_id, i])) 64 65 tcp-trace-* 66 { 67 /* extract connection details */ 68 69 this->mp = (mblk_t *)arg0; 70 this->mp = (this->mp->b_datap->db_type == M_CTL? 71 this->mp->b_cont : this->mp); 72 self->tcpp = (tcp_t *)arg1; 73 this->connp = (conn_t *)self->tcpp->tcp_connp; 74 75 self->iph = (ipha_t *)this->mp->b_rptr; 76 this->iph_length = 77 (int)(((ipha_t *)self->iph)->ipha_version_and_hdr_length 78 & 0xF) << 2; 79 self->tcph = (tcpha_t *)((char *)self->iph + this->iph_length); 80 this->tcph_length = 81 (((tcph_t *)self->tcph)->th_offset_and_rsrvd[0] >>2) &(0xF << 2); 82 83 /* ports */ 84 self->i_lport = ntohs(this->connp->u_port.tcpu_ports.tcpu_lport); 85 self->i_fport = ntohs(this->connp->u_port.tcpu_ports.tcpu_fport); 86 87 /* IP addresses */ 88 this->i_fad = (in6_addr_t *)&this->connp->connua_v6addr.connua_faddr; 89 this->i_lad = (in6_addr_t *)&this->connp->connua_v6addr.connua_laddr; 90 91 /* the address would either be IPv6 or IPv4-mapped-IPv6 */ 92 self->i_faddr = inet_ntop(AF_INET6, (void *)this->i_fad); 93 self->i_laddr = inet_ntop(AF_INET6, (void *)this->i_lad); 94 95 /* create connection identifier, so we can track packets by conn */ 96 self->conn_id = (uint64_t)self->tcpp->tcp_connp; 97 } 98 99 tcp-trace-* 100 /first[self->conn_id] == 0/ 101 { 102 /* initialize counters - this is the first packet for this connection */ 103 pcount[self->conn_id] = -1; 104 rollover[self->conn_id] = 0; 105 end_ptr[self->conn_id] = 0; 106 num[self->conn_id] = 0; 107 108 first[self->conn_id] = 1; 109 110 /* connection info */ 111 laddr[self->conn_id] = self->i_laddr; 112 faddr[self->conn_id] = self->i_faddr; 113 lport[self->conn_id] = self->i_lport; 114 fport[self->conn_id] = self->i_fport; 115 iss[self->conn_id] = self->tcpp->tcp_iss; 116 irs[self->conn_id] = self->tcpp->tcp_irs; 117 118 } 119 120 tcp-trace-* 121 { 122 /* counters, to keep track of how much info to dump */ 123 pcount[self->conn_id]++; 124 rollover[self->conn_id] |= pcount[self->conn_id]/MAX_RECORDS; 125 pcount[self->conn_id] = pcount[self->conn_id]%MAX_RECORDS; 126 self->pcount = pcount[self->conn_id]; 127 end_ptr[self->conn_id] = self->pcount; 128 num[self->conn_id] = (rollover[self->conn_id]? 129 MAX_RECORDS : pcount[self->conn_id] + 1); 130 conn_time[self->conn_id, self->pcount] = walltimestamp; 131 132 /* tcp state info */ 133 seqno[self->conn_id, self->pcount] = ntohl(self->tcph->tha_seq); 134 ack[self->conn_id, self->pcount] = ntohl(self->tcph->tha_ack); 135 datalen[self->conn_id, self->pcount] = ntohs(self->iph->ipha_length); 136 wnd[self->conn_id, self->pcount] = ntohs(self->tcph->tha_win); 137 probe_name[self->conn_id, self->pcount] = probename; 138 139 /* flag 0x04 indicates a RST packet */ 140 flags[self->conn_id, self->pcount] = self->tcph->tha_flags; 141 self->flags = self->tcph->tha_flags; 142 } 143 144 tcp-trace-send 145 { 146 send_count[self->conn_id]++; 147 send_recv[self->conn_id, self->pcount] = "S"; 148 } 149 150 tcp-trace-recv 151 { 152 recv_count[self->conn_id]++; 153 send_recv[self->conn_id, self->pcount] = "R"; 154 } 155 156 tcp-trace-* 157 /(self->flags & TH_RST)/ 158 { 159 PRINT_HEADER(); 160 161 self->i = (end_ptr[self->conn_id] + MAX_RECORDS - num[self->conn_id] 162 + 1)%MAX_RECORDS; 163 } 164 165 tcp-trace-* 166 /(self->flags & TH_RST) && (num[self->conn_id] >= 10)/ 167 { 168 PRINT_RECORD(self->i); 169 self->i = (self->i + 1)%MAX_RECORDS; 170 171 num[self->conn_id]--; 172 } 173 174 tcp-trace-* 175 /(self->flags & TH_RST) && (num[self->conn_id] >= 9)/ 176 { 177 PRINT_RECORD(self->i); 178 self->i = (self->i + 1)%MAX_RECORDS; 179 180 num[self->conn_id]--; 181 } 182 183 tcp-trace-* 184 /(self->flags & TH_RST) && (num[self->conn_id] >= 8)/ 185 { 186 PRINT_RECORD(self->i); 187 self->i = (self->i + 1)%MAX_RECORDS; 188 189 num[self->conn_id]--; 190 } 191 192 tcp-trace-* 193 /(self->flags & TH_RST) && (num[self->conn_id] >= 7)/ 194 { 195 PRINT_RECORD(self->i); 196 self->i = (self->i + 1)%MAX_RECORDS; 197 198 num[self->conn_id]--; 199 } 200 201 tcp-trace-* 202 /(self->flags & TH_RST) && (num[self->conn_id] >= 6)/ 203 { 204 PRINT_RECORD(self->i); 205 self->i = (self->i + 1)%MAX_RECORDS; 206 207 num[self->conn_id]--; 208 } 209 210 tcp-trace-* 211 /(self->flags & TH_RST) && (num[self->conn_id] >= 5)/ 212 { 213 PRINT_RECORD(self->i); 214 self->i = (self->i + 1)%MAX_RECORDS; 215 216 num[self->conn_id]--; 217 } 218 219 tcp-trace-* 220 /(self->flags & TH_RST) && (num[self->conn_id] >= 4)/ 221 { 222 PRINT_RECORD(self->i); 223 self->i = (self->i + 1)%MAX_RECORDS; 224 225 num[self->conn_id]--; 226 } 227 228 tcp-trace-* 229 /(self->flags & TH_RST) && (num[self->conn_id] >= 3)/ 230 { 231 PRINT_RECORD(self->i); 232 self->i = (self->i + 1)%MAX_RECORDS; 233 234 num[self->conn_id]--; 235 } 236 237 tcp-trace-* 238 /(self->flags & TH_RST) && (num[self->conn_id] >= 2)/ 239 { 240 PRINT_RECORD(self->i); 241 self->i = (self->i + 1)%MAX_RECORDS; 242 243 num[self->conn_id]--; 244 } 245 246 tcp-trace-* 247 /(self->flags & TH_RST) && (num[self->conn_id] >= 1)/ 248 { 249 PRINT_RECORD(self->i); 250 self->i = (self->i + 1)%MAX_RECORDS; 251 252 num[self->conn_id]--; 253 self->reset = self->conn_id; 254 } 255 256 tcp-trace-* 257 /self->reset/ 258 { 259 pcount[self->reset] = -1; 260 rollover[self->reset] = 0; 261 end_ptr[self->reset] = 0; 262 num[self->reset] = 0; 263 264 self->reset = 0; 265 } 266 267 conn-destroy 268 { 269 /* clear old connection state */ 270 this->conn_id = (uint64_t)arg0; 271 272 pcount[this->conn_id] = -1; 273 rollover[this->conn_id] = 0; 274 end_ptr[this->conn_id] = 0; 275 num[this->conn_id] = 0; 276 first[this->conn_id] = 0; 277 278 laddr[this->conn_id] = 0; 279 faddr[this->conn_id] = 0; 280 lport[this->conn_id] = 0; 281 fport[this->conn_id] = 0; 282 iss[this->conn_id] = 0; 283 irs[this->conn_id] = 0; 284 } 285