Mengubah nilai TCP RTO di Linux

12

Saya ingin mengubah nilai TCP RTO (retransmission timeout) untuk koneksi, dan beberapa pembacaan yang saya lakukan menunjukkan bahwa saya bisa melakukan ini, tetapi tidak mengungkapkan di mana dan bagaimana mengubahnya.

Saya telah melihat /proc/sys/net/ipv4variabel, tetapi tidak ada variabel yang terkait dengan RTO. Saya akan sangat menghargai jika seseorang dapat memberi tahu saya cara mengubah nilai ini.

obiigbe91
sumber
Ini tidak berhasil untuk saya. Paling tidak termasuk 'ms' dengan waktu rto memberi saya kesalahan! Saya memang mendapatkan perintah untuk bekerja, tetapi ss -i mengatakan sebaliknya. Selain itu, 2 sysctl vars tidak ada. Saya menjalankan kernel 4.4
Mark Seger
Saya mencoba distro yang lebih baru dan berhasil melakukannya ip route replace- sepertinya ip routesintaks telah sedikit berubah. Saya berhasil membuat modifikasi. Sekadar diketahui, Anda harus mengomentari jawabannya, bukan pertanyaan jika Anda ingin mem-ping saya - pada dasarnya saya melihat ini secara tidak sengaja, semoga beruntung bahwa itu baru-baru ini :)
Adam C

Jawaban:

30

Alasan Anda tidak dapat mengubah RTO secara khusus adalah karena itu bukan nilai statis. Sebaliknya (kecuali untuk SYN awal, tentu saja) ini didasarkan pada RTT (Round Trip Time) untuk setiap koneksi. Sebenarnya, ini didasarkan pada versi RTT yang dihaluskan dan varian RTT dengan beberapa konstanta dilemparkan ke dalam campuran. Oleh karena itu, ini adalah nilai yang dinamis dan dihitung untuk setiap koneksi TCP, dan saya sangat merekomendasikan artikel ini yang lebih rinci tentang perhitungan dan RTO secara umum.

Juga relevan adalah RFC 6298 yang menyatakan (di antara banyak hal lainnya):

Setiap kali RTO dihitung, jika kurang dari 1 detik, maka RTO HARUS dibulatkan menjadi 1 detik.

Apakah kernel selalu mengatur RTO ke 1 detik? Nah, dengan Linux Anda dapat menunjukkan nilai RTO saat ini untuk koneksi terbuka Anda dengan menjalankan ss -iperintah:

State       Recv-Q Send-Q                                                  Local Address:Port     Peer Address:Port
ESTAB       0      0                                                           10.0.2.15:52861   216.58.219.46:http
     cubic rto:204 rtt:4/2 cwnd:10 send 29.2Mbps rcv_space:14600
ESTAB       0      0                                                           10.0.2.15:ssh          10.0.2.2:52586
     cubic rto:201 rtt:1.5/0.75 ato:40 cwnd:10 send 77.9Mbps rcv_space:14600
ESTAB       0      0                                                           10.0.2.15:52864   216.58.219.46:http
     cubic rto:204 rtt:4.5/4.5 cwnd:10 send 26.0Mbps rcv_space:14600

Di atas adalah output dari VM yang saya masuki dengan SSH dan memiliki beberapa koneksi terbuka ke google.com. Seperti yang Anda lihat, RTO sebenarnya diatur ke 200-ish (milidetik). Anda akan mencatat bahwa tidak dibulatkan ke nilai 1 detik dari RFC, dan Anda mungkin juga berpikir bahwa itu agak tinggi. Itu karena ada batas minimum min (200 milidetik) dan maks (120 detik) ketika datang ke RTO untuk Linux (ada penjelasan bagus tentang ini dalam artikel yang saya tautkan di atas).

Jadi, Anda tidak dapat mengubah nilai RTO secara langsung, tetapi untuk jaringan lossy (seperti nirkabel) Anda dapat mencoba mengubah-ubah F-RTO (ini mungkin sudah diaktifkan tergantung pada distro Anda). Sebenarnya ada dua opsi terkait yang terkait dengan F-RTO yang dapat Anda atur (ringkasan bagus di sini ):

