Linux QoS 实现简介_第1页
Linux QoS 实现简介_第2页
Linux QoS 实现简介_第3页
Linux QoS 实现简介_第4页
Linux QoS 实现简介_第5页
已阅读5页,还剩5页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、文档名称文档密级Linux QoS 实现简介 摘要:QoS 是当前一个非常热门的话题,几乎所有高端的网络设备都支持QoS功能,并且这个功能也是当前网络设备之间竞争的一个关键技术。Linux为了在在高端服务 器能够占有一席之地,从2.2.x内核开始就支持了QoS。本文在linux 2.4.0的代码基础上对Linux如何支持QoS进行了分析。并且分析了Linux内核的缺省队列处理方法PFIFO的实现。1.1 Linux内核对QoS的支持Linux内核网络协议栈从2.2.x开始,就实现了对服务质量的支持模块。具体的代码位于net/sched/目录。在Linux里面,对这个功能模块的称呼是Traffi

2、c Control ,简称TC。首先我们了解一下Linux网络协议栈在没有TC模块时发送数据包的大致流程。如图1。注:上图的分层是按照Linux实现来画,并没有严格遵守OSI分层从 上图可以看出,没有TC的情况下,每个数据包的发送都会调用dev_queue_xmit,然后判断是否需要向AF_PACKET协议支持体传递数据包内 容,最后直接调用网卡驱动注册的发送函数把数据包发送出去。发送数据包的机制就是本文开始讲到的FIFO机制。一旦出现拥塞,协议栈只是尽自己最大的努力 去调用网卡发送函数。所以这种传统的处理方法存在着很大的弊端。为了支持QoS,Linux的设计者在发送数据包的代码中加入了TC模

3、块。 从而可以对数据包进行分类,管理,检测拥塞和处理拥塞。为了避免和以前的代码冲突,并且让用户可以选择是否使用TC。内核开发者在上图中的两个红色圆圈之间添加了TC模块。(实际上在TC模块中,发送数据包也实现对AF_PACKET协议的支持,本文为了描述方便,把两个地方的AF_PACKET协议处理 分开来了)。下面从具体的代码中分析一下对TC模块的支持。net/core/dev.c: dev_queue_xmit函数中略了部分代码:int dev_queue_xmit(struct sk_buff *skb). q = dev->qdisc; if (q->enqueue) /*如果这

4、个设备启动了TC,那么把数据包压入队列*/ int ret = q->enqueue(skb, q); /*启动这个设备发送*/ qdisc_run(dev); return; if (dev->flags&IFF_UP) . if (netdev_nit) dev_queue_xmit_nit(skb,dev); /*对AF_PACKET协议的支持*/ if (dev->hard_start_xmit(skb, dev) = 0) /*调用网卡驱动发送函数发送数据包*/ return 0; 从上面的代码中可以看出,当q->enqueue为假的时候,就不采用TC

5、处理,而是直接发送这个数据包。如果为真,则对这个数据包进行QoS处理。1.2 TC的具体设计与实现第一节描述了linux内核是如何对QoS进行支持的,以及是如何在以前的代码基础上添加了tc模块。本节将对TC的设计和实现进行详细的描述。QoS有很多的拥塞处理机制,如FIFO Queueing(先入先出队列),PQ(优先队列),CQ(定制队列),WFQ(加权公平队列)等等。QoS还要求能够对每个接口分别采用不同的拥塞处理。为了能够实现上述功能,Linux采用了基于对象的实现方法。上 图是一个数据发送队列管理机制的模型图。其中的QoS策略可以是各种不同的拥塞处理机制。我们可以把这一种策略看成是一个类

6、,策略类。在实现中,这个类有 很多的实例对象,策略对象。使用者可以分别采用不同的对象来管理数据包。策略类有很多的方法。如入队列(enqueue),出队列(dequeue),重新入队列(requeue),初始化(init),撤销(destroy)等方法。在Linux中,用Qdisc_ops结构体来代表上面描述的策略类。前面提到,每个设备可以采用不同的策略对象。所以在设备和对象之间需要有一个桥梁,使设备和设备采用的对象相关。在Linux中,起到桥梁作用的是Qdisc结构体。通过上面的描述,整个TC的架构也就出来了。如下图:加上TC之后,发送数据包的流程应该是这样的:(1) 上层协议开始发送数据包(

7、2) 获得当前设备所采用的策略对象(3) 调用此对象的enqueue方法把数据包压入队列(4) 调用此对象的dequeue方法从队列中取出数据包(5) 调用网卡驱动的发送函数发送接下来从代码上来分析TC是如何对每个设备安装策略对象的。在网卡注册的时候,都会调用register_netdevice,给设备安装一个Qdisc和Qdisc_ops。int register_netdevice(struct net_device *dev).dev_init_scheduler(dev);.void dev_init_scheduler(struct net_device *dev). /*安装设备的

8、qdisc为noop_qdisc*/ dev->qdisc = &noop_qdisc;. dev->qdisc_sleeping = &noop_qdisc; dev_watchdog_init(dev); 此时,网卡设备刚注册,还没有UP,采用的是noop_qdisc,struct Qdisc noop_qdisc = noop_enqueue, noop_dequeue, TCQ_F_BUILTIN, &noop_qdisc_ops, ;noop_qdisc采用的数据包处理方法是noop_qdisc_ops,struct Qdisc_ops noop_

