Skip to content

Commit

Permalink
Add tcp window clamp example
Browse files Browse the repository at this point in the history
Well behaving download from the linked report:

```
ivan@vm:~$ curl -o /dev/null http://localhost:4444
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 3616M    0 3616M    0     0  33.7M      0 --:--:--  0:01:47 --:--:-- 44.7M
```

When it gets clamped:

```
ivan@vm:~$ curl -o /dev/null http://localhost:4444
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 4378M    0 4378M    0     0  30.3M      0 --:--:--  0:02:24 --:--:-- 9832k
```

The corresponding counter:

```
  # HELP ebpf_exporter_tcp_window_clamps_total Number of times that TCP window was clamped to a low value
  # TYPE ebpf_exporter_tcp_window_clamps_total counter
  ebpf_exporter_tcp_window_clamps_total 19668
```
  • Loading branch information
bobrik committed Nov 25, 2022
1 parent 7dbbd85 commit a66d87b
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 0 deletions.
71 changes: 71 additions & 0 deletions examples/tcp-window-clamps.bpf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#include <vmlinux.h>
#include <bpf/bpf_tracing.h>
#include <bpf/bpf_core_read.h>
#include "maps.bpf.h"

/* Minimum value for tp->rcv_ssthresh that is not considered a clamp */
#define MIN_CLAMP 32 * 1024

struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__uint(max_entries, 1);
__type(key, u32);
__type(value, u64);
} tcp_window_clamps_total SEC(".maps");

struct {
__uint(type, BPF_MAP_TYPE_LRU_HASH);
__uint(max_entries, 1024);
__type(key, u64);
__type(value, u64);
} tcp_rmem_schedule_enters SEC(".maps");

static int enter_key()
{
u64 pid = bpf_get_current_pid_tgid();
if (pid) {
return pid;
}

return bpf_get_smp_processor_id();
}

SEC("kprobe/tcp_try_rmem_schedule")
int BPF_KPROBE(tcp_try_rmem_schedule, struct sock *sk)
{
u64 key = enter_key();
u64 value = (u64) sk;

bpf_map_update_elem(&tcp_rmem_schedule_enters, &key, &value, BPF_NOEXIST);

return 0;
}

SEC("kretprobe/tcp_try_rmem_schedule")
int BPF_KRETPROBE(tcp_try_rmem_schedule_ret)
{
u32 rcv_ssthresh, zero = 0;
u64 key = enter_key(), *sk = bpf_map_lookup_elem(&tcp_rmem_schedule_enters, &key);
struct tcp_sock *tp;

if (!sk) {
return 0;
}

tp = (struct tcp_sock *) *sk;

if (!tp) {
return 0;
}

rcv_ssthresh = BPF_CORE_READ(tp, rcv_ssthresh);

if (rcv_ssthresh < MIN_CLAMP) {
increment_map(&tcp_window_clamps_total, &zero, 1);
}

bpf_map_delete_elem(&tcp_rmem_schedule_enters, &key);
return 0;
}

char LICENSE[] SEC("license") = "GPL";
8 changes: 8 additions & 0 deletions examples/tcp-window-clamps.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Linux memory management can overestimate memory pressure and punish well behaving
# TCP sockets with a window clamp. The clamp limits max throughput.
# See: https://lore.kernel.org/netdev/CABWYdi0G7cyNFbndM-ELTDAR3x4Ngm0AehEp5aP0tfNkXUE+Uw@mail.gmail.com/
metrics:
counters:
- name: tcp_window_clamps_total
help: Number of times that TCP window was clamped to a low value
labels: []

0 comments on commit a66d87b

Please sign in to comment.