1*387f9dfdSAndroid Build Coastguard Worker#!/usr/bin/env bcc-lua 2*387f9dfdSAndroid Build Coastguard Worker--[[ 3*387f9dfdSAndroid Build Coastguard WorkerLicensed under the Apache License, Version 2.0 (the "License"); 4*387f9dfdSAndroid Build Coastguard Workeryou may not use this file except in compliance with the License. 5*387f9dfdSAndroid Build Coastguard WorkerYou may obtain a copy of the License at 6*387f9dfdSAndroid Build Coastguard Worker 7*387f9dfdSAndroid Build Coastguard Workerhttp://www.apache.org/licenses/LICENSE-2.0 8*387f9dfdSAndroid Build Coastguard Worker 9*387f9dfdSAndroid Build Coastguard WorkerUnless required by applicable law or agreed to in writing, software 10*387f9dfdSAndroid Build Coastguard Workerdistributed under the License is distributed on an "AS IS" BASIS, 11*387f9dfdSAndroid Build Coastguard WorkerWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*387f9dfdSAndroid Build Coastguard WorkerSee the License for the specific language governing permissions and 13*387f9dfdSAndroid Build Coastguard Workerlimitations under the License. 14*387f9dfdSAndroid Build Coastguard Worker 15*387f9dfdSAndroid Build Coastguard Worker18-Mar-2017 Simon Liu Created this. 16*387f9dfdSAndroid Build Coastguard Worker--]] 17*387f9dfdSAndroid Build Coastguard Worker 18*387f9dfdSAndroid Build Coastguard Workerlocal ffi = require("ffi") 19*387f9dfdSAndroid Build Coastguard Workerlocal bit = require("bit") 20*387f9dfdSAndroid Build Coastguard Worker 21*387f9dfdSAndroid Build Coastguard Workerffi.cdef[[ 22*387f9dfdSAndroid Build Coastguard Workerconst char *inet_ntop(int af, const void *src, char *dst, int size); 23*387f9dfdSAndroid Build Coastguard Workeruint16_t ntohs(uint16_t netshort); 24*387f9dfdSAndroid Build Coastguard Worker]] 25*387f9dfdSAndroid Build Coastguard Worker 26*387f9dfdSAndroid Build Coastguard Workerlocal program = [[ 27*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ptrace.h> 28*387f9dfdSAndroid Build Coastguard Worker#include <linux/tcp.h> 29*387f9dfdSAndroid Build Coastguard Worker#include <net/sock.h> 30*387f9dfdSAndroid Build Coastguard Worker#include <bcc/proto.h> 31*387f9dfdSAndroid Build Coastguard Worker 32*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(birth, struct sock *, u64); 33*387f9dfdSAndroid Build Coastguard Worker 34*387f9dfdSAndroid Build Coastguard Worker// separate data structs for ipv4 and ipv6 35*387f9dfdSAndroid Build Coastguard Workerstruct ipv4_data_t { 36*387f9dfdSAndroid Build Coastguard Worker // XXX: switch some to u32's when supported 37*387f9dfdSAndroid Build Coastguard Worker u64 ts_us; 38*387f9dfdSAndroid Build Coastguard Worker u64 pid; 39*387f9dfdSAndroid Build Coastguard Worker u64 saddr; 40*387f9dfdSAndroid Build Coastguard Worker u64 daddr; 41*387f9dfdSAndroid Build Coastguard Worker u64 ports; 42*387f9dfdSAndroid Build Coastguard Worker u64 rx_b; 43*387f9dfdSAndroid Build Coastguard Worker u64 tx_b; 44*387f9dfdSAndroid Build Coastguard Worker u64 span_us; 45*387f9dfdSAndroid Build Coastguard Worker char task[TASK_COMM_LEN]; 46*387f9dfdSAndroid Build Coastguard Worker}; 47*387f9dfdSAndroid Build Coastguard WorkerBPF_PERF_OUTPUT(ipv4_events); 48*387f9dfdSAndroid Build Coastguard Worker 49*387f9dfdSAndroid Build Coastguard Workerstruct ipv6_data_t { 50*387f9dfdSAndroid Build Coastguard Worker u64 ts_us; 51*387f9dfdSAndroid Build Coastguard Worker u64 pid; 52*387f9dfdSAndroid Build Coastguard Worker u64 saddr[2]; 53*387f9dfdSAndroid Build Coastguard Worker u64 daddr[2]; 54*387f9dfdSAndroid Build Coastguard Worker u64 ports; 55*387f9dfdSAndroid Build Coastguard Worker u64 rx_b; 56*387f9dfdSAndroid Build Coastguard Worker u64 tx_b; 57*387f9dfdSAndroid Build Coastguard Worker u64 span_us; 58*387f9dfdSAndroid Build Coastguard Worker char task[TASK_COMM_LEN]; 59*387f9dfdSAndroid Build Coastguard Worker}; 60*387f9dfdSAndroid Build Coastguard WorkerBPF_PERF_OUTPUT(ipv6_events); 61*387f9dfdSAndroid Build Coastguard Worker 62*387f9dfdSAndroid Build Coastguard Workerstruct id_t { 63*387f9dfdSAndroid Build Coastguard Worker u32 pid; 64*387f9dfdSAndroid Build Coastguard Worker char task[TASK_COMM_LEN]; 65*387f9dfdSAndroid Build Coastguard Worker}; 66*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(whoami, struct sock *, struct id_t); 67*387f9dfdSAndroid Build Coastguard Worker 68*387f9dfdSAndroid Build Coastguard Workerint trace_tcp_set_state(struct pt_regs *ctx, struct sock *sk, int state) 69*387f9dfdSAndroid Build Coastguard Worker{ 70*387f9dfdSAndroid Build Coastguard Worker bpf_trace_printk("tcp_set_stat"); 71*387f9dfdSAndroid Build Coastguard Worker u32 pid = bpf_get_current_pid_tgid() >> 32; 72*387f9dfdSAndroid Build Coastguard Worker 73*387f9dfdSAndroid Build Coastguard Worker // lport is either used in a filter here, or later 74*387f9dfdSAndroid Build Coastguard Worker u16 lport = sk->__sk_common.skc_num; 75*387f9dfdSAndroid Build Coastguard Worker FILTER_LPORT 76*387f9dfdSAndroid Build Coastguard Worker 77*387f9dfdSAndroid Build Coastguard Worker // dport is either used in a filter here, or later 78*387f9dfdSAndroid Build Coastguard Worker u16 dport = sk->__sk_common.skc_dport; 79*387f9dfdSAndroid Build Coastguard Worker FILTER_DPORT 80*387f9dfdSAndroid Build Coastguard Worker 81*387f9dfdSAndroid Build Coastguard Worker /* 82*387f9dfdSAndroid Build Coastguard Worker * This tool includes PID and comm context. It's best effort, and may 83*387f9dfdSAndroid Build Coastguard Worker * be wrong in some situations. It currently works like this: 84*387f9dfdSAndroid Build Coastguard Worker * - record timestamp on any state < TCP_FIN_WAIT1 85*387f9dfdSAndroid Build Coastguard Worker * - cache task context on: 86*387f9dfdSAndroid Build Coastguard Worker * TCP_SYN_SENT: tracing from client 87*387f9dfdSAndroid Build Coastguard Worker * TCP_LAST_ACK: client-closed from server 88*387f9dfdSAndroid Build Coastguard Worker * - do output on TCP_CLOSE: 89*387f9dfdSAndroid Build Coastguard Worker * fetch task context if cached, or use current task 90*387f9dfdSAndroid Build Coastguard Worker */ 91*387f9dfdSAndroid Build Coastguard Worker 92*387f9dfdSAndroid Build Coastguard Worker // capture birth time 93*387f9dfdSAndroid Build Coastguard Worker if (state < TCP_FIN_WAIT1) { 94*387f9dfdSAndroid Build Coastguard Worker /* 95*387f9dfdSAndroid Build Coastguard Worker * Matching just ESTABLISHED may be sufficient, provided no code-path 96*387f9dfdSAndroid Build Coastguard Worker * sets ESTABLISHED without a tcp_set_state() call. Until we know 97*387f9dfdSAndroid Build Coastguard Worker * that for sure, match all early states to increase chances a 98*387f9dfdSAndroid Build Coastguard Worker * timestamp is set. 99*387f9dfdSAndroid Build Coastguard Worker * Note that this needs to be set before the PID filter later on, 100*387f9dfdSAndroid Build Coastguard Worker * since the PID isn't reliable for these early stages, so we must 101*387f9dfdSAndroid Build Coastguard Worker * save all timestamps and do the PID filter later when we can. 102*387f9dfdSAndroid Build Coastguard Worker */ 103*387f9dfdSAndroid Build Coastguard Worker u64 ts = bpf_ktime_get_ns(); 104*387f9dfdSAndroid Build Coastguard Worker birth.update(&sk, &ts); 105*387f9dfdSAndroid Build Coastguard Worker } 106*387f9dfdSAndroid Build Coastguard Worker 107*387f9dfdSAndroid Build Coastguard Worker // record PID & comm on SYN_SENT 108*387f9dfdSAndroid Build Coastguard Worker if (state == TCP_SYN_SENT || state == TCP_LAST_ACK) { 109*387f9dfdSAndroid Build Coastguard Worker // now we can PID filter, both here and a little later on for CLOSE 110*387f9dfdSAndroid Build Coastguard Worker FILTER_PID 111*387f9dfdSAndroid Build Coastguard Worker struct id_t me = {.pid = pid}; 112*387f9dfdSAndroid Build Coastguard Worker bpf_get_current_comm(&me.task, sizeof(me.task)); 113*387f9dfdSAndroid Build Coastguard Worker whoami.update(&sk, &me); 114*387f9dfdSAndroid Build Coastguard Worker } 115*387f9dfdSAndroid Build Coastguard Worker 116*387f9dfdSAndroid Build Coastguard Worker if (state != TCP_CLOSE) 117*387f9dfdSAndroid Build Coastguard Worker return 0; 118*387f9dfdSAndroid Build Coastguard Worker 119*387f9dfdSAndroid Build Coastguard Worker // calculate lifespan 120*387f9dfdSAndroid Build Coastguard Worker u64 *tsp, delta_us; 121*387f9dfdSAndroid Build Coastguard Worker tsp = birth.lookup(&sk); 122*387f9dfdSAndroid Build Coastguard Worker if (tsp == 0) { 123*387f9dfdSAndroid Build Coastguard Worker whoami.delete(&sk); // may not exist 124*387f9dfdSAndroid Build Coastguard Worker return 0; // missed create 125*387f9dfdSAndroid Build Coastguard Worker } 126*387f9dfdSAndroid Build Coastguard Worker delta_us = (bpf_ktime_get_ns() - *tsp) / 1000; 127*387f9dfdSAndroid Build Coastguard Worker birth.delete(&sk); 128*387f9dfdSAndroid Build Coastguard Worker 129*387f9dfdSAndroid Build Coastguard Worker // fetch possible cached data, and filter 130*387f9dfdSAndroid Build Coastguard Worker struct id_t *mep; 131*387f9dfdSAndroid Build Coastguard Worker mep = whoami.lookup(&sk); 132*387f9dfdSAndroid Build Coastguard Worker if (mep != 0) 133*387f9dfdSAndroid Build Coastguard Worker pid = mep->pid; 134*387f9dfdSAndroid Build Coastguard Worker FILTER_PID 135*387f9dfdSAndroid Build Coastguard Worker 136*387f9dfdSAndroid Build Coastguard Worker // get throughput stats. see tcp_get_info(). 137*387f9dfdSAndroid Build Coastguard Worker u64 rx_b = 0, tx_b = 0, sport = 0; 138*387f9dfdSAndroid Build Coastguard Worker struct tcp_sock *tp = (struct tcp_sock *)sk; 139*387f9dfdSAndroid Build Coastguard Worker rx_b = tp->bytes_received; 140*387f9dfdSAndroid Build Coastguard Worker tx_b = tp->bytes_acked; 141*387f9dfdSAndroid Build Coastguard Worker 142*387f9dfdSAndroid Build Coastguard Worker u16 family = sk->__sk_common.skc_family; 143*387f9dfdSAndroid Build Coastguard Worker 144*387f9dfdSAndroid Build Coastguard Worker if (family == AF_INET) { 145*387f9dfdSAndroid Build Coastguard Worker struct ipv4_data_t data4 = {.span_us = delta_us, 146*387f9dfdSAndroid Build Coastguard Worker .rx_b = rx_b, .tx_b = tx_b}; 147*387f9dfdSAndroid Build Coastguard Worker data4.ts_us = bpf_ktime_get_ns() / 1000; 148*387f9dfdSAndroid Build Coastguard Worker data4.saddr = sk->__sk_common.skc_rcv_saddr; 149*387f9dfdSAndroid Build Coastguard Worker data4.daddr = sk->__sk_common.skc_daddr; 150*387f9dfdSAndroid Build Coastguard Worker // a workaround until data4 compiles with separate lport/dport 151*387f9dfdSAndroid Build Coastguard Worker data4.pid = pid; 152*387f9dfdSAndroid Build Coastguard Worker data4.ports = ntohs(dport) + ((0ULL + lport) << 32); 153*387f9dfdSAndroid Build Coastguard Worker if (mep == 0) { 154*387f9dfdSAndroid Build Coastguard Worker bpf_get_current_comm(&data4.task, sizeof(data4.task)); 155*387f9dfdSAndroid Build Coastguard Worker } else { 156*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read_kernel(&data4.task, sizeof(data4.task), (void *)mep->task); 157*387f9dfdSAndroid Build Coastguard Worker } 158*387f9dfdSAndroid Build Coastguard Worker ipv4_events.perf_submit(ctx, &data4, sizeof(data4)); 159*387f9dfdSAndroid Build Coastguard Worker 160*387f9dfdSAndroid Build Coastguard Worker } else /* 6 */ { 161*387f9dfdSAndroid Build Coastguard Worker struct ipv6_data_t data6 = {.span_us = delta_us, 162*387f9dfdSAndroid Build Coastguard Worker .rx_b = rx_b, .tx_b = tx_b}; 163*387f9dfdSAndroid Build Coastguard Worker data6.ts_us = bpf_ktime_get_ns() / 1000; 164*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read_kernel(&data6.saddr, sizeof(data6.saddr), 165*387f9dfdSAndroid Build Coastguard Worker sk->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32); 166*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read_kernel(&data6.daddr, sizeof(data6.daddr), 167*387f9dfdSAndroid Build Coastguard Worker sk->__sk_common.skc_v6_daddr.in6_u.u6_addr32); 168*387f9dfdSAndroid Build Coastguard Worker // a workaround until data6 compiles with separate lport/dport 169*387f9dfdSAndroid Build Coastguard Worker data6.ports = ntohs(dport) + ((0ULL + lport) << 32); 170*387f9dfdSAndroid Build Coastguard Worker data6.pid = pid; 171*387f9dfdSAndroid Build Coastguard Worker if (mep == 0) { 172*387f9dfdSAndroid Build Coastguard Worker bpf_get_current_comm(&data6.task, sizeof(data6.task)); 173*387f9dfdSAndroid Build Coastguard Worker } else { 174*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read_kernel(&data6.task, sizeof(data6.task), (void *)mep->task); 175*387f9dfdSAndroid Build Coastguard Worker } 176*387f9dfdSAndroid Build Coastguard Worker ipv6_events.perf_submit(ctx, &data6, sizeof(data6)); 177*387f9dfdSAndroid Build Coastguard Worker } 178*387f9dfdSAndroid Build Coastguard Worker 179*387f9dfdSAndroid Build Coastguard Worker if (mep != 0) 180*387f9dfdSAndroid Build Coastguard Worker whoami.delete(&sk); 181*387f9dfdSAndroid Build Coastguard Worker 182*387f9dfdSAndroid Build Coastguard Worker return 0; 183*387f9dfdSAndroid Build Coastguard Worker} 184*387f9dfdSAndroid Build Coastguard Worker]] 185*387f9dfdSAndroid Build Coastguard Worker 186*387f9dfdSAndroid Build Coastguard Workerlocal debug = false 187*387f9dfdSAndroid Build Coastguard Workerlocal start_ts = 0 188*387f9dfdSAndroid Build Coastguard Worker 189*387f9dfdSAndroid Build Coastguard Workerlocal inet_addresslen = #"255.255.255.255" 190*387f9dfdSAndroid Build Coastguard Workerlocal inet6_addresslen = #"ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255" 191*387f9dfdSAndroid Build Coastguard Workerlocal AF_INET = 2 192*387f9dfdSAndroid Build Coastguard Workerlocal AF_INET6 = 10 193*387f9dfdSAndroid Build Coastguard Worker 194*387f9dfdSAndroid Build Coastguard Workerlocal header_string = "%-5s %-10.10s %s%-15s %-5s %-15s %-5s %5s %5s %s" 195*387f9dfdSAndroid Build Coastguard Workerlocal format_string = "%-5d %-10.10s %s%-15s %-5d %-15s %-5d %5d %5d %.2f" 196*387f9dfdSAndroid Build Coastguard Workerlocal ip_string = "" 197*387f9dfdSAndroid Build Coastguard Workerlocal ip_version = false 198*387f9dfdSAndroid Build Coastguard Workerlocal arg_timestamp = false 199*387f9dfdSAndroid Build Coastguard Workerlocal arg_csv = false 200*387f9dfdSAndroid Build Coastguard Workerlocal arg_time = false 201*387f9dfdSAndroid Build Coastguard Worker 202*387f9dfdSAndroid Build Coastguard Workerlocal examples = [[examples: 203*387f9dfdSAndroid Build Coastguard Worker ./tcplife # trace all TCP connect()s 204*387f9dfdSAndroid Build Coastguard Worker ./tcplife -t # include time column (HH:MM:SS) 205*387f9dfdSAndroid Build Coastguard Worker ./tcplife -w # wider columns (fit IPv6) 206*387f9dfdSAndroid Build Coastguard Worker ./tcplife -stT # csv output, with times & timestamps 207*387f9dfdSAndroid Build Coastguard Worker ./tcplife -p 181 # only trace PID 181 208*387f9dfdSAndroid Build Coastguard Worker ./tcplife -L 80 # only trace local port 80 209*387f9dfdSAndroid Build Coastguard Worker ./tcplife -L 80,81 # only trace local ports 80 and 81 210*387f9dfdSAndroid Build Coastguard Worker ./tcplife -D 80 # only trace remote port 80 211*387f9dfdSAndroid Build Coastguard Worker]] 212*387f9dfdSAndroid Build Coastguard Worker 213*387f9dfdSAndroid Build Coastguard Workerlocal function split(str,sep) 214*387f9dfdSAndroid Build Coastguard Worker local t = {} 215*387f9dfdSAndroid Build Coastguard Worker for w in string.gmatch(str, '([^,]+)') do 216*387f9dfdSAndroid Build Coastguard Worker table.insert(t, w) 217*387f9dfdSAndroid Build Coastguard Worker end 218*387f9dfdSAndroid Build Coastguard Worker return t 219*387f9dfdSAndroid Build Coastguard Workerend 220*387f9dfdSAndroid Build Coastguard Worker 221*387f9dfdSAndroid Build Coastguard Workerlocal function inet_ntop(af, addr, len) 222*387f9dfdSAndroid Build Coastguard Worker local addr_dst = ffi.new("char[?]", len) 223*387f9dfdSAndroid Build Coastguard Worker local addr_src 224*387f9dfdSAndroid Build Coastguard Worker if af == AF_INET then 225*387f9dfdSAndroid Build Coastguard Worker addr_src = ffi.new("uint64_t[1]", addr) 226*387f9dfdSAndroid Build Coastguard Worker else 227*387f9dfdSAndroid Build Coastguard Worker addr_src = ffi.new("uint64_t[2]", addr) 228*387f9dfdSAndroid Build Coastguard Worker end 229*387f9dfdSAndroid Build Coastguard Worker ffi.C.inet_ntop(af, addr_src, addr_dst, len) 230*387f9dfdSAndroid Build Coastguard Worker return ffi.string(addr_dst, len) 231*387f9dfdSAndroid Build Coastguard Workerend 232*387f9dfdSAndroid Build Coastguard Worker 233*387f9dfdSAndroid Build Coastguard Workerlocal function inet_ntohs(port) 234*387f9dfdSAndroid Build Coastguard Worker local p = tonumber(port) 235*387f9dfdSAndroid Build Coastguard Worker return ffi.C.ntohs(p) 236*387f9dfdSAndroid Build Coastguard Workerend 237*387f9dfdSAndroid Build Coastguard Worker 238*387f9dfdSAndroid Build Coastguard Workerlocal function print_ipv4_event(cpu, event) 239*387f9dfdSAndroid Build Coastguard Worker 240*387f9dfdSAndroid Build Coastguard Worker local event_pid = tonumber(event.pid) 241*387f9dfdSAndroid Build Coastguard Worker local event_task = ffi.string(event.task) 242*387f9dfdSAndroid Build Coastguard Worker local event_ports = tonumber(event.ports) 243*387f9dfdSAndroid Build Coastguard Worker local event_tx_b = tonumber(event.tx_b) 244*387f9dfdSAndroid Build Coastguard Worker local event_rx_b = tonumber(event.rx_b) 245*387f9dfdSAndroid Build Coastguard Worker local event_span_us = tonumber(event.span_us) 246*387f9dfdSAndroid Build Coastguard Worker local event_ts_us = tonumber(event.ts_us) 247*387f9dfdSAndroid Build Coastguard Worker local event_saddr = inet_ntop(AF_INET, tonumber(event.saddr), inet_addresslen) 248*387f9dfdSAndroid Build Coastguard Worker local event_daddr = inet_ntop(AF_INET, tonumber(event.daddr), inet_addresslen) 249*387f9dfdSAndroid Build Coastguard Worker if arg_time then 250*387f9dfdSAndroid Build Coastguard Worker if arg_csv then 251*387f9dfdSAndroid Build Coastguard Worker io.write("%s," % os.date("%H:%M:%S")) 252*387f9dfdSAndroid Build Coastguard Worker else 253*387f9dfdSAndroid Build Coastguard Worker io.write("%-8s " % os.date("%H:%M:%S")) 254*387f9dfdSAndroid Build Coastguard Worker end 255*387f9dfdSAndroid Build Coastguard Worker end 256*387f9dfdSAndroid Build Coastguard Worker if arg_timestamp then 257*387f9dfdSAndroid Build Coastguard Worker if start_ts == 0 then 258*387f9dfdSAndroid Build Coastguard Worker start_ts = event_ts_us 259*387f9dfdSAndroid Build Coastguard Worker end 260*387f9dfdSAndroid Build Coastguard Worker local delta_s = (event_ts_us - start_ts) / 1000000 261*387f9dfdSAndroid Build Coastguard Worker if arg.csv then 262*387f9dfdSAndroid Build Coastguard Worker io.write("%.6f," % delta_s) 263*387f9dfdSAndroid Build Coastguard Worker else 264*387f9dfdSAndroid Build Coastguard Worker io.write("%-9.6f " % delta_s) 265*387f9dfdSAndroid Build Coastguard Worker end 266*387f9dfdSAndroid Build Coastguard Worker end 267*387f9dfdSAndroid Build Coastguard Worker local iv = "" 268*387f9dfdSAndroid Build Coastguard Worker if ip_version then 269*387f9dfdSAndroid Build Coastguard Worker iv = "4" 270*387f9dfdSAndroid Build Coastguard Worker end 271*387f9dfdSAndroid Build Coastguard Worker print(string.format(format_string, event_pid, event_task, iv, 272*387f9dfdSAndroid Build Coastguard Worker event_saddr, bit.rshift(event_ports,32), 273*387f9dfdSAndroid Build Coastguard Worker event_daddr, bit.band(event_ports,0xffffffff), 274*387f9dfdSAndroid Build Coastguard Worker (event_tx_b / 1024), (event_rx_b / 1024), event_span_us/ 1000)) 275*387f9dfdSAndroid Build Coastguard Workerend 276*387f9dfdSAndroid Build Coastguard Worker 277*387f9dfdSAndroid Build Coastguard Worker 278*387f9dfdSAndroid Build Coastguard Workerlocal function print_ipv6_event(cpu, event) 279*387f9dfdSAndroid Build Coastguard Worker local event_pid = tonumber(event.pid) 280*387f9dfdSAndroid Build Coastguard Worker local event_task = ffi.string(event.task) 281*387f9dfdSAndroid Build Coastguard Worker local event_ports = tonumber(event.ports) 282*387f9dfdSAndroid Build Coastguard Worker local event_tx_b = tonumber(event.tx_b) 283*387f9dfdSAndroid Build Coastguard Worker local event_rx_b = tonumber(event.rx_b) 284*387f9dfdSAndroid Build Coastguard Worker local event_span_us = tonumber(event.span_us) 285*387f9dfdSAndroid Build Coastguard Worker local event_ts_us = tonumber(event.ts_us) 286*387f9dfdSAndroid Build Coastguard Worker local event_saddr = inet_ntop(AF_INET6, {tonumber(event.saddr[0]), tonumber(event.saddr[1])}, inet6_addresslen) 287*387f9dfdSAndroid Build Coastguard Worker local event_daddr = inet_ntop(AF_INET6, {tonumber(event.daddr[0]), tonumber(event.daddr[1])}, inet6_addresslen) 288*387f9dfdSAndroid Build Coastguard Worker if arg_time then 289*387f9dfdSAndroid Build Coastguard Worker if arg_csv then 290*387f9dfdSAndroid Build Coastguard Worker io.write("%s," % os.date("%H:%M:%S")) 291*387f9dfdSAndroid Build Coastguard Worker else 292*387f9dfdSAndroid Build Coastguard Worker io.write("%-8s " % os.date("%H:%M:%S")) 293*387f9dfdSAndroid Build Coastguard Worker end 294*387f9dfdSAndroid Build Coastguard Worker end 295*387f9dfdSAndroid Build Coastguard Worker if arg_timestamp then 296*387f9dfdSAndroid Build Coastguard Worker if start_ts == 0 then 297*387f9dfdSAndroid Build Coastguard Worker start_ts = event_ts_us 298*387f9dfdSAndroid Build Coastguard Worker end 299*387f9dfdSAndroid Build Coastguard Worker local delta_s = (event_ts_us - start_ts) / 1000000 300*387f9dfdSAndroid Build Coastguard Worker if arg.csv then 301*387f9dfdSAndroid Build Coastguard Worker io.write("%.6f," % delta_s) 302*387f9dfdSAndroid Build Coastguard Worker else 303*387f9dfdSAndroid Build Coastguard Worker io.write("%-9.6f " % delta_s) 304*387f9dfdSAndroid Build Coastguard Worker end 305*387f9dfdSAndroid Build Coastguard Worker end 306*387f9dfdSAndroid Build Coastguard Worker local iv = "" 307*387f9dfdSAndroid Build Coastguard Worker if ip_version then 308*387f9dfdSAndroid Build Coastguard Worker iv = "6" 309*387f9dfdSAndroid Build Coastguard Worker end 310*387f9dfdSAndroid Build Coastguard Worker print(string.format(format_string, event_pid, event_task, iv, 311*387f9dfdSAndroid Build Coastguard Worker event_saddr, bit.rshift(event_ports,32), 312*387f9dfdSAndroid Build Coastguard Worker event_daddr, bit.band(event_ports,0xffffffff), 313*387f9dfdSAndroid Build Coastguard Worker (event_tx_b / 1024), (event_rx_b / 1024), event_span_us/ 1000)) 314*387f9dfdSAndroid Build Coastguard Workerend 315*387f9dfdSAndroid Build Coastguard Worker 316*387f9dfdSAndroid Build Coastguard Workerlocal function parse_arg(utils) 317*387f9dfdSAndroid Build Coastguard Worker local parser = utils.argparse("tcplife", 318*387f9dfdSAndroid Build Coastguard Worker "Trace the lifespan of TCP sessions and summarize", examples) 319*387f9dfdSAndroid Build Coastguard Worker 320*387f9dfdSAndroid Build Coastguard Worker parser:flag("-T --time", "include time column on output (HH:MM:SS)") 321*387f9dfdSAndroid Build Coastguard Worker parser:flag("-t --timestamp", "include timestamp on output (seconds)") 322*387f9dfdSAndroid Build Coastguard Worker parser:flag("-w --wide", "wide column output (fits IPv6 addresses)") 323*387f9dfdSAndroid Build Coastguard Worker parser:flag("-s --csv", "comma separated values output") 324*387f9dfdSAndroid Build Coastguard Worker parser:option("-p --pid", "trace this PID only"):convert(tonumber) 325*387f9dfdSAndroid Build Coastguard Worker parser:option("-L --localport", "comma-separated list of local ports to trace.") 326*387f9dfdSAndroid Build Coastguard Worker parser:option("-D --remoteport", "comma-separated list of remote ports to trace.") 327*387f9dfdSAndroid Build Coastguard Worker 328*387f9dfdSAndroid Build Coastguard Worker local args = parser:parse() 329*387f9dfdSAndroid Build Coastguard Worker if args.pid then 330*387f9dfdSAndroid Build Coastguard Worker local filter = 'if (pid != %d) { return 0; }' % args.pid 331*387f9dfdSAndroid Build Coastguard Worker program = program.gsub('FILTER_PID', filter) 332*387f9dfdSAndroid Build Coastguard Worker end 333*387f9dfdSAndroid Build Coastguard Worker 334*387f9dfdSAndroid Build Coastguard Worker if args.remoteport then 335*387f9dfdSAndroid Build Coastguard Worker local dports = split(args.remoteport, ",") 336*387f9dfdSAndroid Build Coastguard Worker local dports_if = "" 337*387f9dfdSAndroid Build Coastguard Worker for i,d in ipairs(dports) do 338*387f9dfdSAndroid Build Coastguard Worker if dports_if == "" then 339*387f9dfdSAndroid Build Coastguard Worker dports_if = 'dport != %d' % inet_ntohs(d) 340*387f9dfdSAndroid Build Coastguard Worker else 341*387f9dfdSAndroid Build Coastguard Worker dports_if = dports_if .. ' && ' .. ('dport != %d' % inet_ntohs(d)) 342*387f9dfdSAndroid Build Coastguard Worker end 343*387f9dfdSAndroid Build Coastguard Worker end 344*387f9dfdSAndroid Build Coastguard Worker local filter = "if (%s) { birth.delete(&sk); return 0; }" % dports_if 345*387f9dfdSAndroid Build Coastguard Worker program = program:gsub('FILTER_DPORT', filter) 346*387f9dfdSAndroid Build Coastguard Worker end 347*387f9dfdSAndroid Build Coastguard Worker if args.localport then 348*387f9dfdSAndroid Build Coastguard Worker local lports = split(args.localport,",") 349*387f9dfdSAndroid Build Coastguard Worker local lports_if = "" 350*387f9dfdSAndroid Build Coastguard Worker for i,l in ipairs(lports) do 351*387f9dfdSAndroid Build Coastguard Worker if lports_if == "" then 352*387f9dfdSAndroid Build Coastguard Worker lports_if = 'lport != %d' % inet_ntohs(l) 353*387f9dfdSAndroid Build Coastguard Worker else 354*387f9dfdSAndroid Build Coastguard Worker lports_if = lports_if .. ' && ' .. ('lport != %d' % inet_ntohs(l)) 355*387f9dfdSAndroid Build Coastguard Worker end 356*387f9dfdSAndroid Build Coastguard Worker end 357*387f9dfdSAndroid Build Coastguard Worker local filter = "if (%s) { birth.delete(&sk); return 0; }" % lports_if 358*387f9dfdSAndroid Build Coastguard Worker program = program:gsub('FILTER_LPORT', filter) 359*387f9dfdSAndroid Build Coastguard Worker end 360*387f9dfdSAndroid Build Coastguard Worker program = program:gsub('FILTER_PID', '') 361*387f9dfdSAndroid Build Coastguard Worker program = program:gsub('FILTER_DPORT', '') 362*387f9dfdSAndroid Build Coastguard Worker program = program:gsub('FILTER_LPORT', '') 363*387f9dfdSAndroid Build Coastguard Worker 364*387f9dfdSAndroid Build Coastguard Worker if args.wide then 365*387f9dfdSAndroid Build Coastguard Worker header_string = "%-5s %-16.16s %-2s %-39s %-5s %-39s %-5s %6s %6s %s" 366*387f9dfdSAndroid Build Coastguard Worker format_string = "%-5d %-16.16s %-2s %-39s %-5s %-39s %-5d %6d %6d %.2f" 367*387f9dfdSAndroid Build Coastguard Worker ip_string = "IP" 368*387f9dfdSAndroid Build Coastguard Worker ip_version = true 369*387f9dfdSAndroid Build Coastguard Worker end 370*387f9dfdSAndroid Build Coastguard Worker if args.csv then 371*387f9dfdSAndroid Build Coastguard Worker header_string = "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s" 372*387f9dfdSAndroid Build Coastguard Worker format_string = "%d,%s,%s,%s,%s,%s,%d,%d,%d,%.2f" 373*387f9dfdSAndroid Build Coastguard Worker ip_string = "IP" 374*387f9dfdSAndroid Build Coastguard Worker ip_version = true 375*387f9dfdSAndroid Build Coastguard Worker arg_csv = true 376*387f9dfdSAndroid Build Coastguard Worker end 377*387f9dfdSAndroid Build Coastguard Worker 378*387f9dfdSAndroid Build Coastguard Worker if args.time then 379*387f9dfdSAndroid Build Coastguard Worker arg_time = true 380*387f9dfdSAndroid Build Coastguard Worker if args.csv then 381*387f9dfdSAndroid Build Coastguard Worker io.write("%s," % ("TIME")) 382*387f9dfdSAndroid Build Coastguard Worker else 383*387f9dfdSAndroid Build Coastguard Worker io.write("%-8s " % ("TIME")) 384*387f9dfdSAndroid Build Coastguard Worker end 385*387f9dfdSAndroid Build Coastguard Worker end 386*387f9dfdSAndroid Build Coastguard Worker 387*387f9dfdSAndroid Build Coastguard Worker if args.timestamp then 388*387f9dfdSAndroid Build Coastguard Worker arg_timestamp = true 389*387f9dfdSAndroid Build Coastguard Worker if args.csv then 390*387f9dfdSAndroid Build Coastguard Worker io.write("%s," % ("TIME(s)")) 391*387f9dfdSAndroid Build Coastguard Worker else 392*387f9dfdSAndroid Build Coastguard Worker io.write("%-9s " % ("TIME(s)")) 393*387f9dfdSAndroid Build Coastguard Worker end 394*387f9dfdSAndroid Build Coastguard Worker end 395*387f9dfdSAndroid Build Coastguard Worker 396*387f9dfdSAndroid Build Coastguard Workerend 397*387f9dfdSAndroid Build Coastguard Worker 398*387f9dfdSAndroid Build Coastguard Workerreturn function(BPF, utils) 399*387f9dfdSAndroid Build Coastguard Worker parse_arg(utils) 400*387f9dfdSAndroid Build Coastguard Worker if debug then 401*387f9dfdSAndroid Build Coastguard Worker print(program) 402*387f9dfdSAndroid Build Coastguard Worker end 403*387f9dfdSAndroid Build Coastguard Worker 404*387f9dfdSAndroid Build Coastguard Worker local bpf = BPF:new{text=program} 405*387f9dfdSAndroid Build Coastguard Worker bpf:attach_kprobe{event="tcp_set_state", fn_name="trace_tcp_set_state"} 406*387f9dfdSAndroid Build Coastguard Worker print(header_string % {"PID", "COMM", 407*387f9dfdSAndroid Build Coastguard Worker ip_string, "LADDR", 408*387f9dfdSAndroid Build Coastguard Worker "LPORT", "RADDR", "RPORT", "TX_KB", "RX_KB", "MS"}) 409*387f9dfdSAndroid Build Coastguard Worker local TASK_COMM_LEN = 16 -- linux/sched.h 410*387f9dfdSAndroid Build Coastguard Worker bpf:get_table("ipv4_events"):open_perf_buffer(print_ipv4_event, [[ 411*387f9dfdSAndroid Build Coastguard Worker struct { 412*387f9dfdSAndroid Build Coastguard Worker uint64_t ts_us; 413*387f9dfdSAndroid Build Coastguard Worker uint64_t pid; 414*387f9dfdSAndroid Build Coastguard Worker uint64_t saddr; 415*387f9dfdSAndroid Build Coastguard Worker uint64_t daddr; 416*387f9dfdSAndroid Build Coastguard Worker uint64_t ports; 417*387f9dfdSAndroid Build Coastguard Worker uint64_t rx_b; 418*387f9dfdSAndroid Build Coastguard Worker uint64_t tx_b; 419*387f9dfdSAndroid Build Coastguard Worker uint64_t span_us; 420*387f9dfdSAndroid Build Coastguard Worker char task[$]; 421*387f9dfdSAndroid Build Coastguard Worker } 422*387f9dfdSAndroid Build Coastguard Worker ]], {TASK_COMM_LEN}, 64) 423*387f9dfdSAndroid Build Coastguard Worker bpf:get_table("ipv6_events"):open_perf_buffer(print_ipv6_event, [[ 424*387f9dfdSAndroid Build Coastguard Worker struct { 425*387f9dfdSAndroid Build Coastguard Worker uint64_t ts_us; 426*387f9dfdSAndroid Build Coastguard Worker uint64_t pid; 427*387f9dfdSAndroid Build Coastguard Worker uint64_t saddr[2]; 428*387f9dfdSAndroid Build Coastguard Worker uint64_t daddr[2]; 429*387f9dfdSAndroid Build Coastguard Worker uint64_t ports; 430*387f9dfdSAndroid Build Coastguard Worker uint64_t rx_b; 431*387f9dfdSAndroid Build Coastguard Worker uint64_t tx_b; 432*387f9dfdSAndroid Build Coastguard Worker uint64_t span_us; 433*387f9dfdSAndroid Build Coastguard Worker char task[$]; 434*387f9dfdSAndroid Build Coastguard Worker } 435*387f9dfdSAndroid Build Coastguard Worker ]], {TASK_COMM_LEN}, 64) 436*387f9dfdSAndroid Build Coastguard Worker 437*387f9dfdSAndroid Build Coastguard Worker bpf:perf_buffer_poll_loop() 438*387f9dfdSAndroid Build Coastguard Workerend 439