Bali, Indonesia
Insights

FIB Churn dan Mutex Contention: Dampak Route Flapping BGP pada Rtnetlink Subsystem Linux

Invalid Date
0:00
Pernahkah Anda mendapati sebuah node Anycast DNS tiba-tiba melaporkan lonjakan drastis pada metrik UDP query timeout, sementara throughput jaringan ingress terlihat berada di batas normal dan tidak ada anomali lonjakan QPS? Di layar monitoring, utilitas CPU melonjak ke 100%, tetapi metrik user space CPU tetap rendah—hampir seluruh siklus CPU terbakar di system time (sys) dan ksoftirqd. Masalah seperti ini kerap membingungkan tim SRE karena resolver DNS seperti BIND, Unbound, atau CoreDNS tampak 'sehat' namun tidak pernah menerima paket tersebut. Akar masalah dari degradasi misterius ini jarang bermula dari layer aplikasi DNS. Sebaliknya, pemicunya sering kali berada di lapisan routing BGP upstream: badai penarikan rute (route flapping) yang memicu FIB churn masif di dalam kernel Linux, mengunci subsistem rtnetlink, dan membakar alokasi waktu pemrosesan paket di level softirq.
Ketika sesi BGP berulang kali putus-nyambung atau mengalami fluktuasi akibat masalah propagasi rute dan circular glue records di internet publik, daemon BGP di server lokal (seperti FRR atau BIRD) akan bereaksi agresif. Daemon ini berkewajiban menyinkronkan status rute kernel dengan peer BGP melalui soket NETLINK_ROUTE. Hasilnya adalah rentetan ratusan ribu pesan RTM_DELROUTE dan RTM_NEWROUTE yang ditembakkan ke kernel dalam fraksi detik. Di dalam kernel Linux, Forwarding Information Base (FIB) IPv4 dan IPv6 diorganisasi menggunakan struktur data compressed trie (fib_trie). Setiap kali ada penambahan atau penghapusan rute, struktur trie ini harus di-rebalance dan node-node lama harus direclaim via RCU (Read-Copy Update). Masalah struktural muncul karena antarmuka mutasi rute tradisional diatur oleh lock global legendaris: rtnl_lock (Routing Netlink Mutex).
BASH
# Mendeteksi contention pada lock rtnetlink via perf
sudo perf top -s symbol | grep -E "rtnl_lock|fib_table|mutex_spin_on_owner"
Meskipun kernel modern telah memecah beberapa jalur lock agar lebih fine-grained (misalnya per-namespace fib lock), penarikan rute berulang dalam skala besar tetap memicu mutex contention yang brutal. Daemon BGP yang melakukan write() ke soket netlink akan saling mengunci antrean dengan proses kernel lain yang membutuhkan akses status interface atau routing, mengakibatkan context switching yang liar dan degradasi performa I/O secara vertikal.
DNS adalah protokol berbasis UDP yang stateless dan sangat sensitif terhadap latensi penjadwalan CPU. Ketika sebuah paket query DNS tiba di Network Interface Card (NIC), alur pemrosesannya bergantung sepenuhnya pada mekanisme interupsi kernel:
  1. NIC menerima frame ethernet dan menyimpannya di Ring Buffer, lalu memicu hardware interrupt (IRQ).
  2. CPU melayani IRQ dan menjadwalkan NET_RX_SOFTIRQ untuk pemrosesan paket asinkron.
  3. Kernel memanggil fib_lookup() untuk menentukan apakah paket ditujukan ke interface lokal (local delivery) atau harus di-forward.
Di sinilah petaka terjadi. Jika jutaan mutasi rute sedang berlangsung, cache rute (flow cache atau RCU hash table) terus-menerus diinvalir (cache invalidation storms). Setiap pemanggilan fib_lookup() terpaksa menelusuri ulang rantai trie yang sedang mengalami rebalancing. Latensi lookup yang normalnya diukur dalam skala sub-mikrodetik tiba-tiba melonjak berlipat ganda. Lebih parah lagi, anggaran kuota CPU untuk memproses softirq (yang diatur oleh parameter net.core.netdev_budget) cepat terkuras habis sebelum antrean buffer NIC sempat dikosongkan. Ketika thread ksoftirqd kehabisan jatah waktu CPU akibat berebut core dengan daemon BGP yang terkunci di sys space, paket-paket UDP DNS yang sudah antre di socket backlog tidak sempat disalin ke receive buffer (sk_rcvbuf) milik resolver. Paket-paket ini akhirnya di-drop secara senyap di level kernel sebelum menyentuh cgroups v2 atau layer aplikasi.
Untuk membangun infrastruktur edge yang tahan banting terhadap FIB churn, kita tidak bisa sekadar memperbesar ukuran buffer socket. Pendekatan reaktif seperti menaikkan rmem_max hanya menunda kejatuhan beberapa detik lebih lama saat badai rute berlangsung. Kita membutuhkan pemisahan tegas antara control plane (BGP) dan data plane (DNS forwarding). Langkah fundamental pertama adalah mengisolasi eksekusi BGP daemon ke CPU core khusus menggunakan CPU pinning (taskset atau isolasi cpuset). Dengan menjauhkan thread pemroses pesan BGP dari core yang bertugas melayani IRQ jaringan dan worker thread DNS, kita mencegah perebutan siklus CPU di level scheduler kernel. Langkah kedua adalah mengaktifkan fitur BGP Route Flap Damping (RFD) secara konservatif pada konfigurasi daemon routing Anda. RFD memberikan penalti pada rute yang berfluktuasi terlalu sering dan menahan injeksinya ke FIB lokal hingga rute tersebut stabil kembali selama interval tertentu (misalnya suppress threshold).
YAML
# Contoh parameter flap damping pada FRR (frr.conf)
router bgp 65001
 bgp dampening 15 750 3000 60
Formula penalti RFD menaikkan skor penalti setiap kali terjadi fluktuasi rute; jika skor penalti melampaui ambang batas suppress (misal 3000), rute tersebut ditahan dan tidak diteruskan ke rtnetlink. Skor ini meluruh secara eksponensial berdasarkan waktu paruh (half-life), mencegah badai RTM_DELROUTE menghantam kernel secara berulang saat terjadi osilasi rute di upstream transit.
Untuk arsitektur modern skala besar, ketergantungan DNS resolver pada routing table default Linux adalah sebuah titik kerapuhan (single point of failure). Pertimbangkan dua pendekatan mitigasi struktural berikut:
  • Network Namespace / VRF Isolation: Jalankan sesi BGP dan proses routing di dalam Linux Network Namespace terpisah atau Virtual Routing and Forwarding (VRF). Dengan mengisolasi FIB BGP dari interface loopback Anycast lokal tempat DNS resolver mendengarkan query, contention pada kunci FIB global dapat dikurangi secara signifikan.
  • eBPF / XDP Early Demuxing: Manfaatkan program eBPF di layer XDP (eXpress Data Path) langsung pada driver NIC. Paket UDP dengan port tujuan 53 dapat langsung dialihkan (redirect) ke soket AF_XDP milik DNS resolver tanpa harus melewati stack routing jaringan kernel (ip_route_input_noref dan fib_lookup). Dengan cara ini, query DNS sepenuhnya kebal terhadap FIB churn dan mutex contention di subsistem rtnetlink.
Menjaga ketersediaan edge resolver bukan hanya tentang kapasitas server menahan QPS tinggi, melainkan tentang bagaimana kernel Anda bertahan di saat protokol routing internet di luar kendali Anda mulai mengalami degradasi.