1*387f9dfdSAndroid Build Coastguard Worker#!/usr/bin/env python 2*387f9dfdSAndroid Build Coastguard Worker# @lint-avoid-python-3-compatibility-imports 3*387f9dfdSAndroid Build Coastguard Worker# 4*387f9dfdSAndroid Build Coastguard Worker# tcptop Summarize TCP send/recv throughput by host. 5*387f9dfdSAndroid Build Coastguard Worker# For Linux, uses BCC, eBPF. Embedded C. 6*387f9dfdSAndroid Build Coastguard Worker# 7*387f9dfdSAndroid Build Coastguard Worker# USAGE: tcptop [-h] [-C] [-S] [-p PID] [interval [count]] [-4 | -6] 8*387f9dfdSAndroid Build Coastguard Worker# 9*387f9dfdSAndroid Build Coastguard Worker# This uses dynamic tracing of kernel functions, and will need to be updated 10*387f9dfdSAndroid Build Coastguard Worker# to match kernel changes. 11*387f9dfdSAndroid Build Coastguard Worker# 12*387f9dfdSAndroid Build Coastguard Worker# WARNING: This traces all send/receives at the TCP level, and while it 13*387f9dfdSAndroid Build Coastguard Worker# summarizes data in-kernel to reduce overhead, there may still be some 14*387f9dfdSAndroid Build Coastguard Worker# overhead at high TCP send/receive rates (eg, ~13% of one CPU at 100k TCP 15*387f9dfdSAndroid Build Coastguard Worker# events/sec. This is not the same as packet rate: funccount can be used to 16*387f9dfdSAndroid Build Coastguard Worker# count the kprobes below to find out the TCP rate). Test in a lab environment 17*387f9dfdSAndroid Build Coastguard Worker# first. If your send/receive rate is low (eg, <1k/sec) then the overhead is 18*387f9dfdSAndroid Build Coastguard Worker# expected to be negligible. 19*387f9dfdSAndroid Build Coastguard Worker# 20*387f9dfdSAndroid Build Coastguard Worker# ToDo: Fit output to screen size (top X only) in default (not -C) mode. 21*387f9dfdSAndroid Build Coastguard Worker# 22*387f9dfdSAndroid Build Coastguard Worker# Copyright 2016 Netflix, Inc. 23*387f9dfdSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License") 24*387f9dfdSAndroid Build Coastguard Worker# 25*387f9dfdSAndroid Build Coastguard Worker# 02-Sep-2016 Brendan Gregg Created this. 26*387f9dfdSAndroid Build Coastguard Worker 27*387f9dfdSAndroid Build Coastguard Workerfrom __future__ import print_function 28*387f9dfdSAndroid Build Coastguard Workerfrom bcc import BPF 29*387f9dfdSAndroid Build Coastguard Workerfrom bcc.containers import filter_by_containers 30*387f9dfdSAndroid Build Coastguard Workerimport argparse 31*387f9dfdSAndroid Build Coastguard Workerfrom socket import inet_ntop, AF_INET, AF_INET6 32*387f9dfdSAndroid Build Coastguard Workerfrom struct import pack 33*387f9dfdSAndroid Build Coastguard Workerfrom time import sleep, strftime 34*387f9dfdSAndroid Build Coastguard Workerfrom subprocess import call 35*387f9dfdSAndroid Build Coastguard Workerfrom collections import namedtuple, defaultdict 36*387f9dfdSAndroid Build Coastguard Worker 37*387f9dfdSAndroid Build Coastguard Worker# arguments 38*387f9dfdSAndroid Build Coastguard Workerdef range_check(string): 39*387f9dfdSAndroid Build Coastguard Worker value = int(string) 40*387f9dfdSAndroid Build Coastguard Worker if value < 1: 41*387f9dfdSAndroid Build Coastguard Worker msg = "value must be stricly positive, got %d" % (value,) 42*387f9dfdSAndroid Build Coastguard Worker raise argparse.ArgumentTypeError(msg) 43*387f9dfdSAndroid Build Coastguard Worker return value 44*387f9dfdSAndroid Build Coastguard Worker 45*387f9dfdSAndroid Build Coastguard Workerexamples = """examples: 46*387f9dfdSAndroid Build Coastguard Worker ./tcptop # trace TCP send/recv by host 47*387f9dfdSAndroid Build Coastguard Worker ./tcptop -C # don't clear the screen 48*387f9dfdSAndroid Build Coastguard Worker ./tcptop -p 181 # only trace PID 181 49*387f9dfdSAndroid Build Coastguard Worker ./tcptop --cgroupmap mappath # only trace cgroups in this BPF map 50*387f9dfdSAndroid Build Coastguard Worker ./tcptop --mntnsmap mappath # only trace mount namespaces in the map 51*387f9dfdSAndroid Build Coastguard Worker ./tcptop -4 # trace IPv4 family only 52*387f9dfdSAndroid Build Coastguard Worker ./tcptop -6 # trace IPv6 family only 53*387f9dfdSAndroid Build Coastguard Worker""" 54*387f9dfdSAndroid Build Coastguard Workerparser = argparse.ArgumentParser( 55*387f9dfdSAndroid Build Coastguard Worker description="Summarize TCP send/recv throughput by host", 56*387f9dfdSAndroid Build Coastguard Worker formatter_class=argparse.RawDescriptionHelpFormatter, 57*387f9dfdSAndroid Build Coastguard Worker epilog=examples) 58*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-C", "--noclear", action="store_true", 59*387f9dfdSAndroid Build Coastguard Worker help="don't clear the screen") 60*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-S", "--nosummary", action="store_true", 61*387f9dfdSAndroid Build Coastguard Worker help="skip system summary line") 62*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-p", "--pid", 63*387f9dfdSAndroid Build Coastguard Worker help="trace this PID only") 64*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("interval", nargs="?", default=1, type=range_check, 65*387f9dfdSAndroid Build Coastguard Worker help="output interval, in seconds (default 1)") 66*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("count", nargs="?", default=-1, type=range_check, 67*387f9dfdSAndroid Build Coastguard Worker help="number of outputs") 68*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("--cgroupmap", 69*387f9dfdSAndroid Build Coastguard Worker help="trace cgroups in this BPF map only") 70*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("--mntnsmap", 71*387f9dfdSAndroid Build Coastguard Worker help="trace mount namespaces in this BPF map only") 72*387f9dfdSAndroid Build Coastguard Workergroup = parser.add_mutually_exclusive_group() 73*387f9dfdSAndroid Build Coastguard Workergroup.add_argument("-4", "--ipv4", action="store_true", 74*387f9dfdSAndroid Build Coastguard Worker help="trace IPv4 family only") 75*387f9dfdSAndroid Build Coastguard Workergroup.add_argument("-6", "--ipv6", action="store_true", 76*387f9dfdSAndroid Build Coastguard Worker help="trace IPv6 family only") 77*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("--ebpf", action="store_true", 78*387f9dfdSAndroid Build Coastguard Worker help=argparse.SUPPRESS) 79*387f9dfdSAndroid Build Coastguard Workerargs = parser.parse_args() 80*387f9dfdSAndroid Build Coastguard Workerdebug = 0 81*387f9dfdSAndroid Build Coastguard Worker 82*387f9dfdSAndroid Build Coastguard Worker# linux stats 83*387f9dfdSAndroid Build Coastguard Workerloadavg = "/proc/loadavg" 84*387f9dfdSAndroid Build Coastguard Worker 85*387f9dfdSAndroid Build Coastguard Worker# define BPF program 86*387f9dfdSAndroid Build Coastguard Workerbpf_text = """ 87*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ptrace.h> 88*387f9dfdSAndroid Build Coastguard Worker#include <net/sock.h> 89*387f9dfdSAndroid Build Coastguard Worker#include <bcc/proto.h> 90*387f9dfdSAndroid Build Coastguard Worker 91*387f9dfdSAndroid Build Coastguard Workerstruct ipv4_key_t { 92*387f9dfdSAndroid Build Coastguard Worker u32 pid; 93*387f9dfdSAndroid Build Coastguard Worker char name[TASK_COMM_LEN]; 94*387f9dfdSAndroid Build Coastguard Worker u32 saddr; 95*387f9dfdSAndroid Build Coastguard Worker u32 daddr; 96*387f9dfdSAndroid Build Coastguard Worker u16 lport; 97*387f9dfdSAndroid Build Coastguard Worker u16 dport; 98*387f9dfdSAndroid Build Coastguard Worker}; 99*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(ipv4_send_bytes, struct ipv4_key_t); 100*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(ipv4_recv_bytes, struct ipv4_key_t); 101*387f9dfdSAndroid Build Coastguard Worker 102*387f9dfdSAndroid Build Coastguard Workerstruct ipv6_key_t { 103*387f9dfdSAndroid Build Coastguard Worker unsigned __int128 saddr; 104*387f9dfdSAndroid Build Coastguard Worker unsigned __int128 daddr; 105*387f9dfdSAndroid Build Coastguard Worker u32 pid; 106*387f9dfdSAndroid Build Coastguard Worker char name[TASK_COMM_LEN]; 107*387f9dfdSAndroid Build Coastguard Worker u16 lport; 108*387f9dfdSAndroid Build Coastguard Worker u16 dport; 109*387f9dfdSAndroid Build Coastguard Worker u64 __pad__; 110*387f9dfdSAndroid Build Coastguard Worker}; 111*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(ipv6_send_bytes, struct ipv6_key_t); 112*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(ipv6_recv_bytes, struct ipv6_key_t); 113*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(sock_store, u32, struct sock *); 114*387f9dfdSAndroid Build Coastguard Worker 115*387f9dfdSAndroid Build Coastguard Workerstatic int tcp_sendstat(int size) 116*387f9dfdSAndroid Build Coastguard Worker{ 117*387f9dfdSAndroid Build Coastguard Worker if (container_should_be_filtered()) { 118*387f9dfdSAndroid Build Coastguard Worker return 0; 119*387f9dfdSAndroid Build Coastguard Worker } 120*387f9dfdSAndroid Build Coastguard Worker 121*387f9dfdSAndroid Build Coastguard Worker u32 pid = bpf_get_current_pid_tgid() >> 32; 122*387f9dfdSAndroid Build Coastguard Worker FILTER_PID 123*387f9dfdSAndroid Build Coastguard Worker u32 tid = bpf_get_current_pid_tgid(); 124*387f9dfdSAndroid Build Coastguard Worker struct sock **sockpp; 125*387f9dfdSAndroid Build Coastguard Worker sockpp = sock_store.lookup(&tid); 126*387f9dfdSAndroid Build Coastguard Worker if (sockpp == 0) { 127*387f9dfdSAndroid Build Coastguard Worker return 0; //miss the entry 128*387f9dfdSAndroid Build Coastguard Worker } 129*387f9dfdSAndroid Build Coastguard Worker struct sock *sk = *sockpp; 130*387f9dfdSAndroid Build Coastguard Worker u16 dport = 0, family; 131*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read_kernel(&family, sizeof(family), 132*387f9dfdSAndroid Build Coastguard Worker &sk->__sk_common.skc_family); 133*387f9dfdSAndroid Build Coastguard Worker FILTER_FAMILY 134*387f9dfdSAndroid Build Coastguard Worker 135*387f9dfdSAndroid Build Coastguard Worker if (family == AF_INET) { 136*387f9dfdSAndroid Build Coastguard Worker struct ipv4_key_t ipv4_key = {.pid = pid}; 137*387f9dfdSAndroid Build Coastguard Worker bpf_get_current_comm(&ipv4_key.name, sizeof(ipv4_key.name)); 138*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read_kernel(&ipv4_key.saddr, sizeof(ipv4_key.saddr), 139*387f9dfdSAndroid Build Coastguard Worker &sk->__sk_common.skc_rcv_saddr); 140*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read_kernel(&ipv4_key.daddr, sizeof(ipv4_key.daddr), 141*387f9dfdSAndroid Build Coastguard Worker &sk->__sk_common.skc_daddr); 142*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read_kernel(&ipv4_key.lport, sizeof(ipv4_key.lport), 143*387f9dfdSAndroid Build Coastguard Worker &sk->__sk_common.skc_num); 144*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read_kernel(&dport, sizeof(dport), 145*387f9dfdSAndroid Build Coastguard Worker &sk->__sk_common.skc_dport); 146*387f9dfdSAndroid Build Coastguard Worker ipv4_key.dport = ntohs(dport); 147*387f9dfdSAndroid Build Coastguard Worker ipv4_send_bytes.increment(ipv4_key, size); 148*387f9dfdSAndroid Build Coastguard Worker 149*387f9dfdSAndroid Build Coastguard Worker } else if (family == AF_INET6) { 150*387f9dfdSAndroid Build Coastguard Worker struct ipv6_key_t ipv6_key = {.pid = pid}; 151*387f9dfdSAndroid Build Coastguard Worker bpf_get_current_comm(&ipv6_key.name, sizeof(ipv6_key.name)); 152*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read_kernel(&ipv6_key.saddr, sizeof(ipv6_key.saddr), 153*387f9dfdSAndroid Build Coastguard Worker &sk->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32); 154*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read_kernel(&ipv6_key.daddr, sizeof(ipv6_key.daddr), 155*387f9dfdSAndroid Build Coastguard Worker &sk->__sk_common.skc_v6_daddr.in6_u.u6_addr32); 156*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read_kernel(&ipv6_key.lport, sizeof(ipv6_key.lport), 157*387f9dfdSAndroid Build Coastguard Worker &sk->__sk_common.skc_num); 158*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read_kernel(&dport, sizeof(dport), 159*387f9dfdSAndroid Build Coastguard Worker &sk->__sk_common.skc_dport); 160*387f9dfdSAndroid Build Coastguard Worker ipv6_key.dport = ntohs(dport); 161*387f9dfdSAndroid Build Coastguard Worker ipv6_send_bytes.increment(ipv6_key, size); 162*387f9dfdSAndroid Build Coastguard Worker } 163*387f9dfdSAndroid Build Coastguard Worker sock_store.delete(&tid); 164*387f9dfdSAndroid Build Coastguard Worker // else drop 165*387f9dfdSAndroid Build Coastguard Worker 166*387f9dfdSAndroid Build Coastguard Worker return 0; 167*387f9dfdSAndroid Build Coastguard Worker} 168*387f9dfdSAndroid Build Coastguard Worker 169*387f9dfdSAndroid Build Coastguard Workerint tcp_send_ret(struct pt_regs *ctx) 170*387f9dfdSAndroid Build Coastguard Worker{ 171*387f9dfdSAndroid Build Coastguard Worker int size = PT_REGS_RC(ctx); 172*387f9dfdSAndroid Build Coastguard Worker if (size > 0) 173*387f9dfdSAndroid Build Coastguard Worker return tcp_sendstat(size); 174*387f9dfdSAndroid Build Coastguard Worker else 175*387f9dfdSAndroid Build Coastguard Worker return 0; 176*387f9dfdSAndroid Build Coastguard Worker} 177*387f9dfdSAndroid Build Coastguard Worker 178*387f9dfdSAndroid Build Coastguard Workerint tcp_send_entry(struct pt_regs *ctx, struct sock *sk) 179*387f9dfdSAndroid Build Coastguard Worker{ 180*387f9dfdSAndroid Build Coastguard Worker if (container_should_be_filtered()) { 181*387f9dfdSAndroid Build Coastguard Worker return 0; 182*387f9dfdSAndroid Build Coastguard Worker } 183*387f9dfdSAndroid Build Coastguard Worker u32 pid = bpf_get_current_pid_tgid() >> 32; 184*387f9dfdSAndroid Build Coastguard Worker FILTER_PID 185*387f9dfdSAndroid Build Coastguard Worker u32 tid = bpf_get_current_pid_tgid(); 186*387f9dfdSAndroid Build Coastguard Worker u16 family = sk->__sk_common.skc_family; 187*387f9dfdSAndroid Build Coastguard Worker FILTER_FAMILY 188*387f9dfdSAndroid Build Coastguard Worker sock_store.update(&tid, &sk); 189*387f9dfdSAndroid Build Coastguard Worker return 0; 190*387f9dfdSAndroid Build Coastguard Worker} 191*387f9dfdSAndroid Build Coastguard Worker 192*387f9dfdSAndroid Build Coastguard Worker/* 193*387f9dfdSAndroid Build Coastguard Worker * tcp_recvmsg() would be obvious to trace, but is less suitable because: 194*387f9dfdSAndroid Build Coastguard Worker * - we'd need to trace both entry and return, to have both sock and size 195*387f9dfdSAndroid Build Coastguard Worker * - misses tcp_read_sock() traffic 196*387f9dfdSAndroid Build Coastguard Worker * we'd much prefer tracepoints once they are available. 197*387f9dfdSAndroid Build Coastguard Worker */ 198*387f9dfdSAndroid Build Coastguard Workerint kprobe__tcp_cleanup_rbuf(struct pt_regs *ctx, struct sock *sk, int copied) 199*387f9dfdSAndroid Build Coastguard Worker{ 200*387f9dfdSAndroid Build Coastguard Worker if (container_should_be_filtered()) { 201*387f9dfdSAndroid Build Coastguard Worker return 0; 202*387f9dfdSAndroid Build Coastguard Worker } 203*387f9dfdSAndroid Build Coastguard Worker 204*387f9dfdSAndroid Build Coastguard Worker u32 pid = bpf_get_current_pid_tgid() >> 32; 205*387f9dfdSAndroid Build Coastguard Worker FILTER_PID 206*387f9dfdSAndroid Build Coastguard Worker 207*387f9dfdSAndroid Build Coastguard Worker u16 dport = 0, family = sk->__sk_common.skc_family; 208*387f9dfdSAndroid Build Coastguard Worker u64 *val, zero = 0; 209*387f9dfdSAndroid Build Coastguard Worker 210*387f9dfdSAndroid Build Coastguard Worker if (copied <= 0) 211*387f9dfdSAndroid Build Coastguard Worker return 0; 212*387f9dfdSAndroid Build Coastguard Worker 213*387f9dfdSAndroid Build Coastguard Worker FILTER_FAMILY 214*387f9dfdSAndroid Build Coastguard Worker 215*387f9dfdSAndroid Build Coastguard Worker if (family == AF_INET) { 216*387f9dfdSAndroid Build Coastguard Worker struct ipv4_key_t ipv4_key = {.pid = pid}; 217*387f9dfdSAndroid Build Coastguard Worker bpf_get_current_comm(&ipv4_key.name, sizeof(ipv4_key.name)); 218*387f9dfdSAndroid Build Coastguard Worker ipv4_key.saddr = sk->__sk_common.skc_rcv_saddr; 219*387f9dfdSAndroid Build Coastguard Worker ipv4_key.daddr = sk->__sk_common.skc_daddr; 220*387f9dfdSAndroid Build Coastguard Worker ipv4_key.lport = sk->__sk_common.skc_num; 221*387f9dfdSAndroid Build Coastguard Worker dport = sk->__sk_common.skc_dport; 222*387f9dfdSAndroid Build Coastguard Worker ipv4_key.dport = ntohs(dport); 223*387f9dfdSAndroid Build Coastguard Worker ipv4_recv_bytes.increment(ipv4_key, copied); 224*387f9dfdSAndroid Build Coastguard Worker 225*387f9dfdSAndroid Build Coastguard Worker } else if (family == AF_INET6) { 226*387f9dfdSAndroid Build Coastguard Worker struct ipv6_key_t ipv6_key = {.pid = pid}; 227*387f9dfdSAndroid Build Coastguard Worker bpf_get_current_comm(&ipv6_key.name, sizeof(ipv6_key.name)); 228*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read_kernel(&ipv6_key.saddr, sizeof(ipv6_key.saddr), 229*387f9dfdSAndroid Build Coastguard Worker &sk->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32); 230*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read_kernel(&ipv6_key.daddr, sizeof(ipv6_key.daddr), 231*387f9dfdSAndroid Build Coastguard Worker &sk->__sk_common.skc_v6_daddr.in6_u.u6_addr32); 232*387f9dfdSAndroid Build Coastguard Worker ipv6_key.lport = sk->__sk_common.skc_num; 233*387f9dfdSAndroid Build Coastguard Worker dport = sk->__sk_common.skc_dport; 234*387f9dfdSAndroid Build Coastguard Worker ipv6_key.dport = ntohs(dport); 235*387f9dfdSAndroid Build Coastguard Worker ipv6_recv_bytes.increment(ipv6_key, copied); 236*387f9dfdSAndroid Build Coastguard Worker } 237*387f9dfdSAndroid Build Coastguard Worker // else drop 238*387f9dfdSAndroid Build Coastguard Worker 239*387f9dfdSAndroid Build Coastguard Worker return 0; 240*387f9dfdSAndroid Build Coastguard Worker} 241*387f9dfdSAndroid Build Coastguard Worker""" 242*387f9dfdSAndroid Build Coastguard Worker 243*387f9dfdSAndroid Build Coastguard Worker# code substitutions 244*387f9dfdSAndroid Build Coastguard Workerif args.pid: 245*387f9dfdSAndroid Build Coastguard Worker bpf_text = bpf_text.replace('FILTER_PID', 246*387f9dfdSAndroid Build Coastguard Worker 'if (pid != %s) { return 0; }' % args.pid) 247*387f9dfdSAndroid Build Coastguard Workerelse: 248*387f9dfdSAndroid Build Coastguard Worker bpf_text = bpf_text.replace('FILTER_PID', '') 249*387f9dfdSAndroid Build Coastguard Workerif args.ipv4: 250*387f9dfdSAndroid Build Coastguard Worker bpf_text = bpf_text.replace('FILTER_FAMILY', 251*387f9dfdSAndroid Build Coastguard Worker 'if (family != AF_INET) { return 0; }') 252*387f9dfdSAndroid Build Coastguard Workerelif args.ipv6: 253*387f9dfdSAndroid Build Coastguard Worker bpf_text = bpf_text.replace('FILTER_FAMILY', 254*387f9dfdSAndroid Build Coastguard Worker 'if (family != AF_INET6) { return 0; }') 255*387f9dfdSAndroid Build Coastguard Workerbpf_text = bpf_text.replace('FILTER_FAMILY', '') 256*387f9dfdSAndroid Build Coastguard Workerbpf_text = filter_by_containers(args) + bpf_text 257*387f9dfdSAndroid Build Coastguard Workerif debug or args.ebpf: 258*387f9dfdSAndroid Build Coastguard Worker print(bpf_text) 259*387f9dfdSAndroid Build Coastguard Worker if args.ebpf: 260*387f9dfdSAndroid Build Coastguard Worker exit() 261*387f9dfdSAndroid Build Coastguard Worker 262*387f9dfdSAndroid Build Coastguard WorkerTCPSessionKey = namedtuple('TCPSession', ['pid', 'name', 'laddr', 'lport', 'daddr', 'dport']) 263*387f9dfdSAndroid Build Coastguard Worker 264*387f9dfdSAndroid Build Coastguard Workerdef get_ipv4_session_key(k): 265*387f9dfdSAndroid Build Coastguard Worker return TCPSessionKey(pid=k.pid, 266*387f9dfdSAndroid Build Coastguard Worker name=k.name, 267*387f9dfdSAndroid Build Coastguard Worker laddr=inet_ntop(AF_INET, pack("I", k.saddr)), 268*387f9dfdSAndroid Build Coastguard Worker lport=k.lport, 269*387f9dfdSAndroid Build Coastguard Worker daddr=inet_ntop(AF_INET, pack("I", k.daddr)), 270*387f9dfdSAndroid Build Coastguard Worker dport=k.dport) 271*387f9dfdSAndroid Build Coastguard Worker 272*387f9dfdSAndroid Build Coastguard Workerdef get_ipv6_session_key(k): 273*387f9dfdSAndroid Build Coastguard Worker return TCPSessionKey(pid=k.pid, 274*387f9dfdSAndroid Build Coastguard Worker name=k.name, 275*387f9dfdSAndroid Build Coastguard Worker laddr=inet_ntop(AF_INET6, k.saddr), 276*387f9dfdSAndroid Build Coastguard Worker lport=k.lport, 277*387f9dfdSAndroid Build Coastguard Worker daddr=inet_ntop(AF_INET6, k.daddr), 278*387f9dfdSAndroid Build Coastguard Worker dport=k.dport) 279*387f9dfdSAndroid Build Coastguard Worker 280*387f9dfdSAndroid Build Coastguard Worker# initialize BPF 281*387f9dfdSAndroid Build Coastguard Workerb = BPF(text=bpf_text) 282*387f9dfdSAndroid Build Coastguard Worker 283*387f9dfdSAndroid Build Coastguard Workerb.attach_kprobe(event='tcp_sendmsg', fn_name='tcp_send_entry') 284*387f9dfdSAndroid Build Coastguard Workerb.attach_kretprobe(event='tcp_sendmsg', fn_name='tcp_send_ret') 285*387f9dfdSAndroid Build Coastguard Workerif BPF.get_kprobe_functions(b'tcp_sendpage'): 286*387f9dfdSAndroid Build Coastguard Worker b.attach_kprobe(event='tcp_sendpage', fn_name='tcp_send_entry') 287*387f9dfdSAndroid Build Coastguard Worker b.attach_kretprobe(event='tcp_sendpage', fn_name='tcp_send_ret') 288*387f9dfdSAndroid Build Coastguard Worker 289*387f9dfdSAndroid Build Coastguard Workeripv4_send_bytes = b["ipv4_send_bytes"] 290*387f9dfdSAndroid Build Coastguard Workeripv4_recv_bytes = b["ipv4_recv_bytes"] 291*387f9dfdSAndroid Build Coastguard Workeripv6_send_bytes = b["ipv6_send_bytes"] 292*387f9dfdSAndroid Build Coastguard Workeripv6_recv_bytes = b["ipv6_recv_bytes"] 293*387f9dfdSAndroid Build Coastguard Worker 294*387f9dfdSAndroid Build Coastguard Workerprint('Tracing... Output every %s secs. Hit Ctrl-C to end' % args.interval) 295*387f9dfdSAndroid Build Coastguard Worker 296*387f9dfdSAndroid Build Coastguard Worker# output 297*387f9dfdSAndroid Build Coastguard Workeri = 0 298*387f9dfdSAndroid Build Coastguard Workerexiting = False 299*387f9dfdSAndroid Build Coastguard Workerwhile i != args.count and not exiting: 300*387f9dfdSAndroid Build Coastguard Worker try: 301*387f9dfdSAndroid Build Coastguard Worker sleep(args.interval) 302*387f9dfdSAndroid Build Coastguard Worker except KeyboardInterrupt: 303*387f9dfdSAndroid Build Coastguard Worker exiting = True 304*387f9dfdSAndroid Build Coastguard Worker 305*387f9dfdSAndroid Build Coastguard Worker # header 306*387f9dfdSAndroid Build Coastguard Worker if args.noclear: 307*387f9dfdSAndroid Build Coastguard Worker print() 308*387f9dfdSAndroid Build Coastguard Worker else: 309*387f9dfdSAndroid Build Coastguard Worker call("clear") 310*387f9dfdSAndroid Build Coastguard Worker if not args.nosummary: 311*387f9dfdSAndroid Build Coastguard Worker with open(loadavg) as stats: 312*387f9dfdSAndroid Build Coastguard Worker print("%-8s loadavg: %s" % (strftime("%H:%M:%S"), stats.read())) 313*387f9dfdSAndroid Build Coastguard Worker 314*387f9dfdSAndroid Build Coastguard Worker # IPv4: build dict of all seen keys 315*387f9dfdSAndroid Build Coastguard Worker ipv4_throughput = defaultdict(lambda: [0, 0]) 316*387f9dfdSAndroid Build Coastguard Worker for k, v in ipv4_send_bytes.items(): 317*387f9dfdSAndroid Build Coastguard Worker key = get_ipv4_session_key(k) 318*387f9dfdSAndroid Build Coastguard Worker ipv4_throughput[key][0] = v.value 319*387f9dfdSAndroid Build Coastguard Worker ipv4_send_bytes.clear() 320*387f9dfdSAndroid Build Coastguard Worker 321*387f9dfdSAndroid Build Coastguard Worker for k, v in ipv4_recv_bytes.items(): 322*387f9dfdSAndroid Build Coastguard Worker key = get_ipv4_session_key(k) 323*387f9dfdSAndroid Build Coastguard Worker ipv4_throughput[key][1] = v.value 324*387f9dfdSAndroid Build Coastguard Worker ipv4_recv_bytes.clear() 325*387f9dfdSAndroid Build Coastguard Worker 326*387f9dfdSAndroid Build Coastguard Worker if ipv4_throughput: 327*387f9dfdSAndroid Build Coastguard Worker print("%-7s %-12s %-21s %-21s %6s %6s" % ("PID", "COMM", 328*387f9dfdSAndroid Build Coastguard Worker "LADDR", "RADDR", "RX_KB", "TX_KB")) 329*387f9dfdSAndroid Build Coastguard Worker 330*387f9dfdSAndroid Build Coastguard Worker # output 331*387f9dfdSAndroid Build Coastguard Worker for k, (send_bytes, recv_bytes) in sorted(ipv4_throughput.items(), 332*387f9dfdSAndroid Build Coastguard Worker key=lambda kv: sum(kv[1]), 333*387f9dfdSAndroid Build Coastguard Worker reverse=True): 334*387f9dfdSAndroid Build Coastguard Worker print("%-7d %-12.12s %-21s %-21s %6d %6d" % (k.pid, 335*387f9dfdSAndroid Build Coastguard Worker k.name, 336*387f9dfdSAndroid Build Coastguard Worker k.laddr + ":" + str(k.lport), 337*387f9dfdSAndroid Build Coastguard Worker k.daddr + ":" + str(k.dport), 338*387f9dfdSAndroid Build Coastguard Worker int(recv_bytes / 1024), int(send_bytes / 1024))) 339*387f9dfdSAndroid Build Coastguard Worker 340*387f9dfdSAndroid Build Coastguard Worker # IPv6: build dict of all seen keys 341*387f9dfdSAndroid Build Coastguard Worker ipv6_throughput = defaultdict(lambda: [0, 0]) 342*387f9dfdSAndroid Build Coastguard Worker for k, v in ipv6_send_bytes.items(): 343*387f9dfdSAndroid Build Coastguard Worker key = get_ipv6_session_key(k) 344*387f9dfdSAndroid Build Coastguard Worker ipv6_throughput[key][0] = v.value 345*387f9dfdSAndroid Build Coastguard Worker ipv6_send_bytes.clear() 346*387f9dfdSAndroid Build Coastguard Worker 347*387f9dfdSAndroid Build Coastguard Worker for k, v in ipv6_recv_bytes.items(): 348*387f9dfdSAndroid Build Coastguard Worker key = get_ipv6_session_key(k) 349*387f9dfdSAndroid Build Coastguard Worker ipv6_throughput[key][1] = v.value 350*387f9dfdSAndroid Build Coastguard Worker ipv6_recv_bytes.clear() 351*387f9dfdSAndroid Build Coastguard Worker 352*387f9dfdSAndroid Build Coastguard Worker if ipv6_throughput: 353*387f9dfdSAndroid Build Coastguard Worker # more than 80 chars, sadly. 354*387f9dfdSAndroid Build Coastguard Worker print("\n%-7s %-12s %-32s %-32s %6s %6s" % ("PID", "COMM", 355*387f9dfdSAndroid Build Coastguard Worker "LADDR6", "RADDR6", "RX_KB", "TX_KB")) 356*387f9dfdSAndroid Build Coastguard Worker 357*387f9dfdSAndroid Build Coastguard Worker # output 358*387f9dfdSAndroid Build Coastguard Worker for k, (send_bytes, recv_bytes) in sorted(ipv6_throughput.items(), 359*387f9dfdSAndroid Build Coastguard Worker key=lambda kv: sum(kv[1]), 360*387f9dfdSAndroid Build Coastguard Worker reverse=True): 361*387f9dfdSAndroid Build Coastguard Worker print("%-7d %-12.12s %-32s %-32s %6d %6d" % (k.pid, 362*387f9dfdSAndroid Build Coastguard Worker k.name, 363*387f9dfdSAndroid Build Coastguard Worker k.laddr + ":" + str(k.lport), 364*387f9dfdSAndroid Build Coastguard Worker k.daddr + ":" + str(k.dport), 365*387f9dfdSAndroid Build Coastguard Worker int(recv_bytes / 1024), int(send_bytes / 1024))) 366*387f9dfdSAndroid Build Coastguard Worker 367*387f9dfdSAndroid Build Coastguard Worker i += 1 368