linux网络流控-htb算法简析

Linux TC 流量控制与排队规则 qdisc 树型结构详解(以HTB和RED为例) Linux 操作系统中的流量控制器 TC (Traffic Control) 用于Linux内核的流量控制,它规定建立处理数据包的队列,并定义队列中的数据包被发送的方式,从而实现对流量的控制。 阅读详情

项目中用tc,htb做流控期间,研究了htb(分层令牌桶)算法的实现.觉得这种思想在类似与有消费优先级的生产者消费者场景中也很适用.该算法过于复杂,碍于嘴拙遂在标题中加了简析,只介绍核心思想和关键代码的实现.

一个栗子:

tc qdisc add dev eth0 root handle 1: htb
tc class add dev eth0 parent 1:  classid 1:1  htb rate 100mibps
tc class add dev eth0 parent 1:1 classid 1:10 htb rate 30mibps ceil 80mibps prio 0 burst 10kbit cburst 20kbit quantum 30000
tc class add dev eth0 parent 1:1 classid 1:20 htb rate 20mibps ceil 50mibps prio 1 burst 10kbit cburst 20kbit quantum 20000
tc class add dev eth0 parent 1:10 classid 1:101 htb rate 10mibps ceil 80mibps prio 1 burst 10kbit cburst 20kbit quantum 10000
tc class add dev eth0 parent 1:10 classid 1:102 htb rate 5mibps ceil 40mibps prio 0 burst 10kbit cburst 20kbit quantum 5000

图1


首先创建了一个htb队列,在队列中创建了5个类,他们之间的关系可以表示成上图这样的一棵树.一些关键参数也标出来了,后面会解释.

下面用iptables将流量分类,根据目的ip,将相应的流量分类到1:20  1:101 1:102三个类队列中.这里有两点要说明:
1.分类流量又很多方式,例如cgroup iptables tc filter等工具.但本文中重心在于流量如何出,所以网络包如何进入相应的类队列就省略了.
2.流量只能缓存在树的叶节点(leaf class),其他类节点(inner class)是不能缓存流量的.但innerclass对于不同子类能共享带宽起到重要作用.

iptables -t mangle -A OUTPUT -d 192.168.1.2 -j CLASSIFY --set-class 1:20
iptables -t mangle -A OUTPUT -d 192.168.1.3 -j CLASSIFY --set-class 1:101
iptables -t mangle -A OUTPUT -d 192.168.1.4 -j CLASSIFY --set-class 1:10


htb虽然为每个类设定了rate,但并不是说每个类只能以设定的rate出包.当网卡比较空闲时,leafclass是可以以高于rate的速率出包的.但不能高于ceil.一句话来说就是闲时共享,忙时按照比例(这个比例是rate,quantum共同决定的)分配带宽.网络包只能入/出leafclass,innerclass对于不同子类能共享带宽起作用.
图1中还为每个leafclass标注出了priority属性.htb对类支持0-7  8个优先级,0优先级最高.优先级越高的类可以优先出流量.

原理介绍
某个时刻每个类可以处于三种状态中的一种:

  CAN_SEND(令牌充足的,发送的网络包小于rate,例图中用绿色表示)  

  MAY_BORROW(没有令牌,但可借用.发送的网络包大于rate小于ceil,例图中用黄色表示)

  CANT_SEND(没有令牌不可借用,发送的网络包大于ceil,例图中用红色表示)

htb是如何决策哪个类出包的?
1.htb算法从类树的底部开始往上找CAN_SEND状态的class.如果找到某一层有CAN_SEND状态的类则停止.


2.如果该层中有多个class处于CAN_SEND状态则选取优先级最高(priority最小)的class.如果最高优先级还是有多个class,那就在这些类中轮训处理.每个类每发送自己的quantum个字节后,轮到下一个类发送.

