Openwrt配置QOS流量带宽限制

Openwrt配置QOS流量带宽限制

 

QoS的底层是tc,其目的就是决定先发送哪些包。openwrt默认的规则是hfsc,设计了四个优先级:最高、高、普通、低 。

说到openwrt,就不能不提一下QoS。尤其是如果你需要用P2P软件(目前对迅雷的支持还不大好),基本就不能不开QoS。QoS的全称是Quality of Service,意即服务质量。是专门用于解决拥堵网络上的信号质量一视同仁的问题。例如,我们有一根宽带,两人共用。一个人视频聊天,一个人bt下载(我还不提迅雷个傻X呢)。玩bt的那个一开软件,视频聊天那个立刻没法用了。bt和视频聊天稍微好一点的是,视频聊天消耗的带宽是恒定的。你可以逐步限速,只要给视频聊天留了足够的带宽,两个就都能一起用了。但是,如果另一个人不是视频聊天,而是网络浏览怎么办?网络浏览,视频聊天,p2p下载一起来怎么办?实际上这是很多朋友家中常常碰到的情况。更不说有合租公寓里面你很难监控对方一定限速,软件无法限速甚至恶意抢占带宽(迅雷)。另一个更加技术的问题是,由于上传带宽不足,ACK包回应过慢,导致你的下载速度也不能达到峰值。玩p2p的常常会给上传限速到真实带宽差一点的位置,下载带宽立刻上去,就是这个道理。
怎么办?用QoS,解决你多年老便秘。QoS的底层是tc,其目的就是决定先发送哪些包。openwrt默认的规则是hfsc,设计了四个优先级。Priority最优先,处理22,53,icmp,以及小于128字节的syn,ack包中,不属于bulk类别的。我们可以看到,DNS,syn/ack的优先响应,保证了你的上传不会影响下载。其次是Express,处理5190和小于500字节的UDP包。这个我也不明白是为什么,好像是视频什么的。然后是Normal,包括20,21,25,80,110,443,993,995这些常见端口。涵盖http/https,ftp,邮件系统。最后是Bulk,包括其他包,尤其是ed和bt。

当你启用QoS后,你的p2p软件速度应当不会上升,反而会下降。下载速度不好说,有可能是上升,也有可能下降。因为原来p2p软件抢占了所有带宽,目前他们只能使用普通应用用剩下的带宽,速度当然慢了。然而,当你使用浏览器,收发邮件的时候,速度应当和不使用p2p的时候一样流畅。这才是使用QoS最大的意义。
方法很简单,安装QoS包,然后修改/etc/config/qos,注意修改你的带宽。不修改的话,流量会被无意义的限制死。

另外,打开QoS后,千万记得把你的p2p软件改为不限速。否则不能达到最高性能。

 

 

 

root@ACU:~# cat /etc/config/qos 
# QoS configuration for OpenWrt

# INTERFACES:
config interface wan
	option classgroup  "Default"
	option enabled      0
	option upload       128
	option download     1024

# RULES:
config classify
	option target       "Priority"
	option ports        "22,53"
	option comment      "ssh, dns"
config classify
	option target       "Normal"
	option proto        "tcp"
	option ports        "20,21,25,80,110,443,993,995"
	option comment      "ftp, smtp, http(s), imap"
config classify
	option target       "Express"
	option ports        "5190"
	option comment      "AOL, iChat, ICQ"
config default
	option target       "Express"
	option proto        "udp"
	option pktsize      "-500"
config reclassify
	option target       "Priority"
	option proto        "icmp"
config default
	option target       "Bulk"
	option portrange    "1024-65535"


# Don't change the stuff below unless you
# really know what it means :)

config classgroup "Default"
	option classes      "Priority Express Normal Bulk"
	option default      "Normal"


config class "Priority"
	option packetsize  400
	option avgrate     10
	option priority    20
config class "Priority_down"
	option packetsize  1000
	option avgrate     10


config class "Express"
	option packetsize  1000
	option avgrate     50
	option priority    10

config class "Normal"
	option packetsize  1500
	option packetdelay 100
	option avgrate     10
	option priority    5
config class "Normal_down"
	option avgrate     20

config class "Bulk"
	option avgrate     1
	option packetdelay 200
root@ACU:~# 

 

tc qdisc del dev eth0 root
tc qdisc add dev eth0 root fq_codel target 60ms interval 360ms noecn
tc qdisc show dev eth0

 

IFB是tc过滤器的替代选择,用于处理入口流量,方法是将其重定向到虚拟接口并将其视为出口流量。每个物理接口需要一个ifb接口,以将入口流量从eth0重定向到ifb0,将eth1重定向到ifb1等等上。

插入ifb模块时,告诉它所需的虚拟接口数量。默认值为2:

modprobe ifb numifbs=1

现在,启用所有ifb接口:

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

