Linux内核QoS实现机制

更新时间:2024-04-04 09:40:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

Linux内核QoS实现机制

1. QoS介绍

QoS(Quality of Service)即服务质量。对于网络业务,服务质量包括传输的带宽、传送的时延、数据的丢包率等。在网络中可以通过保证传输的带宽、降低传送的时延、降低数据的丢包率以及时延抖动等措施来提高服务质量。

网络资源总是有限的,只要存在抢夺网络资源的情况,就会出现服务质量的要求。服务质量是相对网络业务而言的,在保证某类业务的服务质量的同时,可能就是在损害其它业务的服务质量。例如,在网络总带宽固定的情况下,如果某类业务占用的带宽越多,那么其他业务能使用的带宽就越少,可能会影响其他业务的使用。因此,网络管理者需要根据各种业务的特点来对网络资源进行合理的规划和分配,从而使网络资源得到高效利用。

流量控制包括以下几种方式: ?

SHAPING(限制)

当流量被限制,它的传输速率就被控制在某个值以下。限制值可以大大小于有效带宽,这样可以平滑突发数据流量,使网络更为稳定。shaping(限制)只适用于向外的流量。

?

SCHEDULING(调度)

通过调度数据包的传输,可以在带宽范围内,按照优先级分配带宽。SCHEDULING(调度)也只适于向外的流量。

?

POLICING(策略)

SHAPING用于处理向外的流量,而POLICIING(策略)用于处理接收到的数据。 ?

DROPPING(丢弃)

如果流量超过某个设定的带宽,就丢弃数据包,不管是向内还是向外。

1

2. 内核实现过程

图表 1 流量控制过程

绿色部分就是Linux内核实现的QoS模块,其中ingress policing 是处理输入数据包的,而output queueing 则是处理输出数据包的。

2.1. Ingress实现机制

Ingress QOS在内核的入口点有两个,但是不能同时启用,这取决于内核编译选项。当打开了CONFIG_NET_CLS_ACT(from 2.6.8 release still available on 2.6.39 release)时,入口点在src/net/core/dev.c的netif_receive_skb函数中;当没有打开CONFIG_NET_CLS_ACT,而是打开了CONFIG_NET_CLS_POLICE (from 2.6.9 release to 2.6.24, thus this is an obsolete configuration)和CONFIG_NETFILTER时,就会在netfilter的PREROUTING钩子点处调用ing_hook函数。

2

CONFIG_NET_CLS_ACTnetif_receive_skbCONFIG_NET_CLS_POLICE&&CONFIG_NETFILTERPREROUTING钩子点调用ing_hook函数ing_filterDev->qdisc_ingressYq->enqueueN进入net/sched/sch_ingress.c文件ingress_enqueuetc_classifyhandle_bridNgetp->next Y……Tp->classify

图表 2 ingress策略实现

当filter中有规则时,遍历规则表,寻找与skb->mark(由ebtables或iptables来配置)相匹配的表项,如果找到了则会进一步调用tcf_exts_exec函数对扩展的action进行处理。

3

fw_classifyTp->classify匹配skb->mark表项tcf_exts_execexts->action NYtcf_action_exectcf_policeNYtcf_police??

图表 3 FW分类器实现过程

2.2. Egress实现机制

系统在注册网络设备时会在register_netdevice函数中调用dev_init_scheduler函数注册一个qdisc的接口,它是一个特殊的qdisc,不做任何处理。当创建好设备,用ifconfig up命令把设备拉起后,会调用到内核的src/net/core/dev.c中的dev_open函数,在dev_open函数中又会调用到src/net/sched/sch_generic.c中的dev_activate函数,给设备配置默认的root qdisc处理机制:pfifo_fast。

4

注册网络设备register_netdevice ifconfig updev_opendev_init_schedulerdev_activate注册noop_qdisc结构实例,该实例不做任何事情qdisc_create_dflt(dev,&pfifo_fast_ops,TC_H_ROOT) 图表 4 以prio qdisc为例的egress初始化过程

出口队列调度的入口点在src/net/core/dev.c的dev_queue_xmit函数中,通过q = rcu_dereference(dev->qdisc)可以获取到设备上root qdisc的指针q(struct Qdisc *)。在下面的处理过程中并没有判断q是否为NULL,这就说明设备上一定会存在egress qdisc,这一点和ingress是不同的,一个设备上可以没有ingress qdisc,即dev-> qdisc_ingress指针一般是NULL,除非通过tc qdisc命令配置了ingress qdisc。

5

数据包发送dev_queue_xmitq->enqueue以Htb qdisc为例htb_enqueueqdisc_enqueue_tail压入队尾返回dev_queue_xmitqdisc_runN匹配子qdisc循环调用qdisc_restart以pfifo disc为例pfifo_enqueue进行分类选择,找出子qdisc htb_classifyq->dequeue队列长度超过限制dev_hard_start_xmitYqdisc_reshape_fail丢弃数据包

图表 5 以htb+pfifo qdisc为例的egress处理流程

6

3. 内核与TC的交互

3.1. 交互方式

Netlink

3.2. 内核处理接口

?

Qdisc和class交互接口

tc qdisc和tc clsss配置命令对应的配置函数在src/net/sched/sch_api.c的pktsched_init函数中进行了初始化注册,由subsys_initcall函数对系统进行申明,该函数在linux系统初始化的时候会被调用到。代码片断如下:

if (link_p) { link_p[RTM_NEWQDISC-RTM_BASE].doit = tc_modify_qdisc; link_p[RTM_DELQDISC-RTM_BASE].doit = tc_get_qdisc; link_p[RTM_GETQDISC-RTM_BASE].doit = tc_get_qdisc; link_p[RTM_GETQDISC-RTM_BASE].dumpit = tc_dump_qdisc; link_p[RTM_NEWTCLASS-RTM_BASE].doit = tc_ctl_tclass; link_p[RTM_DELTCLASS-RTM_BASE].doit = tc_ctl_tclass; link_p[RTM_GETTCLASS-RTM_BASE].doit = tc_ctl_tclass; link_p[RTM_GETTCLASS-RTM_BASE].dumpit = tc_dump_tclass; } ?

filter交互接口

tc filter配置命令对应的配置函数在src/net/sched/cls_api.c的tc_filter_init函数中进行了初始化注册,该函数也会在系统初始化的时候被调用到。代码片段如下: if (link_p) { link_p[RTM_NEWTFILTER-RTM_BASE].doit = tc_ctl_tfilter; link_p[RTM_DELTFILTER-RTM_BASE].doit = tc_ctl_tfilter; link_p[RTM_GETTFILTER-RTM_BASE].doit = tc_ctl_tfilter; link_p[RTM_GETTFILTER-RTM_BASE].dumpit = tc_dump_tfilter; } 3.3. TC与netlink交互的数据格式

Netlink数据头部+tc消息头部

7

? Netlink头部

struct msg_to_kernel /*自定义消息首部,它仅包含了netlink的消息首部*/ { struct nlmsghdr hdr; }; struct nlmsghdr { __u32 nlmsg_len; /* Length of message */ __u16 nlmsg_type; /* Message type*/ __u16 nlmsg_flags; /* Additional flags */ __u32 nlmsg_seq; /* Sequence number */ __u32 nlmsg_pid; /* Sending process PID */ };

? };

TC数据头部:

tcm_family; tcm__pad1; struct tcmsg { unsigned char unsigned char unsigned short tcm__pad2; int tcm_ifindex; __u32 __u32 __u32 tcm_handle; tcm_parent; tcm_info; 4. TC规则

4.1. 流量控制模型

8

图表 6 流量控制实现模型

4.2. 流量控制处理对象

流量的处理由三种对象控制,它们是:qdisc(排队规则)、class(类别)和filter(过滤器)。

4.2.1. Qdisc

QDisc(排队规则)是queueing discipline的简写,它是理解流量控制(traffic control)的基础。无论何时,内核如果需要通过某个网络接口发送数据包,它都需要按照为这个接口配置的qdisc(排队规则)把数据包加入队列。然后,内核会尽可能多地从qdisc里面取出数据包,把它们交给网络适配器驱动模块。最简单的QDisc是pfifo它不对进入的数据包做任何的处理,数据包采用先入先出的方式通过队列。不过,它会保存网络接口一时无法处理的数据包。

QDISC分为无类队列(CLASSLESS QDisc)和分类队列(CLASSFUL QDISC)类别。使用中,无类队列只能作为叶子节点出现,而分类队列作为双亲节点出现,不能作为叶子节点出现。

4.2.1.1. 无类队列

a) Pfifo_fast

默认参数,先进先出的队列,内核参照数据包的TOS标记,将数据包分为3个频道。如果在0频道有数据包等待发送,1频道的包就不会被处理,1频道和2频道之间的关系也

9

是如此。

?

TOS字段说明:

TOS字段的4个bit定义:

二进制 1000 0100 0010 0001 0000 十进制 8 4 2 1 0 最小延迟 (md) 最大throughput (mt) 最大可靠性 (mr) 最小成本 (mmc) 正常服务 意义

图表 7 TOS值与频道的对应

b) TBF

只允许以不超过事先设定的速率到来的数据包通过,但可能允许短暂突发流量超过设定值。3种情景:

1) 数据流以等于令牌流的速率到达TBF。这种情况下,每个到来的数据包都能对应一

个令牌,然后无延迟地通过队列。

2) 数据流以小于令牌流的速度到达TBF。通过队列的数据包只消耗了一部分令牌,剩

下的令牌会在桶里积累下来,直到桶被装满。剩下的令牌可以在需要以高于令牌流

10

速率发送数据流的时候消耗掉,这种情况下会发生突发传输。

3) 数据流以大于令牌流的速率到达TBF。这意味着桶里的令牌很快就会被耗尽。导致

TBF中断一段时间,称为“越限”。如果数据包持续到来,将发生丢包。 ?

参数选项:

? limit/latency:limit确定最多有多少数据(字节数)在队列中等待可用令牌。你也

可以通过设置latency参数来指定这个参数,latency参数确定了一个包在TBF中等待传输的最长等待时间。后者计算决定桶的大小、速率和峰值速率。

? burst/buffer/maxburst:桶的大小,以字节计。这个参数指定了最多可以有多少个令

牌能够即刻被使用。通常,管理的带宽越大,需要的缓冲器就越大。在Intel体系上,10兆bit/s的速率需要至少10k字节的缓冲区才能达到期望的速率。如果你的缓冲区太小,就会导致到达的令牌没有地方放(桶满了),这会导致潜在的丢包。 ? Mpu:一个零长度的包并不是不耗费带宽。比如以太网,数据帧不会小于64字节。

Mpu(Minimum Packet Unit,最小分组单位)决定了令牌的最低消耗。 ? Rate:速度操纵杆,参见上面的limits。

? Peakrate:如果有可用的令牌,数据包一旦到来就会立刻被发送出去,就象光速一

样。那可能并不是你希望的,特别是你有一个比较大的桶的时候。峰值速率可以用来指定令牌以多块的速度被删除。用书面语言来说,就是:释放一个数据包,但后等待足够的时间后再释放下一个。我们通过计算等待时间来控制峰值速率。然而,由于UNIX定时器的分辨率是10毫秒,如果平均包长10k bit,我们的峰值速率被限制在了1Mbps。

? mtu/minburst:但是如果你的常规速率比较高,1Mbps的峰值速率对我们就没有什

么价值。要实现更高的峰值速率,可以在一个时钟周期内发送多个数据包。最有效的办法就是:再创建一个令牌桶! ?

配置范例:

# tc qdisc add dev ppp0 root tbf rate 220kbit latency 50ms burst 1540 c) SFQ

SFQ(Stochastic Fairness Queueing,随机公平队列)是公平队列算法家族中的一个简单实现。它的精确性不如其它的方法,但是它在实现高度公平的同时,需要的计算量却很少。

SFQ的关键词是“会话”(或称作“流”) ,主要针对一个TCP会话或者UDP流。流

11

量被分成相当多数量的FIFO队列中,每个队列对应一个会话。数据按照简单轮转的方式发送, 每个会话都按顺序得到发送机会。

?

参数选项:

? Perturb:多少秒后重新配置一次散列算法。如果取消设置,散列算法将永远不会重

新配置(不建议这样做)。10秒应该是一个合适的值。

? Quantum:一个流至少要传输多少字节后才切换到下一个队列。却省设置为一个最

大包的长度(MTU的大小)。不要设置这个数值低于MTU! ?

配置范例:

# tc qdisc add dev ppp0 root sfq perturb 10 d) [p|b]fifo

使用最简单的qdisc,纯粹的先进先出。只有一个参数:limit,用来设置队列的长度,pfifo是以数据包的个数为单位;bfifo是以字节数为单位。

?

参数选项

? Limit:规定了队列的长度。对于bfifo用字节计,对于pfifo用包的个数计。缺省

值就是网卡的txqueuelen个包那么长(参见pfifo_fast那一章),对于bfifo就是txqueuelen*mtu个字节。 e) red

red是Random Early Detection(随机早期探测)的简写。如果使用这种QDISC,当带宽的占用接近于规定的带宽时,系统会随机地丢弃一些数据包。它非常适合高带宽应用。

为了使用RED,你必须确定三个参数:min、max和burst。Min设置了队列达到多少字节时开始进行丢包,Max是一个软上限,让算法尽量不要超过,burst设置了最多有多少个数据包能够突发通过。

4.2.1.2. 分类队列

a) HTB

HTB是Hierarchy Token Bucket的缩写。通过在实践基础上的改进,它实现了一个丰富的连接共享类别体系。使用HTB可以很容易地保证每个类别的带宽,虽然它也允许特定的类可以突破带宽上限,占用别的类的带宽。HTB可以通过TBF(Token Bucket Filter)实现带宽限制,也能够划分类别的优先级。

12

? 参数选项

? Rate:限速;

? Burst:令牌桶的大小;

? Ceil:上行限速,用于满带宽时对总带宽的占有比; ? Prio:配置优先级; b) CBQ

CBQ是Class Based Queueing(基于类别排队)的缩写。它实现了一个丰富的连接共享类别结构,既有限制(shaping)带宽的能力,也具有带宽优先级管理的能力。带宽限制是通过计算连接的空闲时间完成的。空闲时间的计算标准是数据包离队事件的频率和下层连接(数据链路层)的带宽。

?

CBQ常规参数:

? Avpkt:平均包大小,以字节计。计算maxidle时需要,maxidle从maxburst得出。 ? Bandwidth:网卡的物理带宽,用来计算闲置时间。

? Cell:一个数据包被发送出去的时间可以是基于包长度而阶梯增长的。一个800 字

节的包和一个806字节的包可以认为耗费相同的时间。也就是说它设置时间粒度。通常设置为8,必须是2的整数次幂。

? Maxburst:这个参数的值决定了计算maxidle所使用的数据包的个数。在avgidle

跌落到0之前,这么多的数据包可以突发传输出去。这个值越高,越能够容纳突发传输。你无法直接设置maxidle的值,必须通过这个参数来控制。

? Minburst:如前所述,发生越限时CBQ会禁止发包。实现这个的理想方案是根据

事先计算出的闲置时间进行延迟之后,发一个数据包。然而,UNIX的内核一般来说都有一个固定的调度周期(一般不大于10ms),所以最好是这样:禁止发包的时间稍长一些,然后突发性地传输minburst个数据包,而不是一个一个地传输。等待的时间叫做offtime。从大的时间尺度上说,minburst值越大,整形越精确。但是,从毫秒级的时间尺度上说,就会有越多的突发传输。

? Minidle:如果avgidle值降到0,也就是发生了越限,就需要等待,直到avgidle的

值足够大才发送数据包。为避免因关闭链路太久而引起的以外突发传输,在avgidle的值太低的时候会被强制设置为minidle的值。参数minidle的值是以负微秒记的。所以10代表avgidle被限制在-10us上。

? Mpu:最小包尺寸,因为即使是0长度的数据包,在以太网上也要生成封装成64

13

字节的帧,而需要一定时间去传输。为了精确计算闲置时间,CBQ需要知道这个值。

? Rate:期望中的传输速率 ?

WRR(weighted round robin,加权轮转)参数:

? Allot:当从外部请求一个CBQ发包的时候,它就会按照“priority”参数指定的顺

序轮流尝试其内部的每一个类的队列规定。当轮到一个类发数据时,它只能发送一定量的数据。“allot”参数就是这个量的基值。更多细节请参照“weight”参数。 ? Prio:CBQ可以象PRIO设备那样工作。其中“prio”值较低的类只要有数据就必

须先服务,其他类要延后处理。

? Weight:“weight”参数控制WRR过程。每个类都轮流取得发包的机会。如果其中

一个类要求的带宽显著地高于其他的类,就应该让它每次比其他的类发送更多的数据。

CBQ会把一个类下面所有的weight值加起来后归一化,所以数值可以任意定,只要保持比例合适就可以。人们常把“速率/10”作为参数的值来使用,实际工作得很好。归一化值后的值乘以“allot”参数后,决定了每次传输多少数据。

?

决定链路的共享和借用的CBQ参数:

? Isolated/sharing:凡是使用“isolated”选项配置的类,就不会向其兄弟类出借带宽。

如果你的链路上同时存在着竞争对手或者不友好的其它人,你就可以使用这个选项。选项“sharing”是“isolated”的反义选项。

? bounded/borrow:一个类也可以用“bounded”选项配置,意味着它不会向其兄弟

类借用带宽。选项“borrow”是“bounded”的反义选项。 c) PRIO

PRIO QDisc不能限制带宽,因为属于不同类别的数据包是顺序离队的。使用PRIO QDisc可以很容易对流量进行优先级管理,只有属于高优先级类别的数据包全部发送完毕,才会发送属于低优先级类别的数据包。为了方便管理,需要使用iptables或者ipchains处理数据包的服务类型(Type Of Service,ToS)。

?

参数选项

? Bands:创建频道的数目,每个频道实际上就是一个类。

? Priomap:如果你不给tc提供任何过滤器,PRIO队列规定将参考TC_PRIO的优先

级来决定如何给数据包入队。

14

4.2.2. Class

某些QDisc(排队规则)可以包含一些类别,不同的类别中可以包含更深入的QDisc(排队规则),通过这些细分的QDisc还可以为进入的队列的数据包排队。通过设置各种类别数据包的离队次序,QDisc可以为设置网络数据流量的优先级。

4.2.3. Filter

Filter(过滤器)用于为数据包分类,决定它们按照何种QDisc进入队列。无论何时数据包进入一个划分子类的类别中,都需要进行分类。分类的方法可以有多种,使用fileter(过滤器)就是其中之一。使用filter(过滤器)分类时,内核会调用附属于这个类(class)的所有过滤器,直到返回一个判决。如果没有判决返回,就作进一步的处理,而处理方式和QDISC有关。需要注意的是,filter(过滤器)是在QDisc内部,它们不能作为主体。

过滤器在使用时结合具体的分类器使用: a) fw

根据防火墙如何对这个数据包做标记进行判断,结合iptable工具进行使用。 b) u32

根据数据包中的各个字段进行判断,如源IP地址等等。 c) route

根据数据包将被哪条路由进行路由来判断。 d) rsvp, rsvp6

根据数据包的RSVP情况进行判断。只能用于你自己的网络,互联网并不遵守RSVP。 e) tcindex

用于DSMARK队列规定,参见相关章节。

4.3. TC操作命令

? tc qdisc [ add | change | replace | link ] dev DEV [ parent qdisc-id | root ] [ handle qdisc-id ] qdisc [qdisc specific parameters ] ? tc class [ add | change | replace ] dev DEV parent qdisc-id [ classid class-id ] qdisc [ qdisc specific parameters ] 15

? tc filter [ add | change | replace ] dev DEV [ parent qdisc-id | root ] protocol protocol prio priority filtertype [ filtertype specific parameters ] flowid flow-id ? tc [-s | -d ] qdisc show [ dev DEV ] ? tc [-s | -d ] class show dev DEV ? tc filter show dev DEV tc可以使用以下命令对QDisc、类和过滤器进行操作:

? add:在一个节点里加入一个QDisc、类或者过滤器。添加时,需要传递一个祖先

作为参数,传递参数时既可以使用ID也可以直接传递设备的根。如果要建立一个QDisc或者过滤器,可以使用句柄(handle)来命名;如果要建立一个类,可以使用类识别符(classid)来命名。

? Remove:删除有某个句柄(handle)指定的QDisc,根QDisc(root)也可以删除。被删

除QDisc上的所有子类以及附属于各个类的过滤器都会被自动删除。

? Change:以替代的方式修改某些条目。除了句柄(handle)和祖先不能修改以外,

change命令的语法和add命令相同。换句话说,change命令不能一定节点的位置。 ? Replace:对一个现有节点进行近于原子操作的删除/添加。如果节点不存在,这

个命令就会建立节点。

? Link:只适用于DQisc,替代一个现有的节点。

4.4. 流量控制建立步骤

1) 针对网络物理设备(如以太网卡eth0)绑定一个队列QDisc; 2) 在该队列上建立分类class;

3) 为每一分类建立一个基于路由的过滤器filter;

4) 最后与过滤器等相配合,建立特定分类规则,如路由表(可选)。

4.5. TC规则如何选择

下列提示可以帮你决定使用哪一种队列:

? 如果想单纯地降低出口速率,使用令牌桶过滤器。调整桶的配置后可用于控制很高的带

宽。

? 如果你的链路已经塞满了,而你想保证不会有某一个会话独占出口带宽,使用随机公平

队列。

16

? 如果你有一个很大的骨干带宽,并且了解了相关技术后,可以考虑前向随机丢包(参见

“高级”那一章)。

? 如果希望对入口流量进行“整形”(不是转发流量),可使用入口流量策略,注意,这不

是真正的“整形”。

? 如果你正在转发数据包,在数据流出的网卡上应用TBF。除非你希望让数据包从多个

网卡流出,也就是说入口网卡起决定性作用的时候,还是使用入口策略。

? 如果你并不希望进行流量整形,只是想看看你的网卡是否有比较高的负载而需要使用队

列,使用pfifo队列(不是pfifo_fast)。它缺乏内部频道但是可以统计backlog。 ? 最后,你可以进行所谓的“社交整形”。你不能通过技术手段解决一切问题。用户的经

验技巧永远是不友善的。正确而友好的措辞可能帮助你的正确地分配带宽!

5. 实例分析

5.1. HTB实例分析 5.1.1. 实例要求

Dom 0Vif1.0peth0bridgeVif2.0??

图表 8 虚拟机网络环境

为了实现虚拟机环境中通过网桥bridge实现对虚拟网卡vif之间的流量控制,我们选择分别在各自的vif*上建立QoS的egress策略,实现数据的限速与分流。

流量控制需要:

17

1) 发往vif1.0设备的网络流量带宽控制在6Mbit,最大缓冲15K;

2) 发往vif1.0设备,目的端口为80的网络数据包,网络流量带宽控制在5Mbit,缓

冲控制在15K;

3) 发往vif1.0设备,源端口为25的网络数据包,网络流量带宽控制在3Mbit,缓冲

控制在15K;

