MTKHQoS的一点玩法总结

功能介绍

MTK的HQoS是基于MTK-PPE包硬件转发引擎的一个延申,理论上所有有PPE的硬件(MT762x,mt798x)都能实现 HQoS。按照官方的规格书,总的有4个调度器和128个硬件队列,但在immortalwrt-mt798x项目中只实现了64个硬件队列(可能和hanwckf在issue中讨论过的的v2驱动有问题有关),下述功能针对改仓库代码总结而来。

我的看法更应该叫硬件限速器,QoS的实现完全看开发者的规则实现。

通过对调度器以及队列的配置实现队列限速,再通过数据帧/包标记的方式,将数据帧绑定到不同队列进而实现对数据帧/包进行分级,进而实现HQoS。

工作流程:
数据包 → HNAT 处理 → 检查 fqos 标志 → 读取 qid → 进入指定硬件队列

命令操作

  1. 启动准备步骤

    1. 内核启用与HW_QoS相关的功能模块
    2. Linux系统安装iptables和ebtabels

      iptables工作在L3和L4处理 IP 数据包,而ebtables工作在L2处理以太网帧

    3. 启用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"
        
  2. 配置调度器

    总的有四个调度器,可根据上下行可分为两组不同的设定

    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)
  3. 配置队列器

    在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)
  4. 数据帧/包打标记

    在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的流量控制代码不做分析。

    1. 初始化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
            

标签: none

添加新评论