TC를 사용하여 특정 포트를 통해 들어오고 나가는 대역폭의 대기 시간을 제한하려고 하는데 100% 작동하도록 할 수 없습니다. 내가 제대로 하고 있는지 잘 모르겠습니다.
Google에 ping을 실행하면 대기 시간이 늘어납니다. iperf를 사용하여 포트 5001을 통한 대역폭을 테스트했습니다. 대역폭 조절은 다음 설정이 적용된 클라이언트에서 작동하는 것 같습니다(클라이언트는 iperf -s, 수신). 그러나 이 클라이언트를 사용하여 다른 클라이언트에 연결하면(발신) 대역폭이 1-2Mbit로 제한됩니다. 5Mbit가 예상됩니다.
예를 들어, 내가 원하는 것은 대기 시간을 100ms로 설정하고 대역폭 출력/입력 제한을 5mbit로 설정하는 것이며 이러한 모든 규칙은 포트 5001에 적용됩니다. 나는 올바른 길을 가고 있습니까, 아니면 TC의 개념을 오해하고 있습니까?
Ip link add name ifb0 type ifb 2>/dev/null || :
Ip link set dev ifb0 up
Tc qdisc add dev ifb0 root handle 1: htb
Tc class dev ifb0 parent 1: classid 1:20 htb rate 5mbit
Tc qdisc add dev ifb0 parent 1:20 handle 20: sfq perturb 10
Tc filter add dev ifb0 parent 1: protocol ip prio 1 basic match ‘cmp(u16 at 2 layer transport eq 5001)’ flowid 1:20
Tc qdisc add dev ens192 root netem delay 200ms
Tc qdisc add dev ens192 ingress
Tc filter add add dev ens192 ingress protocol ip basic match ‘cmp(u16 at 2 layer transport eq 5001)’ action mirred egress redirect dev ifb0
답변1
이것은 몇 년 전 내 ISP가 버퍼 팽창 문제를 겪었을 때 실행한 스크립트입니다. root
및 로 실행해야 start
하지만 없이도 stop
실행할 수 있습니다 .status
root
#!/bin/bash
# Traffic shaping script (AQM, fq_codel+tbf)
# Copyright 2018,2019 Mikko Rantalainen <[email protected]>
# License: MIT (X11)
# Usage:
# 21/0.8 Mbps connection (ADSL2): DOWNLINK_RATE=21.7Mbit UPLINK_RATE=0.8Mbit TBF_LATENCY=500ms DOWNLINK_BURST=1500 UPLINK_BURST=1500 bin/traffic-shaping start
# 100/100 Mbps connection: ./traffic-shaping
# 1/1 GBps connection: DOWNLINK_RATE=1Gbit UPLINK_RATE=1Gbit TBF_LATENCY=15ms bin/traffic-shaping start
# Note that using low TBF_LATENCY will require powerful CPU.
#
# See also: https://www.bufferbloat.net/projects/codel/wiki/Best_practices_for_benchmarking_Codel_and_FQ_Codel/
# See also: http://www.jfcarter.net/~jimc/documents/voip-qos-1609.html
# TODO: man 7 tc-hfcs (instead of tbf)
# TODO: try to limit bandwidth using fq_codel only (get rid of tbf) - https://gist.github.com/eqhmcow/939373/8d2e8ad745a7e0a8ddb21abde42538034c2ea65b
#
set -e # abort if a command returns non-zero status (failed)
#set -x # verbose execution
# Note: ip route sometimes outputs multiple lines with prefix "default", use the first one
DEV="${DEV:=$(ip route | grep "^default " | head -n1 | grep -Po "(?<=dev )[^ ]+")}"
# ingress:
DOWNLINK_RATE="${DOWNLINK_RATE:=103000kbit}" # or e.g. "21.5Mbit"
# egress:
UPLINK_RATE="${UPLINK_RATE:=102000kbit}"
CODEL_INTERVAL="${CODEL_INTERVAL:=100ms}" # usually 100ms, high speed links with low latency may need lower values
CODEL_TARGET="${CODEL_TARGET:=5ms}" # unit "us" is also available, usually 5%-10% of CODEL_INTERVAL
CODEL_LIMIT="${CODEL_LIMIT:=1001}" # decrease to reduce latency, too low values will limit throughput
CODEL_FLOWS="${CODEL_FLOWS:=1024}"
# set burst as high as possible without causing dropped packets at the start of the connections
DOWNLINK_BURST="${DOWNLINK_BURST:=8000}"
UPLINK_BURST="${UPLINK_BURST:=55000}"
TBF_LATENCY="${TBF_LATENCY:=10ms}" # set to lower latency to improve control over bandwidth limiting, UPLINK_BURST bytes must be able to be sent in this time
IFB="$DEV.in" # logically this should be $DEV.ingress but max limit might be exceeded (e.g. dev = enp0s29u1u6 -> enp0s29u1u6.ingress is too long
INITCWND="${INITCWND:=15}" # initial congestion window, decrease if packet loss is seen
INITRWND="${INITRWND:=30}" # initial receiving window (advertised from client to servers), can be safely pretty high if you have lots of bandwidth (Windows and OS X have this near 40)
# See also: https://www.cdnplanet.com/blog/tune-tcp-initcwnd-for-optimum-performance/
# See also: https://www.acc.umu.se/~maswan/linux-netperf.txt
# See also: http://intronetworks.cs.luc.edu/1/html/newtcps.html
# See also: https://www.ietf.org/proceedings/84/slides/slides-84-iccrg-1.pdf
configure_shaping()
{
# EGRESS (outgoing traffic, "uploads"):
# setup bandwidth limiting:
tc qdisc add dev "$DEV" root handle 1: tbf rate "$UPLINK_RATE" burst "$UPLINK_BURST" latency "$TBF_LATENCY"
# setup fq_codel for bandwidth shaping
tc qdisc add dev "$DEV" parent 1: fq_codel quantum 300 limit "$CODEL_LIMIT" target "$CODEL_TARGET" interval "$CODEL_INTERVAL" flows "$CODEL_FLOWS" noecn
# INGRESS (incoming traffic, "downloads"):
ip link show ifb0 >&/dev/null && HAD_IFB0=1 || HAD_IFB0=0
ip link show ifb1 >&/dev/null && HAD_IFB1=1 || HAD_IFB1=0
# setup bandwidth limiting (ingress limiting needs IFB or Intermediate Functional Block, see https://wiki.linuxfoundation.org/networking/ifb):
tc qdisc add dev "$DEV" handle ffff: ingress
ip link add name "$IFB" type ifb
tc qdisc add dev "$IFB" root handle 1: tbf rate "$DOWNLINK_RATE" burst "$DOWNLINK_BURST" latency "$TBF_LATENCY"
# setup fq_codel for bandwidth shaping
tc qdisc add dev "$IFB" parent 1: fq_codel quantum 300 limit "$CODEL_LIMIT" target "$CODEL_TARGET" interval "$CODEL_INTERVAL" flows "$CODEL_FLOWS" ecn
ip link set dev "$IFB" up
# connect ingress filtering to actual WAN device
tc filter add dev "$DEV" parent ffff: protocol all prio 10 u32 match u32 0 0 flowid 1:1 action mirred egress redirect dev "$IFB"
# Configure initcwnd and initrwnd
# Note that "ip route" sometimes emit multiple lines with prefix "default" - we'll use first one always
ip route change $(ip route | grep ^default | head -n1) initcwnd "$INITCWND" initrwnd "$INITRWND"
## configure CDG congestion control algorithm
##modprobe tcp_cdg && echo cdg > /proc/sys/net/ipv4/tcp_congestion_control
# cubic seems to be better overall with AQM, let's tune it
echo cubic > /proc/sys/net/ipv4/tcp_congestion_control || true
echo 13 > /sys/module/tcp_cubic/parameters/hystart_low_window
echo 0 > /proc/sys/net/ipv4/tcp_slow_start_after_idle
# TODO: try modprobe tcp_westwood
# Remove any offloading that increases latency (Note that if you don't have enough CPU power, this may reduce max bandwith!)
# Note that due ethtool braindamage, the names used here do not match with ethtool --show-offload, see 'man ethtool' for details!
# ignore possible errors and keep going
ethtool --offload "$DEV" gso off || true
ethtool --offload "$DEV" gro off || true
ethtool --offload "$DEV" tx off || true
ethtool --offload "$DEV" rx off || true
ethtool --offload "$DEV" rxvlan off || true
ethtool --offload "$DEV" txvlan off || true
# cleanup broken ip link add ... type ifb sometimes creating extra ifb links (called "ifb0" and "ifb1")
test "$HAD_IFB0" = "0" && ip link show ifb0 >&/dev/null && ip link del ifb0
test "$HAD_IFB1" = "0" && ip link show ifb1 >&/dev/null && ip link del ifb1
}
remove_shaping()
{
#set -x
tc qdisc list | grep -q "ingress" && tc qdisc del dev "$DEV" ingress || true
# Note: we need to avoid removing root qdisc in case this kernel defaults to fq_codel, "qdisc list" will output "fq_codel 0:" for root qdisc so we look for something different
tc qdisc list | grep -q "fq_codel [1-9]" && tc qdisc del dev "$DEV" root || true
ip link show | grep -q "$IFB" && ip link del "$IFB" || true
# configure CDG congestion control algorithm
modprobe tcp_cdg && echo cdg > /proc/sys/net/ipv4/tcp_congestion_control || true
#set +x
}
status()
{
echo "─── queue discipline configuration: ──────────────────"
tc qdisc list
echo " TIP: use e.g. 'sudo tc qdisc del dev $DEV ingress' to remove ingress filtering"
echo " TIP: use e.g. 'sudo tc qdisc del dev $DEV root' to remove egress filtering"
echo "─── ip link show: ────────────────────────────────────"
ip link show
echo " TIP: use e.g. 'sudo ip link del $IFB' to remove ingress device"
}
color_status()
{
status | grep --color=auto -E "^|$DEV|$IFB|rate [^ ]+"
}
# handle parameters
ACTION="$1"
shift || true
while [ ! -z "$1" ]
do
case "$1" in
-v|--verbose)
echo "Device: $DEV"
echo "Downlink rate (ingress): $DOWNLINK_RATE"
echo "Uplink rate (egress): $UPLINK_RATE"
set -x
;;
*)
if [ ! -z "$2" ]; then
echo "Unknown parameter: '$2'" 1>&2
exit 1
fi
;;
esac
shift || true
done
case "$ACTION" in
start)
remove_shaping
configure_shaping
;;
stop)
remove_shaping
;;
status)
color_status
;;
restart)
remove_shaping
configure_shaping
;;
*)
echo "Unknown action: $1" 1>&2
echo "Usage: $0 <start|stop|restart|status> [--verbose|-v]" 1>&2
exit 1
esac
스크립트를 사용하는 방법은 예를 들어 스크립트를 저장 하고 실행 비트를 활성화한 상태에서 traffic-shaping
실행하는 것입니다 . chmod a+x traffic-shaping
그런 다음 파일의 기본값을 수정하거나 환경 변수를 사용하여 스크립트를 구성할 수 있습니다. 예를 들어, 100/100Mbps 연결이 있는 경우 다음을 실행할 수 있습니다.
DOWNLINK_RATE=95Mbit UPLINK_RATE=95Mbit TBF_LATENCY=25ms ./traffic-shaping start
처럼 root
. 실행하려면 기본 설정을 복원하세요.
./traffic-shaping stop
현재 실행 상태를 표시합니다.
./traffic-shaping stop
위 설정은 영구적이지 않으므로 부팅할 때마다 스크립트를 다시 실행해야 합니다. 나는 이것을 Ubuntu (PREEMPT) Linux 커널 low-latency
과 함께 사용했기 때문에 커널이 어떤 종류의 대기 시간을 도입할지 TBF_LATENCY=10ms
모르겠습니다 . 커널로 실행하는 경우 설정해야 할 수도 있습니다 . 환경 변수를 설정하지 않고 실행 하면 커널에 대한 100/100Mbps FTTH 연결 에 사용하는 자체 구성이 생성됩니다 . 연결 속도가 20Mbps 미만인 경우 새 연결을 시작할 때 일시적인 급증으로 인해 패킷 손실이 발생하지 않도록 설정하는 것이 좋습니다 . 느린 업링크의 경우 빠른 서버에 처음 연결할 때(예: 웹 브라우저 트래픽) 패킷 손실/긴 대기 시간이 발생하면 줄여야 할 수도 있습니다(이 스크립트의 기본값은 15). 7~10 범위의 값은 1Mbps 연결에 적합해야 합니다.generic
TBF_LATENCY=40ms
generic
start
low-latency
DOWNLINK_BURST=1500 UPLINK_BURST=1500
INITCWND