Я хотел бы автоматически формировать требовательные к пропускной способности 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