การเปลี่ยนค่า TCP RTO ใน Linux


12

ฉันต้องการเปลี่ยนค่า TCP RTO (retransmission timeout)สำหรับการเชื่อมต่อและการอ่านบางอย่างที่ฉันทำเสร็จแล้วแสดงให้เห็นว่าฉันสามารถทำได้ แต่ไม่เปิดเผยที่และวิธีการเปลี่ยน

ฉันดู/proc/sys/net/ipv4ตัวแปรแล้ว แต่ไม่มีตัวแปรใดที่เกี่ยวข้องกับ RTO ฉันจะขอบคุณถ้ามีคนบอกฉันว่าจะแก้ไขค่านี้ได้อย่างไร


มันไม่ได้ผลสำหรับฉัน อย่างน้อยที่สุดรวมถึง 'ms' ด้วยเวลา rto ทำให้ฉันมีข้อผิดพลาด! ฉันได้รับคำสั่งให้ทำงาน แต่ ss -i พูดอย่างอื่น นอกจากนี้ยังไม่มี vars 2 sysctl ฉันทำงานบนเคอร์เนล 4.4
Mark Seger

ฉันลองใช้ distro ที่ใหม่กว่าและประสบความสำเร็จในการทำip route replaceแทน - ดูเหมือนว่าip routeไวยากรณ์มีการเปลี่ยนแปลงเล็กน้อย ฉันสามารถทำการปรับเปลี่ยนได้สำเร็จแม้ว่า เพียงเพื่อให้ทราบว่าคุณควรจะแสดงความคิดเห็นในคำตอบที่ไม่ได้เป็นคำถามถ้าคุณต้องการที่จะ ping ฉัน - ฉันเป็นพื้นเห็นนี้โดยบังเอิญโชคบริสุทธิ์ที่ผ่านมามันเป็น :)
อดัม C

คำตอบ:


30

เหตุผลที่คุณไม่สามารถเปลี่ยน RTO โดยเฉพาะได้ก็เพราะมันไม่ใช่ค่าคงที่ แทน (ยกเว้นสำหรับการเริ่มต้น SYN ตามธรรมชาติ) มันขึ้นอยู่กับ RTT (เวลาไปกลับ) สำหรับการเชื่อมต่อแต่ละครั้ง ที่จริงแล้วมันขึ้นอยู่กับรุ่น RTT ที่ราบรื่นและความแปรปรวน RTT ที่มีค่าคงที่บางตัวที่ถูกโยนลงไปในส่วนผสม ดังนั้นจึงเป็นค่าที่คำนวณได้แบบไดนามิกสำหรับการเชื่อมต่อ TCP แต่ละครั้งและฉันขอแนะนำบทความนี้ซึ่งมีรายละเอียดเพิ่มเติมเกี่ยวกับการคำนวณและ RTO โดยทั่วไป

มีความเกี่ยวข้องด้วยเช่นกันคือRFC 6298ซึ่งระบุ (ท่ามกลางสิ่งอื่น ๆ อีกมากมาย):

เมื่อใดก็ตามที่คำนวณ RTO หากน้อยกว่า 1 วินาที RTO SHOULD จะถูกปัดเศษเป็น 1 วินาที

เคอร์เนลตั้งค่า RTO เป็น 1 วินาทีเสมอหรือไม่ ด้วย Linux คุณสามารถแสดงค่า RTO ปัจจุบันสำหรับการเชื่อมต่อที่เปิดอยู่ของคุณโดยการรันss -iคำสั่ง:

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

ด้านบนคือผลลัพธ์จาก VM ที่ฉันเข้าสู่ระบบด้วย SSH และมีการเชื่อมต่อสองสามเปิดที่ google.com อย่างที่คุณเห็น RTO นั้นถูกตั้งค่าเป็น 200-ish (มิลลิวินาที) คุณจะทราบว่าจะไม่ถูกปัดเศษเป็นค่า 1 วินาทีจาก RFC และคุณอาจคิดว่ามันค่อนข้างสูง นั่นเป็นเพราะมีขั้นต่ำในการเล่น (200 มิลลิวินาที) และสูงสุด (120 วินาที) เมื่อพูดถึง RTO สำหรับ Linux (มีคำอธิบายที่ดีในบทความที่ฉันลิงก์ด้านบน)

