linux htb 源代码,LINUX TC:HTB相关源码

LINUX TC:HTB相关源码 收藏

HTB(hierarchy token buffer)是linux tc(traffic control)模块中的排队队列的一种。它的配置比CBQ要简单.同时实现功能也很强大。下面,就来看看,HTB在linux中的源码。

1、             Qdisc_ops的注册

先从module_init函数看起(遵从fudan_abc的建议)

static int __init htb_module_init(void)

{

return register_qdisc(&htb_qdisc_ops);

}

上面的code会调用register_qdisc函数,将htb_qdisc_ops注册到系统中,那么htb_qdisc_ops包含了那些内容:

static struct Qdisc_ops htb_qdisc_ops __read_mostly = {

.cl_ops        =     &htb_class_ops,

.id          =     "htb",

.priv_size   =     sizeof(struct htb_sched),

.enqueue     =     htb_enqueue,

.dequeue     =     htb_dequeue,

.peek            =     qdisc_peek_dequeued,

.drop            =     htb_drop,

.init              =     htb_init,

.reset           =     htb_reset,

.destroy      =     htb_destroy,

.dump          =     htb_dump,

.owner         =     THIS_MODULE,

};

可以看出,htb_qdisc_ops其实就是注册了htb管理queue的函数,最重要的莫过于:enqueue 和dequeue函数,它们作用如同它们的名字一样。那么到底将htb_qdisc_ops注册到那了呢?

这就要看看register函数了

static struct Qdisc_ops *qdisc_base;

/*

*qdisc_base 就是系统维护所以qdisc所使用的变量,系统中的所有的qdisc都要

*注册到这变量变量中

*在struct Qdisc_ops中,包含了成员(struct Qdisc_ops *)next

*也就是,所以的qdisc是以链表的形式存在的

*/

int register_qdisc(struct Qdisc_ops *qops)

{

struct Qdisc_ops *q, **qp;

int rc = -EEXIST;

write_lock(&qdisc_mod_lock);

/*

*首先,检测这个qdisc是否已经注册过了,这是通过比较id实现的,

*id的类型是char 数组:char                 id[IFNAMSIZ];IFNAMESIZ=16

*htb的id=”htb”

*/

for (qp = &qdisc_base; (q = *qp) != NULL; qp = &q->next)

if (!strcmp(qops->id, q->id))

goto out;

/*

*然后检测ops中的enqueue、dequeue、peek函数,

*如果这些函数都没有被初始化,将使用noop_qdisc_ops函数来初始化

*noop_qdisc_ops也是Qdisc_ops结构,

*它的作用就像是定义了Qdisc_ops的默认值

*/

if (qops->enqueue == NULL)

qops->enqueue = noop_qdisc_ops.enqueue;

if (qops->peek == NULL) {

if (qops->dequeue == NULL)

qops->peek = noop_qdisc_ops.peek;

else

goto out_einval;

}

if (qops->dequeue == NULL)

qops->dequeue = noop_qdisc_ops.dequeue;

/*

*然后检测cl_ops成员。

*cl_ops是结构Qdisc_class_ops,

*它定义了用于管理挂载到这个qdisc下的所有class(或者qdisc)

*/

if (qops->cl_ops) {

const struct Qdisc_class_ops *cops = qops->cl_ops;

if (!(cops->get && cops->put && cops->walk && cops->leaf))

goto out_einval;

if (cops->tcf_chain && !(cops->bind_tcf && cops->unbind_tcf))

goto out_einval;

}

/*

*最后将新的qops插入到链表的尾部:*qp = qops;

*这样就注册完成了

*/

qops->next = NULL;

*qp = qops;

rc = 0;

out:

write_unlock(&qdisc_mod_lock);

return rc;

out_einval:

rc = -EINVAL;

goto out;

}

EXPORT_SYMBOL(register_qdisc);

Qdisc_class_ops是管理这个tree的,那么看看htb的cl_ops有哪些函数:

static const struct Qdisc_class_ops htb_class_ops = {

.graft           =     htb_graft,

.leaf             =     htb_leaf,

.qlen_notify      =     htb_qlen_notify,

.get              =     htb_get,

.put              =     htb_put,

.change              =     htb_change_class,

.delete         =     htb_delete,

.walk           =     htb_walk,

.tcf_chain   =     htb_find_tcf,

.bind_tcf     =     htb_bind_filter,

.unbind_tcf =     htb_unbind_filter,

.dump          =     htb_dump_class,

.dump_stats      =     htb_dump_class_stats,

};

我们知道,tc qdisc命令添加qdisc到某个设备后,为了对数据包进行分类,需要使用tc filter 来添加fitler到某个qdisc, 当数据包来时,通过fitler来区分数据包,并转发到不同的subqdisc 或者subclass。而绑定fitler都是通过函数:bind_tcf来实现的。

你可能感兴趣的:(linux,htb,源代码)