Linux(openwrt)下iptables+tc工具实现网络流量限速控制(QoS)

基础介绍

Netfilter是Linux操作系统核心层内部的一个数据包处理模块,它具有如下功能:网络地址转换(Network Address Translate)数据包内容修改以及数据包过滤的防火墙功能。Netfliter框架不仅仅在ipv4中有应用,bridge,ipv4,ipv6,decnet,这四种协议中都有应用,其中ipv4中又分开了arp和ip的两种。其实netfliter是个大的框架,在ipv4中对应的应用层工具是iptables,在bridge中对应的应用层工具是ebtables,在arp中对应的应用层工具是arptables

  • iptables 中有raw,filter,nat,mangle,4个table,
  • ebtables 中有broute,filter,nat,3个table,
  • arptables 中有filter,1个table

Netfilter框架被设计用来在网络协议栈的内核路径上过滤数据包,就像在一条路上的关卡一样,Netfilter在协议栈处理网络数据包的路径上的5个位置设置了这样的关卡,一个数据包在被处理的路径上经过这些关卡被检查,结果就是若干个动作:接受,丢弃,排队,导入其它路径等,框架只需针对一个数据包得出一个结果即可,关卡内部提供什么服务在Netfilter框架中并没有任何规定。

TC旨在对数据包或者数据流提供一种服务,比如限速,整形等,而这并不是一个类似Netfilter的结果可以表达的,提供这些服务需要执行一系列的动作,如何来规划和组织这些动作的执行是TC框架设计的关键,也就是说,TC框架关注的是如何执行而不是仅仅想要得到一个要执行的动作。换句话说,Netfilter框架关注做什么,而TC框架关注怎么做。

QoS的全称是Quality of Service,意即服务质量。是专门用于解决拥堵网络上的信号质量一视同仁的问题。Linux内核内置了一个Traffic Control框架,可以实现流量限速,流量整形,策略应用(丢弃,NAT等), 结合tc和netfilter可以实现基于IP或基于端口的限速需求。

关于iptables的使用可以参考博客:朱双印个人日志

TC基础介绍

大多数排队规则(qdisc)都是用于输出方向的,输入方向只有一个排队规则,即ingress qdisc。ingress qdisc本身的功能很有限。

TC操作原理
类(class)组成一个树,每个类都只有一个父类,而一个类可以有多个子类。某些qdisc (例如:CBQ和 HTB)允许在运行时动态添加类,而其它的qdisc(例如:PRIO)不允许动态建立类。允许动态添加类的qdisc可以有零个或者多个子类,由它们为数据包排队。此外,每个类都有一个叶子qdisc,默认情况下,这个也在qdisc有可分类,不过每个子类只能有一个叶子qdisc。当一个数据包进入一个分类qdisc,它会被归入某个子类。我们可以使用一下三种方式为数据包归类,不过不是所有的qdisc都能够使用这三种方式。

如果过滤器附属于一个类,相关的指令就会对它们进行查询。过滤器能够匹配数据包头所有的域,也可以匹配由ebtables或者iptables做的标记。树的每个节点都可以有自己的过滤器,但是高层的过滤器也可以一直接用于其子类。如果数据包没有被成功归类,就会被排到这个类的叶子qdisc的队中。相关细节在各个qdisc的手册页中。

TC命名规则
所有的qdisc、类、和过滤器都有ID。ID可以手工设置,也可以由内核自动分配。ID由一个主序列号和一个从序列号组成,两个数字用一个冒号分开。qdisc,一个qdisc会被分配一个主序列号,叫做句柄(handle),然后把从序列号作为类的命名空间。句柄才有像1:0一样的表达方式。习惯上,需要为有子类的qdisc显式的分配一个句柄。类(Class),在同一个qdisc里面的类共享这个qdisc的主序列号,但是每个类都有自己的从序列号,叫做类识别符(classid)。类识别符只与父qdisc有关,与父类无关。类的命名习惯和qdisc相同。过滤器(Filter),过滤器的ID有三部分,只有在对过滤器进行散列组织才会用到。

TC流量的处理由三种对象控制,它们是:qdisc(排队规则)、class(类别)和filter(过滤器)。
qdisc 分类:

  • 1.CLASSLESS QDisc(不可分类QDisc)

[p|b]fifo
使用最简单的qdisc,纯粹的先进先出。只有一个参数:limit,用来设置队列的长度,pfifo是以数据包的个数为单位;bfifo是以字节数为单位。

pfifo_fast
在编译内核时,如果打开了高级路由器(Advanced Router)编译选项,pfifo_fast就是系统的标准QDISC。它的队列包括三个波段(band)。在每个波段里面,使用先进先出规则。而三个波段(band)的优先级也不相同,band 0的优先级最高,band 2的最低。如果band里面有数据包,系统就不会处理band 1里面的数据包,band 1和band 2之间也是一样。数据包是按照服务类型(Type of Service,TOS)被分配多三个波段(band)里面的。

red:
red是Random Early Detection(随机早期探测)的简写。如果使用这种QDISC,当带宽的占用接近于规定的带宽时,系统会随机地丢弃一些数据包。它非常适合高带宽应用。

sfq:
sfq是Stochastic Fairness Queueing(随机公平排队)的简写。它按照会话(session–对应于每个TCP连接或者UDP流)为流量进行排序,然后循环发送每个会话的数据包。

tbf
tbf是Token Bucket Filter的简写,适合于把流速降低到某个值。

  • 2.Classful QDisc(分类QDisc)

可分类的qdisc:
CBQ
CBQ是Class Based Queueing(基于类别排队)的缩写。它实现了一个丰富的连接共享类别结构,既有限制(shaping)带宽的能力,也具有带宽优先级管理的能力。带宽限制是通过计算连接的空闲时间完成的。空闲时间的计算标准是数据包离队事件的频率和下层连接(数据链路层)的带宽。

HTB等级令牌桶
HTB是Hierarchy Token Bucket的缩写。通过在实践基础上的改进,它实现了一个丰富的连接共享类别体系。使用HTB可以很容易地保证每个类别的带宽,虽然它也允许特定的类可以突破带宽上限,占用别的类的带宽。HTB可以通过TBF(Token Bucket Filter)实现带宽限制,也能够划分类别的优先级

PRIO
PRIO QDisc不能限制带宽,因为属于不同类别的数据包是顺序离队的。使用PRIO QDisc可以很容易对流量进行优先级管理,只有属于高优先级类别的数据包全部发送完毕,才会发送属于低优先级类别的数据包FILTER(过滤器),Filter(过滤器)用于为数据包分类,决定它们按照何种QDisc进入队列
TC 中的 Filter 规则
filter 用来将用户划入到具体的控制策略中(即不同的 class 中).比如,现在,我们想对 xxa,xxb两个 IP 实行不同的控制策略(A,B),这时,我们可用 filter 将 xxa 划入到控制策略 A,将 xxb 划入到控制策略 B,filter 划分的标志位可用 u32 打标功能或 IPtables的 set-mark (大多使用iptables 来做标记)功能来实现。
目前,TC 可以使用的过滤器有:fwmark 分类器,u32 分类器,基于路由的分类器和 RSVP分类器(分别用于 IPV6、IPV4)等;其中,fwmark分类器允许我们使用 Linux netfilter 代码选择流量,而 u32 分类器允许我们选择基于 ANY 头的流量 .需要注意的是,filter (过滤器)是在 QDisc 内部,它们不能作为主体。
4、命名规则
所有的QDisc、类和过滤器都有ID。ID可以手工设置,也可以有内核自动分配。
ID由一个主序列号和一个从序列号组成,两个数字用一个冒号分开。

关于TC,我们当前限速使用的有htb与sfq。

tc示例:

