linux htb 源代码,LINUX TC:HTB相关源码
LINUX TC:HTB相關(guān)源碼 收藏
HTB(hierarchy token buffer)是linux tc(traffic control)模塊中的排隊(duì)隊(duì)列的一種。它的配置比CBQ要簡(jiǎn)單.同時(shí)實(shí)現(xiàn)功能也很強(qiáng)大。下面,就來(lái)看看,HTB在linux中的源碼。
1、???????????? Qdisc_ops的注冊(cè)
先從module_init函數(shù)看起(遵從fudan_abc的建議)
static int __init htb_module_init(void)
{
return register_qdisc(&htb_qdisc_ops);
}
上面的code會(huì)調(diào)用register_qdisc函數(shù),將htb_qdisc_ops注冊(cè)到系統(tǒng)中,那么htb_qdisc_ops包含了那些內(nèi)容:
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其實(shí)就是注冊(cè)了htb管理queue的函數(shù),最重要的莫過(guò)于:enqueue 和dequeue函數(shù),它們作用如同它們的名字一樣。那么到底將htb_qdisc_ops注冊(cè)到那了呢?
這就要看看register函數(shù)了
static struct Qdisc_ops *qdisc_base;
/*
*qdisc_base 就是系統(tǒng)維護(hù)所以qdisc所使用的變量,系統(tǒng)中的所有的qdisc都要
*注冊(cè)到這變量變量中
*在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);
/*
*首先,檢測(cè)這個(gè)qdisc是否已經(jīng)注冊(cè)過(guò)了,這是通過(guò)比較id實(shí)現(xiàn)的,
*id的類型是char 數(shù)組: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;
/*
*然后檢測(cè)ops中的enqueue、dequeue、peek函數(shù),
*如果這些函數(shù)都沒(méi)有被初始化,將使用noop_qdisc_ops函數(shù)來(lái)初始化
*noop_qdisc_ops也是Qdisc_ops結(jié)構(gòu),
*它的作用就像是定義了Qdisc_ops的默認(rèn)值
*/
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;
/*
*然后檢測(cè)cl_ops成員。
*cl_ops是結(jié)構(gòu)Qdisc_class_ops,
*它定義了用于管理掛載到這個(gè)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;
*這樣就注冊(cè)完成了
*/
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是管理這個(gè)tree的,那么看看htb的cl_ops有哪些函數(shù):
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到某個(gè)設(shè)備后,為了對(duì)數(shù)據(jù)包進(jìn)行分類,需要使用tc filter 來(lái)添加fitler到某個(gè)qdisc, 當(dāng)數(shù)據(jù)包來(lái)時(shí),通過(guò)fitler來(lái)區(qū)分?jǐn)?shù)據(jù)包,并轉(zhuǎn)發(fā)到不同的subqdisc 或者subclass。而綁定fitler都是通過(guò)函數(shù):bind_tcf來(lái)實(shí)現(xiàn)的。
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的linux htb 源代码,LINUX TC:HTB相关源码的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 差点令金融世界崩塌的数学公式
- 下一篇: New directions in au