1*387f9dfdSAndroid Build Coastguard Worker#!/usr/bin/env python 2*387f9dfdSAndroid Build Coastguard Worker# 3*387f9dfdSAndroid Build Coastguard Worker# gethostlatency Show latency for getaddrinfo/gethostbyname[2] calls. 4*387f9dfdSAndroid Build Coastguard Worker# For Linux, uses BCC, eBPF. Embedded C. 5*387f9dfdSAndroid Build Coastguard Worker# 6*387f9dfdSAndroid Build Coastguard Worker# This can be useful for identifying DNS latency, by identifying which 7*387f9dfdSAndroid Build Coastguard Worker# remote host name lookups were slow, and by how much. 8*387f9dfdSAndroid Build Coastguard Worker# 9*387f9dfdSAndroid Build Coastguard Worker# This uses dynamic tracing of user-level functions and registers, and may 10*387f9dfdSAndroid Build Coastguard Worker# need modifications to match your software and processor architecture. 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# 28-Jan-2016 Brendan Gregg Created this. 16*387f9dfdSAndroid Build Coastguard Worker# 30-Mar-2016 Allan McAleavy updated for BPF_PERF_OUTPUT 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 Workerfrom time import strftime 21*387f9dfdSAndroid Build Coastguard Workerimport argparse 22*387f9dfdSAndroid Build Coastguard Worker 23*387f9dfdSAndroid Build Coastguard Workerexamples = """examples: 24*387f9dfdSAndroid Build Coastguard Worker ./gethostlatency # time getaddrinfo/gethostbyname[2] calls 25*387f9dfdSAndroid Build Coastguard Worker ./gethostlatency -p 181 # only trace PID 181 26*387f9dfdSAndroid Build Coastguard Worker""" 27*387f9dfdSAndroid Build Coastguard Workerparser = argparse.ArgumentParser( 28*387f9dfdSAndroid Build Coastguard Worker description="Show latency for getaddrinfo/gethostbyname[2] calls", 29*387f9dfdSAndroid Build Coastguard Worker formatter_class=argparse.RawDescriptionHelpFormatter, 30*387f9dfdSAndroid Build Coastguard Worker epilog=examples) 31*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-p", "--pid", help="trace this PID only", type=int, 32*387f9dfdSAndroid Build Coastguard Worker default=-1) 33*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("--ebpf", action="store_true", 34*387f9dfdSAndroid Build Coastguard Worker help=argparse.SUPPRESS) 35*387f9dfdSAndroid Build Coastguard Workerargs = parser.parse_args() 36*387f9dfdSAndroid Build Coastguard Worker 37*387f9dfdSAndroid Build Coastguard Worker# load BPF program 38*387f9dfdSAndroid Build Coastguard Workerbpf_text = """ 39*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ptrace.h> 40*387f9dfdSAndroid Build Coastguard Worker#include <linux/sched.h> 41*387f9dfdSAndroid Build Coastguard Worker 42*387f9dfdSAndroid Build Coastguard Workerstruct val_t { 43*387f9dfdSAndroid Build Coastguard Worker u32 pid; 44*387f9dfdSAndroid Build Coastguard Worker char comm[TASK_COMM_LEN]; 45*387f9dfdSAndroid Build Coastguard Worker char host[80]; 46*387f9dfdSAndroid Build Coastguard Worker u64 ts; 47*387f9dfdSAndroid Build Coastguard Worker}; 48*387f9dfdSAndroid Build Coastguard Worker 49*387f9dfdSAndroid Build Coastguard Workerstruct data_t { 50*387f9dfdSAndroid Build Coastguard Worker u32 pid; 51*387f9dfdSAndroid Build Coastguard Worker u64 delta; 52*387f9dfdSAndroid Build Coastguard Worker char comm[TASK_COMM_LEN]; 53*387f9dfdSAndroid Build Coastguard Worker char host[80]; 54*387f9dfdSAndroid Build Coastguard Worker}; 55*387f9dfdSAndroid Build Coastguard Worker 56*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(start, u32, struct val_t); 57*387f9dfdSAndroid Build Coastguard WorkerBPF_PERF_OUTPUT(events); 58*387f9dfdSAndroid Build Coastguard Worker 59*387f9dfdSAndroid Build Coastguard Workerint do_entry(struct pt_regs *ctx) { 60*387f9dfdSAndroid Build Coastguard Worker if (!PT_REGS_PARM1(ctx)) 61*387f9dfdSAndroid Build Coastguard Worker return 0; 62*387f9dfdSAndroid Build Coastguard Worker 63*387f9dfdSAndroid Build Coastguard Worker struct val_t val = {}; 64*387f9dfdSAndroid Build Coastguard Worker u64 pid_tgid = bpf_get_current_pid_tgid(); 65*387f9dfdSAndroid Build Coastguard Worker u32 pid = pid_tgid >> 32; 66*387f9dfdSAndroid Build Coastguard Worker u32 tid = (u32)pid_tgid; 67*387f9dfdSAndroid Build Coastguard Worker 68*387f9dfdSAndroid Build Coastguard Worker if (bpf_get_current_comm(&val.comm, sizeof(val.comm)) == 0) { 69*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read_user(&val.host, sizeof(val.host), 70*387f9dfdSAndroid Build Coastguard Worker (void *)PT_REGS_PARM1(ctx)); 71*387f9dfdSAndroid Build Coastguard Worker val.pid = pid; 72*387f9dfdSAndroid Build Coastguard Worker val.ts = bpf_ktime_get_ns(); 73*387f9dfdSAndroid Build Coastguard Worker start.update(&tid, &val); 74*387f9dfdSAndroid Build Coastguard Worker } 75*387f9dfdSAndroid Build Coastguard Worker 76*387f9dfdSAndroid Build Coastguard Worker return 0; 77*387f9dfdSAndroid Build Coastguard Worker} 78*387f9dfdSAndroid Build Coastguard Worker 79*387f9dfdSAndroid Build Coastguard Workerint do_return(struct pt_regs *ctx) { 80*387f9dfdSAndroid Build Coastguard Worker struct val_t *valp; 81*387f9dfdSAndroid Build Coastguard Worker struct data_t data = {}; 82*387f9dfdSAndroid Build Coastguard Worker u64 delta; 83*387f9dfdSAndroid Build Coastguard Worker u64 pid_tgid = bpf_get_current_pid_tgid(); 84*387f9dfdSAndroid Build Coastguard Worker u32 tid = (u32)pid_tgid; 85*387f9dfdSAndroid Build Coastguard Worker 86*387f9dfdSAndroid Build Coastguard Worker u64 tsp = bpf_ktime_get_ns(); 87*387f9dfdSAndroid Build Coastguard Worker 88*387f9dfdSAndroid Build Coastguard Worker valp = start.lookup(&tid); 89*387f9dfdSAndroid Build Coastguard Worker if (valp == 0) 90*387f9dfdSAndroid Build Coastguard Worker return 0; // missed start 91*387f9dfdSAndroid Build Coastguard Worker 92*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read_kernel(&data.comm, sizeof(data.comm), valp->comm); 93*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read_kernel(&data.host, sizeof(data.host), (void *)valp->host); 94*387f9dfdSAndroid Build Coastguard Worker data.pid = valp->pid; 95*387f9dfdSAndroid Build Coastguard Worker data.delta = tsp - valp->ts; 96*387f9dfdSAndroid Build Coastguard Worker events.perf_submit(ctx, &data, sizeof(data)); 97*387f9dfdSAndroid Build Coastguard Worker start.delete(&tid); 98*387f9dfdSAndroid Build Coastguard Worker return 0; 99*387f9dfdSAndroid Build Coastguard Worker} 100*387f9dfdSAndroid Build Coastguard Worker""" 101*387f9dfdSAndroid Build Coastguard Workerif args.ebpf: 102*387f9dfdSAndroid Build Coastguard Worker print(bpf_text) 103*387f9dfdSAndroid Build Coastguard Worker exit() 104*387f9dfdSAndroid Build Coastguard Worker 105*387f9dfdSAndroid Build Coastguard Workerb = BPF(text=bpf_text) 106*387f9dfdSAndroid Build Coastguard Workerb.attach_uprobe(name="c", sym="getaddrinfo", fn_name="do_entry", pid=args.pid) 107*387f9dfdSAndroid Build Coastguard Workerb.attach_uprobe(name="c", sym="gethostbyname", fn_name="do_entry", 108*387f9dfdSAndroid Build Coastguard Worker pid=args.pid) 109*387f9dfdSAndroid Build Coastguard Workerb.attach_uprobe(name="c", sym="gethostbyname2", fn_name="do_entry", 110*387f9dfdSAndroid Build Coastguard Worker pid=args.pid) 111*387f9dfdSAndroid Build Coastguard Workerb.attach_uretprobe(name="c", sym="getaddrinfo", fn_name="do_return", 112*387f9dfdSAndroid Build Coastguard Worker pid=args.pid) 113*387f9dfdSAndroid Build Coastguard Workerb.attach_uretprobe(name="c", sym="gethostbyname", fn_name="do_return", 114*387f9dfdSAndroid Build Coastguard Worker pid=args.pid) 115*387f9dfdSAndroid Build Coastguard Workerb.attach_uretprobe(name="c", sym="gethostbyname2", fn_name="do_return", 116*387f9dfdSAndroid Build Coastguard Worker pid=args.pid) 117*387f9dfdSAndroid Build Coastguard Worker 118*387f9dfdSAndroid Build Coastguard Worker# header 119*387f9dfdSAndroid Build Coastguard Workerprint("%-9s %-7s %-16s %10s %s" % ("TIME", "PID", "COMM", "LATms", "HOST")) 120*387f9dfdSAndroid Build Coastguard Worker 121*387f9dfdSAndroid Build Coastguard Workerdef print_event(cpu, data, size): 122*387f9dfdSAndroid Build Coastguard Worker event = b["events"].event(data) 123*387f9dfdSAndroid Build Coastguard Worker print("%-9s %-7d %-16s %10.2f %s" % (strftime("%H:%M:%S"), event.pid, 124*387f9dfdSAndroid Build Coastguard Worker event.comm.decode('utf-8', 'replace'), (float(event.delta) / 1000000), 125*387f9dfdSAndroid Build Coastguard Worker event.host.decode('utf-8', 'replace'))) 126*387f9dfdSAndroid Build Coastguard Worker 127*387f9dfdSAndroid Build Coastguard Worker# loop with callback to print_event 128*387f9dfdSAndroid Build Coastguard Workerb["events"].open_perf_buffer(print_event) 129*387f9dfdSAndroid Build Coastguard Workerwhile 1: 130*387f9dfdSAndroid Build Coastguard Worker try: 131*387f9dfdSAndroid Build Coastguard Worker b.perf_buffer_poll() 132*387f9dfdSAndroid Build Coastguard Worker except KeyboardInterrupt: 133*387f9dfdSAndroid Build Coastguard Worker exit() 134