Skip to content

Instantly share code, notes, and snippets.

@qnnnnez
Last active March 31, 2025 16:55
Show Gist options
  • Save qnnnnez/a07fcf730889dfe564f13845256da804 to your computer and use it in GitHub Desktop.
Save qnnnnez/a07fcf730889dfe564f13845256da804 to your computer and use it in GitHub Desktop.
Portable ebpf for network packet size stats
#include <stdint.h>
#include <linux/bpf.h>
#include <linux/pkt_sched.h>
/* Misc helper macros. */
#define __section(x) __attribute__((section(x), used))
#define offsetof(x, y) __builtin_offsetof(x, y)
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
/* Object pinning settings */
#define PIN_NONE 0
#define PIN_OBJECT_NS 1
#define PIN_GLOBAL_NS 2
/* ELF map definition */
struct bpf_elf_map {
uint32_t type;
uint32_t size_key;
uint32_t size_value;
uint32_t max_elem;
uint32_t flags;
uint32_t id;
uint32_t pinning;
uint32_t inner_id;
uint32_t inner_idx;
};
/* Some used BPF function calls. */
static int (*bpf_skb_store_bytes)(void *ctx, int off, void *from,
int len, int flags) =
(void *) BPF_FUNC_skb_store_bytes;
static int (*bpf_l4_csum_replace)(void *ctx, int off, int from,
int to, int flags) =
(void *) BPF_FUNC_l4_csum_replace;
static void *(*bpf_map_lookup_elem)(void *map, void *key) =
(void *) BPF_FUNC_map_lookup_elem;
/* Some used BPF intrinsics. */
unsigned long long load_byte(void *skb, unsigned long long off)
asm ("llvm.bpf.load.byte");
unsigned long long load_half(void *skb, unsigned long long off)
asm ("llvm.bpf.load.half");
all: pktsize_hist_bpfel.o pktsize_hist_bpfeb.o
pktsize_hist.ll: pktsize_hist.c
clang -O2 -emit-llvm -g -c $^ -o $@
pktsize_hist_bpfel.o: pktsize_hist.ll
llc -march=bpfel -filetype=obj $^ -o $@
pktsize_hist_bpfeb.o: pktsize_hist.ll
llc -march=bpfeb -filetype=obj $^ -o $@
clean:
rm *.ll *.o
#include <stdint.h>
#include <linux/bpf.h>
#include <linux/if_ether.h>
#include <linux/pkt_cls.h>
#include <linux/swab.h>
#include <linux/pkt_sched.h>
#include <bpf/bpf_endian.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include <bpf/bpf_helpers.h>
#define BPF_MAP_ID_STATS 1 /* agent's map identifier */
#define BPF_MAX_ELEMS 1600
struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__uint(max_entries, BPF_MAX_ELEMS);
__type(key, uint32_t);
__type(value, uint64_t);
} map_pktsize_hist SEC(".maps");
SEC("classifier")
int tc_filter_def(struct __sk_buff *skb)
{
void *data_end = (void *)(unsigned long long)skb->data_end;
void *data = (void *)(unsigned long long)skb->data;
struct ethhdr *eth = data;
if (data + sizeof(struct ethhdr) > data_end)
return TC_ACT_SHOT;
unsigned payload_size = (unsigned)((uintptr_t)data_end - (uintptr_t)data);
uint64_t *size_count = bpf_map_lookup_elem(&map_pktsize_hist, &payload_size);
if (size_count != NULL) {
__sync_fetch_and_add(size_count, 1);
}
return TC_ACT_UNSPEC;
}
#!/bin/bash
# tc direct-action mode: https://qmonnet.github.io/whirl-offload/2020/04/11/tc-bpf-direct-action/
tc qdisc add dev eth0 clsact
tc filter add dev eth0 ingress bpf direct-action obj pktsize_hist_bpfel.o
tc filter add dev eth0 egress bpf direct-action obj pktsize_hist_bpfel.o
#!/bin/bash
bpftool map dump id 4
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment