HTB相关TC命令以及内核实现介绍
HTB相关TC命令以及内核实现介绍
前言... 3
关于此文档... 3
参考资料... 3
第一章 HTB 介绍... 4
1.0 HTB 命令介绍... 5
2.0 Rate ceiling 速率限度... 12
第二章 HTB 程序实现... 13
2.0 用户传递消息的格式... 14
2.1 HTB 命令的解析... 16
举例消息解析过程... 17
2.2 HTB 内核程序的实现... 18
2.2.1 数据包进队... 19
2.2.2 数据包的出队... 21
前言
关于此文档
主要讲述了HTB的原理以及内核的实现部分,不过重点讲的是原理部分,以及如何根据需要给数据流分类,控制不同数据流的速度。
参考资料
mbps = 1024 kbps = 1024 * 1024 bps => byte/s
mbit = 1024 kbit => kilo bit/s.
mb = 1024 kb = 1024 * 1024 b => byte
1Mbit = 1024 Kbit = 1024 * 1024 bps => byte/s
第一章 HTB 介绍
1.0 HTB 命令介绍
案例: 我们有两不同的用户A和B, 都通过网卡 eth0 连接到 internet ,我们想分配 60kbps的带宽给A 和 40 kbps的带宽给B。
HTB 可以保障提供给每个类带宽的数量是它所需求的最小需求或者等于分配给它的数量.当一个类需要的带宽少于分配的带宽时,剩余的带宽被分配给其他需要服务的类.
注: 这里这种情况被称为”借用”剩余带宽, 我们以后将用这个术语, 但无论如何,好像很不好因为这个”借用”是没有义务偿还的.
tc qdisc add dev ifbr0 root handle 1: htb default 12
这个命令建立QDISC 的根类型。默认情况下选择的类为12.
tc class add dev ifbr0 parent 1: classid 1:1 htb rate 100kbps ceil 100kbps
这个命令在根的基础上建立一个类,速度为 100Kbps起到总速度限制的作用。
tc class add dev ifbr0 parent 1:1 classid 1:10 htb rate 30kbps ceil100kbps
tc class add dev ifbr0 parent 1:1 classid 1:11 htb rate 10kbps ceil100kbps
tc class add dev ifbr0 parent 1:1 classid 1:12 htb rate 60kbps ceil100kbps
tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 \
match ip dport 80 0xffff flowid 1:10
tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 \
当然这只是简单的配置,我们也可以根据自己的需要配置成更为复杂的队列规定,接下来我们举如下的例子:
假如内网中的用户通过网卡eth0与外界通讯,这样我们可能需要配置我们的通讯规则。
当然带宽比例是相对的,也就是说在忙的时候会趋向于以上的带宽比例。不忙的时候忙的服务可以借用不忙用户的带宽。
假如我们总带宽为 2048Mbps。这样我们分配给A,B的带宽分别为1228Mbps,820Mbps。带宽分配如下所示:
首先我们需要为网卡建立一个根类型(QDISC)这个是必须的步骤。
按照上图的步骤我们应该在这个类的底下建立两个子类,来进行速度的分发。
接下来我们为叶子节点挂载pfifo的队列规定,当然你也可以根据自己的需要定义自己的队列规定。命令如下:
这样我们根据需要框架是已经搭建完成了,不过我们还不知道哪些包进入哪个类进行处理。接下来我们讲根据需求建立分类器。当然我们使用的是功能强大的U32分类器,
2.0 Rateceiling 速率限度
我们看到了上面配置过程中一直有这个参数,我们接下来讨论下这个参数的用途。
参数ceil指定了一个类可以用的最大带宽, 用来限制类可以借用多少带宽.缺省的ceil是和速率一样。我们看上面的例子:
注: ceil的数值应该至少和它所在的类的速率一样高, 也就是说ceil应该至少和它的任何一个子类一样高。
第二章 HTB 程序实现
2.0 用户传递消息的格式
我们对消息的封装使用如下的格式:首先是消息头然后接下来就是消息的数据部分了。数据部分是按照 类型、 长度、 参数值 的格式来填充数据包的。如下所示:
消息头 |
消息模板TC_MSG |
传递的数据 |
__u32 nlmsg_len; /* Length of message including header */
__u16 nlmsg_type; /* Message content */
__u16 nlmsg_flags; /* Additional flags */
__u32 nlmsg_seq; /* Sequence number */
__u32 nlmsg_pid; /* Sending process PID */
系统中为支持QOS 定义了如下的消息类型:在文件RTNETLINK.H中。
#define RTM_NEWQDISC RTM_NEWQDISC
#define RTM_DELQDISC RTM_DELQDISC
#define RTM_GETQDISC RTM_GETQDISC
#define RTM_NEWTCLASS RTM_NEWTCLASS
#define RTM_DELTCLASS RTM_DELTCLASS
#define RTM_GETTCLASS RTM_GETTCLASS
nlmsg_len |
|
nlmsg_type |
nlmsg_flags |
nlmsg_seq |
|
nlmsg_pid |
|
消息模板TC_MSG |
|
rta_type 16 bits |
rta_len 16 bits |
Values 32 bits |
其中数据部分的rta_type就是传递的参数类型:我们根据HTB可能的参数类型,定义如下的参数类型:定义在文件PKT_SCHED.H中。(我们这里省略一些定义的结构体可以去看看源文件)
#define TC_HTB_PROTOVER 3/* the same as HTB and
2.1 HTB 命令的解析
Usage: tc [ OPTIONS ]OBJECT { COMMAND | help }\n"
"where OBJECT := { qdisc | class | filter | action}\n"
" OPTIONS := {-s[tatistics] | -d[etails] | -r[aw]
可以看出TC 命令中OBJECT := { qdisc | class | filter | action }
也就是 用于建立QDISC以及建立分类CLASS, 建立过滤器FILTER或者是其他的动作ACTION。LINUX 内核中为这不同的命令分别建立了相应的命令解析结构,大致如下:
int (*parse_qopt)(struct qdisc_util *qu, int argc,char **argv, struct nlmsghdr *n);
int (*print_qopt)(struct qdisc_util *qu, FILE *f,struct rtattr *opt);
int (*print_xstats)(struct qdisc_util *qu,FILE *f, struct rtattr *xstats);
int (*parse_copt)(struct qdisc_util *qu, int argc,char **argv, struct nlmsghdr *n);
int (*print_copt)(structqdisc_util *qu, FILE *f, struct rtattr *opt);
struct qdisc_util htb_qdisc_util = {
.print_xstats = htb_print_xstats,
.parse_copt = htb_parse_class_opt,
htb_parse_opt,用于解析qdisc htb参数部分的命令的。
htb_parse_class_opt,用于解析class htb参数部分的命令的。
举例消息解析过程
一个命令:tc qdisc add dev ifbr0 roothandle 1: htb default 12
分析tc:main(int argc, char **argv)被调用,此函数在tc/tc.c中;
分析tc qdisc:do_qdisc(argc-2, argv+2);被调用,此函数在tc/tc_qdisc.c中;
2.2 HTB 内核程序的实现
HTB关键是对不同数据包进行不同的流量控制,以达到控制的目的。对于流量的控制使用的是令牌桶的算法如下图:
2.2.1 数据包进队
我们首先来看看进队的操作:
static inthtb_enqueue(struct sk_buff *skb, struct Qdisc *sch)
{
struct htb_class *cl =htb_classify(skb,sch,&ret);
else if (cl->un.leaf.q->enqueue(skb,cl->un.leaf.q) != NET_XMIT_SUCCESS) {
sch->stats.drops++;
cl->stats.drops++;
return NET_XMIT_DROP;
} else {
cl->stats.packets++; cl->stats.bytes += skb->len;
htb_activate (q,cl);
}
return NET_XMIT_SUCCESS;
}
进队首先调用的是分类器,查看数据包要放到那个队列中,然后再进行进队操作。至于分类过程我们看看下图:
当然这些结果是用户传递进来的信息,我们只是进行匹配然后找到分类结果
Tcf_result。当然分类结果有时候我们只保存了分类的CLASSID 但是我们有时候也保存了CLASS 根据不同的策略有时候是不同的:我们也看看另外一种的分类吧:
这种分类结果比较特殊,直接就有一个指针指向所定义的类,程序就不需要再根据ID来查找相应的类了。直接根据其结果的指针进行必要的操作就可以了。
2.2.2 数据包的出队
出队操作比较复杂整个过程掉的函数如下:
HTB的出队是个非常复杂的处理过程, 函数调用过程为:
htb_dequeue
è __skb_dequeue
è ->htb_do_events
è ->htb_safe_rb_erase
è ->htb_change_class_mode
è ->htb_add_to_wait_tree
è ->htb_dequeue_tree
è ->htb_lookup_leaf
è ->htb_deactivate
è ->q->dequeue
è ->htb_next_rb_node
è ->htb_charge_class
è ->htb_change_class_mode
è ->htb_safe_rb_erase
è ->htb_add_to_wait_tree
è-> htb_delay_by
对于流量的控制总的思想如下:
首先从队列中取出数据包,然后根据数据包的长度算出要消耗的令牌数函数如下:
/* TODO: maybe compute rate when sizeis too large .. or drop ? */
// 将长度转换为令牌数
static inline long L2T(struct htb_class*cl, struct qdisc_rate_table *rate,
int size)
{
// 根据大小计算合适的槽位
int slot = size >> rate->rate.cell_log;
// 如果超过了255, 限制为255
if (slot > 255) {
cl->xstats.giants++;
slot = 255;
}
return rate->data[slot];
}
计算从上次发送数据包到现在的时间里生成的令牌数
toks = PSCHED_TDIFF_SAFE(now,q->t_c, q->buffer);
然后把toks加上原先桶中的令牌数就为总的令牌数,当然总的令牌数是不能比桶大的。
这时候总令牌数-数据包长度转换过来的令牌数, 如果大于0则允许数据包通过,如过小于0则看看能够借用其他类的速度,否则就让数据包重新入队。这就是限速的基本思想。
HTB相关TC命令以及内核实现介绍相关推荐
- Linux内核TC工具链路带宽设计--HTB队列规定及简单的过滤器介绍
1 HTB(Hierarchical Token Bucket, 分层的令牌桶) HTB 使用令牌和存储桶的概念,以及基于类的系统和过滤器,以允许对流量进行复杂和精细的控制.借助复杂的借用模型,HTB ...
- linux htb 源代码,LINUX TC:HTB相关源码
LINUX TC:HTB相关源码 收藏 HTB(hierarchy token buffer)是linux tc(traffic control)模块中的排队队列的一种.它的配置比CBQ要简单.同时实 ...
- Linux中mod相关的命令 内核模块化 mod相关命令都是用来动态加载内核模块/驱动程序模块...
Linux中mod相关的命令 内核模块化 mod相关命令都是用来动态加载内核模块/驱动程序模块 http://baike.baidu.com/link?url=lxiKxFvYm-UfJIxMjz ...
- Linux 下 TC 命令原理及详解<一>
文章目录 1 前言 2 相关概念 3 使用TC 4 创建HTB队列 5 为根队列创建相应的类别 6 为各个类别设置过滤器 7 复杂的实例 Linux 下 TC 命令原理及详解<一> Lin ...
- Linux 下 TC 命令原理及详解
众所周知,在互联网诞生之初都是各个高校和科研机构相互通讯,并没有网络流量控制方面的考虑和设计,IP协议的原则是尽可能好地为所有数据流服务,不同的数据流之间是平等的.然而多年的实践表明,这种原则并不是最 ...
- Network 之四 常用 Linux 网络命令及网络调试工具介绍
网络互连模型 主要就是值得 OSI 参考模型与 TCP/IP 五层模型: 下面再来一张详细点的(来源于科来网络): 网络命令 目前,我们常用的网络相关的命令有两大类:net-tools 和 ipr ...
- linux-iproute2系列-TC命令
TC 规则: 1 流量控制方式: SHAPING(限制) 传输速率限制在某个值一下,只要是对外的流量 SCHEDULING(调度) 在带宽范围内,按照优先级分配带宽 ...
- 【测试】linux tc命令|Linux模拟网络延迟、丢包等|traffic control(流量控制)
目录 一.工具介绍 1.netem 2.tc 二.命令使用说明 1.模拟延迟传输 2.模拟网络丢包: 3.模拟包重复: 4.模拟数据包损坏: 5.模拟数据包乱序: 6.删除模拟配置: 更多高级用法 一 ...
- tc命令——Linux基于IP进行流量限速
主要参考(所有权利归原文作者所有): *http://www.cnblogs.com/endsock/archive/2011/12/09/2281519.html *http://blog.163. ...
- iso linux 内核版本号_Linux内核全面介绍
Linux内核(kernel)和linux操作系统区别 Linux内核指的是一个提供硬件抽象层.磁盘及文件系统控制.多任务等功能的系统软件.一个内核不是一套完整的操作系统.通常我们所说的linux操作 ...
最新文章
- ajax请求php保存数据格式,jQuery ajax与php进行数据交互(数据格式问题)
- 【转】更简单的非递归遍历二叉树的方法
- Android Zygote分析
- 手机和邮箱的正则表达式
- 如何在Java地毯下有效地清除问题
- java事件编程_java基础 ---Swing事件编程
- 准确率(Accuracy) | 查准率(Precision) | 查全率(Recall)
- CentOS修改网络配置
- 设置SQLServer数据库内存
- MySQL的 配置文件编写
- Python socket编程模拟最简单的HTTP响应
- Java反射初探 ——“当类也学会照镜子”
- oozie timezone时区配置
- Idea搭建springcloud(一)---服务注册与发现之Eureka
- android解析xml文件的方式
- 学习方法分享:为何一年半就能拿到大厂 offer
- 紧急大项目的应付手法
- 计算机网络安全文明知识竞赛,网络安全知识竞赛
- 依据前端传递的数字等生成二维码图片
- Consider defining a bean of type ‘com.xingchen.media.service.MediaFileService‘ in your configuration
热门文章
- Android UI 调试常用工具(Dump view UI hierarchy for Automator)
- 深入解析Invoke and BeginInvoke, 同步与异步解析
- server sql 数据总行数_一种快速统计SQL Server每个表行数的方法
- JavaScript系列--类型判断的4种基本方法,研究jquery的type方法,空对象的检测方法,类数组对象...
- 阿里云破世界记录,王坚说新登月计划需十年,我看不用!
- Linux C编程与Shell编程在开发实用工具方面的相同点总结
- WinForm 使用 HttpUtility
- linux定时任务的配置详解
- 优雅的对 list 遍历进行 add 或者 remove 操作
- Spring事务管理实现方式之编程式事务与声明式事务详解