1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* Refer to samples/bpf/tcp_bpf.readme for the instructions on |
3 | * how to run this sample program. |
4 | */ |
5 | #include <linux/bpf.h> |
6 | |
7 | #include <bpf/bpf_helpers.h> |
8 | #include <bpf/bpf_endian.h> |
9 | |
10 | #define INTERVAL 1000000000ULL |
11 | |
12 | int _version SEC("version" ) = 1; |
13 | char _license[] SEC("license" ) = "GPL" ; |
14 | |
15 | struct { |
16 | __u32 type; |
17 | __u32 map_flags; |
18 | int *key; |
19 | __u64 *value; |
20 | } bpf_next_dump SEC(".maps" ) = { |
21 | .type = BPF_MAP_TYPE_SK_STORAGE, |
22 | .map_flags = BPF_F_NO_PREALLOC, |
23 | }; |
24 | |
25 | SEC("sockops" ) |
26 | int _sockops(struct bpf_sock_ops *ctx) |
27 | { |
28 | struct bpf_tcp_sock *tcp_sk; |
29 | struct bpf_sock *sk; |
30 | __u64 *next_dump; |
31 | __u64 now; |
32 | |
33 | switch (ctx->op) { |
34 | case BPF_SOCK_OPS_TCP_CONNECT_CB: |
35 | bpf_sock_ops_cb_flags_set(ctx, BPF_SOCK_OPS_RTT_CB_FLAG); |
36 | return 1; |
37 | case BPF_SOCK_OPS_RTT_CB: |
38 | break; |
39 | default: |
40 | return 1; |
41 | } |
42 | |
43 | sk = ctx->sk; |
44 | if (!sk) |
45 | return 1; |
46 | |
47 | next_dump = bpf_sk_storage_get(&bpf_next_dump, sk, 0, |
48 | BPF_SK_STORAGE_GET_F_CREATE); |
49 | if (!next_dump) |
50 | return 1; |
51 | |
52 | now = bpf_ktime_get_ns(); |
53 | if (now < *next_dump) |
54 | return 1; |
55 | |
56 | tcp_sk = bpf_tcp_sock(sk); |
57 | if (!tcp_sk) |
58 | return 1; |
59 | |
60 | *next_dump = now + INTERVAL; |
61 | |
62 | bpf_printk("dsack_dups=%u delivered=%u\n" , |
63 | tcp_sk->dsack_dups, tcp_sk->delivered); |
64 | bpf_printk("delivered_ce=%u icsk_retransmits=%u\n" , |
65 | tcp_sk->delivered_ce, tcp_sk->icsk_retransmits); |
66 | |
67 | return 1; |
68 | } |
69 | |