#增加ccinet0根队列,未标记数据默认走28
tc qdisc add dev ccinet0 root handle 1: htb default 28
#增加总流量规则
tc class add dev ccinet0 parent 1: classid 1:1 htb rate 1000Mbit burst 15k quantum 60000
#增加子类
tc class add dev ccinet0 parent 1:1 classid 1:11 htb rate 6000kbit ceil 6000kbit prio 0
#为子类添加SFQ公平队列,每10秒重置
tc qdisc add dev ccinet0 parent 1:11 handle 11: sfq perturb 10
#子类过滤规则,匹配标记值为21的数据包
tc filter add dev ccinet0 parent 1:0 prio 0 protocol ip handle 21 fw flowid 1:11

查看tc相关规则:

#查看网络状态信息
ifconfig
#查看网桥信息
brctl show
#查看所有网口的tc信息
tc qdisc
#查看ccinet0 tc信息
tc -s class ls dev ccinet0
#查看ccinet0 tc具体限速规则
tc -s filter ls dev ccinet0

关于tc快速上手可以参考:tc命令详解

需求分析

当前需要通过IP/Mac对特定设备或者ip段进行限速,或者通过固定端口(如USB,WIFI的某个ssid,或者通过LAN口接入的)进行限速。在当前情况下,只能从IP/MAC/端口三者中选一种模式(如果想要同时生效需要考虑冲突的情况以及兼容性处理,可自行实现)

明确网口结构

在正式开始前,需要明确一下要做限速的设备的interface结构,以我自身做过的项目为例,上行网口为ccinet0或者eth1(视具体项目而定),下行接口统一归到三层虚拟网桥br-lan上。
在这里插入图片描述

Linux中的QoS分为入口(ingress)部分和出口(egress)部分,ingress和egress是对router来说的,对于上行数据,设备数据进入到每个连接的网口是ingress方向,最后到ccinet0发出是egress方向,对于下行数据,进入ccinet0是ingress方向,从设备连接的网口发给设备是egress方向。

实现思路

整体的实现思路很简单:就是通过iptables或者ebtables等工具将数据包进行打标,在tc工具中根据打标值分流限速即可。

具体实现过程

一、基于端口限速的实现

主要思路是:
通过ebtables或者iptables对数据包打标,在tc规则中对打标数据进行管控从而进行速率限制。其中上行数据打标后统一放到ccinet0网口子类规则中进行处理,下行数据在每个网口子类规则中进行处理。

打标方法:

  • 1.通过iptables来实现打标

iptables可以在mangle表中对数据包进行打标,使用physdev模块
模块来做,具体示例如下:

#需要该命令开启才能正常打标。
sysctl -w net.bridge.bridge-nf-call-iptables=1iptables -t mangle -N AUTOLANIN
iptables -t mangle -I PREROUTING -m physdev --physdev-in autolan -j AUTOLANIN
iptables -t mangle -A AUTOLANIN -s 0.0.0.0/0 -j MARK --set-mark 21iptables -t mangle -N AUTOLANOUT
iptables -t mangle -I PREROUTING -m physdev --physdev-out autolan -j AUTOLANOUT
iptables -t mangle -A AUTOLANOUT -s 0.0.0.0/0 -j MARK --set-mark 20
  • 2.通过ebtables来实现打标。

打标也可以放到二层来做,由ebtables实现:

ebtables -t filter -I INPUT -i autolan -j mark --mark-set 21 --mark-target CONTINUE
ebtables -t filter -I OUTPUT -o autolan -j mark --mark-set 20 --mark-target CONTINUE
  • 3.其他可能的思路:
    ifb设备,根据tc相关文档描述,使用tc ingress限速,功能有限,似乎只能选择丢弃,并且也不支持分类。实际应用中,我们可以将业务流重定向到ifb设备上,业务流从这个ifb设备中出去,再又相应的端口接收,那我们就可以像正常使用tc对egress限速一样,来对ifb设备进行egress限速,就可以达到对接收方向的限速了(实际是将ingress方向重定向到虚拟设备ifb0,这样可以变相使用tc出口方向规则对流量进行控制,需要安装启用虚拟设备ifb,个人不采用此方式)

限速实现示例:

#需要关闭fastpath才能正常匹配数据包,否则匹配到数量非常少。之所以需要这个是因为当前设备采用的是ASR的芯片,其有一套内核加速机制,不关闭的话会导致无法打标
echo 1 > /sys/kernel/fastpath/fp_forward/bypass_fastpath
#打标
ebtables -t filter -I INPUT -i autolan -j mark --mark-set 21 --mark-target CONTINUE
ebtables -t filter -I OUTPUT -o autolan -j mark --mark-set 20 --mark-target CONTINUE
#上行速率限制
tc qdisc add dev ccinet0 root handle 1: htb default 28
tc class add dev ccinet0 parent 1: classid 1:1 htb rate 1000Mbit burst 15k quantum 60000
tc class add dev ccinet0 parent 1:1 classid 1:11 htb rate 6000kbit ceil 6000kbit prio 0
tc qdisc add dev ccinet0 parent 1:11 handle 11: sfq perturb 10
tc filter add dev ccinet0 parent 1:0 prio 0 protocol ip handle 21 fw flowid 1:11
#下行速率限制
tc qdisc add dev autolan root handle 1: htb default 28
tc class add dev autolan parent 1: classid 1:1 htb rate 1000Mbit burst 15k quantum 60000
tc class add dev autolan parent 1:1 classid 1:12 htb rate 8000kbit ceil 8000kbit prio 0
tc qdisc add dev autolan parent 1:12 handle 12: sfq perturb 10
tc filter add dev autolan parent 1:0 prio 0 protocol ip handle 20 fw flowid 1:12

参考实现:

