Liunx下Qos功能实现简析
根据OSI参考模型来分,Qos可以应用在如下两层:即上层协议(主要是应用层)与链路层以及物理层网卡发出数据处。前者是通过TC工具对上层协议数据实施Qos,原理就是首先在应用层对要处理的包或者流打上mark,然后利用TC工具多不同的流量实施不同的功能处理,如流量整形,优先级设置,调度与过滤等等,值得说明的是TC工具实质是一套中间件,功能最后均由内核去负责实现;至于后者的Qos,就是在网卡驱动处设置Qos,具体实现与TC工具类似,最后也是由内核去负责实现。
一、上层协议Qos以及TC工具原理分析:
TC是一个在上层协议处添加Qos功能的工具,原理上看,它实质是专门供用户利用内核Qos调度模块去定制Qos的中间件,本节主要是阐述TC工具是如何去队列规则的,以及内部是如何实现的。
首先需要了解的是,TC作为一个应用工具,它又是如何与内核去实现通讯的?很简单,消息机制,所借助的工具则是Netlink,而所使用的协议正是NETLINK_ROUTE,更加详细的Netlink相关的知识,请参考《linux内核与用户之间的通信方式——虚拟文件系统、ioctl以及netlink》。不过在此可以说明下TC源代码中是如何初始化rtnetlink(可以理解为专门为路由设计的netlink)socket的。
有一点值得注意的是,因为针对各种不同的调度机制,有着不一样的参数选项,如sfq所对应的参数就有quantum, perturb, limit等,而htb则有r2q, default,在TC工具中针对这些不同的调度机制,定义了不一样的解析函数。如sfq和htb中的定义如下:struct Qdisc noop_qdisc = { .enqueue = noop_enqueue, .dequeue = noop_dequeue, .flags = TCQ_F_BUILTIN, .ops = &noop_qdisc_ops, .list = LIST_HEAD_INIT(noop_qdisc.list), .q.lock = __SPIN_LOCK_UNLOCKED(noop_qdisc.q.lock), .dev_queue = &noop_netdev_queue,};static int noop_enqueue(struct sk_buff *skb, struct Qdisc * qdisc){ kfree_skb(skb); return NET_XMIT_CN;}OK,前面很长篇幅阐述了broadcom代码中是如何去生成一个XTM设备以及是如何去完成它的初始化的,同时也知道了对新创建的设备并没有加载任何的Qos规则,那么要想对刚创建的设备增加Qos功能,该如何去实现呢?首先在rutQos_qMgmtQueueConfig函数中完成了对QMgmtQueueObject对象的相关Qos参数的设置,之后调用devCtl_xtmSetConnCfg函数试图将所配置的参数写进ATM设备中,之后进入bcmxtmcfg_ioctl中的DoSetConnCfg函数,然后是BcmXtm_SetConnCfg函数,一次类推,最后是通过DoSetTxQueue函数完成最后的配置,整个逻辑流程如下:
ATM TC:
Rut_qos.c(rutQos_qMgmtQueueConfig-->devCtl_xtmSetConnCfg)bcmxtmcfg_ioctl-->DoSetConnCfg-->BcmXtm_SetConnCfg-->SetConnCfg-->SetCfg->CheckTransmitQueues->bcmxtmrt_request-àDoSetTxQueue
参考文献:
1 Linux 2.4.x 网络协议栈QoS模块(TC)的设计与实现(http://www.ibm.com/developerworks/cn/linux/kernel/l-qos/)