3.上面有讲到只有leafclass才可以缓存网络包,innerclass是没有网络包的.如果步骤1,2最终选到了innerclass怎么处理?既然是innerclass,肯定有自己的subclass.innerclass会顺着树往下找,找到一个子孙leafclass.并且该leafclass处于MAY_BORROW状态,将自己富余的令牌借给该leafclass让其出包.同样的道理,可能会有多个子孙leafclass处于MAY_BORROW状态,这里的处理跟步骤2是一样的.

多个子类共享父类带宽也就体现在这里了.假设父类富余了10MB, 子类1的quantum为30000,子类2的quantum为20000.那么父类帮子类1发送30000byte,再帮子类2发送20000byte.依次循环.最终效果就是子类1借到了6MB,子类2借到了4MB.因此上文说,当子类之间共享带宽时,rate/quantum共同决定它们分得的带宽.rate处于CAN_SEND状态时能发送多少字节,quantum决定处于MAY_BORROW状态时可借用令牌发送多少字节.

场景举例
1.假设某一时刻,1:101, 1:102都有网络包堆积,并且都处于CAN_SEND状态.1:20因为没有流量因此可视为没有这个节点.图2所示:
图2


按照前面说的,1:101, 1:102这两个类都属于同一层,优先级相同.htb轮训它们出包.1:101每轮发送20000byte,1:102每轮发送5000byte.
某一时刻1:101发送的流量超过了其rate值(10MB),但未超过其ceil值(20MB).因此1:101状态转变成MAY_BORROW状态.如图3:

图3


此时最底层只有1:102这个类是CAN_SEND,只能全力出这个类的包了.当1:102发送的流量超过其rate值(5MB)时,其状态也变为MAY_BORROW.如图4:
图4



这时最底层已经没有CAN_SEND状态的类了.网上找到1:10.1:10的两个子类此时都处于MAY_BORROW状态,因此1:10又轮训着发送1:101,1:102的包.每轮还是发送它们对应的quantum值.  很快1:101发送的流量达到其ceil值(20MB)了,此时1:101状态变成CANT_SEND.如图5:

图5


此时1:10只能全力发送1:102的包.直到达到其ceil值(30MB).此时1:102变为CANT_SEND,1:101和1:102累计发送了50MB数据,达到了其父类1:10的rate值,因此1:10变为MAY_BORROW.如图6:
图6



核心代码
几个核心数据结构,这里就不贴了:
struct Qdisc: tc队列
struct htb_class:  htb类
网络包从协议栈出来经驱动送往网卡之前,会做一个入队/出队操作.这也就是tc的入口.
当我们使用htb算法时,出包回调为htb_dequeue,htb_dequeue返回一个skb给网卡发送.

static struct sk_buff *htb_dequeue(struct Qdisc *sch)
{
    ...
    for(level = 0; level < TC_HTB_MAXDEPTH; level++) {   // 逐层找.这里level是反的,0层表示最底层.
        /* common case optimization - skip event handler quickly */
        int m;
        ...
        m = ~q->row_mask[level];
        while(m !=(int)(-1)) {        // 同一层取优先级高的
            int prio = ffz(m);
            m |= 1 << prio;
            skb = htb_dequeue_tree(q, prio, level);   //出包
            if(likely(skb != NULL)) {
                sch->q.qlen--;
                sch->flags &= ~TCQ_F_THROTTLED;
                goto fin;
            }
        }
    }
    sch->qstats.overlimits++;
    ...
fin:
    return skb;
}

 

htb_dequeue找到对应的层数和优先级之后调用htb_dequeue_tree,只列出htb_dequeue_tree中核心代码:

static struct sk_buff *htb_dequeue_tree(struct htb_sched *q, int prio, int level)
{
    struct sk_buff *skb = NULL;
    struct htb_class *cl, *start;
    ...
    cl = htb_lookup_leaf(q->row[level] + prio,prio, q->ptr[level] + prio,  // 找到该level 该priority下的一个leafclass
                   q->last_ptr_id[level] + prio);

    skb = cl->un.leaf.q->dequeue(cl->un.leaf.q);     // 出包

