Skip to content

Commit c7fb1fb

Browse files
committed
libbpf-tools: tcpstates: Fix CLOSE to SYN_SENT wrong delta
When the TCP socket is initially created, the timestamp of when sk is created is not recorded, so the delay from the CLOSE state to any state is 0, which is obviously wrong. This patch records the time when sk is created as the start time of the CLOSE state, thereby obtaining the time from CLOSE to LISTEN or SYN_SENT. At the same time, because some time differences are really too small, nanosecond level time display support is added (-n). Before: bcc/libbpf-tools$ sudo ./tcpstates | grep CLOSE ffff8b296bd1af80 421523 Chrome_Chi 10.56.52.9 0 10.32.0.200 8080 CLOSE -> SYN_SENT 0.000 ffff8b296bd1df00 421523 Chrome_Chi 10.56.52.9 0 10.32.0.200 8080 CLOSE -> SYN_SENT 0.000 ffff8b29c851a600 421523 Chrome_Chi 10.56.52.9 0 10.32.0.200 8080 CLOSE -> SYN_SENT 0.000 ffff8b29c4ac4c00 421523 Chrome_Chi 10.56.52.9 0 10.32.0.200 8080 CLOSE -> SYN_SENT 0.000 ffff8b29c4ac6880 421523 Chrome_Chi 10.56.52.9 0 10.32.0.200 8080 CLOSE -> SYN_SENT 0.000 ffff8b29c4ac4280 421523 Chrome_Chi 10.56.52.9 0 10.32.0.200 8080 CLOSE -> SYN_SENT 0.000 ffff8b29c4ac5580 421523 Chrome_Chi 10.56.52.9 0 10.32.0.200 8080 CLOSE -> SYN_SENT 0.000 ^^^^^ After: bcc/libbpf-tools$ sudo ./tcpstates | grep CLOSE ffff8b29f6c91300 421523 Chrome_Chi 10.56.52.9 0 10.32.0.200 8080 CLOSE -> SYN_SENT 0.020 ffff8b29f6c94280 421523 Chrome_Chi 10.56.52.9 0 10.32.0.200 8080 CLOSE -> SYN_SENT 0.011 ffff8b2a1d45cc00 421523 Chrome_Chi 10.56.52.9 0 10.32.0.200 8080 CLOSE -> SYN_SENT 0.022 ffff8b2a1d45af80 421523 Chrome_Chi 10.56.52.9 0 10.32.0.200 8080 CLOSE -> SYN_SENT 0.027 ffff8b29c8518980 421523 Chrome_Chi 10.56.52.9 0 10.32.0.200 8080 CLOSE -> SYN_SENT 0.023 Signed-off-by: Rong Tao <[email protected]>
1 parent 982b7d3 commit c7fb1fb

File tree

3 files changed

+37
-9
lines changed

3 files changed

+37
-9
lines changed

libbpf-tools/tcpstates.bpf.c

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,33 @@ struct {
4141
__uint(value_size, sizeof(__u32));
4242
} events SEC(".maps");
4343