#初始化tc队列(当前仅针对ccinet0,如果下行在br-lan中统一处理也放到此处)
qos_init_dev_tc_rule(){#增加根队列,未标记数据默认走28tc qdisc add dev ${UP_DEV} root handle 1: htb default 28#增加上行总流量限制规则tc class add dev ${UP_DEV} parent 1: classid 1:1 htb rate 1000Mbit burst 15k quantum 60000
}
#清空接口tc规则
qos_clear_dev_limit_rule(){local dev=$1tc qdisc del dev $dev root
}
#删除ebtables打标规则
qos_dev_delete_mark(){ebtables -t filter -D INPUT -i $1 -j mark --mark-set $2 --mark-target CONTINUEebtables -t filter -D OUTPUT -o $1 -j mark --mark-set $3 --mark-target CONTINUE
}
#添加ebtables二层打标规则
qos_dev_set_mark(){ebtables -t filter -I INPUT -i $1 -j mark --mark-set $2 --mark-target CONTINUEebtables -t filter -I OUTPUT -o $1 -j mark --mark-set $3 --mark-target CONTINUE#也可以使用physdev模块进行iptables打标,示例如下:#sysctl -w net.bridge.bridge-nf-call-iptables=1#iptables -t mangle -N ETH02#iptables -t mangle -I PREROUTING -m physdev --physdev-out eth0.2 -j ETH02#iptables -t mangle -A ETH02 -s 0.0.0.0/0 -j MARK --set-mark 21
}
#端口限速设置
qos_set_dev_limit(){local config=$1local up_bwlocal down_bwlocal dev_namelocal real_namelocal pri_numlocal dw_classidlocal up_classidlocal dw_marklocal up_marklocal enableconfig_get enable $config enableconfig_get dev_name $config dev_nameconfig_get down_bw $config down_bwconfig_get up_bw $config up_bwif [ "$dev_name" == "LAN1" ]; thenreal_name="autolan"pri_num=0classid=20dw_mark=20up_mark=30elif [ "$dev_name" == "SSID1_24G" ]; thenreal_name="wlan0"pri_num=0classid=21dw_mark=21up_mark=31elif [ "$dev_name" == "SSID2_24G" ]; thenreal_name="wlan0-va0"pri_num=0classid=22dw_mark=22up_mark=32elif [ "$dev_name" == "SSID3_24G" ]; thenreal_name="wlan0-va1"pri_num=0classid=23dw_mark=23up_mark=33elif [ "$dev_name" == "SSID1_5G" ]; thenreal_name="wlan1"pri_num=0classid=24dw_mark=24up_mark=34elif [ "$dev_name" == "SSID2_5G" ]; thenreal_name="wlan1-va0"pri_num=0classid=25dw_mark=25up_mark=35elif [ "$dev_name" == "SSID3_5G" ]; thenreal_name="wlan1-va1"pri_num=0classid=26dw_mark=26up_mark=36elseecho "dev_name is $dev_name" > /dev/kmsgreturn 0fiecho "real_name is $real_name" > /dev/kmsg#先清空一下针对该端口的规则qos_clear_dev_limit_rule ${real_name}qos_dev_delete_mark ${real_name} ${up_mark} ${dw_mark}if [ "$enable" == "0" ]; thenecho "$dev_name enable is 0" > /dev/kmsgreturn 0fiecho "dev_name is $dev_name, down_bw is $down_bw, up_bw is $up_bw" > /dev/kmsg#设置打标规则qos_dev_set_mark ${real_name} ${up_mark} ${dw_mark}#基于端口的上行限速设置
if [ "$up_bw" != "0" ]; then#增加子类tc class add dev ${UP_DEV} parent 1:1 classid 1:${classid} htb rate ${up_bw}Mbit ceil ${up_bw}Mbit prio 0#为子类添加SFQ公平队列,每10秒重置tc qdisc add dev ${UP_DEV} parent 1:${classid} handle ${classid}: sfq perturb 10#根据打标值过滤tc filter add dev ${UP_DEV} parent 1:0 prio 0 protocol ip handle ${up_mark} fw flowid 1:${classid}
fi#基于端口的下行限速设置
if [ "$down_bw" != "0" ]; thentc qdisc add dev ${real_name} root handle 1: htb default 28tc class add dev ${real_name} parent 1: classid 1:1 htb rate 1000Mbit burst 15k quantum 60000#添加子类tc class add dev ${real_name} parent 1:1 classid 1:${classid} htb rate ${down_bw}Mbit ceil ${down_bw}Mbit prio 0#为子类添加SFQ公平队列tc qdisc add dev ${real_name} parent 1:${classid} handle ${classid}: sfq perturb 10#过滤规则tc filter add dev ${real_name} parent 1:0 prio 0 protocol ip handle ${dw_mark} fw flowid 1:${classid}
fi
}
qos_set_dev_rule(){qos_init_dev_tc_ruleconfig_foreach qos_set_dev_limit qos_dev_limit
}

二、基于MAC限速的实现

主要思路是:

  • 1.老思路:通过mac查arp表,最后通过ip来限速

存在的问题及应对思路:
CPE重启后执行脚本时设备未连接,arp表中查找不到mac对应ip会导致规则设置失败,后续设备连接后出现速度不受限情况

应对:新连接进来设备时重新执行脚本(在代码中操作不修改shell脚本,当前已采用新思路,未使用该方法)

老思路参考实现:

#初始化基于ip和mac的tc规则
qos_init_tc_rule(){#新建限速队列tc qdisc add dev ${UP_DEV} root handle 100: htb default 100tc qdisc add dev ${DN_DEV} root handle 200: htb default 200#新建根分类tc class add dev ${UP_DEV} parent 100: classid 100:1 htb rate 1000Mbit burst 15k quantum 60000tc class add dev ${DN_DEV} parent 200: classid 200:1 htb rate 1000Mbit burst 15k quantum 60000
}
#删除旧链
qos_delete_mac_limit_chain(){iptables -t mangle -D FORWARD -j QOS_MAC_FORWARDiptables -t mangle -F QOS_MAC_FORWARDiptables -t mangle -X QOS_MAC_FORWARD
}
#创建qos链
qos_create_mac_limit_chain(){iptables -t mangle -N QOS_MAC_FORWARDiptables -t mangle -I FORWARD -j QOS_MAC_FORWARD
}
qos_set_mac_limit(){local config=$1local up_bwlocal down_bwlocal mac_addrlocal mac_addr_lowerlocal ip_addrlocal ip_taglocal enableconfig_get enable $config enableconfig_get mac_addr $config mac_addrconfig_get down_bw $config down_bwconfig_get up_bw $config up_bwecho "mac_addr is $mac_addr" > /dev/kmsgif [ "$enable" == "0" ]; thenecho "$mac_addr enable is 0" > /dev/kmsgreturn 0fi#将mac地址转换为小写,不然大写的匹配不到ipmac_addr_lower=$(echo $mac_addr | tr '[A-Z]' '[a-z]')local ip_addr=`cat /proc/net/arp |grep $mac_addr_lower | awk -F ' ' '{print $1}'`if [ "$ip_addr" == "" ]; thenecho "the ip addr of $mac_addr is null" > /dev/kmsgreturn 0filocal ip_tag=`echo $ip_addr | awk -F '.' '{print $4}'`echo "ip_addr is $ip_addr, ip_tag is $ip_tag" > /dev/kmsgif [ "$up_bw" != "0" ]; then#创建子分类tc class add dev ${UP_DEV} parent 100:1 classid 100:${ip_tag} htb rate ${up_bw}Mbit ceil ${up_bw}Mbit burst 15k prio 1#创建过滤器	tc filter add dev ${UP_DEV} protocol all parent 100: prio 1 handle $ip_tag fw classid 100:${ip_tag}#创建公平队列tc qdisc add dev ${UP_DEV} parent 100:${ip_tag} handle ${ip_tag}: sfq perturb 10iptables -t mangle -A QOS_MAC_FORWARD -s $ip_addr/32 -j MARK --set-mark ${ip_tag}		
fiif [ "$down_bw" != "0" ]; thentc class add dev ${DN_DEV} parent 200:1 classid 200:${ip_tag} htb rate ${down_bw}Mbit ceil ${down_bw}Mbit burst 15k prio 2tc filter add dev ${DN_DEV} protocol all parent 200: prio 2 handle $ip_tag fw classid 200:${ip_tag}tc qdisc add dev ${DN_DEV} parent 200:${ip_tag} handle ${ip_tag}: sfq perturb 10iptables -t mangle -A QOS_MAC_FORWARD -d $ip_addr/32 -j MARK --set-mark ${ip_tag}
fi
}
qos_set_mac_rule(){qos_init_tc_ruleqos_create_mac_limit_chainconfig_foreach qos_set_mac_limit qos_mac_limit
}
  • 2.新思路:通过mac模块对mac打标直接进行限速

存在的问题及应对思路:
–mac-source 只能用于PREROUTING/INPUT/FORWARD这三个链,下行数据在nat转换前数据包目的mac非目标设备mac,如果直接在iptables中打标会不成功,所以采用ebtables进行打标,但是ebtables打标就无法在br-lan上做下行的限速

应对:在br-lan网桥下挂的所有网口都设定tc规则