    if(likely(skb != NULL)) {
        cl->un.leaf.deficit[level] -= qdisc_pkt_len(skb);  //deficit[level] 扣掉该包的byte数
        if(cl->un.leaf.deficit[level] < 0) {              //当deficit[level]<0时说明该类已经发送了quantum.需要发送下一个类了.
            cl->un.leaf.deficit[level] += cl->quantum;
            htb_next_rb_node((level ? cl->parent->un.inner.ptr : q->
                      ptr[0]) + prio);
        }
        htb_charge_class(q, cl, level, skb);    // 更新令牌.
    }
    return skb;
}

因为不确定传进来的level是不是最底层,因此调用htb_lookup_leaf保证得到的class是leafclass.其中参数(q->ptr[level] + prio)记录该层该优先级当前应该发那个leafclass.
skb = cl->un.leaf.q->dequeue(cl->un.leaf.q) 出包.

当出队一个数据包时,类对应的deficit[level]扣减包的byte数,当deficit[level]<0时说明该类已经发送了quantum.于是虽然再次给deficit[level]加了quantum,
但是htb_next_rb_node((level ? cl->parent->un.inner.ptr : q->ptr[0]) + prio)已经将该层该优先级的出包类指针指向下一个类了.下发出包,将会出另一个类.
可以对比前面提到的1:101,1:102轮流出包.

htb_charge_class最后更新令牌.看下htb_charge_class:

static void htb_charge_class(struct htb_sched *q, struct htb_class *cl,int level, struct sk_buff *skb)
{
    int bytes = qdisc_pkt_len(skb);
    enum htb_cmode old_mode;
    long diff;

    while(cl) {        //这里是一个循环,子类发包,是同时要扣子类和父类的令牌的.
        diff = psched_tdiff_bounded(q->now, cl->t_c, cl->mbuffer);
        if(cl->level >= level) {
            if(cl->level == level)         //令牌的生产,扣减在这里.
                cl->xstats.lends++;
            htb_accnt_tokens(cl, bytes, diff);
        } else {
            cl->xstats.borrows++;
            cl->tokens += diff; /* we moved t_c; update tokens */
        }
        htb_accnt_ctokens(cl, bytes, diff);
        cl->t_c = q->now;

        old_mode = cl->cmode;
        diff = 0;
        htb_change_class_mode(q, cl, &diff);        //判断是不是要切换状态了.
        if(old_mode != cl->cmode) {
            if(old_mode != HTB_CAN_SEND)
                htb_safe_rb_erase(&cl->pq_node, q->wait_pq + cl->level);
            if(cl->cmode != HTB_CAN_SEND)
                htb_add_to_wait_tree(q, cl, diff);
        }
        cl = cl->parent;
    }
}

子类发包同时要口父类的令牌很好理解,本质上子机就是再用父类的带宽.但是当父类令牌富余借给子机出包时,只需从父类开始到祖先扣令牌.子机会更新这个周期生产的令牌,但不会扣了,因为是借用父类的令牌发包的.
令牌计算完后,更改class的状态.大体上就是这样,不再深入了.

为了描述方便,有些地方写的跟代码细节有差别.见谅.

调度算法 HTB 或 CBQ 简介 调度算法在操作系统和网络中起着关键作用,用于分配资源(如CPU时间或带宽)以实现高效和公平的任务处理。以下是关于和。 阅读详情

相关推荐

ROS_HTB_优先限速

ROS_HTB_优先限速,不错的脚本试试吧

服务器出口带宽限速方法

wondershaper 是一个 Linux 下的带宽限制工具,它可以方便地限制网络接口的带宽,支持限制下载速度和上传速度。wondershaper 命令的使用非常简单,只需要指定要限制带宽的网络接口和带宽限制值即可。pyshaper是一个基于Python的Linux网络流量控制工具,可以用来限制网络流量的带宽、延迟、丢包等。pyshaper设置的网络流量控制限制是针对整个系统的,而不仅仅是当前shell。也就是说,一旦设置了流量限制,它将影响整个系统的网络流量。

white_li5的博客 7065

