Cambiar el valor TCP RTO en Linux

12

Quiero alterar el valor TCP RTO (tiempo de espera de retransmisión) para una conexión, y algunas lecturas que he hecho sugieren que podría hacer esto, pero no revela dónde y cómo cambiarlo.

He mirado las /proc/sys/net/ipv4variables, pero ninguna de las variables está relacionada con RTO. Agradecería que alguien me dijera cómo alterar este valor.

obiigbe91
fuente
Esto no funciona para mi. Como mínimo, incluir 'ms' con el tiempo rto me da un error. Obtuve el comando para trabajar, pero ss -i dice lo contrario. Además, los 2 sysctl vars no existen. Estoy corriendo en un kernel 4.4
Mark Seger
Probé una distribución más reciente y tuve éxito en su ip route replacelugar, parece que la ip routesintaxis ha cambiado un poco. Sin embargo, pude hacer la modificación con éxito. Solo para tener en cuenta, deberías comentar la respuesta, no la pregunta si quieres enviarme un ping: básicamente vi esto por accidente, pura suerte de que fuera reciente :)
Adam C

Respuestas:

30

La razón por la que no puede modificar el RTO específicamente es porque no es un valor estático. En cambio (a excepción del SYN inicial, naturalmente) se basa en el RTT (Tiempo de ida y vuelta) para cada conexión. En realidad, se basa en una versión suavizada de RTT y la variación de RTT con algunas constantes agregadas a la mezcla. Por lo tanto, es un valor dinámico y calculado para cada conexión TCP, y recomiendo este artículo que detalla más el cálculo y el RTO en general.

También es relevante el RFC 6298 que establece (entre muchas otras cosas):

Siempre que se calcule RTO, si es menos de 1 segundo, entonces el RTO DEBE redondearse a 1 segundo.

¿El núcleo siempre establece RTO en 1 segundo? Bueno, con Linux puede mostrar los valores actuales de RTO para sus conexiones abiertas ejecutando el ss -icomando:

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

Lo anterior es el resultado de una VM en la que he iniciado sesión con SSH y tiene un par de conexiones abiertas a google.com. Como puede ver, el RTO está configurado en 200 ish (milisegundos). Notará que no se redondea al valor de 1 segundo del RFC, y también puede pensar que es un poco alto. Esto se debe a que hay límites mínimos (200 milisegundos) y máximos (120 segundos) en juego cuando se trata de RTO para Linux (hay una gran explicación de esto en el artículo que vinculé anteriormente).

Por lo tanto, no puede alterar el valor RTO directamente, pero para redes con pérdida (como la inalámbrica) puede intentar ajustar F-RTO (esto puede estar habilitado dependiendo de su distribución). En realidad, hay dos opciones relacionadas relacionadas con F-RTO que puede ajustar (buen resumen aquí ):

net.ipv4.tcp_frto
net.ipv4.tcp_frto_response

Dependiendo de lo que intente optimizar, estos pueden ser útiles o no.

EDITAR: seguimiento de la capacidad de ajustar los valores rto_min / max para TCP a partir de los comentarios.

No puede cambiar el RTO mínimo global para TCP (como un aparte, puede hacerlo para SCTP, que están expuestos en sysctl), pero la buena noticia es que puede ajustar el valor mínimo del RTO en una ruta base. Aquí está mi tabla de enrutamiento en mi VM 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

Puedo cambiar el valor de rto_min en la ruta predeterminada de la siguiente manera:

ip route change default via 10.0.2.2 dev eth0 rto_min 5ms

Y ahora, mi tabla de enrutamiento se ve así:

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

Finalmente, iniciemos una conexión y verifiquemos ss -isi esto se ha respetado:

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

¡Éxito! El rto en la conexión HTTP (después del cambio) es de 15 ms, mientras que la conexión SSH (antes del cambio) es más de 200 como antes.

En realidad, me gusta este enfoque: le permite establecer el valor más bajo en las rutas apropiadas en lugar de globalmente, donde podría arruinar otro tráfico. De manera similar (vea la página de manual de ip ) puede ajustar la estimación de rtt inicial y la rttvar inicial para la ruta (utilizada al calcular el RTO dinámico). Si bien no es una solución completa en términos de ajustes, creo que la mayoría de las piezas importantes están ahí. No puede ajustar la configuración máxima, pero creo que, en cualquier caso, no será tan útil en general.

Adam C
fuente
Gracias @ Adam C por la aclaración, pero mencionaste el mínimo (200 mili) y el máximo (120 segundos), ¿puedo cambiar alguno de estos (mínimo o máximo)? en caso afirmativo, ¿cómo? ...
obiigbe91
Creo que son constantes en el código, y no conozco una forma de configurarlos dinámicamente, pero cavaré un poco y veré, ya que supongo que alterar el código y compilar su propio núcleo es un poco demasiado :)
Adam C
Descubrí cómo ajustar rto_min y lo agregué y un par de otras cosas relacionadas en la respuesta :)
Adam C
¿Por qué no hay nada parecido rto_max? ¿Cómo establecemos un tiempo de espera máximo global?
est
Si establece el mínimo (o acepta el valor predeterminado) y luego modifica el número de reintentos ( net.ipv4.tcp_retries1y / net.ipv4.tcp_retries2o IIRC similares) permitido, creo que puede llegar a un equivalente de un máximo RTO.
Adam C