#新思路参考实现qos_init_mac_tc_rule(){#新建限速队列tc qdisc add dev ${UP_DEV} root handle 100: htb default 100tc qdisc add dev autolan root handle 200: htb default 200tc qdisc add dev wlan0 root handle 300: htb default 300tc qdisc add dev wlan0-va0 root handle 400: htb default 400tc qdisc add dev wlan0-va1 root handle 500: htb default 500tc qdisc add dev wlan1 root handle 600: htb default 600tc qdisc add dev wlan1-va0 root handle 700: htb default 700tc qdisc add dev wlan1-va1 root handle 800: htb default 800#新建根分类tc class add dev ${UP_DEV} parent 100: classid 100:1 htb rate 1000Mbit burst 15k quantum 60000tc class add dev autolan parent 200: classid 200:1 htb rate 1000Mbit burst 15k quantum 60000tc class add dev wlan0 parent 300: classid 300:1 htb rate 1000Mbit burst 15k quantum 60000tc class add dev wlan0-va0 parent 400: classid 400:1 htb rate 1000Mbit burst 15k quantum 60000tc class add dev wlan0-va1 parent 500: classid 500:1 htb rate 1000Mbit burst 15k quantum 60000tc class add dev wlan1 parent 600: classid 600:1 htb rate 1000Mbit burst 15k quantum 60000tc class add dev wlan1-va0 parent 700: classid 700:1 htb rate 1000Mbit burst 15k quantum 60000tc class add dev wlan1-va1 parent 800: classid 800:1 htb rate 1000Mbit burst 15k quantum 60000
}
#删除ebtables旧链
qos_delete_mac_limit_chain(){ebtables -D INPUT -j QOS_MAC_CHAINebtables -D OUTPUT -j QOS_MAC_CHAINebtables -F QOS_MAC_CHAINebtables -X QOS_MAC_CHAIN
}
#创建qos链
qos_create_mac_limit_chain(){ebtables -t filter -N QOS_MAC_CHAINebtables -t filter -I INPUT -j QOS_MAC_CHAINebtables -t filter -I OUTPUT -j QOS_MAC_CHAIN
}
#基于mac的初始打标值
mac_mark_value=10
#mac限速设置
qos_set_mac_limit(){local mark_valuelocal config=$1local up_bwlocal down_bwlocal mac_addrlocal mac_addr_lowerlocal ip_addrlocal ip_taglocal enableconfig_get enable $config enableconfig_get mac_addr $config mac_addrconfig_get down_bw $config down_bwconfig_get up_bw $config up_bwecho "mac_addr is $mac_addr" > /dev/kmsgif [ "$enable" == "0" ]; thenecho "$mac_addr enable is 0" > /dev/kmsgreturn 0fi#统一换成小写mac地址mac_addr_lower=$(echo $mac_addr | tr '[A-Z]' '[a-z]')if [ "$mac_addr_lower" == "" ]; thenecho "the mac addr is null" > /dev/kmsgreturn 0fimark_value=$mac_mark_value#打标值递增,区分下一mac打标值mac_mark_value=$(($mac_mark_value+1))  echo "mac_addr is $mac_addr_lower, mac_tag is $mark_value" > /dev/kmsg#上行统一在各个子类中处理
if [ "$up_bw" != "0" ]; then#创建子分类tc class add dev ${UP_DEV} parent 100:1 classid 100:${mark_value} htb rate ${up_bw}Mbit ceil ${up_bw}Mbit burst 15k prio 1#创建过滤器	tc filter add dev ${UP_DEV} protocol all parent 100: prio 1 handle $mark_value fw classid 100:${mark_value}#创建公平队列tc qdisc add dev ${UP_DEV} parent 100:${mark_value} handle ${mark_value}: sfq perturb 10ebtables -t filter -A QOS_MAC_CHAIN -s "$mac_addr_lower" -j mark --mark-set ${mark_value} --mark-target CONTINUE
fiif [ "$down_bw" != "0" ]; thenebtables -t filter -A QOS_MAC_CHAIN -d "$mac_addr_lower" -j mark --mark-set ${mark_value} --mark-target CONTINUEtc class add dev autolan parent 200:1 classid 200:${mark_value} htb rate ${down_bw}Mbit ceil ${down_bw}Mbit burst 15k prio 2tc filter add dev autolan protocol all parent 200: prio 2 handle $mark_value fw classid 200:${mark_value}tc qdisc add dev autolan parent 200:${mark_value} handle ${mark_value}: sfq perturb 10tc class add dev wlan0 parent 300:1 classid 300:${mark_value} htb rate ${down_bw}Mbit ceil ${down_bw}Mbit burst 15k prio 2tc filter add dev wlan0 protocol all parent 300: prio 2 handle $mark_value fw classid 300:${mark_value}tc qdisc add dev wlan0 parent 300:${mark_value} handle ${mark_value}: sfq perturb 10tc class add dev wlan0-va0 parent 400:1 classid 400:${mark_value} htb rate ${down_bw}Mbit ceil ${down_bw}Mbit burst 15k prio 2tc filter add dev wlan0-va0 protocol all parent 400: prio 2 handle $mark_value fw classid 400:${mark_value}tc qdisc add dev wlan0-va0 parent 400:${mark_value} handle ${mark_value}: sfq perturb 10tc class add dev wlan0-va1 parent 500:1 classid 500:${mark_value} htb rate ${down_bw}Mbit ceil ${down_bw}Mbit burst 15k prio 2tc filter add dev wlan0-va1 protocol all parent 500: prio 2 handle $mark_value fw classid 500:${mark_value}tc qdisc add dev wlan0-va1 parent 500:${mark_value} handle ${mark_value}: sfq perturb 10tc class add dev wlan1 parent 600:1 classid 600:${mark_value} htb rate ${down_bw}Mbit ceil ${down_bw}Mbit burst 15k prio 2tc filter add dev wlan1 protocol all parent 600: prio 2 handle $mark_value fw classid 600:${mark_value}tc qdisc add dev wlan1 parent 600:${mark_value} handle ${mark_value}: sfq perturb 10tc class add dev wlan1-va0 parent 700:1 classid 700:${mark_value} htb rate ${down_bw}Mbit ceil ${down_bw}Mbit burst 15k prio 2tc filter add dev wlan1-va0 protocol all parent 700: prio 2 handle $mark_value fw classid 700:${mark_value}tc qdisc add dev wlan1-va0 parent 700:${mark_value} handle ${mark_value}: sfq perturb 10tc class add dev wlan1-va1 parent 800:1 classid 800:${mark_value} htb rate ${down_bw}Mbit ceil ${down_bw}Mbit burst 15k prio 2tc filter add dev wlan1-va1 protocol all parent 800: prio 2 handle $mark_value fw classid 800:${mark_value}tc qdisc add dev wlan1-va1 parent 800:${mark_value} handle ${mark_value}: sfq perturb 10
fi
}
qos_set_mac_rule(){qos_init_mac_tc_ruleqos_create_mac_limit_chainconfig_foreach qos_set_mac_limit qos_mac_limit
}

三、基于IP限速的实现

主要思路是:
在mangle表中使用-s、-d参数或者使用iprange模块对数据进行打标,然后在ccinet0和br-lan上使用tc规则进行限速处理

参考实现:

#初始化基于ip和mac的tc规则
qos_init_tc_rule(){#新建限速队列tc qdisc add dev ${UP_DEV} root handle 100: htb default 100tc qdisc add dev ${DN_DEV} root handle 200: htb default 200#新建根分类tc class add dev ${UP_DEV} parent 100: classid 100:1 htb rate 1000Mbit burst 15k quantum 60000tc class add dev ${DN_DEV} parent 200: classid 200:1 htb rate 1000Mbit burst 15k quantum 60000
}
#删除旧链
qos_delete_ip_limit_chain(){iptables -t mangle -D FORWARD -j QOS_IP_FORWARDiptables -t mangle -F QOS_IP_FORWARDiptables -t mangle -X QOS_IP_FORWARD
}
#创建qos链
qos_create_ip_limit_chain(){iptables -t mangle -N QOS_IP_FORWARDiptables -t mangle -I FORWARD -j QOS_IP_FORWARD
}
qos_set_ip_limit(){local config=$1local up_bwlocal down_bwlocal start_iplocal end_iplocal enableconfig_get enable $config enableconfig_get start_ip $config start_ipconfig_get end_ip $config end_ipconfig_get down_bw $config down_bwconfig_get up_bw $config up_bwif [ "$enable" == "0" ]; thenecho "$start_ip enable is 0" > /dev/kmsgreturn 0filocal start_last=`echo $start_ip | awk -F '.' '{print $4}'`local end_last=`echo $end_ip | awk -F '.' '{print $4}'`echo "start_last is $start_last, end_last is $end_last" > /dev/kmsgif [ "$up_bw" != "0" ]; then#创建子分类tc class add dev ${UP_DEV} parent 100:1 classid 100:${start_last} htb rate ${up_bw}Mbit ceil ${up_bw}Mbit burst 15k prio 1#创建过滤器	tc filter add dev ${UP_DEV} protocol all parent 100: prio 1 handle $start_last fw classid 100:${start_last}#创建公平队列tc qdisc add dev ${UP_DEV} parent 100:${start_last} handle ${start_last}: sfq perturb 10
fiif [ "$down_bw" != "0" ]; thentc class add dev ${DN_DEV} parent 200:1 classid 200:${start_last} htb rate ${down_bw}Mbit ceil ${down_bw}Mbit burst 15k prio 2tc filter add dev ${DN_DEV} protocol all parent 200: prio 2 handle $start_last fw classid 200:${start_last}tc qdisc add dev ${DN_DEV} parent 200:${start_last} handle ${start_last}: sfq perturb 10fiif [ "$start_ip" == "$end_ip" ]; theniptables -t mangle -A QOS_IP_FORWARD -s $start_ip/32 -j MARK --set-mark ${start_last}iptables -t mangle -A QOS_IP_FORWARD -d $start_ip/32 -j MARK --set-mark ${start_last}elseiptables -t mangle -A QOS_IP_FORWARD -m iprange --src-range ${start_ip}-${end_ip} -j MARK --set-mark ${start_last}iptables -t mangle -A QOS_IP_FORWARD -m iprange --dst-range ${start_ip}-${end_ip} -j MARK --set-mark ${start_last}
fi}
qos_set_ip_rule(){qos_init_tc_ruleqos_create_ip_limit_chainconfig_foreach qos_set_ip_limit qos_ip_limit
}

四、整体shell脚本

