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# tcpretrans Trace or count TCP retransmits and TLPs. 5*387f9dfdSAndroid Build Coastguard Worker# For Linux, uses BCC, eBPF. Embedded C. 6*387f9dfdSAndroid Build Coastguard Worker# 7*387f9dfdSAndroid Build Coastguard Worker# USAGE: tcpretrans [-c] [-h] [-l] [-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# Copyright 2016 Netflix, Inc. 13*387f9dfdSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License") 14*387f9dfdSAndroid Build Coastguard Worker# 15*387f9dfdSAndroid Build Coastguard Worker# 14-Feb-2016 Brendan Gregg Created this. 16*387f9dfdSAndroid Build Coastguard Worker# 03-Nov-2017 Matthias Tafelmeier Extended this. 17*387f9dfdSAndroid Build Coastguard Worker 18*387f9dfdSAndroid Build Coastguard Workerfrom __future__ import print_function 19*387f9dfdSAndroid Build Coastguard Workerfrom bcc import BPF 20*387f9dfdSAndroid Build Coastguard Workerimport argparse 21*387f9dfdSAndroid Build Coastguard Workerfrom time import strftime 22*387f9dfdSAndroid Build Coastguard Workerfrom socket import inet_ntop, AF_INET, AF_INET6 23*387f9dfdSAndroid Build Coastguard Workerfrom struct import pack 24*387f9dfdSAndroid Build Coastguard Workerfrom time import sleep 25*387f9dfdSAndroid Build Coastguard Worker 26*387f9dfdSAndroid Build Coastguard Worker# arguments 27*387f9dfdSAndroid Build Coastguard Workerexamples = """examples: 28*387f9dfdSAndroid Build Coastguard Worker ./tcpretrans # trace TCP retransmits 29*387f9dfdSAndroid Build Coastguard Worker ./tcpretrans -l # include TLP attempts 30*387f9dfdSAndroid Build Coastguard Worker ./tcpretrans -4 # trace IPv4 family only 31*387f9dfdSAndroid Build Coastguard Worker ./tcpretrans -6 # trace IPv6 family only 32*387f9dfdSAndroid Build Coastguard Worker""" 33*387f9dfdSAndroid Build Coastguard Workerparser = argparse.ArgumentParser( 34*387f9dfdSAndroid Build Coastguard Worker description="Trace TCP retransmits", 35*387f9dfdSAndroid Build Coastguard Worker formatter_class=argparse.RawDescriptionHelpFormatter, 36*387f9dfdSAndroid Build Coastguard Worker epilog=examples) 37*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-s", "--sequence", action="store_true", 38*387f9dfdSAndroid Build Coastguard Worker help="display TCP sequence numbers") 39*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-l", "--lossprobe", action="store_true", 40*387f9dfdSAndroid Build Coastguard Worker help="include tail loss probe attempts") 41*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-c", "--count", action="store_true", 42*387f9dfdSAndroid Build Coastguard Worker help="count occurred retransmits per flow") 43*387f9dfdSAndroid Build Coastguard Workergroup = parser.add_mutually_exclusive_group() 44*387f9dfdSAndroid Build Coastguard Workergroup.add_argument("-4", "--ipv4", action="store_true", 45*387f9dfdSAndroid Build Coastguard Worker help="trace IPv4 family only") 46*387f9dfdSAndroid Build Coastguard Workergroup.add_argument("-6", "--ipv6", action="store_true", 47*387f9dfdSAndroid Build Coastguard Worker help="trace IPv6 family only") 48*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("--ebpf", action="store_true", 49*387f9dfdSAndroid Build Coastguard Worker help=argparse.SUPPRESS) 50*387f9dfdSAndroid Build Coastguard Workerargs = parser.parse_args() 51*387f9dfdSAndroid Build Coastguard Workerdebug = 0 52*387f9dfdSAndroid Build Coastguard Worker 53*387f9dfdSAndroid Build Coastguard Worker# define BPF program 54*387f9dfdSAndroid Build Coastguard Workerbpf_text = """ 55*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ptrace.h> 56*387f9dfdSAndroid Build Coastguard Worker#include <net/sock.h> 57*387f9dfdSAndroid Build Coastguard Worker#include <net/tcp.h> 58*387f9dfdSAndroid Build Coastguard Worker#include <bcc/proto.h> 59*387f9dfdSAndroid Build Coastguard Worker 60*387f9dfdSAndroid Build Coastguard Worker#define RETRANSMIT 1 61*387f9dfdSAndroid Build Coastguard Worker#define TLP 2 62*387f9dfdSAndroid Build Coastguard Worker 63*387f9dfdSAndroid Build Coastguard Worker// separate data structs for ipv4 and ipv6 64*387f9dfdSAndroid Build Coastguard Workerstruct ipv4_data_t { 65*387f9dfdSAndroid Build Coastguard Worker u32 pid; 66*387f9dfdSAndroid Build Coastguard Worker u64 ip; 67*387f9dfdSAndroid Build Coastguard Worker u32 seq; 68*387f9dfdSAndroid Build Coastguard Worker u32 saddr; 69*387f9dfdSAndroid Build Coastguard Worker u32 daddr; 70*387f9dfdSAndroid Build Coastguard Worker u16 lport; 71*387f9dfdSAndroid Build Coastguard Worker u16 dport; 72*387f9dfdSAndroid Build Coastguard Worker u64 state; 73*387f9dfdSAndroid Build Coastguard Worker u64 type; 74*387f9dfdSAndroid Build Coastguard Worker}; 75*387f9dfdSAndroid Build Coastguard WorkerBPF_PERF_OUTPUT(ipv4_events); 76*387f9dfdSAndroid Build Coastguard Worker 77*387f9dfdSAndroid Build Coastguard Workerstruct ipv6_data_t { 78*387f9dfdSAndroid Build Coastguard Worker u32 pid; 79*387f9dfdSAndroid Build Coastguard Worker u32 seq; 80*387f9dfdSAndroid Build Coastguard Worker u64 ip; 81*387f9dfdSAndroid Build Coastguard Worker unsigned __int128 saddr; 82*387f9dfdSAndroid Build Coastguard Worker unsigned __int128 daddr; 83*387f9dfdSAndroid Build Coastguard Worker u16 lport; 84*387f9dfdSAndroid Build Coastguard Worker u16 dport; 85*387f9dfdSAndroid Build Coastguard Worker u64 state; 86*387f9dfdSAndroid Build Coastguard Worker u64 type; 87*387f9dfdSAndroid Build Coastguard Worker}; 88*387f9dfdSAndroid Build Coastguard WorkerBPF_PERF_OUTPUT(ipv6_events); 89*387f9dfdSAndroid Build Coastguard Worker 90*387f9dfdSAndroid Build Coastguard Worker// separate flow keys per address family 91*387f9dfdSAndroid Build Coastguard Workerstruct ipv4_flow_key_t { 92*387f9dfdSAndroid Build Coastguard Worker u32 saddr; 93*387f9dfdSAndroid Build Coastguard Worker u32 daddr; 94*387f9dfdSAndroid Build Coastguard Worker u16 lport; 95*387f9dfdSAndroid Build Coastguard Worker u16 dport; 96*387f9dfdSAndroid Build Coastguard Worker}; 97*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(ipv4_count, struct ipv4_flow_key_t); 98*387f9dfdSAndroid Build Coastguard Worker 99*387f9dfdSAndroid Build Coastguard Workerstruct ipv6_flow_key_t { 100*387f9dfdSAndroid Build Coastguard Worker unsigned __int128 saddr; 101*387f9dfdSAndroid Build Coastguard Worker unsigned __int128 daddr; 102*387f9dfdSAndroid Build Coastguard Worker u16 lport; 103*387f9dfdSAndroid Build Coastguard Worker u16 dport; 104*387f9dfdSAndroid Build Coastguard Worker}; 105*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(ipv6_count, struct ipv6_flow_key_t); 106*387f9dfdSAndroid Build Coastguard Worker""" 107*387f9dfdSAndroid Build Coastguard Worker 108*387f9dfdSAndroid Build Coastguard Workerbpf_text_kprobe = """ 109*387f9dfdSAndroid Build Coastguard Workerstatic int trace_event(struct pt_regs *ctx, struct sock *skp, struct sk_buff *skb, int type) 110*387f9dfdSAndroid Build Coastguard Worker{ 111*387f9dfdSAndroid Build Coastguard Worker struct tcp_skb_cb *tcb; 112*387f9dfdSAndroid Build Coastguard Worker u32 seq; 113*387f9dfdSAndroid Build Coastguard Worker 114*387f9dfdSAndroid Build Coastguard Worker if (skp == NULL) 115*387f9dfdSAndroid Build Coastguard Worker return 0; 116*387f9dfdSAndroid Build Coastguard Worker u32 pid = bpf_get_current_pid_tgid() >> 32; 117*387f9dfdSAndroid Build Coastguard Worker 118*387f9dfdSAndroid Build Coastguard Worker // pull in details 119*387f9dfdSAndroid Build Coastguard Worker u16 family = skp->__sk_common.skc_family; 120*387f9dfdSAndroid Build Coastguard Worker u16 lport = skp->__sk_common.skc_num; 121*387f9dfdSAndroid Build Coastguard Worker u16 dport = skp->__sk_common.skc_dport; 122*387f9dfdSAndroid Build Coastguard Worker char state = skp->__sk_common.skc_state; 123*387f9dfdSAndroid Build Coastguard Worker 124*387f9dfdSAndroid Build Coastguard Worker seq = 0; 125*387f9dfdSAndroid Build Coastguard Worker if (skb) { 126*387f9dfdSAndroid Build Coastguard Worker /* macro TCP_SKB_CB from net/tcp.h */ 127*387f9dfdSAndroid Build Coastguard Worker tcb = ((struct tcp_skb_cb *)&((skb)->cb[0])); 128*387f9dfdSAndroid Build Coastguard Worker seq = tcb->seq; 129*387f9dfdSAndroid Build Coastguard Worker } 130*387f9dfdSAndroid Build Coastguard Worker 131*387f9dfdSAndroid Build Coastguard Worker FILTER_FAMILY 132*387f9dfdSAndroid Build Coastguard Worker 133*387f9dfdSAndroid Build Coastguard Worker if (family == AF_INET) { 134*387f9dfdSAndroid Build Coastguard Worker IPV4_INIT 135*387f9dfdSAndroid Build Coastguard Worker IPV4_CORE 136*387f9dfdSAndroid Build Coastguard Worker } else if (family == AF_INET6) { 137*387f9dfdSAndroid Build Coastguard Worker IPV6_INIT 138*387f9dfdSAndroid Build Coastguard Worker IPV6_CORE 139*387f9dfdSAndroid Build Coastguard Worker } 140*387f9dfdSAndroid Build Coastguard Worker // else drop 141*387f9dfdSAndroid Build Coastguard Worker 142*387f9dfdSAndroid Build Coastguard Worker return 0; 143*387f9dfdSAndroid Build Coastguard Worker} 144*387f9dfdSAndroid Build Coastguard Worker""" 145*387f9dfdSAndroid Build Coastguard Worker 146*387f9dfdSAndroid Build Coastguard Workerbpf_text_kprobe_retransmit = """ 147*387f9dfdSAndroid Build Coastguard Workerint trace_retransmit(struct pt_regs *ctx, struct sock *sk, struct sk_buff *skb) 148*387f9dfdSAndroid Build Coastguard Worker{ 149*387f9dfdSAndroid Build Coastguard Worker trace_event(ctx, sk, skb, RETRANSMIT); 150*387f9dfdSAndroid Build Coastguard Worker return 0; 151*387f9dfdSAndroid Build Coastguard Worker} 152*387f9dfdSAndroid Build Coastguard Worker""" 153*387f9dfdSAndroid Build Coastguard Worker 154*387f9dfdSAndroid Build Coastguard Workerbpf_text_kprobe_tlp = """ 155*387f9dfdSAndroid Build Coastguard Workerint trace_tlp(struct pt_regs *ctx, struct sock *sk) 156*387f9dfdSAndroid Build Coastguard Worker{ 157*387f9dfdSAndroid Build Coastguard Worker trace_event(ctx, sk, NULL, TLP); 158*387f9dfdSAndroid Build Coastguard Worker return 0; 159*387f9dfdSAndroid Build Coastguard Worker} 160*387f9dfdSAndroid Build Coastguard Worker""" 161*387f9dfdSAndroid Build Coastguard Worker 162*387f9dfdSAndroid Build Coastguard Workerbpf_text_tracepoint = """ 163*387f9dfdSAndroid Build Coastguard WorkerTRACEPOINT_PROBE(tcp, tcp_retransmit_skb) 164*387f9dfdSAndroid Build Coastguard Worker{ 165*387f9dfdSAndroid Build Coastguard Worker struct tcp_skb_cb *tcb; 166*387f9dfdSAndroid Build Coastguard Worker u32 seq; 167*387f9dfdSAndroid Build Coastguard Worker 168*387f9dfdSAndroid Build Coastguard Worker u32 pid = bpf_get_current_pid_tgid() >> 32; 169*387f9dfdSAndroid Build Coastguard Worker const struct sock *skp = (const struct sock *)args->skaddr; 170*387f9dfdSAndroid Build Coastguard Worker const struct sk_buff *skb = (const struct sk_buff *)args->skbaddr; 171*387f9dfdSAndroid Build Coastguard Worker u16 lport = args->sport; 172*387f9dfdSAndroid Build Coastguard Worker u16 dport = args->dport; 173*387f9dfdSAndroid Build Coastguard Worker char state = skp->__sk_common.skc_state; 174*387f9dfdSAndroid Build Coastguard Worker u16 family = skp->__sk_common.skc_family; 175*387f9dfdSAndroid Build Coastguard Worker 176*387f9dfdSAndroid Build Coastguard Worker seq = 0; 177*387f9dfdSAndroid Build Coastguard Worker if (skb) { 178*387f9dfdSAndroid Build Coastguard Worker /* macro TCP_SKB_CB from net/tcp.h */ 179*387f9dfdSAndroid Build Coastguard Worker tcb = ((struct tcp_skb_cb *)&((skb)->cb[0])); 180*387f9dfdSAndroid Build Coastguard Worker seq = tcb->seq; 181*387f9dfdSAndroid Build Coastguard Worker } 182*387f9dfdSAndroid Build Coastguard Worker 183*387f9dfdSAndroid Build Coastguard Worker FILTER_FAMILY 184*387f9dfdSAndroid Build Coastguard Worker 185*387f9dfdSAndroid Build Coastguard Worker if (family == AF_INET) { 186*387f9dfdSAndroid Build Coastguard Worker IPV4_CODE 187*387f9dfdSAndroid Build Coastguard Worker } else if (family == AF_INET6) { 188*387f9dfdSAndroid Build Coastguard Worker IPV6_CODE 189*387f9dfdSAndroid Build Coastguard Worker } 190*387f9dfdSAndroid Build Coastguard Worker return 0; 191*387f9dfdSAndroid Build Coastguard Worker} 192*387f9dfdSAndroid Build Coastguard Worker""" 193*387f9dfdSAndroid Build Coastguard Worker 194*387f9dfdSAndroid Build Coastguard Workerstruct_init = { 'ipv4': 195*387f9dfdSAndroid Build Coastguard Worker { 'count' : 196*387f9dfdSAndroid Build Coastguard Worker """ 197*387f9dfdSAndroid Build Coastguard Worker struct ipv4_flow_key_t flow_key = {}; 198*387f9dfdSAndroid Build Coastguard Worker flow_key.saddr = skp->__sk_common.skc_rcv_saddr; 199*387f9dfdSAndroid Build Coastguard Worker flow_key.daddr = skp->__sk_common.skc_daddr; 200*387f9dfdSAndroid Build Coastguard Worker // lport is host order 201*387f9dfdSAndroid Build Coastguard Worker flow_key.lport = lport; 202*387f9dfdSAndroid Build Coastguard Worker flow_key.dport = ntohs(dport);""", 203*387f9dfdSAndroid Build Coastguard Worker 'trace' : 204*387f9dfdSAndroid Build Coastguard Worker """ 205*387f9dfdSAndroid Build Coastguard Worker struct ipv4_data_t data4 = {}; 206*387f9dfdSAndroid Build Coastguard Worker data4.pid = pid; 207*387f9dfdSAndroid Build Coastguard Worker data4.ip = 4; 208*387f9dfdSAndroid Build Coastguard Worker data4.seq = seq; 209*387f9dfdSAndroid Build Coastguard Worker data4.type = type; 210*387f9dfdSAndroid Build Coastguard Worker data4.saddr = skp->__sk_common.skc_rcv_saddr; 211*387f9dfdSAndroid Build Coastguard Worker data4.daddr = skp->__sk_common.skc_daddr; 212*387f9dfdSAndroid Build Coastguard Worker // lport is host order 213*387f9dfdSAndroid Build Coastguard Worker data4.lport = lport; 214*387f9dfdSAndroid Build Coastguard Worker data4.dport = ntohs(dport); 215*387f9dfdSAndroid Build Coastguard Worker data4.state = state; """ 216*387f9dfdSAndroid Build Coastguard Worker }, 217*387f9dfdSAndroid Build Coastguard Worker 'ipv6': 218*387f9dfdSAndroid Build Coastguard Worker { 'count' : 219*387f9dfdSAndroid Build Coastguard Worker """ 220*387f9dfdSAndroid Build Coastguard Worker struct ipv6_flow_key_t flow_key = {}; 221*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read_kernel(&flow_key.saddr, sizeof(flow_key.saddr), 222*387f9dfdSAndroid Build Coastguard Worker skp->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32); 223*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read_kernel(&flow_key.daddr, sizeof(flow_key.daddr), 224*387f9dfdSAndroid Build Coastguard Worker skp->__sk_common.skc_v6_daddr.in6_u.u6_addr32); 225*387f9dfdSAndroid Build Coastguard Worker // lport is host order 226*387f9dfdSAndroid Build Coastguard Worker flow_key.lport = lport; 227*387f9dfdSAndroid Build Coastguard Worker flow_key.dport = ntohs(dport);""", 228*387f9dfdSAndroid Build Coastguard Worker 'trace' : """ 229*387f9dfdSAndroid Build Coastguard Worker struct ipv6_data_t data6 = {}; 230*387f9dfdSAndroid Build Coastguard Worker data6.pid = pid; 231*387f9dfdSAndroid Build Coastguard Worker data6.ip = 6; 232*387f9dfdSAndroid Build Coastguard Worker data6.seq = seq; 233*387f9dfdSAndroid Build Coastguard Worker data6.type = type; 234*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read_kernel(&data6.saddr, sizeof(data6.saddr), 235*387f9dfdSAndroid Build Coastguard Worker skp->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32); 236*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read_kernel(&data6.daddr, sizeof(data6.daddr), 237*387f9dfdSAndroid Build Coastguard Worker skp->__sk_common.skc_v6_daddr.in6_u.u6_addr32); 238*387f9dfdSAndroid Build Coastguard Worker // lport is host order 239*387f9dfdSAndroid Build Coastguard Worker data6.lport = lport; 240*387f9dfdSAndroid Build Coastguard Worker data6.dport = ntohs(dport); 241*387f9dfdSAndroid Build Coastguard Worker data6.state = state;""" 242*387f9dfdSAndroid Build Coastguard Worker } 243*387f9dfdSAndroid Build Coastguard Worker } 244*387f9dfdSAndroid Build Coastguard Worker 245*387f9dfdSAndroid Build Coastguard Workerstruct_init_tracepoint = { 'ipv4': 246*387f9dfdSAndroid Build Coastguard Worker { 'count' : """ 247*387f9dfdSAndroid Build Coastguard Worker struct ipv4_flow_key_t flow_key = {}; 248*387f9dfdSAndroid Build Coastguard Worker __builtin_memcpy(&flow_key.saddr, args->saddr, sizeof(flow_key.saddr)); 249*387f9dfdSAndroid Build Coastguard Worker __builtin_memcpy(&flow_key.daddr, args->daddr, sizeof(flow_key.daddr)); 250*387f9dfdSAndroid Build Coastguard Worker flow_key.lport = lport; 251*387f9dfdSAndroid Build Coastguard Worker flow_key.dport = dport; 252*387f9dfdSAndroid Build Coastguard Worker ipv4_count.increment(flow_key); 253*387f9dfdSAndroid Build Coastguard Worker """, 254*387f9dfdSAndroid Build Coastguard Worker 'trace' : """ 255*387f9dfdSAndroid Build Coastguard Worker struct ipv4_data_t data4 = {}; 256*387f9dfdSAndroid Build Coastguard Worker data4.pid = pid; 257*387f9dfdSAndroid Build Coastguard Worker data4.lport = lport; 258*387f9dfdSAndroid Build Coastguard Worker data4.dport = dport; 259*387f9dfdSAndroid Build Coastguard Worker data4.type = RETRANSMIT; 260*387f9dfdSAndroid Build Coastguard Worker data4.ip = 4; 261*387f9dfdSAndroid Build Coastguard Worker data4.seq = seq; 262*387f9dfdSAndroid Build Coastguard Worker data4.state = state; 263*387f9dfdSAndroid Build Coastguard Worker __builtin_memcpy(&data4.saddr, args->saddr, sizeof(data4.saddr)); 264*387f9dfdSAndroid Build Coastguard Worker __builtin_memcpy(&data4.daddr, args->daddr, sizeof(data4.daddr)); 265*387f9dfdSAndroid Build Coastguard Worker ipv4_events.perf_submit(args, &data4, sizeof(data4)); 266*387f9dfdSAndroid Build Coastguard Worker """ 267*387f9dfdSAndroid Build Coastguard Worker }, 268*387f9dfdSAndroid Build Coastguard Worker 'ipv6': 269*387f9dfdSAndroid Build Coastguard Worker { 'count' : """ 270*387f9dfdSAndroid Build Coastguard Worker struct ipv6_flow_key_t flow_key = {}; 271*387f9dfdSAndroid Build Coastguard Worker __builtin_memcpy(&flow_key.saddr, args->saddr_v6, sizeof(flow_key.saddr)); 272*387f9dfdSAndroid Build Coastguard Worker __builtin_memcpy(&flow_key.daddr, args->daddr_v6, sizeof(flow_key.daddr)); 273*387f9dfdSAndroid Build Coastguard Worker flow_key.lport = lport; 274*387f9dfdSAndroid Build Coastguard Worker flow_key.dport = dport; 275*387f9dfdSAndroid Build Coastguard Worker ipv6_count.increment(flow_key); 276*387f9dfdSAndroid Build Coastguard Worker """, 277*387f9dfdSAndroid Build Coastguard Worker 'trace' : """ 278*387f9dfdSAndroid Build Coastguard Worker struct ipv6_data_t data6 = {}; 279*387f9dfdSAndroid Build Coastguard Worker data6.pid = pid; 280*387f9dfdSAndroid Build Coastguard Worker data6.lport = lport; 281*387f9dfdSAndroid Build Coastguard Worker data6.dport = dport; 282*387f9dfdSAndroid Build Coastguard Worker data6.type = RETRANSMIT; 283*387f9dfdSAndroid Build Coastguard Worker data6.ip = 6; 284*387f9dfdSAndroid Build Coastguard Worker data6.seq = seq; 285*387f9dfdSAndroid Build Coastguard Worker data6.state = state; 286*387f9dfdSAndroid Build Coastguard Worker __builtin_memcpy(&data6.saddr, args->saddr_v6, sizeof(data6.saddr)); 287*387f9dfdSAndroid Build Coastguard Worker __builtin_memcpy(&data6.daddr, args->daddr_v6, sizeof(data6.daddr)); 288*387f9dfdSAndroid Build Coastguard Worker ipv6_events.perf_submit(args, &data6, sizeof(data6)); 289*387f9dfdSAndroid Build Coastguard Worker """ 290*387f9dfdSAndroid Build Coastguard Worker } 291*387f9dfdSAndroid Build Coastguard Worker } 292*387f9dfdSAndroid Build Coastguard Worker 293*387f9dfdSAndroid Build Coastguard Workercount_core_base = """ 294*387f9dfdSAndroid Build Coastguard Worker COUNT_STRUCT.increment(flow_key); 295*387f9dfdSAndroid Build Coastguard Worker""" 296*387f9dfdSAndroid Build Coastguard Worker 297*387f9dfdSAndroid Build Coastguard Workerif BPF.tracepoint_exists("tcp", "tcp_retransmit_skb"): 298*387f9dfdSAndroid Build Coastguard Worker if args.count: 299*387f9dfdSAndroid Build Coastguard Worker bpf_text_tracepoint = bpf_text_tracepoint.replace("IPV4_CODE", struct_init_tracepoint['ipv4']['count']) 300*387f9dfdSAndroid Build Coastguard Worker bpf_text_tracepoint = bpf_text_tracepoint.replace("IPV6_CODE", struct_init_tracepoint['ipv6']['count']) 301*387f9dfdSAndroid Build Coastguard Worker else: 302*387f9dfdSAndroid Build Coastguard Worker bpf_text_tracepoint = bpf_text_tracepoint.replace("IPV4_CODE", struct_init_tracepoint['ipv4']['trace']) 303*387f9dfdSAndroid Build Coastguard Worker bpf_text_tracepoint = bpf_text_tracepoint.replace("IPV6_CODE", struct_init_tracepoint['ipv6']['trace']) 304*387f9dfdSAndroid Build Coastguard Worker bpf_text += bpf_text_tracepoint 305*387f9dfdSAndroid Build Coastguard Worker 306*387f9dfdSAndroid Build Coastguard Workerif args.lossprobe or not BPF.tracepoint_exists("tcp", "tcp_retransmit_skb"): 307*387f9dfdSAndroid Build Coastguard Worker bpf_text += bpf_text_kprobe 308*387f9dfdSAndroid Build Coastguard Worker if args.count: 309*387f9dfdSAndroid Build Coastguard Worker bpf_text = bpf_text.replace("IPV4_INIT", struct_init['ipv4']['count']) 310*387f9dfdSAndroid Build Coastguard Worker bpf_text = bpf_text.replace("IPV6_INIT", struct_init['ipv6']['count']) 311*387f9dfdSAndroid Build Coastguard Worker bpf_text = bpf_text.replace("IPV4_CORE", count_core_base.replace("COUNT_STRUCT", 'ipv4_count')) 312*387f9dfdSAndroid Build Coastguard Worker bpf_text = bpf_text.replace("IPV6_CORE", count_core_base.replace("COUNT_STRUCT", 'ipv6_count')) 313*387f9dfdSAndroid Build Coastguard Worker else: 314*387f9dfdSAndroid Build Coastguard Worker bpf_text = bpf_text.replace("IPV4_INIT", struct_init['ipv4']['trace']) 315*387f9dfdSAndroid Build Coastguard Worker bpf_text = bpf_text.replace("IPV6_INIT", struct_init['ipv6']['trace']) 316*387f9dfdSAndroid Build Coastguard Worker bpf_text = bpf_text.replace("IPV4_CORE", "ipv4_events.perf_submit(ctx, &data4, sizeof(data4));") 317*387f9dfdSAndroid Build Coastguard Worker bpf_text = bpf_text.replace("IPV6_CORE", "ipv6_events.perf_submit(ctx, &data6, sizeof(data6));") 318*387f9dfdSAndroid Build Coastguard Worker if args.lossprobe: 319*387f9dfdSAndroid Build Coastguard Worker bpf_text += bpf_text_kprobe_tlp 320*387f9dfdSAndroid Build Coastguard Worker if not BPF.tracepoint_exists("tcp", "tcp_retransmit_skb"): 321*387f9dfdSAndroid Build Coastguard Worker bpf_text += bpf_text_kprobe_retransmit 322*387f9dfdSAndroid Build Coastguard Workerif args.ipv4: 323*387f9dfdSAndroid Build Coastguard Worker bpf_text = bpf_text.replace('FILTER_FAMILY', 324*387f9dfdSAndroid Build Coastguard Worker 'if (family != AF_INET) { return 0; }') 325*387f9dfdSAndroid Build Coastguard Workerelif args.ipv6: 326*387f9dfdSAndroid Build Coastguard Worker bpf_text = bpf_text.replace('FILTER_FAMILY', 327*387f9dfdSAndroid Build Coastguard Worker 'if (family != AF_INET6) { return 0; }') 328*387f9dfdSAndroid Build Coastguard Workerelse: 329*387f9dfdSAndroid Build Coastguard Worker bpf_text = bpf_text.replace('FILTER_FAMILY', '') 330*387f9dfdSAndroid Build Coastguard Workerif debug or args.ebpf: 331*387f9dfdSAndroid Build Coastguard Worker print(bpf_text) 332*387f9dfdSAndroid Build Coastguard Worker if args.ebpf: 333*387f9dfdSAndroid Build Coastguard Worker exit() 334*387f9dfdSAndroid Build Coastguard Worker 335*387f9dfdSAndroid Build Coastguard Worker# from bpf_text: 336*387f9dfdSAndroid Build Coastguard Workertype = {} 337*387f9dfdSAndroid Build Coastguard Workertype[1] = 'R' 338*387f9dfdSAndroid Build Coastguard Workertype[2] = 'L' 339*387f9dfdSAndroid Build Coastguard Worker 340*387f9dfdSAndroid Build Coastguard Worker# from include/net/tcp_states.h: 341*387f9dfdSAndroid Build Coastguard Workertcpstate = {} 342*387f9dfdSAndroid Build Coastguard Workertcpstate[1] = 'ESTABLISHED' 343*387f9dfdSAndroid Build Coastguard Workertcpstate[2] = 'SYN_SENT' 344*387f9dfdSAndroid Build Coastguard Workertcpstate[3] = 'SYN_RECV' 345*387f9dfdSAndroid Build Coastguard Workertcpstate[4] = 'FIN_WAIT1' 346*387f9dfdSAndroid Build Coastguard Workertcpstate[5] = 'FIN_WAIT2' 347*387f9dfdSAndroid Build Coastguard Workertcpstate[6] = 'TIME_WAIT' 348*387f9dfdSAndroid Build Coastguard Workertcpstate[7] = 'CLOSE' 349*387f9dfdSAndroid Build Coastguard Workertcpstate[8] = 'CLOSE_WAIT' 350*387f9dfdSAndroid Build Coastguard Workertcpstate[9] = 'LAST_ACK' 351*387f9dfdSAndroid Build Coastguard Workertcpstate[10] = 'LISTEN' 352*387f9dfdSAndroid Build Coastguard Workertcpstate[11] = 'CLOSING' 353*387f9dfdSAndroid Build Coastguard Workertcpstate[12] = 'NEW_SYN_RECV' 354*387f9dfdSAndroid Build Coastguard Worker 355*387f9dfdSAndroid Build Coastguard Worker# process event 356*387f9dfdSAndroid Build Coastguard Workerdef print_ipv4_event(cpu, data, size): 357*387f9dfdSAndroid Build Coastguard Worker event = b["ipv4_events"].event(data) 358*387f9dfdSAndroid Build Coastguard Worker print("%-8s %-7d %-2d %-20s %1s> %-20s" % ( 359*387f9dfdSAndroid Build Coastguard Worker strftime("%H:%M:%S"), event.pid, event.ip, 360*387f9dfdSAndroid Build Coastguard Worker "%s:%d" % (inet_ntop(AF_INET, pack('I', event.saddr)), event.lport), 361*387f9dfdSAndroid Build Coastguard Worker type[event.type], 362*387f9dfdSAndroid Build Coastguard Worker "%s:%s" % (inet_ntop(AF_INET, pack('I', event.daddr)), event.dport)), 363*387f9dfdSAndroid Build Coastguard Worker end='') 364*387f9dfdSAndroid Build Coastguard Worker if args.sequence: 365*387f9dfdSAndroid Build Coastguard Worker print(" %-12s %s" % (tcpstate[event.state], event.seq)) 366*387f9dfdSAndroid Build Coastguard Worker else: 367*387f9dfdSAndroid Build Coastguard Worker print(" %s" % (tcpstate[event.state])) 368*387f9dfdSAndroid Build Coastguard Worker 369*387f9dfdSAndroid Build Coastguard Workerdef print_ipv6_event(cpu, data, size): 370*387f9dfdSAndroid Build Coastguard Worker event = b["ipv6_events"].event(data) 371*387f9dfdSAndroid Build Coastguard Worker print("%-8s %-7d %-2d %-20s %1s> %-20s" % ( 372*387f9dfdSAndroid Build Coastguard Worker strftime("%H:%M:%S"), event.pid, event.ip, 373*387f9dfdSAndroid Build Coastguard Worker "%s:%d" % (inet_ntop(AF_INET6, event.saddr), event.lport), 374*387f9dfdSAndroid Build Coastguard Worker type[event.type], 375*387f9dfdSAndroid Build Coastguard Worker "%s:%d" % (inet_ntop(AF_INET6, event.daddr), event.dport)), 376*387f9dfdSAndroid Build Coastguard Worker end='') 377*387f9dfdSAndroid Build Coastguard Worker if args.sequence: 378*387f9dfdSAndroid Build Coastguard Worker print(" %-12s %s" % (tcpstate[event.state], event.seq)) 379*387f9dfdSAndroid Build Coastguard Worker else: 380*387f9dfdSAndroid Build Coastguard Worker print(" %s" % (tcpstate[event.state])) 381*387f9dfdSAndroid Build Coastguard Worker 382*387f9dfdSAndroid Build Coastguard Workerdef depict_cnt(counts_tab, l3prot='ipv4'): 383*387f9dfdSAndroid Build Coastguard Worker for k, v in sorted(counts_tab.items(), key=lambda counts: counts[1].value): 384*387f9dfdSAndroid Build Coastguard Worker depict_key = "" 385*387f9dfdSAndroid Build Coastguard Worker ep_fmt = "[%s]#%d" 386*387f9dfdSAndroid Build Coastguard Worker if l3prot == 'ipv4': 387*387f9dfdSAndroid Build Coastguard Worker depict_key = "%-20s <-> %-20s" % (ep_fmt % (inet_ntop(AF_INET, pack('I', k.saddr)), k.lport), 388*387f9dfdSAndroid Build Coastguard Worker ep_fmt % (inet_ntop(AF_INET, pack('I', k.daddr)), k.dport)) 389*387f9dfdSAndroid Build Coastguard Worker else: 390*387f9dfdSAndroid Build Coastguard Worker depict_key = "%-20s <-> %-20s" % (ep_fmt % (inet_ntop(AF_INET6, k.saddr), k.lport), 391*387f9dfdSAndroid Build Coastguard Worker ep_fmt % (inet_ntop(AF_INET6, k.daddr), k.dport)) 392*387f9dfdSAndroid Build Coastguard Worker 393*387f9dfdSAndroid Build Coastguard Worker print ("%s %10d" % (depict_key, v.value)) 394*387f9dfdSAndroid Build Coastguard Worker 395*387f9dfdSAndroid Build Coastguard Worker# initialize BPF 396*387f9dfdSAndroid Build Coastguard Workerb = BPF(text=bpf_text) 397*387f9dfdSAndroid Build Coastguard Workerif not BPF.tracepoint_exists("tcp", "tcp_retransmit_skb"): 398*387f9dfdSAndroid Build Coastguard Worker b.attach_kprobe(event="tcp_retransmit_skb", fn_name="trace_retransmit") 399*387f9dfdSAndroid Build Coastguard Workerif args.lossprobe: 400*387f9dfdSAndroid Build Coastguard Worker b.attach_kprobe(event="tcp_send_loss_probe", fn_name="trace_tlp") 401*387f9dfdSAndroid Build Coastguard Worker 402*387f9dfdSAndroid Build Coastguard Workerprint("Tracing retransmits ... Hit Ctrl-C to end") 403*387f9dfdSAndroid Build Coastguard Workerif args.count: 404*387f9dfdSAndroid Build Coastguard Worker try: 405*387f9dfdSAndroid Build Coastguard Worker while 1: 406*387f9dfdSAndroid Build Coastguard Worker sleep(99999999) 407*387f9dfdSAndroid Build Coastguard Worker except BaseException: 408*387f9dfdSAndroid Build Coastguard Worker pass 409*387f9dfdSAndroid Build Coastguard Worker 410*387f9dfdSAndroid Build Coastguard Worker # header 411*387f9dfdSAndroid Build Coastguard Worker print("\n%-25s %-25s %-10s" % ( 412*387f9dfdSAndroid Build Coastguard Worker "LADDR:LPORT", "RADDR:RPORT", "RETRANSMITS")) 413*387f9dfdSAndroid Build Coastguard Worker depict_cnt(b.get_table("ipv4_count")) 414*387f9dfdSAndroid Build Coastguard Worker depict_cnt(b.get_table("ipv6_count"), l3prot='ipv6') 415*387f9dfdSAndroid Build Coastguard Worker# read events 416*387f9dfdSAndroid Build Coastguard Workerelse: 417*387f9dfdSAndroid Build Coastguard Worker # header 418*387f9dfdSAndroid Build Coastguard Worker print("%-8s %-7s %-2s %-20s %1s> %-20s" % ("TIME", "PID", "IP", 419*387f9dfdSAndroid Build Coastguard Worker "LADDR:LPORT", "T", "RADDR:RPORT"), end='') 420*387f9dfdSAndroid Build Coastguard Worker if args.sequence: 421*387f9dfdSAndroid Build Coastguard Worker print(" %-12s %-10s" % ("STATE", "SEQ")) 422*387f9dfdSAndroid Build Coastguard Worker else: 423*387f9dfdSAndroid Build Coastguard Worker print(" %-4s" % ("STATE")) 424*387f9dfdSAndroid Build Coastguard Worker b["ipv4_events"].open_perf_buffer(print_ipv4_event) 425*387f9dfdSAndroid Build Coastguard Worker b["ipv6_events"].open_perf_buffer(print_ipv6_event) 426*387f9dfdSAndroid Build Coastguard Worker while 1: 427*387f9dfdSAndroid Build Coastguard Worker try: 428*387f9dfdSAndroid Build Coastguard Worker b.perf_buffer_poll() 429*387f9dfdSAndroid Build Coastguard Worker except KeyboardInterrupt: 430*387f9dfdSAndroid Build Coastguard Worker exit() 431