并将入口流量从物理接口重定向到相应的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的出口规则在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的出口规则一样(所有进入ifb0的东西都必须出来,只有eth0入口流量进入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

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

 

看上去现在tc的还是htb加fq_codel的组合为主流。看一下介绍和源码,还有别人的例子。

手册:
====
http://man7.org/linux/man-pages/man8/tc.8.html
http://man7.org/linux/man-pages/man8/tc-ematch.8.html  filter分类支持简单的表达式,cmp/and/or/字节检查/ipset/xtables等等的
http://man7.org/linux/man-pages/man8/tc-flow.8.html    filter分类支持使用flow流表里面的src,dst,iif和NAT前后的nfct-src, nfct-dst,rxhash
                                                       来计算hash分类。比如默认fq_codel 是保证流的公平性的吧,但下面这个fq_codel使用NAT前的源ip地址来做fair-queue的队列选择。
      tc qdisc add dev eth0 parent 1:1 handle 11: fq_codel
      tc filter add dev eth0 parent 11: handle 11 protocol all flow hash keys nfct-src divisor 1024     
      
https://man7.org/linux/man-pages/man8/tc-u32.8.html   filter根据源ip目的ip,tcp,udp等协议字段以及包里面的任意内容的规则
https://man7.org/linux/man-pages/man8/tc-fw.8.html     filter根据skb的mark值来设置规则
https://man7.org/linux/man-pages/man8/tc-flower.8.html filer匹配mac地址和各种流字段
http://man7.org/linux/man-pages/man8/tc-bpf.8.html     filter也是支持bpf的自定义扩展的
http://man7.org/linux/man-pages/man8/tc-htb.8.html
http://man7.org/linux/man-pages/man8/tc-fq_codel.8.html

介绍:
=====
https://www.bufferbloat.net/projects/codel/wiki/Best_practices_for_benchmarking_Codel_and_FQ_Codel/
http://luxik.cdi.cz/~devik/qos/htb/manual/userg.htm
http://tldp.org/HOWTO/Traffic-Control-HOWTO/classful-qdiscs.html#qc-htb
https://www.linuxjournal.com/article/7562
https://www.cnblogs.com/acool/p/7779159.html
https://www.docum.org/docum.org/tests/htb/burst/

源码:
=====
https://elixir.bootlin.com/linux/latest/source/net/sched/em_meta.c
https://elixir.bootlin.com/linux/latest/source/net/sched/sch_tbf.c
https://elixir.bootlin.com/linux/latest/source/net/sched/sch_htb.c
https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/tc/sch_tbf.c
https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/tc/q_htb.c

openwrt的例子:
==============
https://github.com/tohojo/sqm-scripts/blob/master/src/simple.qos



系统帮助
=======
man tc
man tc-htb
man tc-tbf
man tc-fc_codel


centos 7 中 基本表达式中支持的meta
/usr/sbin/tc filter add dev eth1 basic match 'meta(list)'
--------------------------------------------------------
  ID               Type       Description
--------------------------------------------------------
Generic:
  random           INT        Random value (32 bit)
  loadavg_1        INT        Load average in last minute
  loadavg_5        INT        Load average in last 5 minutes
  loadavg_15       INT        Load average in last 15 minutes

Interfaces:
  dev              INT,VAR    Device the packet is on

Packet attributes:
  priority         INT        Priority of packet
  protocol         INT        Link layer protocol
  pkt_type         INT        Packet type (uni|multi|broad|...)cast
  pkt_len          INT        Length of packet
  data_len         INT        Length of data in packet
  mac_len          INT        Length of link layer header

Netfilter:
  nf_mark          INT        Netfilter mark
  fwmark           INT        Alias for nf_mark

Traffic Control:
  tc_index         INT        TC Index

Routing:
  rt_classid       INT        Routing ClassID (cls_route)
  rt_iif           INT        Incoming interface index
  vlan             INT        Vlan tag

Sockets:
  sk_family        INT        Address family
  sk_state         INT        State
  sk_reuse         INT        Reuse Flag
  sk_bind_if       INT,VAR    Bound interface
  sk_refcnt        INT        Reference counter
  sk_shutdown      INT        Shutdown mask
  sk_proto         INT        Protocol
  sk_type          INT        Type
  sk_rcvbuf        INT        Receive buffer size
  sk_rmem          INT        RMEM
  sk_wmem          INT        WMEM
  sk_omem          INT        OMEM
  sk_wmem_queue    INT        WMEM queue
  sk_snd_queue     INT        Send queue length
  sk_rcv_queue     INT        Receive queue length
  sk_err_queue     INT        Error queue length
  sk_fwd_alloc     INT        Forward allocations
  sk_sndbuf        INT        Send buffer size
--------------------------------------------------------




概念:
======
qdisc 是队列,下面可以包含多个class,每个class就是分类了,可以多个树形结构的级别,
filter是就是分类规则了,每个class可以设置不同的filter来分类决定包被分到那个子级别的class里面去。
可以先看一下 tc的man page里面THEORY OF OPERATION。小节的说明。 htb的话,根据http://man7.org/linux/man-pages/man8/tc-htb.8.html的说明,
一个包只有被分类的叶子节点了才会正在的被认为分类成功,如果在中间节点就没有被filter分到叶子节点,最后还是会放到htb 创建时设置的default class id去。  


实例
====
tc qdisc show dev eth1
tc -s qdisc show dev eth1
tc -s -d class show dev eth1
tc --g -s class show dev eth1
tc -s filter show dev eth1

tc qdisc del dev eth1 root
tc qdisc add dev eth1 root handle 1: htb default 13  r2q 10
tc class add dev eth1 parent 1: classid 1:1 htb quantum 125000 rate 1000mbit ceil 1000mbit burst 125000 cburst 125000
tc class add dev eth1 parent 1:1 classid 1:11 htb quantum 12500 rate 100mbit ceil 1000mbit burst 12500 cburst 12500 prio 1
tc class add dev eth1 parent 1:1 classid 1:12 htb rate 500mbit ceil 1000mbit burst 15000 cburst 125000 prio 2
tc class add dev eth1 parent 1:1 classid 1:13 htb rate 50mbit ceil 50mbit burst 3000 cburst 3000 prio 3
tc class add dev eth1 parent 1:13 classid 1:14 htb rate 20mbit ceil 20mbit burst 3000 cburst 3000 prio 1
tc class add dev eth1 parent 1:13 classid 1:15 htb rate 30mbit ceil 30mbit burst 3000 cburst 3000 prio 1

tc qdisc add dev eth1 parent 1:11 handle 110: fq_codel quantum 300 limit 1024 flows 2048 ecn
tc qdisc add dev eth1 parent 1:12 handle 120: fq_codel quantum 300 limit 1024 flows 1024 ecn
tc qdisc add dev eth1 parent 1:14 handle 140: fq_codel quantum 300 limit 1024 flows 1024 ecn
tc qdisc add dev eth1 parent 1:15 handle 150: fq_codel quantum 300 limit 1024 flows 1024 noecn

# tc filter add dev eth1 basic match 'meta(pkt_len gt 0)' flowid 1:13
# tc filter add dev eth1 protocol ip basic match 'meta(pkt_len gt 0)'  flowid 1:13
# tc filter add dev eth1 basic match 'meta(dev eq 8)' flowid 1:13
# tc filter add dev eth1 basic match 'meta(rt_iif gt 0)' flowid 1:14
tc filter add dev eth1 basic match 'meta(fwmark gt 24)' flowid 1:15
tc filter add dev eth1 parent 1:13 handle 100 fw flowid 1:14
tc filter add dev eth1 parent 1:13 handle 101 fw flowid 1:15
tc filter add dev eth1 parent 1:13 priority 10 matchall classid 1:15



# 通常来说队列是应用于出去的就流量的,也就是内核发网络包到网卡之前的,但 ingres 这个qdisc可以
# 对接收上了的包应用tc队列,可以把收上来的转到一个ifb然后在那个ifb 设备上面限制接收方向的流量吧,
# 不过一般很少用这个吧。
# ingres qdisc的id 不能添加子qdisc
tc qdisc add dev eth1 handle ffff: ingress
modprobe ifb
ip link set dev ifb0 up

# 使用ifb0做输入方向的重定向
tc filter add dev bond0 parent ffff: protocol ip u32 match u32 0 0 flowid 1:1 action mirred egress redirect dev ifb0

# 使用ifb0做输出方向的重定向
tc filter add dev bond0 parent 1: protocol ip u32 match u32 0 0 flowid 1:1 action mirred egress redirect dev ifb0


htb的burst和burst
=================
tc 本身会自动计算burst和cburst,设置为
/* compute minimal allowed burst from rate; mtu is added here to make
   sute that buffer is larger than mtu and to have some safeguard space */
if (!buffer)
  buffer = rate64 / get_hz() + mtu;
if (!cbuffer)
  cbuffer = ceil64 / get_hz() + mtu;

/ # cat /proc/net/psched
000003e8 00000040 000f4240 3b9aca00

但现在的系统tc从/proc/net/psched获取的HZ都是很大的,跟网卡NAPI等接口有关?
所以基本算出来都是默认的mtu 1600byte,但HTB这些算法,现在的都是把包长度表示成
纳秒的时间刻度的,所以转换完再转换回来好像数值有点不一样,经常看到比MTU要小的。
本来HZ比较小的时候,这个burst和cburst是要设置的很大的比较十几KB的,这样才能发
完带宽。但好像现在内核API变化了,这个跟系统时钟周期没关系了,


sqm-scripts叫里面burst和cburst都是用同一个值, 默认允许的突发时间是 t = 1ms (1000微秒),
用下面这个公式来计算的: 
busrt(byte) = rate(kbit/s) * 1000(t=1ms) / 8000 
来计算的,然后不能 小于 MTU + 200的样子
quantum 用的也是busrt 一样的数值。 
说是quantum不能大于burst。burst说设置小了比较耗cpu。quantum是每一轮调度允许发送量?quantum设置小了,不同class之间的均衡性更好吧。

fq_codel的quantum 说是默认设置300,不能再小了,设置成300是可能有小包优先的作用? fq_codel的flows对应流(连接)数量,用于保证多流之间的公平性的


ecn / noecn
===
外网上行接口不开ecn,内网可以开ecn。 就是支持enc标记的tcp连接之类的,会用ecn标记一下包吧,不是直接丢弃,终端系统看到网络包有这个标记就会知道发生拥堵了。

 

网上关于openwrt的tc限速描述有很多,目前主流用的是IMQ和ifb,其中IMQ的设置比较复杂,ifb的描述相当于简单点,下面我简单总结下ifb的使用,

TC的大概流程如下,具体每条命令的作用我就不做详细介绍,大家可以百度

 tc qdisc add dev eth0 ingress
 tc filter add dev br-eth0 parent ffff: protocol ip u32 match u32 0 0 action mirred egress redirect dev ifb0
 tc qdisc add dev ifb0 root handle 1: htb default 1000
 tc class add dev ifb0 parent 1: classid 1:1 htb rate 2000kbit ceil 2000kbit   #限速2M

tc class add dev ifb0 parent 1:1 classid 1:1000 htb rate 1kbit ceil 8000kbit prio 3
 tc qdisc add dev ifb0 parent 1:1000 handle 1000: sfq perturb 10

 

 tc class add dev ifb0 parent 1:1 classid 1:8 htb rate 1000kbit ceil 2000kbit prio 1
 tc qdisc add dev ifb0 parent 1:8 handle 8: sfq perturb 10
 tc filter add dev ifb0 parent 1:0 prio 1 protocol ip handle 8 fw flowid 1:8

 iptables -t mangle -A PREROUTING -p udp -j MARK --set-mark 8
 iptables -t mangle -A PREROUTING  -p udp -j RETURN

 

上述的使用的netfilter和tc相结合,通过fw,是的mark打入skb中,下面重点来了,

我发现在不同设备上,出现下面问题,百度了一下,居然老外也遇到过(be aware that if you use iptable to mark your packet and then filters them, you can't use ifb since all ingress trafic will be forwarded BEFORE any marking. so you will se your class stay at 0 and all forwarded to the default. IMQ seem the rigth solution for iptables users.)

为了解决这个问题,查了很多资料,终于get到了,在iptables中使用connmark这个参数进行mark的标记,从而使得skb头里也能成功打上mark

使用netfilter的原因是因为涉及到ipset 地址集,以及域名。

tc也提供了另外一种方法,下面方法比较简单了,也可以涉及到多地址,但可能比较繁琐点(至少我认为没有IPtables简便)

#tc qdisc add dev imq0 root handle 1: htb default 20
#tc class add dev imq0 parent 1: classid 1:1 htb rate 2mbit burst 15k
#tc class add dev imq0 parent 1:1 classid 1:10 htb rate 1mbit
#tc class add dev imq0 parent 1:1 classid 1:20 htb rate 1mbit
#tc qdisc add dev imq0 parent 1:10 handle 10: pfifo
#tc qdisc add dev imq0 parent 1:20 handle 20: sfq
#tc filter add dev imq0 parent 10:0 protocol ip prio 1 u32 match ip dst 10.0.0.230/32 flowid 1:10

这里其实也可以对protol协议进行限制,以及端口范围

协议”

tc filter add dev ifb0 parent 1: protocol ip prio 2 u32 match ip protocol 1 0xff flowid 1:8

1 0xff是icmp 协议,这里1 代表icmp,你可以在/etc/protocols查看每个协议具体是什么

关于端口范围

tc filter add dev eth2 protocol ip parent 1: prio 2 u32 match ip sport 22 0xffff flowid 1:12
0xffB2-0xffff的数值,表示从起始端口开始后多少。

 

--------------

来源 https://www.right.com.cn/forum/thread-53500-1-1.html

要完成自定义QOS,需要先把tc,iptable, htb算法, opendpi , xt_recent 这些都搞清楚,起码基本的命令都会用。否则就看看热闹好了。
命令很多人都懂,我就主要讲下思路。tc的流量控制很准确,前提是要对tc,htb有足够的了解。htb的分类主要以openwrt原版qos为基础,上传增加一个第五类。iptables的设置,也是以openwrt的原版为基础,将l7-filter换成opendpi作七层识别,并作了一些小改动来符合我的需求。

                           上传
                            1:  root htb
                             |
                            1:1
            /          /            \
        1:10      1:20        1:3
                                /              \            \
                            1:30            1:40      1:50

tc qdisc add dev eth1 root handle 1: htb default 40
tc class add dev eth1 parent 1: classid 1:1 htb rate 58kbps ceil 58kbps  burst 5k cburst 5k
tc class add dev eth1 parent 1:1 classid 1:10 htb rate 10kbps ceil 58kbps  prio 1
tc class add dev eth1 parent 1:1 classid 1:20 htb rate 15kbps ceil 58kbps  prio 2
tc class add dev eth1 parent 1:1 classid 1:3 htb rate 15kbps ceil 45kbps
tc class add dev eth1 parent 1:3 classid 1:30 htb rate 10kbps ceil 45kbps  prio 3 burst 2k cburst 2k
tc class add dev eth1 parent 1:3 classid 1:40 htb rate 5kbps ceil 45kbps  prio 4
tc class add dev eth1 parent 1:3 classid 1:50 htb rate 5kbps ceil 45kbps  prio 5


这是上传500kbit带宽的分类情况, 1:10是游戏, 1:20是dns, tcp  syn,tcp ack ,ssh,QQ语音之类的,  1:30是网页、virtual**、代理、rdp,1:40是BT,迅雷,PPS和其他未分类,包大小小于300的流量,1:50是BT,迅雷,PPS和未分类,包大小大于300的流量。

下载也作了tc和iptable的配置,不过相对来说没那么重要,就不帖了。主要思路跟上传差不多,没用imq而是用了ifb模块,也就是上传和下载都在同一个interface(即出口)上整形。好像ifb是在iptable之前,具体有空测试一下,所以iptable对下行来说也不重要了,但对于七层识别还是有点用,所以也加上了,openwrt的原版QOS在iptable中是不对下行作mark的。

按这个速率设定来用的话,开下载的同时,游戏的延迟是可以保证的。当然最重要的是在iptable 上把流量用mark分好类,我的分类是按端口和七层识别同时用,比如22,80,53都可以按端口来设,虽然有些应用也会用这些端口,但一般没多大影响。除非有特意改端口的,有影响了,那可以都用七层识别来做。opendpi在七层识别方面还是不错的,openwrt的开发者在几个月前已经开始计划用opendpi换掉l7-filter,不知道最近进展如何。不过我们可以自己编译到openwrt里。

另外,很多QOS的设定都会推荐限制连接数,我没有做方面的限制,至少在我这里没有什么问题。测试3M下行,500k上行的时候迅雷开了3个种子,基本满速,上行还有富余,游戏延迟没问题,QQ语音同时连3个人流畅。 测试20M下行,1M上行的时候,迅雷开20个种子,下行不满速,上行已经满了,迅雷上传显示0,游戏延迟没问题,QQ语音同时连3个人流畅。

因为我玩DOTA经常上浩方,所以自己分析了浩方的数据包特征,CS,WAR3都能匹配,最近去11平台玩DOTA,也分析了下,可以匹配了。opendpi对PPS支持很好,QQ需要修改匹配方法。迅雷和风行这种,只是部分能有些特征包,已经足够了,可以配合recent来mark,要改recent模块。

本来想贴几个图,想想没什么意义。如果有人感兴趣,可以联系我,帮忙写个脚本。

最后贴下iptable的统计信息。其中war3的匹配都在下行里,这里看不到,帖子长度的问题,就不贴了。

上行:

Chain Default (2 references)
    pkts      bytes target     prot opt in     out     source               destination         
41447462 17211275535 CONNMARK   all  --  *      *       0.0.0.0/0            0.0.0.0/0           CONNMARK restore
11384650 1499982652 Default_ct  all  --  *      *       0.0.0.0/0            0.0.0.0/0           mark match 0x0
      34    23446 MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0           mark match 0x1 length 400:65535 MARK and 0x0
   24641 20134127 MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0           mark match 0x2 length 800:65535 MARK and 0x0
   37746  5394916 MARK       icmp --  *      *       0.0.0.0/0            0.0.0.0/0           MARK set 0x1
2077725 101041304 MARK       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           length 0:128 mark match !0x4 tcp flags:0x3F/0x02 MARK set 0x2
1418481 59188992 MARK       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           length 0:128 mark match !0x4 tcp flags:0x3F/0x10 MARK set 0x2
6699462 697530975 MARK       udp  --  *      *       0.0.0.0/0            0.0.0.0/0           mark match 0x0 length 0:65535 MARK set 0x4
  896620 621880446 MARK       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           mark match 0x0 length 0:65535 MARK set 0x4
2822843 3713061114 MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0           mark match 0x4 length 300:65535 MARK set 0x5

Chain Default_ct (1 references)
    pkts      bytes target     prot opt in     out     source               destination         
     379    18200 MARK       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           mark match 0x0 tcp multiport ports 22,53 MARK set 0x2
   27432  1704319 MARK       udp  --  *      *       0.0.0.0/0            0.0.0.0/0           mark match 0x0 udp multiport ports 22,53 MARK set 0x2
  144061  7137731 MARK       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           mark match 0x0 tcp multiport ports 20,21,25,80,110,443,993,995,5190,3389,3390,5900,1080,1194 MARK set 0x3
     364    23960 MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0           mark match 0x0 protocol HF MARK set 0x1
       1       45 MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0           mark match 0x0 protocol COUNTERSTRIKE MARK set 0x1
       0        0 MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0           mark match 0x0 protocol WARCRAFT3 MARK set 0x1
     966    51955 MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0           mark match 0x0 protocol PT11 MARK set 0x1
     174    31318 MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0           mark match 0x0 protocol QQ MARK set 0x2
     727   256830 MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0           mark match 0x0 protocol HTTP MARK set 0x3
     753   102156 MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0           mark match 0x0 protocol PPStream MARK set 0x4
       0        0 MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0           mark match 0x0 protocol PPLive MARK set 0x4
  683701 50272737 MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0           mark match 0x0 protocol Bittorrent MARK set 0x4
    4534   268934 MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0           mark match 0x0 protocol Thunder/Webthunder MARK set 0x8
  103919  7200135 MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0           mark match 0x0 recent: UPDATE seconds: 60 name: DEFAULT side:source port MARK set 0x4
    4534   268934 MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0           mark match 0x8 recent: SET name: DEFAULT side:source port MARK set 0x4
11384650 1499982652 CONNMARK   all  --  *      *       0.0.0.0/0            0.0.0.0/0           CONNMARK save

 

################################

# 查看 ifb 接口
ip link show | grep ifb

# 删除 ifb 模块
rmmod ifb

# 插入 ifb 模块
insmod ifb

# 插入 ifb 模块 并指定虚拟接口数量为2
modprobe ifb numifbs=2

# 启用 ifb 接口
ifconfig ifb0 up
ifconfig ifb1 up

################################

# 查看所有队列规则
tc qdisc show 

# 查看eth0.2所有队列规则
tc qdisc show dev eth0.2

# 删除eth0.2的出队规则
tc qdisc del dev eth0.2 root 

# 删除eth0.2的入队规则
tc qdisc del dev eth0.2 ingress

# 删除ifb0的入队规则
tc qdisc del dev ifb0 root

# 设置eth0.2发送队列长度为32
ip link set dev eth0.2 txqueuelen 32

################################

 

有PM要脚本的,贴一下完整的脚本  ,供大家研究,可能需要安装一些模块后才能用。 但准确的分类也很重要,这不是一个脚本能解决的。目前还在研究一些http协议的P2P流量,这个对看网页有些影响。等东西成熟了,会做成安装包放出来。

3M下行,500K上行带宽。

insmod cls_u32
insmod em_u32
insmod act_connmark
insmod act_mirred
insmod sch_ingress
insmod cls_fw
insmod sch_htb
insmod sch_sfq
insmod sch_red
上行:
ifconfig eth1 up txqueuelen 5
tc qdisc del dev eth1 root 2> /dev/null > /dev/null
tc qdisc add dev eth1 root handle 1: htb default 40
tc class add dev eth1 parent 1: classid 1:1 htb rate 58kbps ceil 58kbps  burst 5k cburst 5k
tc class add dev eth1 parent 1:1 classid 1:10 htb rate 10kbps ceil 58kbps  prio 1
tc class add dev eth1 parent 1:1 classid 1:20 htb rate 15kbps ceil 58kbps  prio 2
tc class add dev eth1 parent 1:1 classid 1:3 htb rate 15kbps ceil 45kbps
tc class add dev eth1 parent 1:3 classid 1:30 htb rate 10kbps ceil 45kbps  prio 3 burst 2k cburst 2k
tc class add dev eth1 parent 1:3 classid 1:40 htb rate 5kbps ceil 45kbps  prio 4
tc class add dev eth1 parent 1:3 classid 1:50 htb rate 5kbps ceil 45kbps  prio 5
tc qdisc add dev eth1 parent 1:10 handle 100: sfq perturb 2 limit 36000
tc qdisc add dev eth1 parent 1:20 handle 200: sfq perturb 2 limit 36000
tc qdisc add dev eth1 parent 1:30 handle 300: red min 3116 max 9348 burst 3 avpkt 1500 limit 37392 probability 0.12 ecn
tc qdisc add dev eth1 parent 1:40 handle 400: red min 3116 max 9348 burst 3 avpkt 1500 limit 37392 probability 0.12 ecn
tc qdisc add dev eth1 parent 1:50 handle 500: red min 3116 max 9348 burst 3 avpkt 1500 limit 37392 probability 0.12 ecn
tc filter add dev eth1 parent 1: prio 1 protocol ip handle 1 fw flowid 1:10
tc filter add dev eth1 parent 1: prio 2 protocol ip handle 2 fw flowid 1:20
tc filter add dev eth1 parent 1: prio 3 protocol ip handle 3 fw flowid 1:30
tc filter add dev eth1 parent 1: prio 4 protocol ip handle 4 fw flowid 1:40
tc filter add dev eth1 parent 1: prio 5 protocol ip handle 5 fw flowid 1:50

下行
ifconfig ifb0 up txqueuelen 5
tc qdisc del dev ifb0 root 2> /dev/null > /dev/null
tc qdisc add dev ifb0 root handle 1: htb default 40
tc class add dev ifb0 parent 1: classid 1:1 htb rate 360kbps ceil 360kbps burst 50k cburst 50k
tc qdisc del dev eth1 ingress
tc qdisc add dev eth1 ingress
tc filter add dev eth1 parent ffff: protocol ip prio 1 u32 match u32 0 0 flowid 1:1 action connmark action mirred egress redirect dev ifb0
tc class add dev ifb0 parent 1:1 classid 1:10 htb rate 20kbps ceil 360kbps prio 1
tc class add dev ifb0 parent 1:1 classid 1:20 htb rate 50kbps ceil 360kbps prio 2
tc class add dev ifb0 parent 1:1 classid 1:3 htb rate 200kbps ceil 320kbps
tc class add dev ifb0 parent 1:3 classid 1:30 htb rate 100kbps ceil 320kbps prio 3 burst 50k cburst 50k
tc class add dev ifb0 parent 1:3 classid 1:40 htb rate 20kbps ceil 320kbps prio 4
tc qdisc add dev ifb0 parent 1:10 handle 100: sfq perturb 2 limit 223716
tc qdisc add dev ifb0 parent 1:20 handle 200: sfq perturb 2 limit 223716
tc qdisc add dev ifb0 parent 1:30 handle 300: red min 18643 max 55929 burst 20 avpkt 1500 limit 223716 probability 0.12 ecn
tc qdisc add dev ifb0 parent 1:40 handle 400: red min 18643 max 55929 burst 20 avpkt 1500 limit 223716 probability 0.12 ecn
tc filter add dev ifb0 parent 1: prio 1 protocol ip handle 1 fw flowid 1:10
tc filter add dev ifb0 parent 1: prio 2 protocol ip handle 2 fw flowid 1:20
tc filter add dev ifb0 parent 1: prio 3 protocol ip handle 3 fw flowid 1:30
tc filter add dev ifb0 parent 1: prio 4 protocol ip handle 4 fw flowid 1:40

iptables :
+ iptables -t mangle -F
+ iptables -t mangle -X
+ insmod ipt_multiport
+ insmod ipt_CONNMARK
+ insmod xt_opendpi
+ insmod ipt_length
+ iptables -t mangle -N Default
+ iptables -t mangle -N Default_ct
+ iptables -t mangle -A Default_ct -m mark --mark 0 -m tcp -p tcp -m multiport --ports 22,53 -j MARK --set-mark 2
+ iptables -t mangle -A Default_ct -m mark --mark 0 -p udp -m udp -m multiport --ports 22,53 -j MARK --set-mark 2
+ iptables -t mangle -A Default_ct -m mark --mark 0 -p tcp -m tcp -m multiport --ports 20,21,25,80,110,443,993,995,5190,3389,3390,5900,1080,1194 -j MARK --set-mark 3
+ iptables -t mangle -A Default_ct -m mark --mark 0 -m opendpi --hf -j MARK --set-mark 1
+ iptables -t mangle -A Default_ct -m mark --mark 0 -m opendpi --qq -j MARK --set-mark 2
+ iptables -t mangle -A Default_ct -m mark --mark 0 -m opendpi --http -j MARK --set-mark 3
+ iptables -t mangle -A Default_ct -m mark --mark 0 -m opendpi --ppstream -j MARK --set-mark 4
+ iptables -t mangle -A Default_ct -m mark --mark 0 -m opendpi --pplive -j MARK --set-mark 4
+ iptables -t mangle -A Default_ct -m mark --mark 0 -m opendpi --bittorrent -j MARK --set-mark 4
+ iptables -t mangle -A Default_ct -m mark --mark 0 -m opendpi --thunder -j MARK --set-mark 4
+ iptables -t mangle -A Default_ct -j CONNMARK --save-mark
+ iptables -t mangle -A Default -j CONNMARK --restore-mark
+ iptables -t mangle -A Default -m mark --mark 0 -j Default_ct
+ iptables -t mangle -A Default -m mark --mark 1 -m length --length 400: -j MARK --set-mark 0
+ iptables -t mangle -A Default -m mark --mark 2 -m length --length 800: -j MARK --set-mark 0
+ iptables -t mangle -A Default -p icmp -j MARK --set-mark 1
+ iptables -t mangle -A Default -p tcp -m length --length :128 -m mark ! --mark 4 -m tcp --tcp-flags ALL SYN -j MARK --set-mark 2
+ iptables -t mangle -A Default -p tcp -m length --length :128 -m mark ! --mark 4 -m tcp --tcp-flags ALL ACK -j MARK --set-mark 2
+ iptables -t mangle -A Default -m mark --mark 0 -p udp -m length --length 0: -j MARK --set-mark 4
+ iptables -t mangle -A Default -m mark --mark 0 -p tcp -m length --length 0: -j MARK --set-mark 4
+ iptables -t mangle -A OUTPUT -o eth1 -j Default
+ iptables -t mangle -A FORWARD -o eth1 -j Default
+ iptables -t mangle -D Default_ct 10
+ iptables -t mangle -I Default_ct 10 -m mark --mark 0x0 -m opendpi --thunder -j MARK --set-xmark 0x8/0xffffffff
+ iptables -t mangle -I Default_ct 11 -m mark --mark 0x0 -m recent --update --seconds 60 --name DEFAULT --rsource --rport -j MARK --set-xmark 0x4/0xffffffff
+ iptables -t mangle -I Default_ct 12 -m mark --mark 0x8 -m recent --set --name DEFAULT --rsource --rport -j MARK --set-xmark 0x4/0xffffffff
+ iptables -t mangle -N Default_dn
+ iptables -t mangle -N Default_ct_dn
+ iptables -t mangle -A Default_ct_dn -m mark --mark 0 -m tcp -p tcp -m multiport --ports 22,53 -j MARK --set-mark 2
+ iptables -t mangle -A Default_ct_dn -m mark --mark 0 -p udp -m udp -m multiport --ports 22,53 -j MARK --set-mark 2
+ iptables -t mangle -A Default_ct_dn -m mark --mark 0 -p tcp -m tcp -m multiport --ports 20,21,25,80,110,443,993,995,5190,3389,3390,5900,1080,1194 -j MARK --set-mark 3
+ iptables -t mangle -A Default_ct_dn -m mark --mark 0 -m opendpi --hf -j MARK --set-mark 1
+ iptables -t mangle -A Default_ct_dn -m mark --mark 0 -m opendpi --qq -j MARK --set-mark 2
+ iptables -t mangle -A Default_ct_dn -m mark --mark 0 -m opendpi --http -j MARK --set-mark 3
+ iptables -t mangle -A Default_ct_dn -m mark --mark 0 -m opendpi --ppstream -j MARK --set-mark 4
+ iptables -t mangle -A Default_ct_dn -m mark --mark 0 -m opendpi --pplive -j MARK --set-mark 4
+ iptables -t mangle -A Default_ct_dn -m mark --mark 0 -m opendpi --bittorrent -j MARK --set-mark 4
+ iptables -t mangle -A Default_ct_dn -m mark --mark 0 -m opendpi --thunder -j MARK --set-mark 4
+ iptables -t mangle -A Default_ct_dn -j CONNMARK --save-mark
+ iptables -t mangle -A Default_dn -j CONNMARK --restore-mark
+ iptables -t mangle -A Default_dn -m mark --mark 0 -j Default_ct_dn
+ iptables -t mangle -A Default_dn -m mark --mark 1 -m length --length 400: -j MARK --set-mark 0
+ iptables -t mangle -A Default_dn -m mark --mark 2 -m length --length 800: -j MARK --set-mark 0
+ iptables -t mangle -A Default_dn -p icmp -j MARK --set-mark 1
+ iptables -t mangle -A Default_dn -p tcp -m length --length :128 -m mark ! --mark 4 -m tcp --tcp-flags ALL SYN -j MARK --set-mark 2
+ iptables -t mangle -A Default_dn -p tcp -m length --length :128 -m mark ! --mark 4 -m tcp --tcp-flags ALL ACK -j MARK --set-mark 2
+ iptables -t mangle -A Default_dn -m mark --mark 0 -p udp -m length --length 0: -j MARK --set-mark 4
+ iptables -t mangle -A Default_dn -m mark --mark 0 -p tcp -m length --length 0: -j MARK --set-mark 4
+ iptables -t mangle -A INPUT -i eth1 -j Default_dn
+ iptables -t mangle -A FORWARD -i eth1 -j Default_dn
+ iptables -t mangle -I Default_ct_dn 11 -m mark --mark 0x0 -m recent --update --seconds 60 --name DEFAULT --rdest --rport -j MARK --set-xmark 0x4/0xffffffff
root@OpenWrt:~#

 

------------------------

来源 https://www.haiyun.me/archives/openwrt-tc-qos.html

Openwrt配置QOS流量带宽限制
#加载模块:

insmod xt_IPID
insmod cls_u32                                                                                         
insmod cls_fw  
insmod sch_htb
insmod sch_sfq
insmod sch_prio

#启用IMQ虚拟网卡
ip link set imq0 up
ip link set imq1 up

#删除旧队列
tc qdisc del dev imq0 root
tc qdisc del dev imq1 root

#上传设置
#增加根队列,未标记数据默认走26
tc qdisc add dev imq0 root handle 1: htb default 26

#增加总流量规则
tc class add dev imq0 parent 1: classid 1:1 htb rate 350kbit

#增加子类
tc class add dev imq0 parent 1:1 classid 1:20 htb rate 80kbit ceil 250kbit prio 0
tc class add dev imq0 parent 1:1 classid 1:21 htb rate 80kbit ceil 250kbit prio 1
tc class add dev imq0 parent 1:1 classid 1:22 htb rate 80kbit ceil 250kbit prio 2
tc class add dev imq0 parent 1:1 classid 1:23 htb rate 80kbit ceil 250kbit prio 3
tc class add dev imq0 parent 1:1 classid 1:24 htb rate 80kbit ceil 250kbit prio 4
tc class add dev imq0 parent 1:1 classid 1:25 htb rate 50kbit ceil 250kbit prio 5
tc class add dev imq0 parent 1:1 classid 1:26 htb rate 50kbit ceil 150kbit prio 6
tc class add dev imq0 parent 1:1 classid 1:27 htb rate 50kbit ceil 100kbit prio 7

#为子类添加SFQ公平队列,每10秒重置
tc qdisc add dev imq0 parent 1:20 handle 20: sfq perturb 10
tc qdisc add dev imq0 parent 1:21 handle 21: sfq perturb 10
tc qdisc add dev imq0 parent 1:22 handle 22: sfq perturb 10
tc qdisc add dev imq0 parent 1:23 handle 23: sfq perturb 10
tc qdisc add dev imq0 parent 1:24 handle 24: sfq perturb 10
tc qdisc add dev imq0 parent 1:25 handle 25: sfq perturb 10
tc qdisc add dev imq0 parent 1:26 handle 26: sfq perturb 10
tc qdisc add dev imq0 parent 1:27 handle 27: sfq perturb 10

#添加过滤规则配合Iptables Mark标记
#tc filter add dev imq0 parent 1:0 protocol ip u32 match ip sport 22 0xffff flowid 1:10

#使用U32标记数据,下面使用Iptables mark,容易。
tc filter add dev imq0 parent 1:0 prio 0 protocol ip handle 20 fw flowid 1:20
tc filter add dev imq0 parent 1:0 prio 0 protocol ip handle 21 fw flowid 1:21
tc filter add dev imq0 parent 1:0 prio 0 protocol ip handle 22 fw flowid 1:22
tc filter add dev imq0 parent 1:0 prio 0 protocol ip handle 23 fw flowid 1:23
tc filter add dev imq0 parent 1:0 prio 0 protocol ip handle 24 fw flowid 1:24
tc filter add dev imq0 parent 1:0 prio 0 protocol ip handle 25 fw flowid 1:25
tc filter add dev imq0 parent 1:0 prio 0 protocol ip handle 26 fw flowid 1:26
tc filter add dev imq0 parent 1:0 prio 0 protocol ip handle 27 fw flowid 1:27

#上传数据转入特定链
iptables -t mangle -N MYSHAPER-OUT
iptables -t mangle -A POSTROUTING -o pppoe-wan -j MYSHAPER-OUT
iptables -t mangle -A MYSHAPER-OUT -j IMQ --todev 0

#为特定数据打上标记配合之前过滤规则
#iptables -t mangle -I MYSHAPER-OUT -s 192.168.1.16 -j MARK --set-mark 27 

#限制特定IP上传速度
#iptables -t mangle -I MYSHAPER-OUT -s 192.168.1.16 -j RETURN
iptables -t mangle -A MYSHAPER-OUT -p tcp --tcp-flags SYN,RST,ACK SYN -j MARK --set-mark 20 

#提高HTTP连接速度
iptables -t mangle -A MYSHAPER-OUT -p tcp --tcp-flags SYN,RST,ACK SYN -j RETURN
iptables -t mangle -A MYSHAPER-OUT -p udp --dport 53 -j MARK --set-mark 20 

#DNS查询
iptables -t mangle -A MYSHAPER-OUT -p udp --dport 53 -j RETURN
iptables -t mangle -A MYSHAPER-OUT -p icmp -j MARK --set-mark 21 

#ICMP数据
iptables -t mangle -A MYSHAPER-OUT -p icmp -j RETURN
iptables -t mangle -A MYSHAPER-OUT -p tcp -m length --length :64 -j MARK --set-mark 21 

#小数据包
iptables -t mangle -A MYSHAPER-OUT -p tcp -m length --length :64 -j RETURN
iptables -t mangle -A MYSHAPER-OUT -p tcp --dport 22 -j MARK --set-mark 22 

#SSH连接
iptables -t mangle -A MYSHAPER-OUT -p tcp --dport 22 -j RETURN
iptables -t mangle -A MYSHAPER-OUT -p udp --dport 1194 -j MARK --set-mark 22

#VPN连接
iptables -t mangle -A MYSHAPER-OUT -p udp --dport 1194 -j RETURN
iptables -t mangle -A MYSHAPER-OUT -p tcp --dport 80 -j MARK --set-mark 23 

#HTTP连接
iptables -t mangle -A MYSHAPER-OUT -p tcp --dport 80 -j RETURN
iptables -t mangle -A MYSHAPER-OUT -p tcp --dport 443 -j MARK --set-mark 24 

#HTTPS连接
iptables -t mangle -A MYSHAPER-OUT -p tcp --dport 443 -j RETURN
#上传设置完成

#下载设置
#增加根队列,未标记数据默认走24
tc qdisc add dev imq1 handle 1: root htb default 24
tc class add dev imq1 parent 1: classid 1:1 htb rate 3500kbit

#添加子类
tc class add dev imq1 parent 1:1 classid 1:20 htb rate 1000kbit ceil 1500kbit prio 0
tc class add dev imq1 parent 1:1 classid 1:21 htb rate 1500kbit ceil 2500kbit prio 1
tc class add dev imq1 parent 1:1 classid 1:22 htb rate 2000kbit ceil 3500kbit prio 2
tc class add dev imq1 parent 1:1 classid 1:23 htb rate 1000kbit ceil 1500kbit prio 3
tc class add dev imq1 parent 1:1 classid 1:24 htb rate 1000kbit ceil 1500kbit prio 4

#为子类添加SFQ公平队列
tc qdisc add dev imq1 parent 1:20 handle 20: sfq perturb 10
tc qdisc add dev imq1 parent 1:21 handle 21: sfq perturb 10
tc qdisc add dev imq1 parent 1:22 handle 22: sfq perturb 10
tc qdisc add dev imq1 parent 1:23 handle 23: sfq perturb 10
tc qdisc add dev imq1 parent 1:24 handle 24: sfq perturb 10

#过滤规则
tc filter add dev imq1 parent 1:0 prio 0 protocol ip handle 20 fw flowid 1:20
tc filter add dev imq1 parent 1:0 prio 0 protocol ip handle 21 fw flowid 1:21
tc filter add dev imq1 parent 1:0 prio 0 protocol ip handle 22 fw flowid 1:22
tc filter add dev imq1 parent 1:0 prio 0 protocol ip handle 23 fw flowid 1:23
tc filter add dev imq1 parent 1:0 prio 0 protocol ip handle 24 fw flowid 1:24

#下载数据转入特定链
iptables -t mangle -N MYSHAPER-IN
iptables -t mangle -A PREROUTING -i pppoe-wan -j MYSHAPER-IN
iptables -t mangle -A MYSHAPER-IN -j IMQ --todev 1

#分类标记数据
#iptables -t mangle -A MYSHAPER-IN -d 192.168.1.16 -j MARK --set-mark 23 

#限制特定IP下载速度
#iptables -t mangle -A MYSHAPER-IN -d 192.168.1.16 -j RETURN
iptables -t mangle -A MYSHAPER-IN -p tcp -m length --length :64 -j MARK --set-mark 20 

#小数据优先
iptables -t mangle -A MYSHAPER-IN -p tcp -m length --length :64 -j RETURN
iptables -t mangle -A MYSHAPER-IN -p icmp -j MARK --set-mark 20 

#ICMP数据
iptables -t mangle -A MYSHAPER-IN -p icmp -j RETURN
iptables -t mangle -A MYSHAPER-IN -p tcp --sport 22 -j MARK --set-mark 21

#SSH连接
iptables -t mangle -A MYSHAPER-IN -p tcp --sport 22 -j RETURN
iptables -t mangle -A MYSHAPER-IN -p udp --sport 1194 -j MARK --set-mark 21 

#VPN连接
iptables -t mangle -A MYSHAPER-IN -p udp --sport 1194 -j RETURN
iptables -t mangle -A MYSHAPER-IN -p tcp --sport 443 -j MARK --set-mark 22 

#HTTPS连接
iptables -t mangle -A MYSHAPER-IN -p tcp --sport 443 -j RETURN
iptables -t mangle -A MYSHAPER-IN -p tcp --sport 80 -j MARK --set-mark 22 

#HTTP连接
iptables -t mangle -A MYSHAPER-IN -p tcp --sport 80 -j RETURN
iptables -t mangle -A MYSHAPER-IN -p tcp --sport 0:1024 -j MARK --set-mark 23 

#系统服务端口连接
iptables -t mangle -A MYSHAPER-IN -p tcp --sport 0:1024 -j RETURN

 

=============== End

 

posted @ 2022-02-09 22:25  lsgxeva  阅读(19625)  评论(0编辑  收藏  举报