44+
static inline int tcp_sock_create(struct sock *sk)
45+
{
46+
__u64 ts = bpf_ktime_get_ns();
47+
bpf_map_update_elem(&timestamps, &sk, &ts, BPF_ANY);
48+
return 0;
49+
}
50+
51+
SEC("kprobe/tcp_v4_init_sock")
52+
int BPF_KPROBE(tcp_v4_init_sock, struct sock *sk)
53+
{
54+
return tcp_sock_create(sk);
55+
}
56+
57+
SEC("kprobe/tcp_v6_init_sock")
58+
int BPF_KPROBE(tcp_v6_init_sock, struct sock *sk)
59+
{
60+
return tcp_sock_create(sk);
61+
}
62+
4463
SEC("tracepoint/sock/inet_sock_set_state")
4564
int handle_set_state(struct trace_event_raw_inet_sock_set_state *ctx)
4665
{
4766
struct sock *sk = (struct sock *)ctx->skaddr;
4867
__u16 family = ctx->family;
4968
__u16 sport = ctx->sport;
5069
__u16 dport = ctx->dport;
51-
__u64 *tsp, delta_us, ts;
70+
__u64 *tsp, delta_ns, ts;
5271
struct event event = {};
5372

5473
if (ctx->protocol != IPPROTO_TCP)
@@ -66,13 +85,13 @@ int handle_set_state(struct trace_event_raw_inet_sock_set_state *ctx)
6685
tsp = bpf_map_lookup_elem(&timestamps, &sk);
6786
ts = bpf_ktime_get_ns();
6887
if (!tsp)
69-
delta_us = 0;
88+
delta_ns = 0;
7089
else
71-
delta_us = (ts - *tsp) / 1000;
90+
delta_ns = (ts - *tsp);
7291

7392
event.skaddr = (__u64)sk;
7493
event.ts_us = ts / 1000;
75-
event.delta_us = delta_us;
94+
event.delta_ns = delta_ns;
7695
event.pid = bpf_get_current_pid_tgid() >> 32;
7796
event.oldstate = ctx->oldstate;
7897
event.newstate = ctx->newstate;

libbpf-tools/tcpstates.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ static short target_family = 0;
3333
static char *target_sports = NULL;
3434
static char *target_dports = NULL;
3535
static bool wide_output = false;
36+
static bool nanoseconds = false;
3637
static bool verbose = false;
3738
static const char *tcp_states[] = {
3839
[1] = "ESTABLISHED",
@@ -70,6 +71,7 @@ static const struct argp_option opts[] = {
7071
{ "ipv4", '4', NULL, 0, "Trace IPv4 family only", 0 },
7172
{ "ipv6", '6', NULL, 0, "Trace IPv6 family only", 0 },
7273
{ "wide", 'w', NULL, 0, "Wide column output (fits IPv6 addresses)", 0 },
74+
{ "nanoseconds", 'n', NULL, 0, "Display nanosecond delay", 0 },
7375
{ "localport", 'L', "LPORT", 0, "Comma-separated list of local ports to trace.", 0 },
7476
{ "remoteport", 'D', "DPORT", 0, "Comma-separated list of remote ports to trace.", 0 },
7577
{ NULL, 'h', NULL, OPTION_HIDDEN, "Show the full help", 0 },
@@ -97,6 +99,9 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state)
9799
case 'w':
98100
wide_output = true;
99101
break;
102+
case 'n':
103+
nanoseconds = true;
104+
break;
100105
case 'L':
101106
if (!arg) {
102107
warn("No ports specified\n");
@@ -175,11 +180,13 @@ static void handle_event(void *ctx, int cpu, void *data, __u32 data_sz)
175180
family = e.family == AF_INET ? 4 : 6;
176181
printf("%-16llx %-7d %-16s %-2d %-39s %-5d %-39s %-5d %-11s -> %-11s %.3f\n",
177182
e.skaddr, e.pid, e.task, family, saddr, e.sport, daddr, e.dport,
178-
tcp_states[e.oldstate], tcp_states[e.newstate], (double)e.delta_us / 1000);
183+
tcp_states[e.oldstate], tcp_states[e.newstate],
184+
(double)e.delta_ns / (nanoseconds ? 1 : 1000000));
179185
} else {
180186
printf("%-16llx %-7d %-10.10s %-15s %-5d %-15s %-5d %-11s -> %-11s %.3f\n",
181187
e.skaddr, e.pid, e.task, saddr, e.sport, daddr, e.dport,
182-
tcp_states[e.oldstate], tcp_states[e.newstate], (double)e.delta_us / 1000);
188+
tcp_states[e.oldstate], tcp_states[e.newstate],
189+
(double)e.delta_ns / (nanoseconds ? 1 : 1000000));
183190
}
184191
}
185192

@@ -274,11 +281,13 @@ int main(int argc, char **argv)
274281
if (wide_output)
275282
printf("%-16s %-7s %-16s %-2s %-39s %-5s %-39s %-5s %-11s -> %-11s %s\n",
276283
"SKADDR", "PID", "COMM", "IP", "LADDR", "LPORT",
277-
"RADDR", "RPORT", "OLDSTATE", "NEWSTATE", "MS");
284+
"RADDR", "RPORT", "OLDSTATE", "NEWSTATE",
285+
nanoseconds ? "NS" : "MS");
278286
else
279287
printf("%-16s %-7s %-10s %-15s %-5s %-15s %-5s %-11s -> %-11s %s\n",
280288
"SKADDR", "PID", "COMM", "LADDR", "LPORT",
281-
"RADDR", "RPORT", "OLDSTATE", "NEWSTATE", "MS");
289+
"RADDR", "RPORT", "OLDSTATE", "NEWSTATE",
290+
nanoseconds ? "NS" : "MS");
282291

283292
while (!exiting) {
284293
err = perf_buffer__poll(pb, PERF_POLL_TIMEOUT_MS);

libbpf-tools/tcpstates.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ struct event {
1010
unsigned __int128 daddr;
1111
__u64 skaddr;
1212
__u64 ts_us;
13-
__u64 delta_us;
13+
__u64 delta_ns;
1414
__u32 pid;
1515
int oldstate;
1616
int newstate;

0 commit comments

Comments
 (0)