4) 发往vif1.0设备的其余数据包,网络流量带宽控制在1Mbit,缓冲控制在15K;

5.1.2. HTB策略配置

#tc qdisc add dev vif1.0 root handle 1: htb default 30 #tc class add dev vif1.0 parent 1: classid 1:1 htb rate 6mbit burst 15k #tc class add dev vif1.0 parent 1:1 classid 1:10 htb rate 5mbit burst 15k #tc class add dev vif1.0 parent 1:1 classid 1:20 htb rate 3mbit ceil 6mbit burst 15k #tc class add dev vif1.0 parent 1:1 classid 1:30 htb rate 1mbit ceil 6mbit burst 15k #在叶子节点中使用sfq规则: #tc qdisc add dev eth0 parent 1:10 handle 10: sfq perturb 10 #tc qdisc add dev eth0 parent 1:20 handle 20: sfq perturb 10 #tc qdisc add dev eth0 parent 1:30 handle 30: sfq perturb 10 #添加过滤器,直接把流量导向相应的类: #U32=\#$U32 match ip dport 80 0xffff flowid 1:10 #$U32 match ip sport 25 0xffff flowid 1:20 5.1.3. 逻辑图

Root qdisc

1:0

| |

Root class 1:1 / | \\ / | \\

/ | \\

Leaf class 10: leaf class 20: leaf class 30:

18

5.2. CBQ实例分析 5.2.1. 实例要求

流量控制器上的以太网卡(eth0) 的IP地址为192.168.1.66,在其上建立一个CBQ队列。假设包的平均大小为1000字节,包间隔发送单元的大小为8字节,可接收冲突的发送最长包数目为20字节。

假如有三种类型的流量需要控制:

1) 发往主机1的,其IP地址为192.168.1.24。其流量带宽控制在8Mbit,优先级为2; 2) 发往主机2的,其IP地址为192.168.1.30。其流量带宽控制在1Mbit,优先级为1; 3) 发往子网1的,其子网号为192.168.1.0,子网掩码为255.255.255.0。流量带宽控制

在1Mbit,优先级为6。

5.2.2. 建立跟队列

将一个cbq队列绑定到网络物理设备eth0上,其编号为1:0;网络物理设备eth0的实际带宽为100 Mbit,包的平均大小为1000字节;包间隔发送单元的大小为8字节,最小传输包大小为64字节。

·tc qdisc add dev eth0 root handle 1: cbq bandwidth 100Mbit avpkt 1000 cell 8 mpu 64 5.2.3. 建立分类

分类建立在队列之上。

一般情况下,针对一个队列需建立一个根分类,然后再在其上建立子分类。对于分类,按其分类的编号顺序起作用,编号小的优先;一旦符合某个分类匹配规则,通过该分类发送数据包,则其后的分类不再起作用。

1) 创建根分类1:1;分配带宽为10Mbit,优先级别为8。

·tc class add dev eth0 parent 1:0 classid 1:1 cbq bandwidth 100Mbit rate 10Mbit maxburst 20 allot 1514 prio 8 avpkt 1000 cell 8 weight 1Mbit 19

该队列的最大可用带宽为100Mbit,实际分配的带宽为10Mbit,可接收冲突的发送最长包数目为20字节;最大传输单元加MAC头的大小为1514字节,优先级别为8,包的平均大小为1000字节,包间隔发送单元的大小为8字节,相应于实际带宽的加权速率为1Mbit。

2)创建分类1:2,其父分类为1:1,分配带宽为8Mbit,优先级别为2。 ·tc class add dev eth0 parent 1:1 classid 1:2 cbq bandwidth 100Mbit rate 8Mbit maxburst 20 allot 1514 prio 2 avpkt 1000 cell 8 weight 800Kbit split 1:0 bounded 该队列的最大可用带宽为100Mbit,实际分配的带宽为 8Mbit,可接收冲突的发送最长包数目为20字节;最大传输单元加MAC头的大小为1514字节,优先级别为1,包的平均大小为1000字节,包间隔发送单元的大小为8字节,相应于实际带宽的加权速率为800Kbit,分类的分离点为1:0,且不可借用未使用带宽。