#!/bin/sh
. /lib/functions.sh
. /lib/config/uci.shQOS_FILE="qos"
g_qos_enable=""
g_limit_mode=""
UP_DEV="ccinet0"
DN_DEV="br-lan"LAN_NAME=""
DEVICE_LAN_SWITCH=""
#LAN_NAME="eth0.2"  #with switch
#LAN_NAME="eth0"  #without switch#######################################################start of qos based on dev
#初始化tc队列(当前仅针对ccinet0,如果下行在br-lan中统一处理也放到此处)
qos_init_dev_tc_rule(){#增加根队列,未标记数据默认走28tc qdisc add dev ${UP_DEV} root handle 1: htb default 28#增加上行总流量限制规则tc class add dev ${UP_DEV} parent 1: classid 1:1 htb rate 1000Mbit burst 15k quantum 60000
}
#清空接口tc规则
qos_clear_dev_limit_rule(){local dev=$1tc qdisc del dev $dev root
}
#删除ebtables打标规则
qos_dev_delete_mark(){ebtables -t filter -D INPUT -i $1 -j mark --mark-set $2 --mark-target CONTINUEebtables -t filter -D OUTPUT -o $1 -j mark --mark-set $3 --mark-target CONTINUE
}
#添加ebtables二层打标规则
qos_dev_set_mark(){ebtables -t filter -I INPUT -i $1 -j mark --mark-set $2 --mark-target CONTINUEebtables -t filter -I OUTPUT -o $1 -j mark --mark-set $3 --mark-target CONTINUE#也可以使用physdev模块进行iptables打标,示例如下:#sysctl -w net.bridge.bridge-nf-call-iptables=1#iptables -w -t mangle -N ETH02#iptables -w -t mangle -I PREROUTING -m physdev --physdev-out eth0.2 -j ETH02#iptables -w -t mangle -A ETH02 -s 0.0.0.0/0 -j MARK --set-mark 21
}
#端口限速设置
qos_set_dev_limit(){local config=$1local up_bwlocal down_bwlocal dev_namelocal real_namelocal pri_numlocal dw_classidlocal up_classidlocal dw_marklocal up_marklocal enableconfig_get enable $config enableconfig_get dev_name $config dev_nameconfig_get down_bw $config down_bwconfig_get up_bw $config up_bwif [ "$dev_name" == "LAN1" ]; thenreal_name="${LAN_NAME}"pri_num=0classid=20dw_mark=20up_mark=30elif [ "$dev_name" == "SSID1_24G" ]; thenreal_name="wlan0"pri_num=0classid=21dw_mark=21up_mark=31elif [ "$dev_name" == "SSID2_24G" ]; thenreal_name="wlan0-va0"pri_num=0classid=22dw_mark=22up_mark=32elif [ "$dev_name" == "SSID3_24G" ]; thenreal_name="wlan0-va1"pri_num=0classid=23dw_mark=23up_mark=33elif [ "$dev_name" == "SSID1_5G" ]; thenreal_name="wlan1"pri_num=0classid=24dw_mark=24up_mark=34elif [ "$dev_name" == "SSID2_5G" ]; thenreal_name="wlan1-va0"pri_num=0classid=25dw_mark=25up_mark=35elif [ "$dev_name" == "SSID3_5G" ]; thenreal_name="wlan1-va1"pri_num=0classid=26dw_mark=26up_mark=36elseecho "dev_name is $dev_name" > /dev/kmsgreturn 0fiecho "real_name is $real_name" > /dev/kmsg#先清空一下针对该端口的规则qos_clear_dev_limit_rule ${real_name}qos_dev_delete_mark ${real_name} ${up_mark} ${dw_mark}if [ "$enable" == "0" ]; thenecho "$dev_name enable is 0" > /dev/kmsgreturn 0fiecho "dev_name is $dev_name, down_bw is $down_bw, up_bw is $up_bw" > /dev/kmsg#设置打标规则qos_dev_set_mark ${real_name} ${up_mark} ${dw_mark}#基于端口的上行限速设置if [ "$up_bw" != "0" ]; then#增加子类tc class add dev ${UP_DEV} parent 1:1 classid 1:${classid} htb rate ${up_bw}Mbit ceil ${up_bw}Mbit prio 0#为子类添加SFQ公平队列,每10秒重置tc qdisc add dev ${UP_DEV} parent 1:${classid} handle ${classid}: sfq perturb 10#根据打标值过滤tc filter add dev ${UP_DEV} parent 1:0 prio 0 protocol ip handle ${up_mark} fw flowid 1:${classid}fi#基于端口的下行限速设置if [ "$down_bw" != "0" ]; thentc qdisc add dev ${real_name} root handle 1: htb default 28tc class add dev ${real_name} parent 1: classid 1:1 htb rate 1000Mbit burst 15k quantum 60000#添加子类tc class add dev ${real_name} parent 1:1 classid 1:${classid} htb rate ${down_bw}Mbit ceil ${down_bw}Mbit prio 0#为子类添加SFQ公平队列tc qdisc add dev ${real_name} parent 1:${classid} handle ${classid}: sfq perturb 10#过滤规则tc filter add dev ${real_name} parent 1:0 prio 0 protocol ip handle ${dw_mark} fw flowid 1:${classid}fi
}
qos_set_dev_rule(){#上行速率控制统一放到ccinet0子类中分开处理,下行速率控制放到每一个dev中处理(如果不生效考虑在br-lan中用子类进行处理)#`echo 1 > /sys/kernel/fastpath/fp_forward/bypass_fastpath`qos_init_dev_tc_ruleconfig_foreach qos_set_dev_limit qos_dev_limit
}
#######################################################end of qos based on dev#######################################################start of qos based on mac
#当前只能在ebtables上对特定mac打标,处理采用在每个dev上都做限制#初始化基于mac的tc规则
qos_init_mac_tc_rule(){#新建限速队列tc qdisc add dev ${UP_DEV} root handle 100: htb default 100tc qdisc add dev ${LAN_NAME} root handle 200: htb default 200tc qdisc add dev wlan0 root handle 300: htb default 300tc qdisc add dev wlan0-va0 root handle 400: htb default 400tc qdisc add dev wlan0-va1 root handle 500: htb default 500tc qdisc add dev wlan1 root handle 600: htb default 600tc qdisc add dev wlan1-va0 root handle 700: htb default 700tc qdisc add dev wlan1-va1 root handle 800: htb default 800#新建根分类tc class add dev ${UP_DEV} parent 100: classid 100:1 htb rate 1000Mbit burst 15k quantum 60000tc class add dev ${LAN_NAME} parent 200: classid 200:1 htb rate 1000Mbit burst 15k quantum 60000tc class add dev wlan0 parent 300: classid 300:1 htb rate 1000Mbit burst 15k quantum 60000tc class add dev wlan0-va0 parent 400: classid 400:1 htb rate 1000Mbit burst 15k quantum 60000tc class add dev wlan0-va1 parent 500: classid 500:1 htb rate 1000Mbit burst 15k quantum 60000tc class add dev wlan1 parent 600: classid 600:1 htb rate 1000Mbit burst 15k quantum 60000tc class add dev wlan1-va0 parent 700: classid 700:1 htb rate 1000Mbit burst 15k quantum 60000tc class add dev wlan1-va1 parent 800: classid 800:1 htb rate 1000Mbit burst 15k quantum 60000
}
#删除ebtables旧链
qos_delete_mac_limit_chain(){#iptables -w -t mangle -D FORWARD -j QOS_MAC_FORWARD#iptables -w -t mangle -F QOS_MAC_FORWARD#iptables -w -t mangle -X QOS_MAC_FORWARDebtables -D INPUT -j QOS_MAC_CHAINebtables -D OUTPUT -j QOS_MAC_CHAINebtables -F QOS_MAC_CHAINebtables -X QOS_MAC_CHAIN
}
#创建qos链
qos_create_mac_limit_chain(){#iptables -w -t mangle -N QOS_MAC_FORWARD#iptables -w -t mangle -I FORWARD -j QOS_MAC_FORWARDebtables -t filter -N QOS_MAC_CHAINebtables -t filter -I INPUT -j QOS_MAC_CHAINebtables -t filter -I OUTPUT -j QOS_MAC_CHAIN
}
#基于mac的初始打标值
mac_mark_value=10
#mac限速设置
qos_set_mac_limit(){local mark_valuelocal config=$1local up_bwlocal down_bwlocal mac_addrlocal mac_addr_lowerlocal ip_addrlocal ip_taglocal enableconfig_get enable $config enableconfig_get mac_addr $config mac_addrconfig_get down_bw $config down_bwconfig_get up_bw $config up_bwecho "mac_addr is $mac_addr" > /dev/kmsgif [ "$enable" == "0" ]; thenecho "$mac_addr enable is 0" > /dev/kmsgreturn 0fi#统一换成小写mac地址mac_addr_lower=$(echo $mac_addr | tr '[A-Z]' '[a-z]')if [ "$mac_addr_lower" == "" ]; thenecho "the mac addr is null" > /dev/kmsgreturn 0fimark_value=$mac_mark_value#打标值递增,区分下一mac打标值mac_mark_value=$(($mac_mark_value+1))  echo "mac_addr is $mac_addr_lower, mac_tag is $mark_value" > /dev/kmsg#上行统一在各个子类中处理if [ "$up_bw" != "0" ]; then#创建子分类tc class add dev ${UP_DEV} parent 100:1 classid 100:${mark_value} htb rate ${up_bw}Mbit ceil ${up_bw}Mbit burst 15k prio 1#创建过滤器	tc filter add dev ${UP_DEV} protocol all parent 100: prio 1 handle $mark_value fw classid 100:${mark_value}#创建公平队列tc qdisc add dev ${UP_DEV} parent 100:${mark_value} handle ${mark_value}: sfq perturb 10ebtables -t filter -A QOS_MAC_CHAIN -s "$mac_addr_lower" -j mark --mark-set ${mark_value} --mark-target CONTINUEfiif [ "$down_bw" != "0" ]; then#iptables mac模块--mac-source只能在PREROUTING/INPUT/FORWARD中使用,nat转换之前的目的mac非设备mac无法正确匹配#针对真实mac地址无法在nat修改mac后打标,只能在ebtables上打标,br-lan无法处理所以在br-lan下每一个端口都加上tc规则(另一种方式:接入设备重新加载脚本,未采用)ebtables -t filter -A QOS_MAC_CHAIN -d "$mac_addr_lower" -j mark --mark-set ${mark_value} --mark-target CONTINUEtc class add dev ${LAN_NAME} parent 200:1 classid 200:${mark_value} htb rate ${down_bw}Mbit ceil ${down_bw}Mbit burst 15k prio 2tc filter add dev ${LAN_NAME} protocol all parent 200: prio 2 handle $mark_value fw classid 200:${mark_value}tc qdisc add dev ${LAN_NAME} parent 200:${mark_value} handle ${mark_value}: sfq perturb 10tc class add dev wlan0 parent 300:1 classid 300:${mark_value} htb rate ${down_bw}Mbit ceil ${down_bw}Mbit burst 15k prio 2tc filter add dev wlan0 protocol all parent 300: prio 2 handle $mark_value fw classid 300:${mark_value}tc qdisc add dev wlan0 parent 300:${mark_value} handle ${mark_value}: sfq perturb 10tc class add dev wlan0-va0 parent 400:1 classid 400:${mark_value} htb rate ${down_bw}Mbit ceil ${down_bw}Mbit burst 15k prio 2tc filter add dev wlan0-va0 protocol all parent 400: prio 2 handle $mark_value fw classid 400:${mark_value}tc qdisc add dev wlan0-va0 parent 400:${mark_value} handle ${mark_value}: sfq perturb 10tc class add dev wlan0-va1 parent 500:1 classid 500:${mark_value} htb rate ${down_bw}Mbit ceil ${down_bw}Mbit burst 15k prio 2tc filter add dev wlan0-va1 protocol all parent 500: prio 2 handle $mark_value fw classid 500:${mark_value}tc qdisc add dev wlan0-va1 parent 500:${mark_value} handle ${mark_value}: sfq perturb 10tc class add dev wlan1 parent 600:1 classid 600:${mark_value} htb rate ${down_bw}Mbit ceil ${down_bw}Mbit burst 15k prio 2tc filter add dev wlan1 protocol all parent 600: prio 2 handle $mark_value fw classid 600:${mark_value}tc qdisc add dev wlan1 parent 600:${mark_value} handle ${mark_value}: sfq perturb 10tc class add dev wlan1-va0 parent 700:1 classid 700:${mark_value} htb rate ${down_bw}Mbit ceil ${down_bw}Mbit burst 15k prio 2tc filter add dev wlan1-va0 protocol all parent 700: prio 2 handle $mark_value fw classid 700:${mark_value}tc qdisc add dev wlan1-va0 parent 700:${mark_value} handle ${mark_value}: sfq perturb 10tc class add dev wlan1-va1 parent 800:1 classid 800:${mark_value} htb rate ${down_bw}Mbit ceil ${down_bw}Mbit burst 15k prio 2tc filter add dev wlan1-va1 protocol all parent 800: prio 2 handle $mark_value fw classid 800:${mark_value}tc qdisc add dev wlan1-va1 parent 800:${mark_value} handle ${mark_value}: sfq perturb 10fi
}
qos_set_mac_rule(){qos_init_mac_tc_ruleqos_create_mac_limit_chainconfig_foreach qos_set_mac_limit qos_mac_limit
}
#######################################################end of qos based on mac#######################################################start of qos based on ip
#初始化基于ip的tc规则
qos_init_ip_tc_rule(){#新建限速队列tc qdisc add dev ${UP_DEV} root handle 100: htb default 100tc qdisc add dev ${DN_DEV} root handle 200: htb default 200#新建根分类tc class add dev ${UP_DEV} parent 100: classid 100:1 htb rate 1000Mbit burst 15k quantum 60000tc class add dev ${DN_DEV} parent 200: classid 200:1 htb rate 1000Mbit burst 15k quantum 60000
}
#删除旧链
qos_delete_ip_limit_chain(){iptables -w -t mangle -D FORWARD -j QOS_IP_FORWARDiptables -w -t mangle -F QOS_IP_FORWARDiptables -w -t mangle -X QOS_IP_FORWARD
}
#创建qos链
qos_create_ip_limit_chain(){iptables -w -t mangle -N QOS_IP_FORWARDiptables -w -t mangle -I FORWARD -j QOS_IP_FORWARD
}
qos_set_ip_limit(){local config=$1local up_bwlocal down_bwlocal start_iplocal end_iplocal enableconfig_get enable $config enableconfig_get start_ip $config start_ipconfig_get end_ip $config end_ipconfig_get down_bw $config down_bwconfig_get up_bw $config up_bwif [ "$enable" == "0" ]; thenecho "$start_ip enable is 0" > /dev/kmsgreturn 0filocal start_last=`echo $start_ip | awk -F '.' '{print $4}'`local end_last=`echo $end_ip | awk -F '.' '{print $4}'`echo "start_last is $start_last, end_last is $end_last" > /dev/kmsgif [ "$up_bw" != "0" ]; then#创建子分类tc class add dev ${UP_DEV} parent 100:1 classid 100:${start_last} htb rate ${up_bw}Mbit ceil ${up_bw}Mbit burst 15k prio 1#创建过滤器	tc filter add dev ${UP_DEV} protocol all parent 100: prio 1 handle $start_last fw classid 100:${start_last}#创建公平队列tc qdisc add dev ${UP_DEV} parent 100:${start_last} handle ${start_last}: sfq perturb 10fiif [ "$down_bw" != "0" ]; thentc class add dev ${DN_DEV} parent 200:1 classid 200:${start_last} htb rate ${down_bw}Mbit ceil ${down_bw}Mbit burst 15k prio 2tc filter add dev ${DN_DEV} protocol all parent 200: prio 2 handle $start_last fw classid 200:${start_last}tc qdisc add dev ${DN_DEV} parent 200:${start_last} handle ${start_last}: sfq perturb 10fiif [ "$start_ip" == "$end_ip" ]; theniptables -w -t mangle -A QOS_IP_FORWARD -s $start_ip/32 -j MARK --set-mark ${start_last}iptables -w -t mangle -A QOS_IP_FORWARD -d $start_ip/32 -j MARK --set-mark ${start_last}elseiptables -w -t mangle -A QOS_IP_FORWARD -m iprange --src-range ${start_ip}-${end_ip} -j MARK --set-mark ${start_last}iptables -w -t mangle -A QOS_IP_FORWARD -m iprange --dst-range ${start_ip}-${end_ip} -j MARK --set-mark ${start_last}fi}
qos_set_ip_rule(){qos_init_ip_tc_ruleqos_create_ip_limit_chainconfig_foreach qos_set_ip_limit qos_ip_limit
}
#######################################################end of qos based on ipqos_del_all_rule(){tc qdisc del dev ${UP_DEV} roottc qdisc del dev ${DN_DEV} roottc qdisc del dev ${LAN_NAME} roottc qdisc del dev wlan0 roottc qdisc del dev wlan0-va0 roottc qdisc del dev wlan0-va1 roottc qdisc del dev wlan1 roottc qdisc del dev wlan1-va0 roottc qdisc del dev wlan1-va1 root#qos_delete_dev_limit_chainqos_delete_mac_limit_chainqos_delete_ip_limit_chain}#qos_init
qos_init(){config_load "$QOS_FILE"config_get g_qos_enable qos_ctrl qos_enableconfig_get g_limit_mode qos_ctrl current_mode#config_get LAN_NAME qos_ctrl lan_nameDEVICE_LAN_SWITCH=$(uci get properties.DEVICE_LAN_SWITCH)if [ "$DEVICE_LAN_SWITCH" == "1" ];thenLAN_NAME="eth0.2"elseLAN_NAME="eth0"fiecho "DEVICE_LAN_SWITCH: $DEVICE_LAN_SWITCH" > /dev/kmsgqos_del_all_ruleecho "g_qos_enable=$g_qos_enable g_limit_mode=$g_limit_mode" > /dev/kmsgecho "modified on 2023.8.1" > /dev/kmsgif [ -z "$g_qos_enable" ]; thenecho "g_qos_enable is null" > /dev/kmsgexit 0fiif [ "$g_qos_enable" = "1" ] ; then`echo 1 > /sys/kernel/fastpath/fp_forward/bypass_fastpath`echo "qos_enable is 1, start config!" > /dev/kmsgif [ "$g_limit_mode" == "dev" ]; thenqos_set_dev_ruleelif [ "$g_limit_mode" == "mac" ]; thenqos_set_mac_ruleelif [ "$g_limit_mode" == "ip" ]; thenqos_set_ip_ruleelseecho "g_limit_mode is error, qos exit!" > /dev/kmsgfielif [ "$g_qos_enable" = "0" ] ; then	echo "qos_enable is 0, exit!" > /dev/kmsg`echo 0 > /sys/kernel/fastpath/fp_forward/bypass_fastpath`exit 0elseecho "g_qos_enable value is error" > /dev/kmsgfi
}input_type=$1
case $input_type in"init")qos_init ;;
esac 