2023-12-26~2025-07-04备份

一、海康视觉与汇川机器人 服务器-客户端通信设置IP在同一网段名称IP端口类型海康相机工控机7930服务器机器人3000客户端海康VM服务器设置1通信管理 增添TCP服务端,设置本机IP:192.168.0.20,端口号79302 协议解析 通信双方约定通信格式(设置收发数据格式,分隔符)机器人客户端设置(不同类型机器人设置有差别)1 通讯服务设置 设置连接服务器IP、服务端端口号、机器人端口号,确保连接正常2 协议解析 使用指令代码构建通讯解析。

青铜小码农 3126

Linux内核TC工具链路带宽设计--HTB队列规定及简单的过滤器介绍

1HTB(Hierarchical Token Bucket,分层的令牌桶) HTB 使用令牌和存储桶的概念,以及基于类的系统和过滤器,以允许对流量进行复杂和精细的控制。借助复杂的借用模型,HTB 可以执行各种复杂的流量控制技术。该队列规则允许用户定义所使用的令牌和桶的特征,并允许用户以任意方式嵌套这些桶。当与分类方案结合使用时,可以非常精细地控制流量。HTB 非常适用于这种情况...

weixin_30360497的博客 599

巨量千川M-API实战:5分钟搞定短视频计划数据自动获取(Python版)

本文详细介绍了如何利用巨量千川M-API和Python快速搭建自动化工具,实现短视频计划数据的自动获取。通过实战代码演示了从环境准备、Token管理到核心数据接口调用的完整流程,帮助电商运营和技术开发者告别手动导出,高效完成数据汇总与分析。

weixin_29325515的博客 1357

Keil5实战:如何高效导出变量数据并实现可视化分析

本文详细介绍了在Keil5开发环境中,如何利用调试脚本高效导出程序运行时变量数据的方法。通过编写脚本自动捕获数据并保存为文件,再结合Excel或Python进行可视化分析,为嵌入式调试与算法优化提供了数据支撑,显著提升开发效率。

silver的专栏 1104

HTB在内核实现

Linux内核中流量控制(11) 本文档的Copyleft归yfydz所有,使用GPL发布,可以自由拷贝,转载,转载时请保持文档的完整性, 严禁用于任何商业用途。 msn: yfydz_no1@hotmail.com 来源:http://yfydz.cublog.cn Java代码   5.11 HTB(Hierarchical token bu

关注云计算,与中国云计算共成长 3069

多模型对抗性审查:用AI辩论提升技术文档质量

在软件工程领域,技术文档是团队协作和项目成功的关键基础。传统的文档评审依赖人工经验,存在盲区和效率瓶颈。通过引入多模型对抗性审查机制,不同大语言模型从各自视角对文档进行批判性分析,模拟现实中的专家评审过程。这种技术方法的核心价值在于利用模型间的思维差异,自动发现单个视角容易忽略的边界情况、逻辑漏洞和隐含假设。在应用场景上,特别适合产品需求文档和技术规格书这类需要多角度审视的复杂文档。adversarial-spec工具通过Claude协调多模型辩论,实现从概念到实现的完整文档质量保障,显著提升文档的完整性和

weixin_42531579的博客 379

tc网络流控详解及常用队列