3) 创建分类1:3,其父分类为1:1,分配带宽为1Mbit,优先级别为1。

·tc class add dev eth0 parent 1:1 classid 1:3 cbq bandwidth 100Mbit rate 1Mbit maxburst 20 allot 1514 prio 1 avpkt 1000 cell 8 weight 100Kbit split 1:0 该队列的最大可用带宽为10Mbit,实际分配的带宽为 1Mbit,可接收冲突的发送最长包数目为20字节;最大传输单元加MAC头的大小为1514字节,优先级别为2,包的平均大小为1000字节,包间隔发送单元的大小为8字节,相应于实际带宽的加权速率为100Kbit,分类的分离点为1:0。

4)创建分类1:4,其父分类为1:1,分配带宽为1Mbit,优先级别为6。

·tc class add dev eth0 parent 1:1 classid 1:4 cbq bandwidth 100Mbit rate 1Mbit maxburst 20 allot 1514 prio 6 avpkt 1000 cell 8 weight 100Kbit split 1:0 该队列的最大可用带宽为10Mbit,实际分配的带宽为1Mbit,可接收冲突的发送最长包数目为20字节;最大传输单元加MAC头的大小为1514字节,优先级别为6,包的平均大小为1000字节,包间隔发送单元的大小为8字节,相应于实际带宽的加权速率为100Kbit,分类的分离点为1:0。

5.2.4. 建立过滤器

过滤器主要服务于分类。

一般只需针对根分类提供一个过滤器,然后为每个子分类提供路由映射。

20

1) 应用路由分类器到cbq队列的根,父分类编号为1:0;过滤协议为ip,优先级别为100,过滤器为基于路由表。

tc filter add dev eth0 parent 1:0 protocol ip prio 100 route ·2) 建立路由映射分类1:2, 1:3, 1:4 tc filter add dev eth0 parent 1:0 protocol ip prio 100 route to 2 flowid 1:2 ··tc filter add dev eth0 parent 1:0 protocol ip prio 100 route to 3 flowid 1:3 ·tc filter add dev eth0 parent 1:0 protocol ip prio 100 route to 4 flowid 1:4 5.2.5. 建立路由

该路由是与前面所建立的路由映射一一对应。

1) 发往主机192.168.1.24的数据包通过分类2转发(分类2的速率8Mbit) ·ip route add 192.168.1.24 dev eth0 via 192.168.1.66 realm 2 2) 发往主机192.168.1.30的数据包通过分类3转发(分类3的速率1Mbit) ·ip route add 192.168.1.30 dev eth0 via 192.168.1.66 realm 3 3)发往子网192.168.1.0/24的数据包通过分类4转发(分类4的速率1Mbit) ·ip route add 192.168.1.0/24 dev eth0 via 192.168.1.66 realm 4 注:一般对于流量控制器所直接连接的网段建议使用IP主机地址流量控制限制,不要使用子网流量控制限制。如一定需要对直连子网使用子网流量控制限制,则在建立该子网的路由映射前,需将原先由系统建立的路由删除,才可完成相应步骤。

5.3. PRIO实例分析

配置实例:

# tc qdisc add dev eth0 root handle 1: prio ## 这个命令立即创建了类: 1:1, 1:2, 1:3 # tc qdisc add dev eth0 parent 1:1 handle 10: sfq # tc qdisc add dev eth0 parent 1:2 handle 20: tbf rate 20kbit buffer 1600 limit 3000 # tc qdisc add dev eth0 parent 1:3 handle 30: sfq

21

6. 遗留问题:

1) Ingress策略应该如何配置?

2) Ingress策略中如何实现U32和FW的分类? 3) QoS与ACL之间的关系?

4) 交换机中实现的QoS机制与内核中QoS之间的关系?

22

本文来源:https://www.bwwdw.com/article/h9tr.html

Top