Zmiana wartości TCP RTO w systemie Linux

12

Chcę zmienić wartość TCP RTO (limit czasu retransmisji) dla połączenia, a niektóre odczytane wyniki sugerują, że mógłbym to zrobić, ale nie ujawniają, gdzie i jak to zmienić.

Patrzyłem na /proc/sys/net/ipv4zmienne, ale żadna ze zmiennych nie jest związana z RTO. Byłbym wdzięczny, gdyby ktoś mógł mi powiedzieć, jak zmienić tę wartość.

obiigbe91
źródło
To mi nie działa. Przy minimalnym uwzględnieniu „ms” z czasem rto daje mi błąd! Mam polecenie do działania, ale ss -i mówi inaczej. Co więcej, 2 zmienne systemowe nie istnieją. Korzystam z jądra 4.4
Mark Seger
Wypróbowałem nowszą dystrybucję i odniosłem sukces ip route replace- wydaje się, że ip routeskładnia nieco się zmieniła. Udało mi się jednak dokonać modyfikacji. Dla przypomnienia, powinieneś skomentować odpowiedź, a nie pytanie, czy chcesz mnie pingować - Zasadniczo widziałem to przez przypadek, szczęście, że to było ostatnie :)
Adam C

Odpowiedzi:

30

Powodem, dla którego nie możesz zmienić RTO, jest to, że nie jest to wartość statyczna. Zamiast tego (oczywiście z wyjątkiem początkowej SYN), jest ona oparta na RTT (Round Trip Time) dla każdego połączenia. W rzeczywistości opiera się na wygładzonej wersji RTT i wariancji RTT z pewnymi stałymi wrzuconymi do miksu. Dlatego jest to dynamiczna, obliczona wartość dla każdego połączenia TCP i bardzo polecam ten artykuł, który szczegółowo omawia obliczenia i RTO.

Istotna jest również RFC 6298, która stwierdza (między innymi):

Za każdym razem, gdy RTO jest obliczane, jeśli jest ono krótsze niż 1 sekunda, wówczas RTO POWINNY być zaokrąglane w górę do 1 sekundy.

Czy wtedy jądro zawsze ustawia RTO na 1 sekundę? Cóż, w systemie Linux możesz wyświetlić bieżące wartości RTO dla otwartych połączeń, uruchamiając ss -ipolecenie:

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

Powyżej jest wyjście z maszyny wirtualnej, do której jestem zalogowany za pomocą SSH i ma kilka połączeń otwartych na google.com. Jak widać RTO jest ustawiony na 200-ish (milisekund). Zauważysz, że nie jest on zaokrąglany do 1 sekundy wartości z RFC, i możesz również pomyśleć, że jest trochę wysoki. To dlatego, że istnieją granice min (200 milisekund) i maksimum (120 sekund), jeśli chodzi o RTO dla Linuksa (jest to świetne wyjaśnienie w artykule, który podłączyłem powyżej).

Nie możesz więc bezpośrednio zmieniać wartości RTO, ale w przypadku sieci o dużej mocy (takich jak sieć bezprzewodowa) możesz spróbować ulepszyć F-RTO (może to być już włączone w zależności od dystrybucji). W rzeczywistości istnieją dwie powiązane opcje związane z F-RTO, które można dostosować (dobre podsumowanie tutaj ):

net.ipv4.tcp_frto
net.ipv4.tcp_frto_response

W zależności od tego, co próbujesz zoptymalizować, mogą one być przydatne lub nie.

EDYCJA: w następstwie możliwości dostosowania wartości rto_min / max dla TCP z komentarzy.

Nie możesz zmienić globalnego minimalnego RTO dla TCP (na marginesie, możesz to zrobić dla SCTP - są one widoczne w sysctl), ale dobrą wiadomością jest to, że możesz dostosować minimalną wartość RTO na trasie podstawa. Oto moja tabela routingu na mojej maszynie Wirtualnej CentOS:

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

Mogę zmienić wartość rto_min na domyślnej trasie w następujący sposób:

ip route change default via 10.0.2.2 dev eth0 rto_min 5ms

A teraz moja tabela routingu wygląda następująco:

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

Na koniec zainicjuj połączenie i sprawdź, ss -iczy zostało to przestrzegane:

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

Sukces! Rto na połączeniu HTTP (po zmianie) wynosi 15ms, podczas gdy połączenie SSH (przed zmianą) wynosi 200+ jak poprzednio.

Naprawdę podoba mi się to podejście - pozwala ustawić niższą wartość na odpowiednich trasach, a nie globalnie, gdzie może to zepsuć inny ruch. Podobnie (patrz strona podręcznika użytkownika ip ) możesz dostosować początkową wartość szacunkową rtt i początkową wartość rttvar dla trasy (używaną przy obliczaniu dynamicznego RTO). Chociaż nie jest to kompletne rozwiązanie w zakresie poprawiania, myślę, że większość ważnych elementów jest tam. Nie możesz zmienić maksymalnego ustawienia, ale myślę, że w ogóle nie będzie to tak przydatne.

Adam C.
źródło
Dzięki @Adam C za wyjaśnienie, ale wspomniałeś o min (200 mili) i max (120 s), czy mogę zmienić którekolwiek z nich (min. Lub maks.)? jeśli tak, to jak? ...
obiigbe91
Wierzę, że są stałe w kodzie i nie jestem świadomy sposobu, aby ustawić je dynamicznie, ale wykopię trochę i zobaczę, ponieważ zakładam, że zmieniam kod i kompiluję własne jądro jest trochę dużo :)
Adam C
Wymyśliłem, jak dostosować rto_min i dodałem go oraz kilka innych powiązanych rzeczy w odpowiedzi :)
Adam C
Dlaczego nie ma czegoś takiego rto_max? Jak ustawić globalny maksymalny limit czasu?
est
Jeśli ustawisz minimum (lub zaakceptujesz wartość domyślną), a następnie zmienisz dozwoloną liczbę ponownych prób ( net.ipv4.tcp_retries1i net.ipv4.tcp_retries2podobnych IIRC), myślę, że możesz uzyskać równowartość maksimum RTO.
Adam C