Modern segment-routed service provider fabrics use Segment Routing over IPv6 (SRv6) End.B6-Encapsulation (Endpoint bound to an SRv6 Policy with IPv6 encapsulation) to enforce policy routing across transit autonomous systems. For cryptographic session integrity across control-plane BGP sessions, network engineers configure TCP Authentication Option (TCP-AO, RFC 5925). However, during asynchronous key rollover events, an asymmetric key mismatch combined with dynamic SRv6 segment list insertion can cause receive window clamping and SYN-ACK retransmissions tracked via tcpi_retrans_synack in Linux struct tcp_info. Investigating these transient drops requires low-overhead extended Berkeley Packet Filter (eBPF) tracing attached directly to kernel packet ingress and socket transmission paths. This guide explains how to author, compile, and execute an eBPF tracing workflow for SRv6 End.B6 drops in Linux.
Kernel Mechanics: TCP-AO and SRv6 End.B6 Encapsulation
In the Linux kernel network stack (version 6.x and newer), TCP-AO validates inbound segments against active cryptographic master keys held in struct tcp_ao_info. When an asymmetric key rollover is initiated, if the remote router uses a new key identifier before local storage is synchronised, SYN-ACK verification fails, triggering exponential backoff retransmissions reflected in tcpi_retrans_synack.
Concurrently, when packets transit through an SRv6 End.B6 behaviour (seg6_do_srh_encap), an outer IPv6 header and a Segment Routing Header (SRH) are appended to the payload. If the additional 24 to 56 bytes exceed the path MTU without proper TCP MSS clamping, the kernel silently discards the segment in seg6_output_core() or throttles the TCP receive window to prevent buffer overruns. Diagnosing these simultaneous crypto and encapsulation faults requires targeted eBPF kprobes.
Authoring the eBPF Telemetry Program
Save the following source code as trace_srv6_b6_ao.bpf.c:
#include <vmlinux.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_core_read.h>
#include <bpf/bpf_tracing.h>
char LICENSE[] SEC("license") = "Dual BSD/GPL";
struct drop_event {
__u32 saddr[4];
__u32 daddr[4];
__u16 sport;
__u16 dport;
__u8 retrans_synack;
__u32 snd_wnd;
__u32 rcv_wnd;
__u32 drop_reason;
};
struct {
__uint(type, BPF_MAP_TYPE_RINGBUF);
__uint(max_entries, 1 << 24);
} events SEC(".maps");
SEC("kprobe/tcp_rtx_synack")
int BPF_KPROBE(trace_tcp_rtx_synack, struct sock *sk, struct request_sock *req)
{
struct tcp_sock *tp = (struct tcp_sock *)sk;
struct drop_event *e;
e = bpf_ringbuf_reserve(&events, sizeof(*e), 0);
if (!e)
return 0;
e->sport = BPF_CORE_READ(sk, __sk_common.skc_num);
e->dport = BPF_CORE_READ(sk, __sk_common.skc_dport);
e->retrans_synack = BPF_CORE_READ(tp, total_retrans);
e->snd_wnd = BPF_CORE_READ(tp, snd_wnd);
e->rcv_wnd = BPF_CORE_READ(tp, rcv_wnd);
e->drop_reason = 301; // AO Key Rollover SYN-ACK drop
bpf_ringbuf_submit(e, 0);
return 0;
}
SEC("kprobe/seg6_do_srh_encap")
int BPF_KPROBE(trace_seg6_srh_encap, struct sk_buff *skb, struct ipv6_sr_hdr *osrh)
{
__u32 len = BPF_CORE_READ(skb, len);
if (len > 1460) {
struct drop_event *e = bpf_ringbuf_reserve(&events, sizeof(*e), 0);
if (e) {
e->drop_reason = 402; // SRv6 End.B6 MTU overflow
bpf_ringbuf_submit(e, 0);
}
}
return 0;
}
Compiling and Loading the eBPF Program
Compile the BPF object file using Clang and load it into the kernel via bpftool:
# Install build dependencies
sudo apt-get install -y clang llvm libbpf-dev linux-tools-common linux-tools-$(uname -r)
# Compile bytecode
clang -g -O2 -target bpf -D__TARGET_ARCH_x86 -c trace_srv6_b6_ao.bpf.c -o trace_srv6_b6_ao.bpf.o
# Load probe into kernel
bpftool prog load trace_srv6_b6_ao.bpf.o /sys/fs/bpf/trace_srv6_b6_ao type kprobe
Observing Kernel Ring Buffer Events
Consume live diagnostic events streamed from kernel space:
# Stream decoded JSON ringbuffer output
sudo bpftool map dump name events -j | jq '.[] | {sport: .value.sport, dport: .value.dport, retrans: .value.retrans_synack, reason: .value.drop_reason}'
Diagnostic Reference for SRv6 and TCP-AO Encapsulation
| Observed Drop Event | Underlying Cause | Targeted Remediation |
|---|---|---|
| Reason 301 (SYN-ACK Retrans) | Asymmetric TCP-AO key ID negotiation mismatch | Verify Key IDs in ip tcp_metrics and re-sync peer keyrings |
| Reason 402 (SRH Encap Drop) | Appended SRH header exceeds link MTU limit | Enable MSS clamping: iptables -t mangle -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1380 |
| Window clamp collapsing | Burst buffer exhaustion under deep segment routing headers | Tune net.ipv4.tcp_wmem and net.ipv4.tcp_rmem buffers |
This eBPF telemetry pattern empowers network architects to pinpoint and rectify encapsulation bottlenecks and crypto mismatches across carrier-grade Linux deployments.