Tc:入口pipe制和ifb镜像

我正在尝试在Linux网关上设置stream量整形。 脚本需要定制,因为我有多个LAN接口。 因此,为了塑造LAN端,我打算创build一个ifb伪设备,如下所示:

modprobe ifb ip link set dev ifb0 up /sbin/tc qdisc add dev $WAN_INTERFACE ingress /sbin/tc filter add dev $WAN_INTERFACE parent ffff: protocol ip u32 match u32 0 0 action mirred egress redirect dev ifb0 

从上面提到的要点回购脚本有这些行:

  /sbin/tc qdisc add dev $WAN_INTERFACE handle ffff: ingress /sbin/tc filter add dev $WAN_INTERFACE parent ffff: protocol ip prio 1 u32 match ip sport $INTERACTIVE_PORT 0xffff flowid :1 /sbin/tc filter add dev $WAN_INTERFACE parent ffff: protocol ip prio 1 u32 match ip dport $INTERACTIVE_PORT 0xffff flowid :1 /sbin/tc filter add dev $WAN_INTERFACE parent ffff: protocol ip prio 5 0 u32 match ip src 0.0.0.0/0 police rate $MAX_DOWNRATE_INGRESS burst 20k drop flowid :2 

这段代码和ifb接口创build代码不能很好地结合在一起。 自定义脚本得到执行,但ifb0设备不显示任何stream量统计。 如果我注释了入口要点回购码(上面引用的),那么ifb0设备显示传输的数据包数量。 而且这些行不能一起执行:

 /sbin/tc qdisc add dev $WAN_INTERFACE ingress /sbin/tc qdisc add dev $WAN_INTERFACE handle ffff: ingress 

我得到文件存在错误。 那么,如何在WAN_INTERFACE上形成入口,同时还可以通过ifb0设备形成通往局域网的stream量?

IFB是用于处理入口stream量的tcfilter的一种替代scheme,通过将其redirect到虚拟接口并将其视为出口stream量。每个物理接口需要一个ifb接口,将入口stream量从eth0redirect到ifb0,eth1到ifb1等上。

当插入ifb模块时,告诉它你需要的虚拟接口的数量。 默认是2:

 modprobe ifb numifbs=1 

现在,启用所有的ifb接口:

 ip link set dev ifb0 up # repeat for ifb1, ifb2, ... 

并将入口stream量从物理接口redirect到相应的ifb接口。 对于eth0 – > ifb0:

 tc qdisc add dev eth0 handle ffff: ingress tc filter add dev eth0 parent ffff: protocol ip u32 match u32 0 0 action mirred egress redirect dev ifb0 

再次重复eth1 – > ifb1,eth2 – > ifb2等等,直到所有想要形成的接口都被覆盖。

现在,你可以应用你想要的所有规则。 eth0的出口规则和往常一样。 我们来限制带宽,例如:

 tc qdisc add dev eth0 root handle 1: htb default 10 tc class add dev eth0 parent 1: classid 1:1 htb rate 1mbit tc class add dev eth0 parent 1:1 classid 1:10 htb rate 1mbit 

不用说,重复eth1,eth2,…

eth0的入口规则,现在作为ifb0上的出口规则(不pipe进入ifb0必须出来,只有eth0入口stream量进入ifb0)。 再次,带宽限制的例子:

 tc qdisc add dev ifb0 root handle 1: htb default 10 tc class add dev ifb0 parent 1: classid 1:1 htb rate 1mbit tc class add dev ifb0 parent 1:1 classid 1:10 htb rate 1mbit 

这种方法的优点是出口规则比入口filter灵活得多。 例如,filter只允许丢弃数据包,不会引入等待时间。 通过将入口stream量作为出口进行处理,您可以设置队列规则,使用stream量类和filter(如果需要)。 您可以访问整个tc树,而不仅仅是简单的filter。

基于塞尔吉奥·卡瓦略的回答,我做了一个小型的bash脚本来限制带宽:

文件名称:netspeed

 #!/bin/bash #USAGE: sudo ./netspeed -l limit_in_kbit -s usage="sudo $(basename "$0") -l speed_limit -s -l speed_limit - speed limit with units (eg. 1mbit, 100kbit, more on \`man tc\`) -s - remove all limits " # default values LIMIT=0 STOP=0 # hardcoded constats IFACE=ifb0 # fake interface name which will be used for shaping the traffic NETFACE=wlan0 # interface which in connected to the internet # shift all required and leave only optional while getopts ':hl:s' option; do case "$option" in l) LIMIT=$OPTARG ;; s) STOP=1 ;; h) echo "$usage" exit ;; esac done # # functions used in script # function limitExists { # detected by ingress on $NETFACE qdisc # -n equals true if non-zero string length if [[ -n `tc qdisc show | grep "ingress .* $NETFACE"` ]] then return 0 # true else return 1 # false fi } function ifaceExists { # -n equals true if non-zero string length if [[ -n `ifconfig -a | sed 's/[ \t].*//;/^\(lo\|\)$/d' | grep $IFACE` ]] then return 0 # true else return 1 # false fi } function ifaceIsUp { # -n equals true if non-zero string length if [[ -n `ifconfig | sed 's/[ \t].*//;/^\(lo\|\)$/d' | grep $IFACE` ]] then return 0 # true else return 1 # false fi } function createLimit { #3. redirect ingress tc qdisc add dev $NETFACE handle ffff: ingress tc filter add dev $NETFACE parent ffff: protocol ip u32 match u32 0 0 action mirred egress redirect dev $IFACE #4. apply egress rules to local inteface (like wlan0) tc qdisc add dev $NETFACE root handle 1: htb default 10 tc class add dev $NETFACE parent 1: classid 1:1 htb rate $LIMIT tc class add dev $NETFACE parent 1:1 classid 1:10 htb rate $LIMIT #5. and same for our relaying virtual interfaces (to simulate ingress) tc qdisc add dev $IFACE root handle 1: htb default 10 tc class add dev $IFACE parent 1: classid 1:1 htb rate $LIMIT tc class add dev $IFACE parent 1:1 classid 1:10 htb rate $LIMIT } function updateLimit { #3. redirect ingress tc filter replace dev $NETFACE parent ffff: protocol ip u32 match u32 0 0 action mirred egress redirect dev $IFACE #4. apply egress rules to local inteface (like wlan0) tc class replace dev $NETFACE parent 1: classid 1:1 htb rate $LIMIT tc class replace dev $NETFACE parent 1:1 classid 1:10 htb rate $LIMIT #5. and same for our relaying virtual interfaces (to simulate ingress) tc class replace dev $IFACE parent 1: classid 1:1 htb rate $LIMIT tc class replace dev $IFACE parent 1:1 classid 1:10 htb rate $LIMIT } function removeLimit { if limitExists ; then tc qdisc del dev $NETFACE ingress tc qdisc del dev $NETFACE root tc qdisc del dev $IFACE root fi if ifaceIsUp ; then ip link set dev $IFACE down fi } # # main script # if [[ `whoami` != "root" ]]; then echo "WARNING: script must be executed with root privileges!" echo $usage exit 1 fi if [ $STOP -eq 1 ]; then echo "REMOVING limit" removeLimit echo "limit REMOVED" elif [ "$LIMIT" != "0" ]; then # prepare interface if ! ifaceExists ; then echo "CREATING $IFACE by modprobe" modprobe ifb numifbs=1 if ! ifaceExists ; then echo "creating $IFACE by modprobe FAILED" echo "exit with ERROR code 2" exit 2 fi fi # set interface up if ifaceIsUp ; then echo "$IFACE is already up" else echo "set $IFACE up" ip link set dev $IFACE up # ( use ifconfig to see results) if ifaceIsUp ; then echo "$IFACE is up" else echo "enabling $IFACE by ip link FAILED" echo "exit with ERROR code 3" exit 3 fi fi # create/update limits if limitExists ; then echo "update limit" updateLimit else echo "create limit" createLimit fi echo "limit CREATED" exit 0 else echo $usage fi 

你有一个简单的脚本,它可以在一个linux路由器框中input和输出stream量:

https://github.com/rfrail3/misc/blob/master/tc/traffic-control.sh