ดังนั้นคุณไม่สามารถแก้ไขค่า RTO ได้โดยตรง แต่สำหรับเครือข่ายที่สูญเสีย (เช่นไร้สาย) คุณสามารถลองปรับแต่งF-RTO ได้ (อาจเปิดใช้งานแล้วขึ้นอยู่กับ distro ของคุณ) จริงๆแล้วมีสองตัวเลือกที่เกี่ยวข้องกับ F-RTO ที่คุณสามารถปรับแต่ง (สรุปดีที่นี่ ):

net.ipv4.tcp_frto
net.ipv4.tcp_frto_response

สิ่งเหล่านี้อาจมีประโยชน์หรือไม่ก็ได้ขึ้นอยู่กับสิ่งที่คุณพยายามปรับให้เหมาะสม

แก้ไข: ติดตามความสามารถในการปรับแต่งค่า rto_min / max สำหรับ TCP จากความคิดเห็น

คุณไม่สามารถเปลี่ยน RTO ขั้นต่ำทั่วโลกสำหรับ TCP (นอกเหนือไปจากนี้คุณสามารถทำได้สำหรับ SCTP - ที่แสดงเป็น sysctl) แต่ข่าวดีก็คือคุณสามารถปรับแต่งค่าต่ำสุดของ RTO บนเส้นทางต่อ รากฐาน นี่คือตารางเส้นทางของฉันบน CentOS VM ของฉัน:

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 บนเส้นทางเริ่มต้นดังนี้

ip route change default via 10.0.2.2 dev eth0 rto_min 5ms

และตอนนี้ตารางเส้นทางของฉันมีลักษณะดังนี้:

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

ในที่สุดเรามาเริ่มต้นการเชื่อมต่อและตรวจสอบss -iเพื่อดูว่ามีการเคารพ:

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

ที่ประสบความสำเร็จ! rto บนการเชื่อมต่อ HTTP (หลังการเปลี่ยนแปลง) คือ 15ms ในขณะที่การเชื่อมต่อ SSH (ก่อนการเปลี่ยนแปลง) คือ 200+ เหมือนก่อน

ฉันชอบวิธีนี้จริง ๆ - ช่วยให้คุณกำหนดค่าที่ต่ำกว่าในเส้นทางที่เหมาะสมมากกว่าในระดับโลก ในทำนองเดียวกัน (ดูที่หน้า man ip ) คุณสามารถปรับแต่ง rtt เริ่มต้นและ rttvar เริ่มต้นสำหรับเส้นทาง (ใช้เมื่อคำนวณ RTO แบบไดนามิก) แม้ว่ามันจะไม่ใช่วิธีแก้ปัญหาที่สมบูรณ์ในแง่ของการปรับแต่ง แต่ฉันคิดว่าสิ่งสำคัญส่วนใหญ่จะอยู่ที่นั่น คุณไม่สามารถปรับแต่งการตั้งค่าสูงสุด แต่ฉันคิดว่ามันจะไม่เป็นประโยชน์โดยทั่วไปในทุกกรณี


ขอบคุณ @Adam C สำหรับการชี้แจง แต่คุณพูดถึงนาที (200 milli) และสูงสุด (120sec) ฉันจะเปลี่ยนสิ่งเหล่านี้ (min หรือ max) ได้ไหม? ถ้าใช่เป็นอย่างไร ...
obiigbe91

ฉันเชื่อว่าพวกเขาเป็นค่าคงที่ในรหัสและฉันไม่ทราบวิธีการตั้งค่าแบบไดนามิก แต่จะขุดเล็กน้อยและดูเนื่องจากฉันถือว่าการแก้ไขรหัสและรวบรวมเคอร์เนลของคุณเองเป็นบิตมาก :)
Adam C

คิดออกวิธีการปรับแต่ง rto_min และเพิ่มความมันและคู่ของสิ่งอื่น ๆ ที่เกี่ยวข้องในคำตอบ :)
อดัม C

ทำไมไม่ได้มีอะไรที่เหมือนrto_max? เราจะตั้งค่าการหมดเวลาสูงสุดทั่วโลกได้อย่างไร
คือ

หากคุณตั้งค่าต่ำสุด (หรือยอมรับค่าเริ่มต้น) จากนั้นเปลี่ยนจำนวนครั้งในการลองใหม่ ( net.ipv4.tcp_retries1และnet.ipv4.tcp_retries2หรือ IIRC ที่คล้ายกัน) ที่ได้รับอนุญาตฉันคิดว่าคุณสามารถเข้าถึง RTO ได้สูงสุดเทียบเท่า
Adam C
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.