Post

The One eBPF Command That Pinpoints Exactly Which Container Dropped Your Packet

The One eBPF Command That Pinpoints Exactly Which Container Dropped Your Packet: hands-on walkthrough with commands, expected outputs and a checklist.

The One eBPF Command That Pinpoints Exactly Which Container Dropped Your Packet

Intermittent 502 errors trigger an immediate blame game between engineering departments. The application team points to the network mesh dropping packets, while the infrastructure team blames poor application logic for rejecting connections. You need hard data from the kernel itself to prove exactly where the connection died.

TL;DR: By attaching an eBPF tracepoint to the kernel’s discard function, you can definitively pinpoint the exact container, cgroup, and process ID dropping TCP packets. Here is the single command you need to isolate infrastructure faults from application errors on Linux 6.8.

1
bpftool prog load tcp_drop.bpf.o /sys/fs/bpf/tcp_drop type tracepoint autoattach
Flag/Argument Function
prog load Instructs the tool to load a compiled program into the kernel.
tcp_drop.bpf.o The compiled ELF object containing your C-based tracepoint logic.
/sys/fs/bpf/tcp_drop The pinned mount path ensuring the program survives after the command exits.
type tracepoint Explicitly declares the kernel hook type, bypassing auto-detection errors.
autoattach Immediately binds the loaded program to the event specified in its ELF section.
1
2
3
4
5
6
7
8
# Variation 1: Attach specifically to an interface for XDP hardware drops
bpftool prog load tcp_drop.bpf.o /sys/fs/bpf/xdp_drop type xdp dev eth0

# Variation 2: Pin multiple programs from a single compiled object file
bpftool prog loadall tcp_drop.bpf.o /sys/fs/bpf/network_mon

# Variation 3: Verify the loaded programs attached to a specific interface
bpftool net show dev eth0

Warning: Do not use the autoattach flag if your infrastructure requires manual cgroup v2 linking; it forces a global tracepoint binding that will heavily flood logs on multi-tenant nodes.

1
<idle>-0       [002] d.s. 12345.678901: kfree_skb: skbaddr=0xffff888123456780 protocol=2048 location=0xffffffff81765432 reason=TCP_CSUM
View verbose BPF verifier log
1
2
3
4
5
6
bpftool prog load tcp_drop.bpf.o /sys/fs/bpf/tcp_drop type tracepoint autoattach -d
libbpf: loading object 'tcp_drop.bpf.o' from buffer
libbpf: elf: section(3) tracepoint/skb/kfree_skb, size 120, link 0, flags 6, type=1
libbpf: bpf_prog_load(tracepoint)
...
processed 15 insns (limit 1000000) max_states_per_insn 0 total_states 1 peak_states 1 mark_read 1

How Do You Prove Which Container Dropped A Packet?

You prove it by attaching an eBPF (Extended Berkeley Packet Filter) program to the kernel’s kfree_skb function, which captures exactly which cgroup and process name discarded the buffer. eBPF is a kernel technology that lets you run sandboxed programs directly inside the operating system without changing source code or loading modules. This approach decisively separates application timeouts from routing faults.

On Linux 6.8, the kfree_skb tracepoint exposes a standardized reason field mapping directly to specific drop codes, completely eliminating ambiguity. Default to tracing at this kernel socket buffer level before inspecting the mesh layer, as the kernel sees the exact truth before proxy sidecars intercept traffic. When developers blame the infrastructure team for a 502 error in Aicademy’s checkout service, this tracepoint settles the argument.

Use tracepoints over kprobes for network drops, as kernel function signatures frequently change between patch versions while tracepoints remain stable API contracts.

What Are The Prerequisites For Tracing?

You prepare the node by validating tooling versions, mounting the virtual file system, and confirming kernel configuration flags. These explicit steps prevent silent attachment failures by ensuring the operating system exposes the internal event buffers required by the verifier. Without them, your tracepoint immediately rejects the load request.

  • Verify bpftool is exactly version 7.3 or higher.
  • Mount the virtual BPF filesystem at /sys/fs/bpf.
  • Ensure CONFIG_DEBUG_INFO_BTF=y is active in your kernel configuration.

Many teams attempt to use sysctl logging before realizing its severe limitations under load.

1
2
- sysctl -w net.ipv4.conf.all.log_martians=1
+ bpftool prog load tcp_drop.bpf.o /sys/fs/bpf/tcp_drop type tracepoint autoattach

If you want to practice deploying these probes safely before hitting production, try Aicademy Labs. This initial deployment leverages constraints detailed in Building Custom eBPF Programs to Catch Production Anomalies Before They Escalate.

Always check /sys/kernel/debug/tracing/trace_pipe for raw string output if your user-space agent fails to poll the perf buffer correctly.

Why Not Just Use tcpdump?

Classic packet sniffers cannot see inside internal kernel drop logic. They only observe traffic successfully traversing the wire, completely missing packets discarded deep within the network stack due to resource limits. This leaves you totally blind to application-layer faults masquerading as external network timeouts.

Tool Processing Overhead Inspection Context Best For
tcpdump High Wire-level bytes Physical routing issues
bpftool Near-zero PID and cgroup Identifying dropping processes

If you are attempting to correlate these drops with performance delays, reference The bpftool perf Command That Reveals Hidden Network Latency in Kubernetes. We outlined why context-aware tooling obsoletes raw packet captures in eBPF Unleashed: The Future of Cloud-Native Observability.

flowchart TD
    A["Packet Arrival"] --> B{"App Accepts?"}
    B -->|"Yes"| C["Userspace (Aicademy App)"]
    B -->|"No"| D["kfree_skb (Kernel Drop)"]
    D -->|"Fires Event"| E["Probe Execution"]
    E -->|"Logs PID"| F["trace_pipe Output"]

Only run packet captures for physical wire-level faults; default to eBPF tools for anything involving application processing or container memory limits.

In the next part of the advanced-ebpf-observability series, we expose hidden TLS handshakes using uprobes.

Bottom Line

Stop relying on generic packet sniffers when troubleshooting internal application-level timeouts. Pinning a tracepoint directly to the kernel’s drop function isolates the exact process killing your connection. Deploy this compiled object immediately the next time a mesh proxy is falsely blamed for a dropped request.

FAQ

Why does bpftool require the BPF filesystem to be mounted?

The virtual filesystem allows compiled programs and maps to persist in memory after the loading process exits. Without it, the kernel destroys the probe immediately upon completion.

How do I read the output of an auto-attached tracepoint?

The kernel writes raw events to a shared debug buffer. You can read it directly by running cat /sys/kernel/debug/tracing/trace_pipe.

Does attaching to kfree_skb impact network throughput?

The programs run natively in kernel space with negligible overhead. However, logging a string format for every single dropped packet on a saturated 10Gbps link can introduce minor CPU usage.

How do I detach the program when finished?

Delete the pinned file using rm /sys/fs/bpf/tcp_drop. The kernel automatically unloads the program once all user-space references are cleared.

Part of the series: advanced-ebpf-observability

  1. The One eBPF Command That Pinpoints Exactly Which Container Dropped Your Packet (you are here)
  2. Are Your eBPF Tracers Actually Crushing Your CPU Performance?
  3. The eBPF Map Setting That Silently Exhausts Your Kernel Memory

Further Reading


🚀 Ready to get hands-on? Spin up an interactive AI or Kubernetes Sandbox at Aicademy Labs for free.

This post is licensed under CC BY 4.0 by the author.