📚 TCP Congestion Control — Slow Start, AIMD, dan BBR
Sesi: 05:00 Deep Learning · Kategori: Networking · Level: intermediate–advanced
🎯 Tujuan Belajar
Setelah sesi ini kamu harus bisa:
- Menjelaskan kenapa TCP butuh congestion control (bukan cuma flow control).
- Menelusuri alur state machine: slow start → congestion avoidance → fast retransmit/recovery.
- Menuliskan dan memahami matematika AIMD beserta konsekuensi "TCP friendliness".
- Membedakan kelas algoritma loss-based (Reno/CUBIC) vs model-based/delay & bandwidth (BBR) dan tahu kapan masing-masing gagal.
- Mengerti kenapa buffer besar merusak TCP (bufferbloat) dan apa yang dilakukan BBR soal itu.
🧠 Penjelasan Inti
Masalah apa yang diselesaikan?
TCP punya dua mekanisme yang sering tertukar:
| Mekanisme | Yang dikontrol | Tujuan | Di mana |
|---|---|---|---|
| Flow control | Receiver | Jangan membanjiri buffer penerima | rwnd (receive window) di header TCP |
| Congestion control | Network | Jangan membanjiri bottleneck link / router | cwnd (congestion window), state di sender saja |
Masalahnya: sender tidak punya informasi langsung tentang kapasitas jaringan. Router tidak memberi tahu "saya penuh". Satu-satunya sinyal murah yang tersedia di internet klasik adalah packet loss — dan loss itu ambigu: bisa karena kongesti, bisa karena error fisik.
Ini inti TCP congestion control: sender menginferensi kondisi jaringan yang tak terlihat hanya dari ACK yang kembali dan paket yang hilang. Ini disebut distributed, implicit feedback control loop.
Konsekuensi arsitektural: kontrol dilakukan end-to-end di ujung, tanpa bantuan router. Itu sebabnya TCP bisa bertahan 40+ tahun tanpa perubahan router. Trade-off: konvergensinya lambat dan tidak akurat.
Definisi operasional
cwnd = jumlah byte yang boleh "in flight" (terkirim tapi belum di-ACK). Effective window = min(cwnd, rwnd). Throughput teoretis ≈ cwnd / RTT. Kalau cwnd = BDP (bandwidth-delay product), pipa penuh.
BDP = bandwidth × RTT. Contoh: 100 Mbps × 100 ms = 12.5 Mbit… tunggu, hitung: 100e6 × 0.1 = 1e7 bit = 1.25 MB = ~12.5 Mbit? No — 100 Mbps × 0.1 s = 10 Mbit = 1.25 MB. Ini angka penting: ini jumlah data yang harus in-flight untuk mengisi pipa. Kalau cwnd < BDP, kamu tidak bisa mencapai link speed berapa pun RTT-nya.
⚙️ Cara Kerjanya
1. Slow Start (SS)
Mulai dari cwnd = 1 MSS (~1460 byte). Setiap ACK yang meng-ACK data baru → cwnd += 1 MSS. Efeknya eksponensial per RTT: 1, 2, 4, 8, 16… doubling per RTT.
Kenapa eksponensial? Karena sender sama sekali tidak tahu kapasitas jaringan — exponensial adalah cara tercepat "memetakan" kapasitas tanpa asumsi. Namanya "slow start" karena titik awalnya kecil, bukan karena lambat (ini miskonsepsi umum, lihat bawah).
Slow start berhenti saat cwnd >= ssthresh (slow start threshold). ssthresh awal biasanya besar (atau tak terhingga pada implementasi modern), lalu diperkecil saat loss terdeteksi. Saat pertama kali loss, ssthresh = cwnd/2.
2. Congestion Avoidance (CA) — AIMD
Setelah melewati ssthresh, pertumbuhan jadi linear: cwnd += 1 MSS per RTT (dalam praktik: cwnd += MSS*MSS/cwnd per ACK, sehingga agregat ≈ 1 MSS per RTT).
- Additive Increase: +1 MSS per RTT selama tidak ada loss.
- Multiplicative Decrease: saat loss,
cwnd = cwnd/2.
AIMD menghasilkan pola sawtooth: naik linear, jatuh setengah, naik lagi. Properti formalnya (Chiu & Jain, 1989): AIMD adalah skema yang konvergen secara global — dua AIMD flow bersaing akan bertemu di titik yang menyeimbangkan (bandwidth split merata), sedangkan AIAD/MIMD/MIAD tidak.
Bukti sketch Chiu-Jain: plot cwnd_A vs cwnd_B. AI = garis naik; MD = garis bagi-separuh menuju titik (0,0). Sistem bergerak zig-zag menuju garis cwnd_A = cwnd_B dan konvergen. Ini sebabnya AIMD menang, bukan karena optimal — karena stabil.
3. Deteksi loss & respons (Reno)
| Sinyal | Arti | Aksi |
|---|---|---|
| 3 duplicate ACK | Satu paket hilang, paket berikutnya sampai → jaringan masih bisa mengalir | Fast retransmit paket hilang, lalu Fast Recovery: ssthresh=cwnd/2, cwnd=ssthresh+3 |
| RTO (timeout) | Serius — bisa berarti kongesti parah | ssthresh=cwnd/2, cwnd=1, kembali ke slow start |
Fast recovery menghindari penalti ke cwnd=1 saat loss ringan terdeteksi cepat. Ini yang membedakan Reno (1990) dari Tahoe (yang selalu reset ke 1).
4. Evolusi: Reno → NewReno → SACK → CUBIC
- NewReno: tambal retransmit multi-loss tanpa fallback RTO.
- SACK: receiver melaporkan blok mana yang sampai → sender retransmit hanya yang hilang.
- CUBIC (default Linux sejak 2.6.19, 2006): ganti pertumbuhan linear dengan fungsi kubik terhadap waktu sejak loss terakhir:
W(t) = C(t-K)³ + Wmax. Keuntungan: tumbuh agresif saat jauh di bawah titik loss terakhir, melambat saat mendekatiWmax(plateau stabil), dan tidak bergantung pada RTT (RTT-fairness — Reno tidak adil karena flow dengan RTT kecil tumbuh lebih cepat).
5. BBR (Google, 2016) — paradigm shift
Semua di atas adalah loss-based: menganggap loss = kongesti. Ini salah di jaringan ber-buffer besar (bufferbloat): buffer menyerap data, RTT naik, tapi tidak ada loss → sender terus naik → queue makin panjang → latency ratusan ms. Juga salah di link dengan loss acak (WiFi/5G) → TCP turun cwnd tanpa alasan.
BBR (Bottleneck Bandwidth and Round-trip propagation time) mengubah model:
- Kirim pada kecepatan = estimate bottleneck bandwidth, dengan jumlah in-flight = BDP (bukan sebesar mungkin sampai loss).
- Secara periodik (tiap ~10s) probe bandwidth lebih tinggi; kalau RTT naik tanpa kenaikan throughput → lewat bottleneck, berhenti sebelum loss terjadi.
- Setiap fase (windowed probe, ~8 RTT) juga probe RTT minimum untuk mengukur queue.
Hasil (paper Google: Cardwell et al., "BBR: Congestion-Based Congestion Control", ACM Queue 2016): throughput jauh lebih tinggi pada loss sedang, dan RTT turun drastis (mis. dari 2000+ ms → puluhan ms) di YouTube. BBRv2/v3 (2019+) menambahkan respons ke loss dan ECN untuk fairness terhadap CUBIC dan mengekang agresi saat bersaing dengan loss-based flow.
💡 Contoh / Analogi
Analogi AIMD — water tap. Kamu tidak tahu seberapa besar pipa di ujung selang. Kamu buka keran sedikit-sedikit; aliran naik terus. Saat air tumpah (loss) kamu balik ke setengah. Buka lagi sedikit-sedikit. Kamu selalu berosilasi di sekitar batas — tidak pernah jauh di bawah (mangkas bandwidth) dan tidak lama di atas (tumpah).
Kenapa eksponensial di slow start. Awal koneksi, informasi = nol. Cara tercepat memetakan kapasitas = doubling: 10 RTT untuk naik dari 1 ke 1024 MSS. Kalau linear, butuh 1024 RTT.
Bufferbloat nyata. Router pada link konsumen jam 8 malam: buffer 2 MB, jitter RTT naik dari 20 ms ke 1500 ms, tapi nol loss. Reno sama sekali tidak tahu ada masalah — ia tetap menaikkan cwnd sampai loss. Hasil: video call patah-patah meski diukur "bandwidth masih cukup". BBR mendeteksi kenaikan RTT dan berhenti naik sebelum titik itu.
Contoh numerik BDP. Link 1 Gbps, RTT 100 ms. BDP = 1e9 × 0.1 = 1e8 bit = 12.5 MB. Untuk mencapai 1 Gbps, cwnd harus ~12.5 MB. Slow start butuh ~14 RTT doubling (2^14 × 1460 ≈ 24 MB). Kalau RTO atau ssthresh kecil, transfer file besar tidak akan pernah "panas" sebelum selesai — ini masalah bandwidth-delay tinggi (satelit, long-haul), dan kenapa parameter initcwnd Linux dinaikkan (10 MSS, RFC 6928) dari 4 sebelumnya.
⚠️ Miskonsepsi Umum
- "Slow start itu lambat." Salah. Pertumbuhan eksponensial = fase tercepat. Namanya "slow" karena start rendah. Fase terlambat justru di congestion avoidance (linear).
- "Congestion control = flow control." Beda. Flow control mencegah receiver kewalahan (
rwnd); congestion control mencegah jaringan kewalahan (cwnd). Window efektif =min. - "Loss selalu berarti kongesti." Di WiFi/mobile, loss bisa bit-error acak. Tetapi TCP klasik tetap memotong
cwnd→ performa turun tanpa alasan valid. Motivasi utama BBR. - "cwnd di header TCP." Tidak.
cwndmurni state internal sender, tidak pernah masuk header. Header punyarwnd. Ini penting: router tidak tahucwnd, itulah kenapa kontrol tetap end-to-end. - "AIMD konvergen karena adil." Tidak — AIMD adil karena konvergen. Adil bukan tujuan, tapi hasil samping dari properti stabilitas. Ini yang tidak intuitif.
- "TCP habis-habisan pakai bandwidth." Justru sebaliknya: karena MD saat loss, TCP flow tipikal rata-rata hanya ~75% dari kapasitas puncaknya. Itu "harga" stabilitas.
⚖️ Trade-off / Limitasi
| Aspek | Loss-based (Reno/CUBIC) | Model-based (BBR) |
|---|---|---|
| Sinyal utama | Packet loss | RTT + delivery rate |
| Kelebihan | Sudah sangat telepas, fair antar flow global, low overhead | Latency rendah, throughput tinggi di buffer besar, toleran loss acak |
| Kelemahan | Bufferbloat, tidak tahan loss acak, RTT-unfair (Reno) | Agresif vs CUBIC di shared bottleneck; fairness belum sekuat loss-based |
| Fairness | Baik (properti AIMD) | BBRv1 kontroversial: bisa "mencuri" bandwidth dari CUBIC |
| Kompleksitas | Rendah | Tinggi (state machine probing) |
Masalah yang belum tuntas / area riset:
- Fairness BBRv1. Dikritik (Hock et al., 2017, "Experimental evaluation of BBR congestion control") karena memonopoli buffer di bottleneck bersama. BBRv2/v3 menambahkan cap dan respons loss. Per 2026, sudah deploy luas (Google, Cloudflare), tapi belum setara "ekosistem 30 tahun" CUBIC.
- ECN & L4S (Low Latency, Low Loss, Scalable throughput). Arah IETF sekarang: bukan loss, bukan delay — tapi ECN marker dari router sebagai sinyal kongesti eksplisit. L4S (RFC 9330, 2023) + DCTCP/Coupled CCA: jaminan latency rendah sambil throughput tinggi. Ini belum deploy global.
- QUIC/HTTP3 punya congestion control sendiri (sendiri, di userspace). BBR/CUBIC tersedia sebagai opsi; initcwnd lebih besar, tapi esensi AIMD/loss-based tetap.
Catatan verifikasi: angka YouTube BBR (RTT turun dari >2000 ms) berasal dari blog Google 2016 dan paper ACM Queue; saya tidak menemukan re-publikasi peer-reviewed independen yang mereplikasi angka persis itu — perlakukan sebagai klaim vendor yang terdokumentasi, bukan hasil replikasi netral. Detail per RFC 9438 adalah referensi paling akurat untuk CUBIC per spec.
🛠️ Latihan Praktis
- Cek algoritma TCP aktif di mesin kamu:
bash sysctl net.ipv4.tcp_congestion_control sysctl net.ipv4.tcp_available_congestion_control # ganti (butuh root) # sysctl -w net.ipv4.tcp_congestion_control=bbr - Amati sawtooth:
ss -tinsaat download besar. Cari fieldcwnd:danrtt:— lihatcwndnaik linear lalu turun setengah. - Simulasi: pakai
tc+netemuntuk bikin RTT buatan dan loss acak, lalu bandingkaniperf3dengan CUBIC vs BBR pada loss 1%. BBR harus jauh lebih tangguh. - Baca:
sysctl net.ipv4.tcp_slow_start_after_idle— apa pengaruh mematikan fitur ini pada koneksi idle lama?
✅ Cek Pemahaman
- Kalau
ssthreshdi-set ke 100 MSS dancwndsaat ini 40 MSS, apakah koneksi sedang di slow start atau congestion avoidance? Pada ACK berikutnya, berapacwnd? - Dua flow CUBIC dan satu flow BBR berbagi bottleneck 100 Mbps. Secara kualitatif, siapa yang cenderung menang dan mengapa? Bagaimana BBRv2 memperbaiki ini?
- Kenapa AIMD (bukan MIMD) menghasilkan alokasi bandwidth yang adil? Jelaskan lewat sifat geometris dari garis AI dan MD di ruang
cwnd_A × cwnd_B.
🔑 Poin Kunci
- TCP congestion control = kontrol loop tertutup terdistribusi dengan feedback implisit (loss/RTT), tanpa bantuan router.
- Slow start = doubling (memetakan kapasitas), CA = AIMD linear (stabilitas).
- AIMD menang bukan karena optimal, tapi karena konvergen dan stabil secara global (Chiu-Jain).
- Loss-based (Reno/CUBIC) cepat tapi buta terhadap bufferbloat dan loss acak. Kelemahan fundamental, bukan bug.
- BBR mengubah sinyal dari loss → RTT + delivery rate, mengincar BDP, hasilnya latency rendah + throughput tinggi; trade-off-nya fairness.
- Arah masa depan: ECN eksplisit (L4S/DCTCP) — sinyal kongesti dari router, bukan tebakan dari ujung.
➡️ Eksplorasi Lanjut
L4S & DCTCP: Explicit Congestion Notification sebagai sinyal kongesti — bagaimana router menandai paket (bukan membuang) saat queue mendekati penuh, dan bagaimana sender merespons fraksi mark sebagai sinyal kongesti kontinu alih-alih biner. Memakai model kontrol yang jauh lebih baik daripada AIMD dan mendasari janji latency rendah untuk aplikasi real-time.