- How to Adjust the TCP Window Size Limit on Linux
- How to Adjust the TCP Window Size Limit on Linux
- What affects iPerf throughput?
- How to calculate maximum achievable TCP throughput
- Window size tcp linux
- Узкие места сетевой подсистемы Linux. Тюнинг сети в Linux. Настройка производительности сети в модели NAPI и с прерываниями.
How to Adjust the TCP Window Size Limit on Linux
iPerf is a bandwidth testing tool that many networking folks use for stress testing their networks, but also for troubleshooting. For some iPerf basics, take a look at some of these past posts:
The maximum bandwidth that iPerf can push between a source and a destination depends on many factors. To name a few:
- Interface: if you are using a Raspberry Pi that has a 10/100 interface, then the upper limit is 100 Mbps.
- CPU capabilities: pushing several Gbps of traffic needs quite a bit of CPU performance.
- Latency: the greater the latency between source and destination, the larger the TCP window size needs to be.
The interface and the CPU put hard limits on the maximum bandwidth you can achieve. You can’t bypass them unless you get new hardware.
However, given your link’s latency, you can adjust the TCP window size in order to achieve the desired bandwidth. But it can be tricky…
The maximum achievable bandwidth is equal to:
[TCP Window Size in bits] / [Latency in seconds] = [Throughput in bits per second]
Here is a calculator for getting the TCP window size.
The default window size that iPerf uses varies by machine type and operating system. If it’s 64 KBytes, with a modest latency of 10 ms, the maximum bandwidth you can get is 52.43 Mbits/sec. For 50 ms the maximum is 10.49 Mbits/sec.
The obvious option would be to increase the window size to a larger value and get up to, let’s say, 500 Mbps. For a 50 ms latency, the window size needs to be 3.1 Mbytes.
Indeed, iPerf gives you the option to set the window size, but if you try to set it to 3.1 or 4.0 Mbytes you may get the following warning from iPerf:
Get real-time metrics from all your network locations and from the user perspective.
“TCP window size: 416 KByte (WARNING: requested 4.00 MByte)”
Oops… Why didn’t iPerf follow your command and used only a 416 Kbyte window?
The devil is in the details!
In this case, the devil is the operating system that has a hard limit on the TCP window size that an application can use. It looks like in this case the limit is 416 Kbytes. These limits exist for good reasons. Larger TCP windows take more system memory and if you have multiple applications running, using large windows they may bog down the system. Or the system may deny TCP connections if it is running out of memory.
In your case, if you have full control of the system and you know what you are doing, you may want to increase the OS limits. As an example, to increase those limits to 4 MBytes, run the following commands as root on a Debian Linux machine:
Источник
How to Adjust the TCP Window Size Limit on Linux
How to Adjust the TCP Window Size Limit on Linux is one of the most popular post on the NetBeez blog. Since we definitely hit a nerve with this topic, I wanted to enhance it by adding a step-by-step video to it as well. Below you’ll find the original blog post and a new “how-to” video. Enjoy!
What affects iPerf throughput?
The maximum bandwidth that iPerf can push between a source and a destination depends on many factors. To name a few:
- Interface: if you are using a Raspberry Pi that has a 10/100 interface, then the upper limit is 100 Mbps.
- CPU capabilities: pushing several Gbps of traffic needs quite a bit of CPU performance.
- Latency: the greater the latency between source and destination, the larger the TCP window size needs to be.
The interface and the CPU put hard limits on the maximum bandwidth you can achieve. You can’t bypass them unless you get new hardware.
However, given your link’s latency, you can adjust the TCP window size in order to achieve the desired bandwidth. But it can be tricky…
How to calculate maximum achievable TCP throughput
The maximum achievable throughput is equal to:
[TCP Window Size in bits] / [Latency in seconds] = [Throughput in bits per second]
The default window size that iPerf uses varies by machine type and operating system. If it’s 64 KBytes, with a modest latency of 10 ms, the maximum bandwidth you can get is 52.43 Mbits/sec. For 500 ms the maximum is 524 Kbits/sec.
The obvious option would be to increase the window size to a larger value and get up to, let’s say, 500 Mbps. For a 50 ms latency, the window size needs to be 3.1 Mbytes.
Indeed, iPerf gives you the option to set the window size, but if you try to set it to 3.1 or 8.0 Mbytes you may get the following warning from iPerf:
Get real-time metrics from all your network locations and from the user perspective.
“TCP window size: 250 KByte (WARNING: requested 8.00 MByte)”
Oops… Why didn’t iPerf follow your command and used only a 250 Kbyte window?
The devil is in the details!
In this case, the devil is the operating system that has a hard limit on the TCP window size that an application can use. It looks like in this case the limit is 250 Kbytes. These limits exist for good reasons. Larger TCP windows take more system memory and if you have multiple applications running, using large windows they may bog down the system. Or the system may deny TCP connections if it is running out of memory.
In your case, if you have full control of the system and you know what you are doing, you may want to increase the OS limits. As an example, to increase those limits to 8 MBytes, run the following commands as root on a Debian Linux machine:
Источник
Window size tcp linux
Узкие места сетевой подсистемы Linux. Тюнинг сети в Linux. Настройка производительности сети в модели NAPI и с прерываниями.
Создано 22.11.2016 11:53
Опубликовано 22.11.2016 11:53
Узкие места сетевой подсистемы Linux. Тюнинг сети в Linux. Настройка производительности сети в модели NAPI и с прерываниями.
Кольцевой буфер
Кольцевые буферы, совместно используются драйвером устройства и сетевой картой. TX – есть передача данных, а RX – получение данных в кольцевом буфере. Как следует из названия, переполнение буфера просто перезаписывает существующие данные. Есть два способа переместить данные от сетевой карты до ядра: аппаратные прерывания и программные прерывания, названные SoftIRQs.
Кольцевой буфер RX используется, чтобы сохранить входящие пакеты, пока они не могут быть обработаны драйвером устройства. Драйвер устройства опустошает буфер RX, обычно через SoftIRQs, который помещает входящие пакеты в структуру данных ядра, названную sk_buff или «skb», чтобы начать свой путь через ядро и до приложения, которому принадлежит соответствующий сокет. Кольцевой буфер TX используется для хранения исходящих пакетов, которые предназначенные для отправки по проводам.
Эти кольцевые буферы находятся у основания стека и являются критическим моментом, в который может произойти удаление (drop) пакетов, что негативно влияет на производительность сети.
Прерывания и обработчики прерываний
Прерывания от аппаратных средств известны как прерывания «top-half».
Сетевые карты, как правило, работают с кольцевыми буферами (DMA ring buffer) организованными в памяти, разделяемой с процессором. Каждый входящий пакет размещается в следующем доступном буфере кольца. (DMA — Direct Memory Access (Прямой доступ к памяти) — режим обмена данными между устройствами или же между устройством и основной памятью, в котором центральный процессор (ЦП) не участвует). После этого требуется сообщить системе о появлении нового пакета и передать данные дальше, в специально выделенный буфер (Linux выделяет такие буферы для каждого пакета). Для этой цели в Linux используется механизм прерываний: прерывание генерируется всякий раз, когда новый пакет поступает в систему. Чаще используется отложенные прерывания (см. в статье Linux, принципы работы с сетевой подсистемой ). В ядро Linux начиная с версии ядра 2.6 был добавлен так называемый NAPI (New API), в котором метод прерываний сочетается с методом опроса. Сначала сетевая карта работает в режиме прерываний, но как только пакет поступает на сетевой интерфейс, она регистрирует себя в poll-списке и отключает прерывания. Система периодически проверяет список на наличие новых устройств и забирает пакеты для дальнейшей обработки. Как только пакеты обработаны, карта будет удалена из списка, а прерывания включатся снова.
Жесткие прерывания можно увидеть в /proc/interrupts, где у каждой очереди есть vector прерывания в 1-м столбце. Каждой очереди RX и TX присвоен уникальный vector, который сообщает обработчику прерываний, относительно какого NIC/queue пришло прерывание. Столбцы представляют количество входящих прерываний:
#egrep «CPU0|eth1» /proc/interrupts
CPU0 CPU1 CPU2 CPU3 CPU4 CPU5 CPU6 CPU7
45: 28324194 0 0 0 0 0 0 0 PCI-MSI-edge eth1
SoftIRQs
Иизвестны как прерывания «bottom-half», запросы программного прерывания (SoftIRQs), являются подпрограммами ядра, которые планируется запустить в то время, когда другие задачи не должны быть прерваны. Цель SoftIRQ состоит в извлечении данных из кольцевых буферов. Эти подпрограммы, выполненные в форме процессов ksoftirqd/cpu-number и, вызывают специфичные для драйвера функции кода.
После перемещения данных от драйвера к ядру, трафик двигатется вверх к сокету приложения.
SoftIRQs можно контролировать следующим образом. Каждый столбец есть ЦП:
# watch -n1 grep RX /proc/softirqs
# watch -n1 grep TX /proc/softirqs
NAPI Polling
Поиск узкого места
Отбрасывание пакетов и переполнени границ (packet drops и overruns) обычно происходит, когда буфер RX сетевой карты не может достаточно быстро опустошиться ядром. Когда скорость, с которой данные поступают из сети превышает скорость, с которой ядро забирает на обработку пакеты, сетевая карта начинает отбрасывать входящие пакеты, т.к. буфер NIC (сетевой карты) полон, и увеличивает счетчик удаления.Соответствующий счетчик можно увидеть в ethtool статистике. Основные критерии здесь — прерывания и SoftIRQs.
Для примера вывод статистики ethtool:
Существуют различные инструменты, доступные для поиска проблемной области. Следует исследовать:
• Уровень встроенного ПО адаптера
— Следим за статистикой ethtool -S ethX
• Уровень драйвера адаптера
• Ядро Linux, IRQs или SoftIRQs
— Проверяем /proc/interrupts и /proc/net/softnet_stat
• Уровни протокола IP, TCP, UDP
— Используем netstat -s и смотрим счетчики ошибок
Вот некоторые типичные примеры узких мест:
- Прерывания (IRQs) неправильно сбалансированы. В некоторых случаях служба irqbalance может работать неправильно или не работает вообще. Проверьте /proc/interrupts и удостоверьтесь, что прерывания распределены на разные ядра ЦП. Обратитесь к irqbalance руководству, или вручную сбалансируйте IRQs. В следующем примере прерывания становятся обработанными только одним процессором:
# egrep “CPU0|eth2” /proc/interrupts
CPU0 CPU1 CPU2 CPU3 CPU4 CPU5
105: 1430000 0 0 0 0 0 IR-PCI-MSI-edge eth2-rx-0
106: 1200000 0 0 0 0 0 IR-PCI-MSI-edge eth2-rx-1
107: 1399999 0 0 0 0 0 IR-PCI-MSI-edge eth2-rx-2
108: 1350000 0 0 0 0 0 IR-PCI-MSI-edge eth2-rx-3
109: 80000 0 0 0 0 0 IR-PCI-MSI-edge eth2-tx
- Посмотрите, увеличивается ли какая-либо из колонок помимо 1-й колонки в /proc/net/softnet_stat. В следующем примере счетчик большой для CPU0, и budget должен быть увеличен:
0073d76b 00000000 000049ae 00000000 00000000 00000000 00000000 00000000 00000000 00000000 000000d2 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 0000015c 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 |
- SoftIRQs не может получать достаточное количество процессорного времени для опроса адаптера. Используйте инструменты, такие как sar, mpstat или top, чтобы определить, что отнимает много процессорного времени.
- Используйте ethtool -S ethX, чтобы проверить определенный адаптер:
#sysctl -w net.core.netdev_max_backlog=X |
Adapter RX and TX Buffer
Буфер адаптера по умолчанию обычно установлен в меньшем размере, чем максимальный. Часто, увеличить размер буфера приема RX вполне достаточно, чтобы предотвратить потери пакетов, так как это может приводит к тому, что у ядра будет немного больше времени, чтобы опустошить буфер. В результате, это может предотвратить возможные потери пакетов.
Буферы можно посмотреть так:
Ring parameters for eth3:
Current hardware settings:
Тут видим что кольцевой буфер RX входящих пакетов равен 1024 дескрипторам в оперативной памяти, и можно увеличить до 8192.
Очередь передачи (Adapter Transmit Queue Length)
Длина очереди передачи определяет количество пакетов, которые могут быть поставлены в очередь перед передачей. Значение по умолчанию 1000 — обычно достаточно для сегодняшней скорости до 10 Гбит/с или даже 40 Гбит/с сетей. Однако, если число ошибок передачи увеличиваются на адаптере, то значение можно удвоить. Используйте ip -slink, чтобы увидеть, если есть какие-то потери на очереди TX для адаптера.
Увеличить длину очереди можно так:
# ip link set dev em1 txqueuelen 2000 |
TCP Window Scaling (масштабирование окна TCP)
Размер TCP окна (TCP Window Size) – количество октетов (начиная с номера подтверждения), которое принимающая сторона готова принять в настоящий момент без подтверждения. На стадии установления соединения рабочая станция и сервер обмениваются значениями максимального размера TCP окна (TCP Window Size), которые присутствуют в пакете. Например, если размер окна получателя равен 16384 байта, то отправитель может отправить 16384 байта без остановки. Принимая во внимание, что максимальная длина сегмента (MSS) может быть 1460 байт, то отправитель сможет передать данный объем в 12 фреймах, и затем будет ждать подтверждение доставки от получателя и информации по обновлению размера окна. Если процесс прошел без ошибок, то размер окна может быть увеличен. Таким образом, реализуется размер скользящего окна в стеке протокола TCP. В современных версиях операционных систем можно увеличить размер окна TCP Window Size и включить динамическое изменение окна в зависимости от состояния канала связи. Динамическое увеличение и уменьшение размера окна является непрерывным процессом в TCP и определяет оптимальный размер окна для каждого сеанса. В очень эффективных сетях размеры окна могут стать очень большими, потому что данные не теряются.
Масштабирование Окна TCP включено по умолчанию:
# sysctl net.ipv4.tcp_window_scaling net.ipv4.tcp_window_scaling = 1 |
TCP буфер
После того, как сетевой трафик обрабатывается от сетевого адаптера, предпринимается попытка приема трафика непосредственно в приложение. Если это не представляется возможным, данные ставятся в очередь на буфер сокета приложения. Есть 3 структуры очереди в сокете:
sk_rmem_alloc – очередь получения
sk_wmem_alloc – очередь передачи
sk_omem_alloc — out-of-order queue
Существует также sk_rcvbuf переменная, которая является пределом, измеренный в байтах, что сокет может получить. В этом случае sk_rcvbuf = 125336.
Из приведенного выше вывода можно вычислить, что очередь получения почти полна. Когда sk_rmem_alloc > sk_rcvbuf то буфер начинает рушится, т.е. наблюдаются потери пакетов. Выполните следующую команду, чтобы определить, происодит это или нет:
# netstat -sn | egrep «prune|collap»; sleep 30; netstat -sn | egrep «prune|collap»
17671 packets pruned from receive queue because of socket buffer overrun
18671 packets pruned from receive queue because of socket buffer overrun
Если счетчик обрезки пакетов растет, то требуется тюнинг.
tcp_rmem: У настраиваемой памяти сокета есть три значения, описывающих минимальное, значение по умолчанию и максимальное значения в байтах. Чтобы просмотреть эти настройки и увеличить:
4096 87380 4194304
# sysctl -w net.ipv4.tcp_rmem=“16384 349520 16777216”
# sysctl net.core.rmem_max 4194304
# sysctl -w net.core.rmem_max=16777216
TCP Listen Backlog: отвечает за размер очереди одновременно ожидающих подключений к сокету, то есть инициированных (SYN — SYN, ACK — ACK), но еще не принятых сервером (established).
Параметр ядра net.core.somaxconn — максимальное число открытых сокетов, ждущих соединения. Изменяем:
# sysctl -w net.core.somaxconn=2048
UDP Buffer Tuning: UDP является гораздо менее сложным, чем протокол TCP. Поскольку UDP не содержит надежности сеанса, он не несет ответственности за повторную передачу потерянных пакетов. Там не существует понятия размера окна и потерянные данные не восстанавливается протоколом. Единственная доступная настройка включает в себя увеличение размера приемного буфера. Если netstat -us показывает “packet receive errors” , попробуйте увеличить число буферов для приема. Буферы UDP могут быть настроены таким образом:
# sysctl -w net.core.rmem_max=16777216
После изменения максимального размера, требуется перезапуск приложения.
Источник