%PDF- %PDF-
Direktori : /sbin/ |
Current File : //sbin/tcplife.bt |
#!/usr/bin/env bpftrace /* * tcplife - Trace TCP session lifespans with connection details. * * See BPF Performance Tools, Chapter 10, for an explanation of this tool. * * Copyright (c) 2019 Brendan Gregg. * Licensed under the Apache License, Version 2.0 (the "License"). * This was originally created for the BPF Performance Tools book * published by Addison Wesley. ISBN-13: 9780136554820 * When copying or porting, include this comment. * * 17-Apr-2019 Brendan Gregg Created this. */ #ifndef BPFTRACE_HAVE_BTF #include <net/tcp_states.h> #include <net/sock.h> #include <linux/socket.h> #include <linux/tcp.h> #else #include <sys/socket.h> #endif BEGIN { printf("%-5s %-10s %-15s %-5s %-15s %-5s ", "PID", "COMM", "LADDR", "LPORT", "RADDR", "RPORT"); printf("%5s %5s %s\n", "TX_KB", "RX_KB", "MS"); } kprobe:tcp_set_state { $sk = (struct sock *)arg0; $newstate = arg1; /* * This tool includes PID and comm context. From TCP this is best * effort, and may be wrong in some situations. It does this: * - record timestamp on any state < TCP_FIN_WAIT1 * note some state transitions may not be present via this kprobe * - cache task context on: * TCP_SYN_SENT: tracing from client * TCP_LAST_ACK: client-closed from server * - do output on TCP_CLOSE: * fetch task context if cached, or use current task */ // record first timestamp seen for this socket if ($newstate < TCP_FIN_WAIT1 && @birth[$sk] == 0) { @birth[$sk] = nsecs; } // record PID & comm on SYN_SENT if ($newstate == TCP_SYN_SENT || $newstate == TCP_LAST_ACK) { @skpid[$sk] = pid; @skcomm[$sk] = comm; } // session ended: calculate lifespan and print if ($newstate == TCP_CLOSE && @birth[$sk]) { $delta_ms = (nsecs - @birth[$sk]) / 1e6; $lport = $sk->__sk_common.skc_num; $dport = $sk->__sk_common.skc_dport; $dport = bswap($dport); $tp = (struct tcp_sock *)$sk; $pid = @skpid[$sk]; $comm = @skcomm[$sk]; if ($comm == "") { // not cached, use current task $pid = pid; $comm = comm; } $family = $sk->__sk_common.skc_family; $saddr = ntop(0); $daddr = ntop(0); if ($family == AF_INET) { $saddr = ntop(AF_INET, $sk->__sk_common.skc_rcv_saddr); $daddr = ntop(AF_INET, $sk->__sk_common.skc_daddr); } else { // AF_INET6 $saddr = ntop(AF_INET6, $sk->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr8); $daddr = ntop(AF_INET6, $sk->__sk_common.skc_v6_daddr.in6_u.u6_addr8); } printf("%-5d %-10.10s %-15s %-5d %-15s %-6d ", $pid, $comm, $saddr, $lport, $daddr, $dport); printf("%5d %5d %d\n", $tp->bytes_acked / 1024, $tp->bytes_received / 1024, $delta_ms); delete(@birth[$sk]); delete(@skpid[$sk]); delete(@skcomm[$sk]); } } END { clear(@birth); clear(@skpid); clear(@skcomm); }