xref: /aosp_15_r20/external/bcc/libbpf-tools/tcplife.bpf.c (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1*387f9dfdSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0
2*387f9dfdSAndroid Build Coastguard Worker /* Copyright (c) 2022 Hengqi Chen */
3*387f9dfdSAndroid Build Coastguard Worker #include <vmlinux.h>
4*387f9dfdSAndroid Build Coastguard Worker #include <bpf/bpf_core_read.h>
5*387f9dfdSAndroid Build Coastguard Worker #include <bpf/bpf_helpers.h>
6*387f9dfdSAndroid Build Coastguard Worker #include <bpf/bpf_tracing.h>
7*387f9dfdSAndroid Build Coastguard Worker #include "tcplife.h"
8*387f9dfdSAndroid Build Coastguard Worker 
9*387f9dfdSAndroid Build Coastguard Worker #define MAX_ENTRIES	10240
10*387f9dfdSAndroid Build Coastguard Worker #define AF_INET		2
11*387f9dfdSAndroid Build Coastguard Worker #define AF_INET6	10
12*387f9dfdSAndroid Build Coastguard Worker 
13*387f9dfdSAndroid Build Coastguard Worker const volatile bool filter_sport = false;
14*387f9dfdSAndroid Build Coastguard Worker const volatile bool filter_dport = false;
15*387f9dfdSAndroid Build Coastguard Worker const volatile __u16 target_sports[MAX_PORTS] = {};
16*387f9dfdSAndroid Build Coastguard Worker const volatile __u16 target_dports[MAX_PORTS] = {};
17*387f9dfdSAndroid Build Coastguard Worker const volatile pid_t target_pid = 0;
18*387f9dfdSAndroid Build Coastguard Worker const volatile __u16 target_family = 0;
19*387f9dfdSAndroid Build Coastguard Worker 
20*387f9dfdSAndroid Build Coastguard Worker struct {
21*387f9dfdSAndroid Build Coastguard Worker 	__uint(type, BPF_MAP_TYPE_HASH);
22*387f9dfdSAndroid Build Coastguard Worker 	__uint(max_entries, MAX_ENTRIES);
23*387f9dfdSAndroid Build Coastguard Worker 	__type(key, struct sock *);
24*387f9dfdSAndroid Build Coastguard Worker 	__type(value, __u64);
25*387f9dfdSAndroid Build Coastguard Worker } birth SEC(".maps");
26*387f9dfdSAndroid Build Coastguard Worker 
27*387f9dfdSAndroid Build Coastguard Worker struct {
28*387f9dfdSAndroid Build Coastguard Worker 	__uint(type, BPF_MAP_TYPE_HASH);
29*387f9dfdSAndroid Build Coastguard Worker 	__uint(max_entries, MAX_ENTRIES);
30*387f9dfdSAndroid Build Coastguard Worker 	__type(key, struct sock *);
31*387f9dfdSAndroid Build Coastguard Worker 	__type(value, struct ident);
32*387f9dfdSAndroid Build Coastguard Worker } idents SEC(".maps");
33*387f9dfdSAndroid Build Coastguard Worker 
34*387f9dfdSAndroid Build Coastguard Worker struct {
35*387f9dfdSAndroid Build Coastguard Worker 	__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
36*387f9dfdSAndroid Build Coastguard Worker 	__uint(key_size, sizeof(__u32));
37*387f9dfdSAndroid Build Coastguard Worker 	__uint(value_size, sizeof(__u32));
38*387f9dfdSAndroid Build Coastguard Worker } events SEC(".maps");
39*387f9dfdSAndroid Build Coastguard Worker 
40*387f9dfdSAndroid Build Coastguard Worker SEC("tracepoint/sock/inet_sock_set_state")
inet_sock_set_state(struct trace_event_raw_inet_sock_set_state * args)41*387f9dfdSAndroid Build Coastguard Worker int inet_sock_set_state(struct trace_event_raw_inet_sock_set_state *args)
42*387f9dfdSAndroid Build Coastguard Worker {
43*387f9dfdSAndroid Build Coastguard Worker 	__u64 ts, *start, delta_us, rx_b, tx_b;
44*387f9dfdSAndroid Build Coastguard Worker 	struct ident ident = {}, *identp;
45*387f9dfdSAndroid Build Coastguard Worker 	__u16 sport, dport, family;
46*387f9dfdSAndroid Build Coastguard Worker 	struct event event = {};
47*387f9dfdSAndroid Build Coastguard Worker 	struct tcp_sock *tp;
48*387f9dfdSAndroid Build Coastguard Worker 	struct sock *sk;
49*387f9dfdSAndroid Build Coastguard Worker 	bool found;
50*387f9dfdSAndroid Build Coastguard Worker 	__u32 pid;
51*387f9dfdSAndroid Build Coastguard Worker 	int i;
52*387f9dfdSAndroid Build Coastguard Worker 
53*387f9dfdSAndroid Build Coastguard Worker 	if (BPF_CORE_READ(args, protocol) != IPPROTO_TCP)
54*387f9dfdSAndroid Build Coastguard Worker 		return 0;
55*387f9dfdSAndroid Build Coastguard Worker 
56*387f9dfdSAndroid Build Coastguard Worker 	family = BPF_CORE_READ(args, family);
57*387f9dfdSAndroid Build Coastguard Worker 	if (target_family && family != target_family)
58*387f9dfdSAndroid Build Coastguard Worker 		return 0;
59*387f9dfdSAndroid Build Coastguard Worker 
60*387f9dfdSAndroid Build Coastguard Worker 	sport = BPF_CORE_READ(args, sport);
61*387f9dfdSAndroid Build Coastguard Worker 	if (filter_sport) {
62*387f9dfdSAndroid Build Coastguard Worker 		found = false;
63*387f9dfdSAndroid Build Coastguard Worker 		for (i = 0; i < MAX_PORTS; i++) {
64*387f9dfdSAndroid Build Coastguard Worker 			if (!target_sports[i])
65*387f9dfdSAndroid Build Coastguard Worker 				return 0;
66*387f9dfdSAndroid Build Coastguard Worker 			if (sport != target_sports[i])
67*387f9dfdSAndroid Build Coastguard Worker 				continue;
68*387f9dfdSAndroid Build Coastguard Worker 			found = true;
69*387f9dfdSAndroid Build Coastguard Worker 			break;
70*387f9dfdSAndroid Build Coastguard Worker 		}
71*387f9dfdSAndroid Build Coastguard Worker 		if (!found)
72*387f9dfdSAndroid Build Coastguard Worker 			return 0;
73*387f9dfdSAndroid Build Coastguard Worker 	}
74*387f9dfdSAndroid Build Coastguard Worker 
75*387f9dfdSAndroid Build Coastguard Worker 	dport = BPF_CORE_READ(args, dport);
76*387f9dfdSAndroid Build Coastguard Worker 	if (filter_dport) {
77*387f9dfdSAndroid Build Coastguard Worker 		found = false;
78*387f9dfdSAndroid Build Coastguard Worker 		for (i = 0; i < MAX_PORTS; i++) {
79*387f9dfdSAndroid Build Coastguard Worker 			if (!target_dports[i])
80*387f9dfdSAndroid Build Coastguard Worker 				return 0;
81*387f9dfdSAndroid Build Coastguard Worker 			if (dport != target_dports[i])
82*387f9dfdSAndroid Build Coastguard Worker 				continue;
83*387f9dfdSAndroid Build Coastguard Worker 			found = true;
84*387f9dfdSAndroid Build Coastguard Worker 			break;
85*387f9dfdSAndroid Build Coastguard Worker 		}
86*387f9dfdSAndroid Build Coastguard Worker 		if (!found)
87*387f9dfdSAndroid Build Coastguard Worker 			return 0;
88*387f9dfdSAndroid Build Coastguard Worker 	}
89*387f9dfdSAndroid Build Coastguard Worker 
90*387f9dfdSAndroid Build Coastguard Worker 	sk = (struct sock *)BPF_CORE_READ(args, skaddr);
91*387f9dfdSAndroid Build Coastguard Worker 	if (BPF_CORE_READ(args, newstate) < TCP_FIN_WAIT1) {
92*387f9dfdSAndroid Build Coastguard Worker 		ts = bpf_ktime_get_ns();
93*387f9dfdSAndroid Build Coastguard Worker 		bpf_map_update_elem(&birth, &sk, &ts, BPF_ANY);
94*387f9dfdSAndroid Build Coastguard Worker 	}
95*387f9dfdSAndroid Build Coastguard Worker 
96*387f9dfdSAndroid Build Coastguard Worker 	if (BPF_CORE_READ(args, newstate) == TCP_SYN_SENT || BPF_CORE_READ(args, newstate) == TCP_LAST_ACK) {
97*387f9dfdSAndroid Build Coastguard Worker 		pid = bpf_get_current_pid_tgid() >> 32;
98*387f9dfdSAndroid Build Coastguard Worker 		if (target_pid && pid != target_pid)
99*387f9dfdSAndroid Build Coastguard Worker 			return 0;
100*387f9dfdSAndroid Build Coastguard Worker 		ident.pid = pid;
101*387f9dfdSAndroid Build Coastguard Worker 		bpf_get_current_comm(ident.comm, sizeof(ident.comm));
102*387f9dfdSAndroid Build Coastguard Worker 		bpf_map_update_elem(&idents, &sk, &ident, BPF_ANY);
103*387f9dfdSAndroid Build Coastguard Worker 	}
104*387f9dfdSAndroid Build Coastguard Worker 
105*387f9dfdSAndroid Build Coastguard Worker 	if (BPF_CORE_READ(args, newstate) != TCP_CLOSE)
106*387f9dfdSAndroid Build Coastguard Worker 		return 0;
107*387f9dfdSAndroid Build Coastguard Worker 
108*387f9dfdSAndroid Build Coastguard Worker 	start = bpf_map_lookup_elem(&birth, &sk);
109*387f9dfdSAndroid Build Coastguard Worker 	if (!start) {
110*387f9dfdSAndroid Build Coastguard Worker 		bpf_map_delete_elem(&idents, &sk);
111*387f9dfdSAndroid Build Coastguard Worker 		return 0;
112*387f9dfdSAndroid Build Coastguard Worker 	}
113*387f9dfdSAndroid Build Coastguard Worker 	ts = bpf_ktime_get_ns();
114*387f9dfdSAndroid Build Coastguard Worker 	delta_us = (ts - *start) / 1000;
115*387f9dfdSAndroid Build Coastguard Worker 
116*387f9dfdSAndroid Build Coastguard Worker 	identp = bpf_map_lookup_elem(&idents, &sk);
117*387f9dfdSAndroid Build Coastguard Worker 	pid = identp ? identp->pid : bpf_get_current_pid_tgid() >> 32;
118*387f9dfdSAndroid Build Coastguard Worker 	if (target_pid && pid != target_pid)
119*387f9dfdSAndroid Build Coastguard Worker 		goto cleanup;
120*387f9dfdSAndroid Build Coastguard Worker 
121*387f9dfdSAndroid Build Coastguard Worker 	tp = (struct tcp_sock *)sk;
122*387f9dfdSAndroid Build Coastguard Worker 	rx_b = BPF_CORE_READ(tp, bytes_received);
123*387f9dfdSAndroid Build Coastguard Worker 	tx_b = BPF_CORE_READ(tp, bytes_acked);
124*387f9dfdSAndroid Build Coastguard Worker 
125*387f9dfdSAndroid Build Coastguard Worker 	event.ts_us = ts / 1000;
126*387f9dfdSAndroid Build Coastguard Worker 	event.span_us = delta_us;
127*387f9dfdSAndroid Build Coastguard Worker 	event.rx_b = rx_b;
128*387f9dfdSAndroid Build Coastguard Worker 	event.tx_b = tx_b;
129*387f9dfdSAndroid Build Coastguard Worker 	event.pid = pid;
130*387f9dfdSAndroid Build Coastguard Worker 	event.sport = sport;
131*387f9dfdSAndroid Build Coastguard Worker 	event.dport = dport;
132*387f9dfdSAndroid Build Coastguard Worker 	event.family = family;
133*387f9dfdSAndroid Build Coastguard Worker 	if (!identp)
134*387f9dfdSAndroid Build Coastguard Worker 		bpf_get_current_comm(event.comm, sizeof(event.comm));
135*387f9dfdSAndroid Build Coastguard Worker 	else
136*387f9dfdSAndroid Build Coastguard Worker 		bpf_probe_read_kernel(event.comm, sizeof(event.comm), (void *)identp->comm);
137*387f9dfdSAndroid Build Coastguard Worker 	if (family == AF_INET) {
138*387f9dfdSAndroid Build Coastguard Worker 		bpf_probe_read_kernel(&event.saddr, sizeof(args->saddr), BPF_CORE_READ(args, saddr));
139*387f9dfdSAndroid Build Coastguard Worker 		bpf_probe_read_kernel(&event.daddr, sizeof(args->daddr), BPF_CORE_READ(args, daddr));
140*387f9dfdSAndroid Build Coastguard Worker 	} else {	/*  AF_INET6 */
141*387f9dfdSAndroid Build Coastguard Worker 		bpf_probe_read_kernel(&event.saddr, sizeof(args->saddr_v6), BPF_CORE_READ(args, saddr_v6));
142*387f9dfdSAndroid Build Coastguard Worker 		bpf_probe_read_kernel(&event.daddr, sizeof(args->daddr_v6), BPF_CORE_READ(args, daddr_v6));
143*387f9dfdSAndroid Build Coastguard Worker 	}
144*387f9dfdSAndroid Build Coastguard Worker 	bpf_perf_event_output(args, &events, BPF_F_CURRENT_CPU, &event, sizeof(event));
145*387f9dfdSAndroid Build Coastguard Worker 
146*387f9dfdSAndroid Build Coastguard Worker cleanup:
147*387f9dfdSAndroid Build Coastguard Worker 	bpf_map_delete_elem(&birth, &sk);
148*387f9dfdSAndroid Build Coastguard Worker 	bpf_map_delete_elem(&idents, &sk);
149*387f9dfdSAndroid Build Coastguard Worker 	return 0;
150*387f9dfdSAndroid Build Coastguard Worker }
151*387f9dfdSAndroid Build Coastguard Worker 
152*387f9dfdSAndroid Build Coastguard Worker char LICENSE[] SEC("license") = "GPL";
153