Server IP : 184.154.167.98 / Your IP : 3.146.107.49 Web Server : Apache System : Linux pink.dnsnetservice.com 4.18.0-553.22.1.lve.1.el8.x86_64 #1 SMP Tue Oct 8 15:52:54 UTC 2024 x86_64 User : puertode ( 1767) PHP Version : 7.2.34 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : ON Directory : /usr/libexec/pcp/pmdas/bcc/modules/ |
Upload File : |
// Copyright 2016 Netflix, Inc. // Licensed under the Apache License, Version 2.0 (the "License") #include <uapi/linux/ptrace.h> #include <linux/tcp.h> #include <net/sock.h> #include <bcc/proto.h> BPF_HASH(birth, struct sock *, u64); // separate data structs for ipv4 and ipv6 struct ipv4_data_t { u64 ts_us; u32 pid; u32 saddr; u32 daddr; u64 ports; u64 rx_b; u64 tx_b; u64 span_us; char task[TASK_COMM_LEN]; }; BPF_PERF_OUTPUT(ipv4_events); struct ipv6_data_t { u64 ts_us; u32 pid; unsigned __int128 saddr; unsigned __int128 daddr; u64 ports; u64 rx_b; u64 tx_b; u64 span_us; char task[TASK_COMM_LEN]; }; BPF_PERF_OUTPUT(ipv6_events); struct id_t { u32 pid; char task[TASK_COMM_LEN]; }; BPF_HASH(whoami, struct sock *, struct id_t); TRACEPOINT_PROBE(sock, inet_sock_set_state) { if (args->protocol != IPPROTO_TCP) return 0; u32 pid = bpf_get_current_pid_tgid() >> 32; // sk is mostly used as a UUID, and for two tcp stats: struct sock *sk = (struct sock *)args->skaddr; // lport is either used in a filter here, or later u16 lport = args->sport; FILTER_LPORT // dport is either used in a filter here, or later u16 dport = args->dport; FILTER_DPORT /* * This tool includes PID and comm context. It's best effort, and may * be wrong in some situations. It currently works like this: * - record timestamp on any state < TCP_FIN_WAIT1 * - 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 */ // capture birth time if (args->newstate < TCP_FIN_WAIT1) { /* * Matching just ESTABLISHED may be sufficient, provided no code-path * sets ESTABLISHED without a tcp_set_state() call. Until we know * that for sure, match all early states to increase chances a * timestamp is set. * Note that this needs to be set before the PID filter later on, * since the PID isn't reliable for these early stages, so we must * save all timestamps and do the PID filter later when we can. */ u64 ts = bpf_ktime_get_ns(); birth.update(&sk, &ts); } // record PID & comm on SYN_SENT if (args->newstate == TCP_SYN_SENT || args->newstate == TCP_LAST_ACK) { // now we can PID filter, both here and a little later on for CLOSE FILTER_PID struct id_t me = {.pid = pid}; bpf_get_current_comm(&me.task, sizeof(me.task)); whoami.update(&sk, &me); } if (args->newstate != TCP_CLOSE) return 0; // calculate lifespan u64 *tsp, delta_us; tsp = birth.lookup(&sk); if (tsp == 0) { whoami.delete(&sk); // may not exist return 0; // missed create } delta_us = (bpf_ktime_get_ns() - *tsp) / 1000; birth.delete(&sk); // fetch possible cached data, and filter struct id_t *mep; mep = whoami.lookup(&sk); if (mep != 0) pid = mep->pid; FILTER_PID u16 family = args->family; FILTER_FAMILY // get throughput stats. see tcp_get_info(). u64 rx_b = 0, tx_b = 0, sport = 0; struct tcp_sock *tp = (struct tcp_sock *)sk; rx_b = tp->bytes_received; tx_b = tp->bytes_acked; if (args->family == AF_INET) { struct ipv4_data_t data4 = {}; data4.span_us = delta_us; data4.rx_b = rx_b; data4.tx_b = tx_b; data4.ts_us = bpf_ktime_get_ns() / 1000; __builtin_memcpy(&data4.saddr, args->saddr, sizeof(data4.saddr)); __builtin_memcpy(&data4.daddr, args->daddr, sizeof(data4.daddr)); // a workaround until data4 compiles with separate lport/dport data4.ports = dport + ((0ULL + lport) << 32); data4.pid = pid; if (mep == 0) { bpf_get_current_comm(&data4.task, sizeof(data4.task)); } else { bpf_probe_read_kernel(&data4.task, sizeof(data4.task), (void *)mep->task); } ipv4_events.perf_submit(args, &data4, sizeof(data4)); } else /* 6 */ { struct ipv6_data_t data6 = {}; data6.span_us = delta_us; data6.rx_b = rx_b; data6.tx_b = tx_b; data6.ts_us = bpf_ktime_get_ns() / 1000; __builtin_memcpy(&data6.saddr, args->saddr_v6, sizeof(data6.saddr)); __builtin_memcpy(&data6.daddr, args->daddr_v6, sizeof(data6.daddr)); // a workaround until data6 compiles with separate lport/dport data6.ports = dport + ((0ULL + lport) << 32); data6.pid = pid; if (mep == 0) { bpf_get_current_comm(&data6.task, sizeof(data6.task)); } else { bpf_probe_read_kernel(&data6.task, sizeof(data6.task), (void *)mep->task); } ipv6_events.perf_submit(args, &data6, sizeof(data6)); } if (mep != 0) whoami.delete(&sk); return 0; }