MTKHQoS的一点玩法总结
MTKHQoS的一点玩法总结
功能介绍
MTK的HQoS是基于MTK-PPE包硬件转发引擎的一个延申,理论上所有有PPE的硬件(MT762x,mt798x)都能实现 HQoS。按照官方的规格书,总的有4个调度器和128个硬件队列,但在immortalwrt-mt798x项目中只实现了64个硬件队列(可能和hanwckf在issue中讨论过的的v2驱动有问题有关),下述功能针对改仓库代码总结而来。
我的看法更应该叫硬件限速器,QoS的实现完全看开发者的规则实现。
通过对调度器以及队列的配置实现队列限速,再通过数据帧/包标记的方式,将数据帧绑定到不同队列进而实现对数据帧/包进行分级,进而实现HQoS。
工作流程:
数据包 → HNAT 处理 → 检查 fqos 标志 → 读取 qid → 进入指定硬件队列
命令操作
-
启动准备步骤
- 内核启用与HW_QoS相关的功能模块
- Linux系统安装iptables和ebtabels
iptables工作在L3和L4处理 IP 数据包,而ebtables工作在L2处理以太网帧
- 启用HQoS(在启用HNAT的前提下)
-
启动HQoS和DSCP支持
echo 1 > /sys/kernel/debug/hnat/qos_toggle echo "10 1" > /sys/kernel/debug/hnat/hnat_setting -
下调HNAT Bind Rate
echo "11 5" >/sys/kernel/debug/hnat/hnat_setting uci -q set "turboacc.config.fastpath_mh_eth_hnat_bind_rate"="5" uci -q commit "turboacc"
-
-
配置调度器
总的有四个调度器,可根据上下行可分为两组不同的设定
ehco ${sch_ebl} ${sch_policy} ${sch_bw} > /sys/keenel/debug/hant/qdma_schX- sch_ebl: 是否启动改调度器(0/1)
- sch_policy: 设置调度器策略(WRR/SP)
- WRR:满足最小带宽后按权重分配
- SP:队列号越小优先级越高
- sch_bw: 调度器速率限制(unit:Kbps)
-
配置队列器
在immortalwrt-mt798x的仓库中队列器的数目是64个
echo X ${queue_minebl} ${minirate} ${queue_maxbl} ${maxrate} ${queue_weight} ${queue_resv} > /sys/kernel/debug/hnat/qdma_txqY- X:指定调度器(0-3)
- queue_minebl:是否启动最小速率限制(0/1)
- minirate:最小速率限制(unit:Kbps)
- queue_maxbl:是否启动最大速率限制(0/1)
- maxrate:最大速率限制(unit:Kbps)
- queue_weight:WRR权重(0-15)
这里的weight值的大小和权重是相反的
- queue_resv:保留缓冲区大小(int)
- Y:队列器(0-63)
-
数据帧/包打标记
在immortalwrt-mt798x仓库中,比手册多了一个基于DSCP标记的功能,和传统DSCP的定义不要太一样,传统DSCP有指定的分级,其实等价于本来的MARK功能。且按照官方手册可以使用ebtabels实现基于mac的双向限速,比iptables只能单向mac匹配会灵活一点。
-
基于设备(IP/MAC)QoS:
-
上行:
iptables -t mangle -A eqos -m mac --mac-source $macaddr -j DSCP --set-dscp Y ip6tables -t mangle -A eqos -m mac --mac-source $macaddr -j DSCP --set-dscp Y -
下行:
ebtables -t nat -A eqos -d $macaddr -j mark --mark-set Y
-
-
基于数据包类型的QoS:
iptables -t mangle -A eqos -i br-lan -p tcp -m multiport --dports 80,443,8080,8081 -j DSCP --set-dscp Y iptables -t mangle -A eqos -o br-lan -p tcp -m multiport --sports 80,443,8080,8081 -j DSCP --set-dscp Y
-
EQoS-MTK工作流程分析
-
流程图
graph TD A[启动服务] --> B[读取配置] B --> C[启动主QoS] C --> D[配置总带宽] D --> E[初始化硬件队列] E --> F[负载均衡设置] F --> G[处理设备限速] G --> H[DHCP动态标记] subgraph 主QoS启动 C --> D1[创建HTB队列] D1 --> D2[设置总带宽] D2 --> D3[初始化IFB虚拟设备] end subgraph 硬件加速 E --> E1[配置HNAT] E1 --> E2[设置调度器] E2 --> E3[预分配队列] end subgraph 设备限速 G --> G1[分配索引] G1 -->|索引≤31| G2[硬件限速] G1 -->|索引>31| G3[软件TC限速] G2 --> G4[配置HNAT队列] G4 --> G5[设置DSCP标记] G3 --> G6[创建TC类和过滤器] end subgraph DHCP动态处理 H --> H1[监听DHCP事件] H1 --> H2[分配MARK值] H2 --> H3[更新iptables规则] H3 --> H4[保存MAC-MARK映射] end -
启动代码分析
只分析和HQoS有关的部分,原EQoS基于tc和iptables的流量控制代码不做分析。
- 初始化iptables、调度器和队列
-
清空相关链、重置标记、清空调度器以及队列参数
# 删除eqos链 ## 删除调用 iptables -t mangle -D FORWARD -j eqos ip6tables -t mangle -D FORWARD -j eqos ebtables -t nat -D POSTROUTING -j eqos ## 删除链 iptables -t mangle -F eqos ip6tables -t mangle -F eqos ebtables -t nat -F eqos iptables -t mangle -X eqos ip6tables -t mangle -X eqos ebtables -t nat -X eqos # 关闭HQoS echo 0 > /sys/kernel/debug/hnat/qos_toggle # 删除firewall的规则 sed -i '/\/etc\/init.d\/eqos start/d' /etc/firewall.user # 设置所有删除设置的DSCP标记 iptables -t mangle -D FORWARD -i br-lan -j DSCP --set-dscp 0 iptables -t mangle -D FORWARD -o br-lan -j DSCP --set-dscp 0 ip6tables -t mangle -D FORWARD -i br-lan -j DSCP --set-dscp 0 ip6tables -t mangle -D FORWARD -o br-lan -j DSCP --set-dscp 0 # 关闭HNat的DSCP支持 echo "10 0" > /sys/kernel/debug/hnat/hnat_setting # 回调hnat band rate echo "11 30" >/sys/kernel/debug/hnat/hnat_setting uci -q set "turboacc.config.fastpath_mh_eth_hnat_bind_rate"="30" uci -q commit "turboacc" # 清空HQoS上传下载限速 for i in $(seq 0 31); do echo 0 0 0 0 0 4 4 > /sys/kernel/debug/hnat/qdma_txq$i done for i in $(seq 32 63); do echo 1 0 0 0 0 4 4 > /sys/kernel/debug/hnat/qdma_txq$i done # 禁用全局限速 echo 0 wrr 25000000 > /sys/kernel/debug/hnat/qdma_sch0 echo 0 wrr 25000000 > /sys/kernel/debug/hnat/qdma_sch1 echo 0 wrr 25000000 > /sys/kernel/debug/hnat/qdma_sch2 echo 0 wrr 25000000 > /sys/kernel/debug/hnat/qdma_sch3 # 清除所有现存的DSCP标记 iptables -t mangle -D FORWARD -i br-lan -j DSCP --set-dscp 0 iptables -t mangle -D FORWARD -o br-lan -j DSCP --set-dscp 0 iptables -t mangle -A FORWARD -i br-lan -j DSCP --set-dscp 0 iptables -t mangle -A FORWARD -o br-lan -j DSCP --set-dscp 0 ip6tables -t mangle -D FORWARD -i br-lan -j DSCP --set-dscp 0 ip6tables -t mangle -D FORWARD -o br-lan -j DSCP --set-dscp 0 ip6tables -t mangle -A FORWARD -i br-lan -j DSCP --set-dscp 0 ip6tables -t mangle -A FORWARD -o br-lan -j DSCP --set-dscp 0 -
新建所需链、初始化调度器以及队列参数
# 创建并清空eqos链 iptables -t mangle -N eqos iptables -t mangle -F eqos # 为ipv6新建并且清空eqos链 ip6tables -t mangle -N eqos ip6tables -t mangle -F eqos # 删除现存eqos链,并且重新调用 ip6tables -t mangle -D FORWARD -j eqos ip6tables -t mangle -A FORWARD -j eqos # 调用eqos链 iptables -t mangle -D FORWARD -j eqos iptables -t mangle -A FORWARD -j eqos || log "ERROR: Failed to attach eqos chain to FORWARD" # 开启HQoS echo 1 > /sys/kernel/debug/hnat/qos_toggle # 设置0和1HQoS调度器参数(不限速2.5G,WRR策略) echo 0 wrr 25000000 > /sys/kernel/debug/hnat/qdma_sch0 echo 0 wrr 25000000 > /sys/kernel/debug/hnat/qdma_sch1 # 绑定特定HQoS队列参数到调度器0和1(绑定到0和1调度器,不启用最大最小限速,权重0等价于最高权重) echo 0 0 0 0 0 0 0 > /sys/kernel/debug/hnat/qdma_txq0 echo 1 0 0 0 0 0 0 > /sys/kernel/debug/hnat/qdma_txq32 # 下调HNat band rate echo "11 5" >/sys/kernel/debug/hnat/hnat_setting uci -q set "turboacc.config.fastpath_mh_eth_hnat_bind_rate"="5" uci -q commit "turboacc" # 添加firewall触发eqos的指令 sed -i '/\/etc\/init.d\/eqos start/d' /etc/firewall.user echo "/etc/init.d/eqos start" >> /etc/firewall.user # 开启HNat DSCP支持 echo "10 1" > /sys/kernel/debug/hnat/hnat_setting -
设置用于QoS的调度器参数
WRR策略
echo 1 wrr $(($upload*1000)) > /sys/kernel/debug/hnat/qdma_sch2 echo 1 wrr $(($download*1000)) > /sys/kernel/debug/hnat/qdma_sch3 -
绑定队列到指定的调度器
# 设置全局上传 for i in $(seq 1 31); do if [ "$upload" -ne "0" ]; then echo 2 1 $(($upload*225)) 1 $(($upload*1000)) 4 1 > /sys/kernel/debug/hnat/qdma_txq$i fi done # 设置全局下载 for i in $(seq 33 63); do if [ "$download" -ne "0" ]; then echo 3 1 $(($download*200)) 1 $(($download*1000)) 4 1 > /sys/kernel/debug/hnat/qdma_txq$i fi done # 设置特殊队列的限速 echo 2 1 $(($upload*100)) 1 $(($upload*1000)) 4 1 > /sys/kernel/debug/hnat/qdma_txq30 echo 3 1 $(($download*150)) 1 $(($download*1000)) 4 1 > /sys/kernel/debug/hnat/qdma_txq62 echo 2 1 $(($upload*100)) 1 $(($upload*1000)) 4 1 > /sys/kernel/debug/hnat/qdma_txq27 echo 3 1 $(($download*150)) 1 $(($download*1000)) 4 1 > /sys/kernel/debug/hnat/qdma_txq59 -
iptables/ebtables打标记
-
基于数据包规则
# 小包优先 iptables -t mangle -A eqos -i br-lan -m length --length :256 -j DSCP --set-dscp 28 -m comment --comment "EQoS_PACKETS_PREFER" iptables -t mangle -A eqos -o br-lan -m length --length :256 -j DSCP --set-dscp 60 -m comment --comment "EQoS_PACKETS_PREFER_RELAY" -
客户端限速
-
基于IP
# 删除现有规则 iptables -t mangle -D eqos -s $ip -j DSCP --set-dscp ${id} iptables -t mangle -D eqos -d $ip -j DSCP --set-dscp ${idpair} ip6tables -t mangle -D eqos -m mac --mac-source $macaddr -j MARK --set-mark ${id} ebtables -t nat -D eqos -p ipv6 -d $macaddr -j mark --mark-set ${idpair} # 创建上传规则 if [ $up -ne 0 ]; then echo 2 0 0 1 ${up} 4 1 > /sys/kernel/debug/hnat/qdma_txq${id} iptables -t mangle -A eqos -s $ip -j DSCP --set-dscp ${id} ip6tables -t mangle -A eqos -m mac --mac-source $macaddr -j MARK --set-mark ${id} fi # 创建下载规则 if [ $dl -ne 0 ]; then echo 3 0 0 1 ${dl} 4 1 > /sys/kernel/debug/hnat/qdma_txq${idpair} iptables -t mangle -A eqos -d $ip -j DSCP --set-dscp ${idpair} ebtables -t nat -A eqos -p ipv6 -d $macaddr -j mark --mark-set $ {idpair} fi -
基于mac
# 删除现有规则 iptables -t mangle -D eqos -m mac --mac-source $macaddr -j DSCP --set-dscp ${id} ip6tables -t mangle -D eqos -m mac --mac-source $macaddr -j DSCP --set-dscp ${id} ebtables -t nat -D eqos -d $macaddr -j mark --mark-set ${idpair} # 创建上传规则 if [ $up -ne 0 ]; then echo 2 0 0 1 ${up} 4 1 > /sys/kernel/debug/hnat/qdma_txq${id} iptables -t mangle -A eqos -m mac --mac-source $macaddr -j DSCP --set-dscp ${id} ip6tables -t mangle -A eqos -m mac --mac-source $macaddr -j DSCP --set-dscp ${id} fi # 创建下载规则 if [ $dl -ne 0 ]; then echo 3 0 0 1 ${dl} 4 1 > /sys/kernel/debug/hnat/qdma_txq${idpair} ebtables -t nat -A eqos -d $macaddr -j mark --mark-set ${idpair} fi
-
-
-
- 初始化iptables、调度器和队列