net.ipv4.tcp_frto
net.ipv4.tcp_frto_response

Bergantung pada apa yang Anda coba optimalkan, ini mungkin bermanfaat atau tidak.

EDIT: menindaklanjuti kemampuan untuk mengubah nilai rto_min / max untuk TCP dari komentar.

Anda tidak dapat mengubah RTO minimum global untuk TCP (selain itu, Anda dapat melakukannya untuk SCTP - yang diekspos dalam sysctl), tetapi kabar baiknya adalah Anda dapat mengubah nilai minimum RTO pada per-rute dasar. Ini tabel routing saya di CentOS VM saya:

ip route
10.0.2.0/24 dev eth0  proto kernel  scope link  src 10.0.2.15 
169.254.0.0/16 dev eth0  scope link  metric 1002 
default via 10.0.2.2 dev eth0

Saya dapat mengubah nilai rto_min pada rute default sebagai berikut:

ip route change default via 10.0.2.2 dev eth0 rto_min 5ms

Dan sekarang, tabel perutean saya terlihat seperti ini:

ip route
10.0.2.0/24 dev eth0  proto kernel  scope link  src 10.0.2.15 
169.254.0.0/16 dev eth0  scope link  metric 1002 
default via 10.0.2.2 dev eth0  rto_min lock 5ms

Akhirnya, mari kita mulai koneksi dan periksa ss -iuntuk melihat apakah ini telah dihormati:

ss -i
State       Recv-Q Send-Q                                               Local Address:Port                                                   Peer Address:Port   
ESTAB       0      0                                                        10.0.2.15:ssh                                                        10.0.2.2:50714   
     cubic rto:201 rtt:1.5/0.75 ato:40 cwnd:10 send 77.9Mbps rcv_space:14600
ESTAB       0      0                                                        10.0.2.15:39042                                                 216.58.216.14:http    
     cubic rto:15 rtt:5/2.5 cwnd:10 send 23.4Mbps rcv_space:14600

Keberhasilan! Rto pada koneksi HTTP (setelah perubahan) adalah 15ms, sedangkan koneksi SSH (sebelum perubahan) adalah 200+ seperti sebelumnya.

Saya sebenarnya menyukai pendekatan ini - ini memungkinkan Anda untuk mengatur nilai yang lebih rendah pada rute yang sesuai daripada secara global di mana mungkin mengacaukan lalu lintas lainnya. Demikian pula (lihat halaman manual ip ) Anda dapat men-tweak estimasi rtt awal dan rttvar awal untuk rute (digunakan saat menghitung RTO dinamis). Meskipun ini bukan solusi lengkap dalam hal tweaker, saya pikir sebagian besar bagian penting ada di sana. Anda tidak dapat mengubah pengaturan maks, tapi saya pikir itu tidak akan berguna secara umum dalam hal apa pun.

Adam C
sumber
Terima kasih @ Adam C untuk klarifikasi, tetapi Anda menyebutkan min (200 juta) dan maks (120sec), dapatkah saya mengubah semua ini (min atau maks)? jika ya, bagaimana? ...
obiigbe91
Saya percaya mereka adalah konstanta dalam kode, dan saya tidak mengetahui cara untuk mengaturnya secara dinamis tetapi akan menggali sedikit dan melihat karena saya menganggap mengubah kode dan mengkompilasi kernel Anda sendiri agak banyak :)
Adam C
Menemukan cara men-tweak rto_min dan menambahkannya serta beberapa hal terkait lainnya dalam jawabannya :)
Adam C
Mengapa tidak ada yang seperti itu rto_max? Bagaimana cara menetapkan batas waktu maksimum global?
est
Jika Anda menetapkan minimum (atau menerima default) dan kemudian mengubah jumlah coba lagi ( net.ipv4.tcp_retries1dan net.ipv4.tcp_retries2atau IIRC serupa) diperbolehkan, saya pikir Anda bisa mendapatkan setara dengan maksimum RTO.
Adam C