Назад | Перейти на главную страницу

Автоматическое замедление TCP-соединения (формирование)

Я хотел бы автоматически формировать требовательные к пропускной способности TCP-соединения, соответствующие уже переданным данным.

Резюме: «Первый Мбит передается с полной пропускной способностью, затем он постепенно падает до 1% от пропускной способности, когда достигает 10 Мбит, и остается там».

Пример лучше 1к слов:

 b-w  ^
      |        .         .
100%  | ********         .
      |        . *       .
      |        .    *    .
      |        .       * .
  1%  |        .         .********
      +----------------------------> Data transfered.
         1Mbit .         . 10Mbit

Я знаю, что полное формирование трафика было бы лучше, поскольку оно позволило бы разбивать и использовать оставшуюся полосу пропускания, но идея состоит в том, чтобы автоматически ограничивать передачу больших данных без какой-либо дополнительной настройки.

Как мне реализовать это на хосте Linux ?

Обновить: Это не сразу очевидно, но счетчик данных считает обе способами (загрузка и загрузка), поскольку я намеренно не уточнил загрузку или загрузку.

В HTB qdisc реализует концепцию всплески что немного из того, что вы хотите - он отправляет с полной аппаратной скоростью до объема данных, указанного в параметре "burst". Чтобы получить постепенное уменьшение, вам нужно будет вложить классы HTB, и, вероятно, вы не захотите делать это слишком чрезмерно, поскольку это значительно увеличивает сложность настройки. Но сам движок формирования трафика Linux не имеет состояния, он просто воздействует на пакеты, а не на соединения. Используя только tc-фильтры, вы можете различать пакеты только на основе заголовков IP / TCP.

Поэтому, если вам нужно классифицировать по-разному на основе подключений, наиболее простой подход, вероятно, будет использовать совпадение iptables «--connbytes» и метку пакета (-j MARK target), чтобы поместить пакеты подключения в нужную очередь (быстро / замедленно )

Увидеть многословный раздел по управлению пропускной способностью в LARTC howto и / или всеобъемлющий «Решения с открытым исходным кодом» технический документ для более глубокого понимания.

Кроме того, если вам нужно сформировать как восходящий, так и нисходящий поток, взгляните на реализацию виртуальный интерфейс IMQ - он был разработан специально для этой цели.

Меня вдохновило решение @ the-wabbit, и мне удалось это решить. Я писал об этом решении в своей личной вики: https://giki.wiki/@nubela/Software-Engineering/Per-Connection-Throttling

Вот мое решение этого вопроса с помощью реального сценария оболочки:

#!/bin/sh

dev=eth0
ip_port=3002
rate_limit=512kbit
rate_ceil=1024kbit
htb_class=10
max_byte=10485760

if [ "$(id -u)" != "0" ]; then
    echo "This script must be run as root" 1>&2
    exit 1
fi

if [ "$1" = "enable" ]; then
    echo "enabling rate limits"
    tc qdisc del dev $dev root > /dev/null 2>&1
    tc qdisc add dev $dev root handle 1: htb

    tc class add dev $dev parent 1: classid 1:$htb_class htb rate $rate_limit ceil $rate_ceil
    tc filter add dev $dev parent 1: prio 0 protocol ip handle $htb_class fw flowid 1:$htb_class

    #iptables -t mangle -A OUTPUT -p tcp --sport $ip_port -j MARK --set-mark $htb_class

    # small packet is probably interactive or flow control
    iptables -t mangle -A OUTPUT -p tcp --sport $ip_port -m length --length 0:500 -j RETURN

    # small packet connections: multi purpose (don't harm since not maxed out)
    iptables -t mangle -A OUTPUT -p tcp --sport $ip_port -m connbytes --connbytes 0:250 --connbytes-dir both --connbytes-mode avgpkt -j RETURN

    #after 10 megabyte a connection is considered a download
    iptables -t mangle -A OUTPUT -p tcp --sport $ip_port -m connbytes --connbytes $max_byte: --connbytes-dir both --connbytes-mode bytes -j MARK --set-mark $htb_class
    iptables -t mangle -A OUTPUT -j RETURN

elif [ "$1" = "disable" ]; then
    echo "disabling rate limits"
    tc qdisc del dev $dev root > /dev/null 2>&1

    iptables -t mangle -F
    iptables -t mangle -X

elif [ "$1" = "show" ]; then
    tc qdisc show dev $dev
    tc class show dev $dev
    tc filter show dev $dev
    iptables -t mangle -vnL INPUT
    iptables -t mangle -vnL OUTPUT
else
    echo "invalid arg $1"
fi