五、注意事项

  • 1.确认上行网口名称,当前上行为UP_DEV="ccinet0"下行为DN_DEV=“br-lan”
  • 2.确认LAN口和wifi的实际名称,该信息在基于端口和基于MAC的限速中会用到
  • 3.手动测试时需要将fastpath关闭否则打标匹配存在问题 echo 1 > /sys/kernel/fastpath/fp_forward/bypass_fastpath
  • 4.如果需要对WAN接入做限制,需要对应修改相关内容

六、其他补充信息

常用的一些命令:

#显示信息
ebtables -L --Lc
iptables -t mangle -nvL
tc qdisc
tc  qdisc show dev ccinet0
tc -s class ls dev ccinet0
tc -s filter ls dev ccinet0
#清空tc规则
tc qdisc del dev ${UP_DEV} root
tc qdisc del dev ${DN_DEV} root
tc qdisc del dev autolan root
tc qdisc del dev wlan0 root
tc qdisc del dev wlan0-va0 root
tc qdisc del dev wlan0-va1 root
tc qdisc del dev wlan1 root
tc qdisc del dev wlan1-va0 root
tc qdisc del dev wlan1-va1 root
#调用函数清空打标规则
qos_delete_mac_limit_chain
qos_delete_ip_limit_chain

常用限速单位

kbps                            千字节/秒
mbps                            兆字节/秒
kbit                            KBits/秒
mbit                            MBits/秒
bps或者一个无单位数字             字节数/秒