9、qdisc_ops = NULL, NULL, "noop", 0, noop_enqueue, noop_dequeue, noop_requeue,;从noop_enqueue,noop_dequeue,noop_requeue函数的定义可以看出,他们并没有对数据包进行任何的分类或者排队,而是直接释放掉skb。所以此时网卡设备还不能发送任何数据包。必须ifconfig up起来之后才能发送数据包。调用ifconfig up来启动网卡设备会走到dev_open函数。int dev_open(struct net_device *dev).dev_activate(dev)

10、;.void dev_activate(struct net_device *dev). if (dev->qdisc_sleeping = &noop_qdisc) qdisc = qdisc_create_dflt(dev, &pfifo_fast_ops); /*安装缺省的qdisc*/if (dev->qdisc = dev->qdisc_sleeping) != &noqueue_qdisc) ./*.安装特定的qdisc*/ .设备启动之后,此时当前设备缺省的Qdisc->ops是pfifo_fast_ops。如果需要采用不同的 op

11、s,那么就需要为设备安装其他的Qdisc。本质上是替换掉dev->Qdisc指针。见sched/sch_api.c 的dev_graft_qdisc函数。static struct Qdisc *dev_graft_qdisc(struct net_device *dev, struct Qdisc *qdisc) oqdisc = dev->qdisc_sleeping; /* 首先删除掉旧的qdisc */ if (oqdisc && atomic_read(&oqdisc->refcnt) <= 1) qdisc_reset(oqdisc)

12、; /*安装新的qdisc */ if (qdisc = NULL) qdisc = &noop_qdisc; dev->qdisc_sleeping = qdisc; dev->qdisc = &noop_qdisc; /*启动新安装的qdisc*/ if (dev->flags & IFF_UP) dev_activate(dev);从dev_graft_qdisc可以看出,如果需要使用新的Qdisc,那么首先需要删除旧的,然后安装新的,使 dev->qdisc_sleeping 为新的qdisc,然后调用dev_activate函数来启动新

13、的qdisc。结合dev_activate函数中的语句:if (dev->qdisc = dev->qdisc_sleeping) != &noqueue_qdisc)可以看出,此时的dev->qdisc所指的就是新的qdisc。在网卡down掉的时候,通过调用dev_close -> dev_deactivate重新使设备的qdisc为noop_qdisc,停止发送数据包。Linux 中的所有的QoS策略最终都是通过上面这个方法来安装的。在sch_api.c中,对dev_graft_qdisc函数又封装了一层函数 (register_qdisc),供模块来安装

14、新的Qdisc。如RED模块,就调用register_qdisc来安装RED对象(net/sched/sch_red.c->init_module())。1.3 Linux缺省策略对象pfifo_fast_ops分析在Linux中,如果设备启动之后,没有配置特定的QoS策略,内核对每个设备采用缺省的策略,pfifo_fast_ops。下面的pfifo_fast_ops进行详细的分析。上图中的信息可以对应于pfifo_fast_ops结构体的每个部分:static struct Qdisc_ops pfifo_fast_ops = NULL, NULL, "pfifo_fast&

15、quot;, /*ops名称*/ 3 * sizeof(struct sk_buff_head), /*数据包skb队列*/ pfifo_fast_enqueue, /*入队列函数*/ pfifo_fast_dequeue, /*出队列函数*/ pfifo_fast_requeue, /*重新压入队列函数*/ NULL, pfifo_fast_init, /*队列管理初始化函数*/ pfifo_fast_reset, /*队列管理重置函数*/;在注册pfifo_fast_ops的时候首先会调用pfifo_fast_init来初始化队列管理,见qdisc_create_dflt函数。static

16、 int pfifo_fast_init(struct Qdisc *qdisc, struct rtattr *opt) for (i=0; i<3; i+) skb_queue_head_init(list+i); /*初始化3个优先级队列*/.init函数的作用就是初始化3个队列。在注销一个Qdisc的时候都会调用Qdisc的ops的reset函数。见dev_graft_qdisc函数。static voidpfifo_fast_reset(struct Qdisc* qdisc). for (prio=0; prio < 3; prio+) skb_queue_purge(

17、list+prio); /*释放3个优先级队列中的所有数据包*/.在数据包发送的时候会调用Qdisc->enqueue函数(在qdisc_create_dflt函数中已经将Qdisc_ops的enqueue,dequeue,requeue函数分别赋值于Qdisc分别对应的函数指针)。int dev_queue_xmit(struct sk_buff *skb). q = dev->qdisc; if (q->enqueue) /* 对应于pfifo_fast_enqueue 函数*/ int ret = q->enqueue(skb, q); /*启动这个设备的发送,这

18、里涉及到两个函数pfifo_fast_dequeue ,pfifo_fast_requeue 稍后介绍*/ qdisc_run(dev); return; 入队列函数pfifo_fast_enqueue:static intpfifo_fast_enqueue(struct sk_buff *skb, struct Qdisc* qdisc). list = (struct sk_buff_head*)qdisc->data) + prio2bandskb->priority&TC_PRIO_MAX; /*首先确定这个数据包的优先级,决定放入的队列*/ if (list-&

19、gt;qlen <= skb->dev->tx_queue_len) _skb_queue_tail(list, skb); /*将数据包放入队列的尾部*/ qdisc->q.qlen+; return 0; .在数据包放入队列之后,调用qdisc_run来发送数据包。static inline void qdisc_run(struct net_device *dev) while (!netif_queue_stopped(dev) && qdisc_restart(dev)<0) /* NOTHING */;在qdisc_restart函数中,首先从队列中取出一个数据包(调用函数pfifo_fast_dequeue)。 然后调用网卡驱动的发送函数(dev->hard_start_xmit)发送数据包,

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论