diff --git a/examples/unix-socket-backlog.bpf.c b/examples/unix-socket-backlog.bpf.c new file mode 100644 index 00000000..e407fb7c --- /dev/null +++ b/examples/unix-socket-backlog.bpf.c @@ -0,0 +1,76 @@ +#include +#include +#include +#include "bits.bpf.h" +#include "maps.bpf.h" + +// 17 buckets for backlog sizes, max range is 64k..128k +#define MAX_BUCKET_SLOT 17 + +// Address on which docker accepts connections +#define DOCKER_SOCK_ADDR_PATH "/var/run/docker.sock" + +// Keep in sync with static_map in the config +enum unix_addr { + DOCKER_SOCK_ADDR, + MAX_PATHS // Max number of paths to track +}; + +struct key_t { + enum unix_addr addr; + u64 bucket; +}; + +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, (MAX_BUCKET_SLOT + 2) * MAX_PATHS); + __type(key, struct key_t); + __type(value, u64); +} unix_socket_backlog SEC(".maps"); + +// https://elixir.bootlin.com/linux/v6.6-rc1/source/include/linux/skbuff.h#L2133 +static inline __u32 skb_queue_len(const struct sk_buff_head *list_) +{ + return list_->qlen; +} + +static int do_count(enum unix_addr addr, u64 backlog) +{ + struct key_t key = {}; + + key.addr = addr; + + if (backlog == 0) { + key.bucket = 0; + } else { + key.bucket = log2l(backlog) + 1; + } + + if (key.bucket > MAX_BUCKET_SLOT) { + key.bucket = MAX_BUCKET_SLOT; + } + + increment_map(&unix_socket_backlog, &key, 1); + + // No use incrementing by zero + if (backlog > 0) { + key.bucket = MAX_BUCKET_SLOT + 1; + increment_map(&unix_socket_backlog, &key, backlog); + } + + return 0; +} + +SEC("fexit/unix_find_other") +int BPF_PROG(unix_find_other, struct net *net, struct sockaddr_un *sunaddr, int addr_len, int type, struct sock *other) +{ + // Make sure to use clang-15, otherwise you might see: + // libbpf: failed to find BTF for extern 'memcmp': -2 + if (__builtin_memcmp(sunaddr->sun_path, DOCKER_SOCK_ADDR_PATH, sizeof(DOCKER_SOCK_ADDR_PATH)) == 0) { + return do_count(DOCKER_SOCK_ADDR, skb_queue_len(&other->sk_receive_queue)); + } + + return 0; +} + +char LICENSE[] SEC("license") = "GPL"; diff --git a/examples/unix-socket-backlog.yaml b/examples/unix-socket-backlog.yaml new file mode 100644 index 00000000..7e88cfdf --- /dev/null +++ b/examples/unix-socket-backlog.yaml @@ -0,0 +1,19 @@ +metrics: + histograms: + - name: unix_socket_backlog + help: Unix socket backlog size + bucket_type: exp2zero + bucket_min: 0 + bucket_max: 17 + labels: + - name: addr + size: 8 + decoders: + - name: uint + - name: static_map + static_map: + 0: /var/run/docker/metrics.sock + - name: bucket + size: 8 + decoders: + - name: uint