Ref:
https://blog.51cto.com/u_15065849/3803690
http://doc.aiwaly.com/docs/arm/arm-1ek8uo3rs27s1
https://blog.csdn.net/Van_male/article/details/98938160
https://www.cnblogs.com/yxwkf/p/5424383.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3245589.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

【学习笔记】无人机系统(UAS)的连接、识别和跟踪(一)-3GPP TS 23.256 技术规范概述

3GPP TS 23.256 技术规范,主要定义了3GPP系统对无人机(UAV)的连接性、身份识别、跟踪及A2X(Aircraft-to-Everything)服务的支持。 3GPP TS 23.256 技术规范: 以下是文档的核心内容总结: UAV系…

在 PostgreSQL 里如何处理数据的归档和清理过程中的数据完整性验证?

🍅关注博主🎗️ 带你畅游技术世界,不错过每一次成长机会!📚领书:PostgreSQL 入门到精通.pdf 文章目录 在 PostgreSQL 里如何处理数据的归档和清理过程中的数据完整性验证 在 PostgreSQL 里如何处理数据的归…

数据驱动未来,Xinstall全渠道统计方案引领行业变革

在这个信息爆炸的时代,App市场的竞争日益激烈。对于每一个开发者或营销人员来说,掌握准确、全面的数据分析能力,是提升产品竞争力、优化营销策略的关键。然而,面对投放渠道的分散、数据打通的困难以及作弊流量的困扰,许…

RocketMQ源码学习笔记:消费者启动流程

这是本人学习的总结,主要学习资料如下 马士兵教育rocketMq官方文档 目录 1、前置知识1.1、pull和push型消费者1.2、消息CommitLog到ConsumeQueue1.3、自动创建的重试主题1.4、广播型消费和集群型消费中offset的存储位置 2、消费中的启动流程2.1、Preview2.2、校验&…

《AIGC:智能创作时代》—开启智能创作的全新时代

在人工智能发展的漫长历程中,如何让机器学会创作一直被视为难以逾越的天堑。然而,人类的创造力终将赋予机器创造力,把世界送入智能创作的新时代。 书名:《AIGC:智能创作时代》,作者:杜雨、张孜铭…

150个pb网站模板(都是成品网站,上传php空间即可使用),建站必备

一网友提供的150个pb网站模板,其实就是成品网站,上传php空间即可使用,属于建站公司或者建站开发人员必备的资源。 一共150个基于pb的成品网站,基本上都可以找到适应你手头客户需要的一款,简单修改一下即可交活收钱了。…

【爬虫基础入门课件:第二课:爬虫入门】

爬虫入门 什么是爬虫? 不知道各位是否遇到过这样的需求. 就是我们总是希望能够保存互联网上的一些重要的数据信息为己所用. 比如, 在浏览到一些优秀的让人血脉喷张的图片时. 总想保存起来留为日后做桌面上的壁纸在浏览到一些重要的数据时(各行各业), 希望保留下来日后为自…

美式键盘 QWERTY 布局的起源

注:机翻,未校对。 The QWERTY Keyboard Is Tech’s Biggest Unsolved Mystery QWERTY 键盘是科技界最大的未解之谜 It’s on your computer keyboard and your smartphone screen: QWERTY, the first six letters of the top row of the standard keybo…

C语言 | Leetcode C语言题解之第238题除自身以外的数组的乘积

题目&#xff1a; 题解&#xff1a; // 数组中除自身以外元素的乘积 int* productExceptSelf(int* nums, int numsSize, int* returnSize) {static int ra[100000]; // 结果数组for (int i 0; i < numsSize; i) {ra[i] 1; // 初始化结果数组为1}int pre 1, suf 1; /…

MongoDB教程(八):mongoDB数据备份与恢复

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; 文章目录 引言MongoDB 备…

【学习】美国虚拟信用卡申请流程

WildCard 官方网址&#xff1a;https://bewildcard.com/i/PEACEFUL &#xff08;使用邀请码“PEACEFUL”可以享受开卡88 折优惠&#xff0c;注册时提示填写邀请码就可以填写&#xff09;

如何通过成熟的外发平台,实现文档安全外发管理?

文档安全外发管理是企业信息安全管理的重要组成部分&#xff0c;它涉及到企业向外发送的文件&#xff0c;需要进行严格的控制和管理&#xff0c;防止敏感或机密信息的泄露。以下是一些关键考虑因素&#xff1a; 文件外发的挑战&#xff1a;企业在文件外发时面临的主要挑战包括…

QT纯代码实现滑动开关控件

开关按钮大家应该很熟悉&#xff0c;在设置里面经常遇到&#xff0c;切换时候的滑动效果比较帅气。通常说的开关按钮&#xff0c;有两个状态&#xff1a;on、off。大部分的开关按钮控件&#xff0c;基本上有两大类&#xff0c;第一类是纯代码绘制&#xff0c;这种对代码的掌控度…

vue2迁移到vue3注意点

vue2迁移到vue3注意点 1、插槽的修改 使用 #default &#xff0c; 以及加上template 模板 2、 类型的定义&#xff0c;以及路由&#xff0c;vue相关资源&#xff08;ref, reactive,watch&#xff09;的引入等 3、类装饰器 1&#xff09;vue-class-component是vue官方库,作…

WordPress 6.6 “Dorsey多尔西”发布

WordPress 6.6 “Dorsey多尔西”已经发布&#xff0c;它以传奇的美国大乐队领袖 Tommy Dorsey 名字命名。Dorsey 以其音调流畅的长号和作品而闻名&#xff0c;他的音乐以其情感深度和充满活力的能量吸引了观众。 当您探索 WordPress 6.6 的新功能和增强功能时&#xff0c;让您的…

【初阶数据结构】3.单链表

文章目录 3.单链表3.1 概念与结构3.1.1 结点3.1.2 链表的性质3.1.3 链表的打印 3.2 实现单链表3.3 链表的分类3.4 单链表算法题3.4.1 移除链表元素3.4.2 反转链表3.4.3 链表的中间结点3.4.4 合并两个有序链表3.4.5 链表分割3.4.6 链表的回文结构3.4.7 相交链表3.4.8 环形链表I3…

几何相关计算

目录 一、 判断两个矩形是否相交 二、判断两条线段是否相交 三、判断点是否在多边形内 四、垂足计算 五、贝塞尔曲线 六、坐标系 一、 判断两个矩形是否相交 当矩形1的最大值比矩形2的最小值都小&#xff0c;那矩形1和矩形2一定不相交&#xff0c;其他同理。 struct Po…

ETL之DataX模板(数据同步)

今天跟大家分享数据同步datax的模板&#xff0c;小伙伴们简单直接借鉴使用。 还记得上一篇关于大数据DS调度工具的分享嘛&#xff1f; 主流大数据调度工具DolphinScheduler之数据ETL流程-CSDN博客 里面的核心就是采用了DATAX的数据同步原理。 1&#xff0c;什么是DataX Da…

逻辑漏洞-垂直越权

【实验介绍】 垂直越权&#xff1a;是不同级别之间或不同角色之间的越权。由于后台应用没有做权限控制&#xff0c;或仅仅在菜单、按钮上做了权限控制&#xff0c;导致恶意用户只要猜测其他管理页面的 URL 或者敏感的参数信息&#xff0c;就可以访问或控制其他角色拥有的数据或…

使用工作日志 - 更快地恢复专注并理清思路

原文&#xff1a;Charles Fval - 2024.07.12 你正在处理计算机科学中最复杂的问题&#xff1a;修复部署管道上的权限。这已经是你开始处理这个简单任务的第 4 天了。你的经理明确告诉你&#xff0c;你在这方面的表现远低于她对一个中期实习生的期望。你的同事们都尽量远离你&a…