← semua materi
05:00 Arsitektur · 15 Oct 2026 · 22:01

📚 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:

  1. Menjelaskan kenapa TCP butuh congestion control (bukan cuma flow control).
  2. Menelusuri alur state machine: slow start → congestion avoidance → fast retransmit/recovery.
  3. Menuliskan dan memahami matematika AIMD beserta konsekuensi "TCP friendliness".
  4. Membedakan kelas algoritma loss-based (Reno/CUBIC) vs model-based/delay & bandwidth (BBR) dan tahu kapan masing-masing gagal.
  5. 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).

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

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:

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

  1. "Slow start itu lambat." Salah. Pertumbuhan eksponensial = fase tercepat. Namanya "slow" karena start rendah. Fase terlambat justru di congestion avoidance (linear).
  2. "Congestion control = flow control." Beda. Flow control mencegah receiver kewalahan (rwnd); congestion control mencegah jaringan kewalahan (cwnd). Window efektif = min.
  3. "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.
  4. "cwnd di header TCP." Tidak. cwnd murni state internal sender, tidak pernah masuk header. Header punya rwnd. Ini penting: router tidak tahu cwnd, itulah kenapa kontrol tetap end-to-end.
  5. "AIMD konvergen karena adil." Tidak — AIMD adil karena konvergen. Adil bukan tujuan, tapi hasil samping dari properti stabilitas. Ini yang tidak intuitif.
  6. "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:

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

  1. 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
  2. Amati sawtooth: ss -tin saat download besar. Cari field cwnd: dan rtt: — lihat cwnd naik linear lalu turun setengah.
  3. Simulasi: pakai tc + netem untuk bikin RTT buatan dan loss acak, lalu bandingkan iperf3 dengan CUBIC vs BBR pada loss 1%. BBR harus jauh lebih tangguh.
  4. Baca: sysctl net.ipv4.tcp_slow_start_after_idle — apa pengaruh mematikan fitur ini pada koneksi idle lama?

✅ Cek Pemahaman

  1. Kalau ssthresh di-set ke 100 MSS dan cwnd saat ini 40 MSS, apakah koneksi sedang di slow start atau congestion avoidance? Pada ACK berikutnya, berapa cwnd?
  2. Dua flow CUBIC dan satu flow BBR berbagi bottleneck 100 Mbps. Secara kualitatif, siapa yang cenderung menang dan mengapa? Bagaimana BBRv2 memperbaiki ini?
  3. 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


➡️ 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.