tc网络流控详解及常用队列TC是什么?tc的组成有哪些?队列、类别、过滤器可分类别队列简单的无类别队列(pfifo_fast)简单的无类队列(TBF)无类别随机公平队列(SFQ)可分队列中的数据流向PRIO队列著名的CBQ队列常用简单的过滤命令HTB(Hierarchical Token Bucket, 分层的令牌桶)一个复杂的实例IMQ(Intermediate queueing device,...

Van_male的博客 7326

Windows11配置WSL2支持代理上网

说起来本来这个功能我也不需要的,只是最近突然有个需求就顺便研究了下,WSL2默认的网络方式是NAT,即WSL2的网卡本身是虚拟网卡,通过以太网或WIFI的地址转换来上互联网,我试了下是不能直接走代理的,最近比较忙没具体研究,但是我用另一种方式实现了,下面介绍给需要的人。注意:这个方法只能是WIndows11系统,WIndows10系统上的WSL2缺少了一项功能导致不可用。1、方法总体没什么难度,NAT方式暂时没研究透,后续有时间再研究2、WIndows10系统不支持mirrored,暂时需要另辟蹊径。

jiexijihe945的博客 9590

微信小程序 - 最新详细实现气泡菜单功能,点击任意元素在底部或附近周围弹出气泡菜单列表,仿微信气泡弹框显示菜单快捷功能收纳,自定义气泡弹窗/菜单气泡弹窗,小程序气泡框嵌套菜单组件插件,自动计算弹出定位

微信小程序,vue2,vue3,气泡列表,汽泡菜单,气泡框,泡泡框,悬浮框,悬浮菜单,点击菜单按钮弹出气泡,对话箭头气泡框,弹出的气泡准确定位并吸附在附近,弹出式气泡,弹窗菜单,气泡自定义HTML弹窗,带三角的气泡弹框,三角气泡框里面嵌套菜单,当点击一个按钮或元素时,会从附近弹出一个小气泡一样的菜单列表,自定义气泡框内的内容,点击一个元素在附近弹出一个气泡弹框功能效果,气泡弹框不准怎么办,被盖住了,挡住了,长按弹出,组件插件,微信,自定义气泡菜单组件,气泡弹出框,小程序自定义气泡框,菜单气泡,包裹列表的三角

🏆 前端领域优质创作者 3915

gh_mirrors/li/linux内核网络流量整形:TC HTB分类器配置

在高并发网络环境中,服务器带宽资源的公平分配与精细化管理一直是系统管理员面临的核心挑战。当多个应用程序或用户共享有限的网络带宽时,缺乏有效的流量控制机制可能导致关键业务被非关键流量挤占,甚至引发网络拥塞和服务质量下降。Linux内核提供的**HTB(Hierarchical Token Bucket,分层令牌桶)** 分类器正是解决这一问题的强大工具。 本文将深入剖析Linux内核中HTB分类器...

gitblog_00587的博客 1140

PyTorch深度学习实战(29)——变分自编码器(Variational Autoencoder, VAE)

变分自编码器 (Variational Autoencoder, VAE) 是一种结合了自编码器和概率建模的生成模型,通过编码器将输入数据映射到潜在空间中的概率分布,并通过解码器将从潜在空间采样得到的潜在变量映射回原始数据空间,实现了数据的生成和特征学习。

盼小辉丶的博客 1万+

linux下TC+HTB流量控制

C规则涉及到 队列(QUEUE) 分类器(CLASS) 过滤器(FILTER),filter划分的标志位可用U32或iptables的set-mark来实现 ) 一般是"控发"不控收 linux下有两块网卡,一个eth1是外网,另一块eth0是内网.在eth0上做HTB。(注意:filter划分标志位可用u32打标功能或iptables的set-mark功能,如果用iptables来打标记的话

zehoa0105的专栏 1246

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

linux htb 源码学习-----------一篇我2012年写的Linux流控的文章给大家分享,本人已经不做这一行了

Linux 流量控制源码学习 队列的数据结构图 网络设备的结构体 红色粗体斜体,是流控相关的部分。 struct net_device { /*  * This is the first field of the "visible" part of this structure  * (i.e. as seen by users in the "Space.c" file).  I...

qingsong1001的专栏 1273

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

HTB分层令牌桶排队规则分析

之前通过《默认FIFO_FAST出口排队规则分析》、《ingress入口排队规则分析》分析,已经对排队规则的基础架框有了简单的了解。那两种排队规则都是无类的,这里选出可以分类的HTB排队规则进行分析。 当前实例分析的基本对象关联图 一、当前分析的配置范例 //在eth0设备上创建一个根HTB排队规则,当未匹配任何过滤器时,将报文放入ID为20 //的分类中 tc qdisc add de

技术人生 7213

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

ip -4 a 查看网卡上有htb代表什么?

在 Linux 系统中,ip -4 a命令用于查看 IPv4 地址和相关网络信息。当输出中的网卡名称后面带有htb时,表示该网卡上启用了 HTB(Hierarchical Token Bucket)调度算法。HTB 是一种流量调度算法,用于实现流量控制和优先级管理。它可以将可用带宽分割成多个等级,然后为每个等级分配不同的带宽比例。这样可以确保高优先级的流量获得更高的带宽份额,从而实现对网络流量的有效管理和控制。

喝醉酒的小白 919

Linux 高级流控

在 IBM Bluemix 云平台上开发并部署您的下一个应用。 开始您的试用 Linux 高级流量控制 本篇主要讲用 TC 对 Linux 进行高级流量控制 通过大量实践结合 TC 流控 HOWTO 文档整理而得 如果你对 Linux 流控感兴趣,如果你需要搭建高性能的 Linux 网关 , 本文将会使你受益颇多。 注:至少具备 Linux OS 的中级水平

eydwyz的专栏 2332

HTB相关TC命令以及内核实现介绍

HTB相关TC命令以及内核实现介绍                                           HTB相关TC命令以及内核实现介绍   前言... 3 关于此文档... 3 参考资料... 3 第一章       HTB 介绍... 4 1.0 HTB 命令介绍... 5 2.0 Rate ceiling

~~ LINUX ~~ 4199

linux进入cbq文件夹,Linux流量控制(SFQ/TBFPRIO/CBQ/HTB原理介绍)

Linux流量控制控发不控收,所以只能对产生瓶颈网卡处的发包速率进行控制..而网络瓶颈分析亦为Linux网络流控的第一步。二种流控算法Linux流量控制控发不控收,所以只能对产生瓶颈网卡处的发包速率进行控制..而网络瓶颈分析亦为Linux网络流控的第一步。二种流控算法上分:无类算法 用于树叶级无分支的队列 SFQ TBF pFIFO分类算法 用于多分支的队列 PRIO HTB CBQ调度在分类器的...

weixin_33378701的博客 935

linux系统关闭流控,Linux流量控制III---过滤规则(接着上文)

Linux流量控制IV---实例解析以下二例是工作中用到的,贴出来算对流量控制的一种理解吧..呵呵.1.PRIO 分类优先算法(从左至右优先发包)eth0 1:/ | \1:11:2 1:3/ | \11: 12: 13:#tc ad add dev eth0 root handle 1: prio hands3 priomap 1---1 16个1(tos比特) 表示所有数据包注:此命令自动...

weixin_35805055的博客 706

wondershaper深度解析:HTB队列管理与优先级流量分类原理

wondershaper是一款强大的命令行带宽管理工具,通过HTB(Hierarchical Token Bucket)队列管理和优先级流量分类技术,帮助用户轻松限制网络适配器的带宽使用。本文将深入剖析其核心原理,带你了解如何通过简单配置实现高效的网络流量控制。 ## 什么是HTB队列管理? HTB(Hierarchical Token Bucket)是一种先进的流量控制算法,它允许将带宽资源

gitblog_00460的博客 871

使用TC的htb队列控制网络流量

起因,放在公司内的部分服务器对外提供服务,而且是很重要的服务,但由于公司员工上网也要占据很大的流量,往往导致服务器抢不到带宽,严重影响服务器的对外服务,于是考虑限制公司员工上网的带宽,确保服务器对外提供服务的带宽。网络设备及网络结构:一根外接光缆专线,isp提供的带宽为4M(实际为不到5M,大概在4.8左右,也可能是换算方式不同导致的),对端(ISP方面)一个网关1.1.1....

weixin_34187862的博客 207
上一篇: DPDK QOS1 -- Linux HQOS的框架
下一篇: Internet路由之路由表查找算法概述-哈希/LC-Trie树/256-way-mtrie树
废言Pro
博客等级 码龄16年 1093粉丝 142原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值