1 #!/usr/sbin/dtrace -s 2 /* 3 * tcptop: display top TCP network packets by process. 4 * Written using DTrace tcp Provider. 5 * 6 * Usage: dtrace -s tcptop.d [count] [interval] 7 * 8 * This analyses TCP network packets and prints the responsible PID plus 9 * standard details such as IP address and port. This captures traffic 10 * of newly created TCP connections that were established while this program 11 * was running along with traffic from existing connections. It can help 12 * identify which processes is causing TCP traffic. 13 * 14 * CDDL HEADER START 15 * 16 * The contents of this file are subject to the terms of the 17 * Common Development and Distribution License (the "License"). 18 * You may not use this file except in compliance with the License. 19 * 20 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 21 * or http://www.opensolaris.org/os/licensing. 22 * See the License for the specific language governing permissions 23 * and limitations under the License. 24 * 25 * When distributing Covered Code, include this CDDL HEADER in each 26 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 27 * If applicable, add the following below this CDDL HEADER, with the 28 * fields enclosed by brackets "[]" replaced with your own identifying 29 * information: Portions Copyright [yyyy] [name of copyright owner] 30 * 31 * CDDL HEADER END 32 */ 33 /* 34 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 35 * 36 * Portions Copyright 2010 Brendan Gregg 37 */ 38 39 #pragma D option quiet 40 #pragma D option defaultargs 41 #pragma D option switchrate=10hz 42 43 /* 44 * Print header 45 */ 46 dtrace:::BEGIN 47 { 48 /* starting values */ 49 counts = $1 ? $1 : 10; 50 secs = $2 ? $2 : 5; 51 TCP_out = 0; 52 TCP_in = 0; 53 54 printf("Sampling... Please wait.\n"); 55 } 56 57 58 tcp:::send 59 / args[1]->cs_pid != -1 / 60 { 61 @out[args[1]->cs_zoneid, args[1]->cs_pid, args[2]->ip_saddr, 62 args[4]->tcp_sport, args[2]->ip_daddr, args[4]->tcp_dport] = 63 sum(args[2]->ip_plength - args[4]->tcp_offset); 64 } 65 66 tcp:::receive 67 / args[1]->cs_pid != -1 / 68 { 69 @out[args[1]->cs_zoneid, args[1]->cs_pid, args[2]->ip_daddr, 70 args[4]->tcp_dport, args[2]->ip_saddr, args[4]->tcp_sport] = 71 sum(args[2]->ip_plength - args[4]->tcp_offset); 72 } 73 74 /* 75 * TCP Systemwide Stats 76 */ 77 mib:::tcpOutDataBytes { TCP_out += args[0]; } 78 mib:::tcpRetransBytes { TCP_out += args[0]; } 79 mib:::tcpInDataInorderBytes { TCP_in += args[0]; } 80 mib:::tcpInDataDupBytes { TCP_in += args[0]; } 81 mib:::tcpInDataUnorderBytes { TCP_in += args[0]; } 82 83 profile:::tick-1sec 84 /secs != 0/ 85 { 86 secs--; 87 } 88 89 /* 90 * Print Report 91 */ 92 profile:::tick-1sec 93 /secs == 0/ 94 { 95 /* fetch 1 min load average */ 96 this->load1a = `hp_avenrun[0] / 65536; 97 this->load1b = ((`hp_avenrun[0] % 65536) * 100) / 65536; 98 99 /* convert TCP counters to Kb */ 100 TCP_out /= 1024; 101 TCP_in /= 1024; 102 103 /* print status */ 104 printf("%Y, load: %d.%02d, TCPin: %6d Kb, TCPout: %6d Kb\n\n", 105 walltimestamp, this->load1a, this->load1b, TCP_in, TCP_out); 106 107 /* print headers */ 108 printf("%6s %6s %-15s %5s %-15s %5s %9s\n", 109 "ZONE", "PID", "LADDR", "LPORT", "RADDR", "RPORT", "SIZE"); 110 111 /* print data */ 112 printa("%6d %6d %-15s %5d %-15s %5d %@9d\n", @out); 113 printf("\n"); 114 115 /* clear data */ 116 trunc(@out); 117 TCP_in = 0; 118 TCP_out = 0; 119 secs = 5; 120 counts--; 121 } 122 123 /* 124 * End of program 125 */ 126 profile:::tick-1sec 127 /counts == 0/ 128 { 129 exit(0); 130 } 131 132 /* 133 * Cleanup for Ctrl-C 134 */ 135 dtrace:::END 136 { 137 trunc(@out); 138 } 139