Изменение значения TCP RTO в Linux

12

Я хочу изменить значение TCP RTO (время ожидания повторной передачи) для соединения, и некоторые прочитанные мною чтения показывают, что я могу это сделать, но не показывают, где и как это изменить.

Я посмотрел на /proc/sys/net/ipv4переменные, но ни одна из переменных не связана с RTO. Буду признателен, если кто-нибудь подскажет, как изменить это значение.

obiigbe91
источник
Это не работает для меня. Как минимум, включая «мс» со временем rto, я получаю ошибку! Я заставил команду работать, но ss -i говорит иначе. Кроме того, 2 sysctl vars не существуют. Я работаю на ядре 4.4
Марк Сегер
Я попробовал более свежий дистрибутив, и ip route replaceвместо этого добился успеха - кажется, ip routeсинтаксис немного изменился. Я был в состоянии сделать модификацию успешно, хотя. Просто чтобы отметить, вы должны прокомментировать ответ, а не вопрос, если вы хотите пинговать меня - я в основном видел это случайно, просто удача, что это было недавно :)
Адам С

Ответы:

30

Причина, по которой вы не можете изменить RTO, заключается в том, что это не статическое значение. Вместо этого (за исключением первоначального SYN, естественно), он основан на RTT (Round Trip Time) для каждого соединения. На самом деле, он основан на сглаженной версии RTT и дисперсии RTT с некоторыми константами, добавленными в микс. Следовательно, это динамическое вычисляемое значение для каждого TCP-соединения, и я настоятельно рекомендую эту статью, в которой более подробно рассматриваются вычисления и RTO в целом.

Также актуальным является RFC 6298, в котором говорится (среди прочего):

Всякий раз, когда вычисляется RTO, если оно меньше 1 секунды, тогда RTO ДОЛЖНО быть округлено до 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

Выше приведен вывод с виртуальной машины, в которую я вошел с помощью SSH и которая имеет пару открытых соединений с google.com. Как вы можете видеть, RTO на самом деле установлен на 200 мкс (миллисекунд). Вы заметите, что значение не округлено до 1 секунды из RFC, и вы также можете подумать, что оно немного выше. Это связано с тем, что для RTO для Linux существуют минимальные (200 миллисекунды) и максимальные (120 секунд) границы (это прекрасно объясняется в статье, на которую я ссылался выше).

Таким образом, вы не можете изменить значение RTO напрямую, но для сетей с потерями (например, беспроводных) вы можете попробовать настроить F-RTO (это может быть уже включено в зависимости от вашего дистрибутива). На самом деле есть два связанных параметра, связанных с 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-соединения (после изменения) составляет 15 мс, тогда как SSH-соединение (до изменения) составляет 200+, как и раньше.

Мне действительно нравится этот подход - он позволяет вам установить более низкое значение на соответствующих маршрутах, а не глобально, где это может испортить другой трафик. Аналогично (см. Справочную страницу ip ) вы можете настроить начальную оценку rtt и начальную rttvar для маршрута (используется при расчете динамического RTO). Хотя это не полное решение с точки зрения настройки, я думаю, что большинство важных частей есть. Вы не можете настроить максимальную настройку, но я думаю, что в общем случае она не будет столь полезной.

Адам С
источник
Спасибо @Adam C за разъяснения, но вы упомянули минимальное (200 милли) и максимальное (120 секунд), могу ли я изменить что-либо из этого (минимальное или максимальное)? если да, то как? ...
obiigbe91
Я полагаю, что они являются константами в коде, и я не знаю, как установить их динамически, но немного покопаюсь и посмотрю, так как я предполагаю, что изменение кода и компиляция вашего собственного ядра - это очень много :)
Адам С.
Выяснил, как настроить rto_min и добавил его и пару других связанных вещей в ответ :)
Adam C
Почему нет ничего подобного rto_max? Как мы устанавливаем глобальное максимальное время ожидания?
Текущая
Если вы установите минимум (или примете значение по умолчанию), а затем измените количество разрешенных повторных попыток ( net.ipv4.tcp_retries1и / net.ipv4.tcp_retries2или аналогичных IIRC), я думаю, вы сможете получить эквивалент максимума RTO.
Адам С