我想自动塑造与已传输的数据相对应的耗带宽的 TCP 连接。
总结如下:“第一个Mbit以全带宽传输,然后当达到10Mbit时逐渐下降到带宽的1%,并保持在这个水平”。
一个例子胜过千言万语:
b-w ^
| . .
100% | ******** .
| . * .
| . * .
| . * .
1% | . .********
+----------------------------> Data transfered.
1Mbit . . 10Mbit
我知道完整的流量整形会更好,因为它允许突发和使用剩余带宽,但其想法是具体地自动限制大数据传输而无需任何进一步的配置。
我如何在 Linux 主机上实现这个?
更新:虽然不是很明显,但数据计量表很重要两个都方式(上传和下载),因为我故意没有精确下载或上传。
答案1
这HTB 队列规定实现的概念爆发这正是您想要的 - 它以全硬件速率发送“burst”参数中指定的数据量。要逐渐减少,您需要嵌套 HTB 类,并且您可能不想过度这样做,因为这会大大增加设置的复杂性。但是 Linux 流量整形引擎本身是无状态的,它只对数据包起作用,而不是对连接起作用。单独使用 tc 过滤器,您只能根据 IP/TCP 标头区分数据包。
因此,如果您需要根据连接进行不同的分类,最直接的方法可能是使用 iptables“--connbytes”匹配和数据包标记(-j MARK 目标)将连接的数据包推入正确的队列(快速/减速)
查看LARTC 指南中关于带宽管理的冗长部分和/或综合“开源带宽解决方案”白皮书以获得更多见解。
此外,如果你需要塑造上游和下游,请查看虚拟 IMQ 接口- 它是专门为此目的而设计的。
答案2
我受到 @the-wabbit 解决方案的启发,并设法解决了这个问题。我在个人 wiki 中发布了关于此解决方案的博文:https://giki.wiki/@nubela/Software-Engineering/Per-Connection-Throttling
下面是我使用实际的 shell 脚本对此问题的解决方案:
#!/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