linux tc模块源代码,LINUX TC:HTB相关源码

static struct Qdisc *

qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue,

struct Qdisc *p, u32 parent, u32 handle,

struct nlattr **tca, int *errp)

{

/*

*dev:创建的qdisc最终会关联到这个设备上

*tca:是找到想要的Qdisc_ops的关键

*handle:qdisc_id

*parent:parent_id

*p:parent

*/

int err;

struct nlattr *kind = tca[TCA_KIND];

struct Qdisc *sch;//要创建的qdisc

struct Qdisc_ops *ops;

struct qdisc_size_table *stab;

/*

*首要的事情是找到想要的Qdisc_ops

*函数qdiscc_lookup_ops通过kind来搜索qdisc_base中注册的所有qdisc_ops

*直到找到为止,它会通过Qdisc_ops中的id来判断是否找到

*/

ops = qdisc_lookup_ops(kind);

#ifdef CONFIG_MODULES

if (ops == NULL && kind != NULL) {

/**

*如果没有找到,但是确实存在,那么重新注册,安装这个moduel模块实现

*/

char name[IFNAMSIZ];

if (nla_strlcpy(name, kind, IFNAMSIZ) < IFNAMSIZ) {

/* We dropped the RTNL semaphore in order to

* perform the module load.  So, even if we

* succeeded in loading the module we have to

* tell the caller to replay the request.  We

* indicate this using -EAGAIN.

* We replay the request because the device may

* go away in the mean time.

*/

rtnl_unlock();

request_module("sch_%s", name);

rtnl_lock();

//ok,安装这个moduel后,从新查找需要的Qdisc_ops

ops = qdisc_lookup_ops(kind);

if (ops != NULL) {

/* We will try again qdisc_lookup_ops,

* so don't keep a reference.

*/

module_put(ops->owner);

err = -EAGAIN;

goto err_out;

}

}

}

#endif

err = -ENOENT;

if (ops == NULL)

goto err_out;

/**

*到这里,找到了相应的Qdisc_ops,那么就开始创建Qdisc了

*函数会将ops赋值给Qdisc中的ops

*Qdisc的enqueue和dequeue函数也是ops中的enqueue和dequeue函数

*同时dev_queue也会赋值给Qdisc中的dev_queue,注意dev_queue包含了

*Qdisc所在的dev信息,即通过dev_queue就知道Qdisc的dev

*/

sch = qdisc_alloc(dev_queue, ops);

if (IS_ERR(sch)) {

err = PTR_ERR(sch);

goto err_out2;

}

/**

*初始化parent_id

*/

sch->parent = parent;

/**

* #define TC_H_UNSPEC   (0U)

*#define TC_H_ROOT (0xFFFFFFFFU)

*#define TC_H_INGRESS    (0xFFFFFFF1U)

*0       4294967295      4294967281

*对于handle,要比parent要弹性些。Parent需要用户指定其正确性,

*而handler系统会检查handle的值的有效性,当handle等于TC_H_INGRESS

*或者为0时,系统会数据分配一个handle:即qdisc_id

*例如:

Add:tc qdisc add dev eth0 root handle 1: htb default 12

Dump:tc qdisc ls dev eth0

Result:qdisc htb 1: r2q 10 default 12 direct_packets_stat 5

ADD:tc qdisc add dev eth0 root handle 0: htb default 12

DUMP:tc qdisc ls dev eth0

RESULT:qdisc htb 8002: r2q 10 default 12 direct_packets_stat 34

*/

if (handle == TC_H_INGRESS) {

sch->flags |= TCQ_F_INGRESS;

handle = TC_H_MAKE(TC_H_INGRESS, 0);

lockdep_set_class(qdisc_lock(sch), &qdisc_rx_lock);

} else {

if (handle == 0) {

handle = qdisc_alloc_handle(dev);

err = -ENOMEM;

if (handle == 0)

goto err_out3;

}

lockdep_set_class(qdisc_lock(sch), &qdisc_tx_lock);

}

//将合法的handle赋值给Qdisc-> handle

sch->handle = handle;

/**

*如果opt中不存在init函数,或者存在并且初始化的成功时

*然后做进一步的初始化,如果创建的是HTB,

*那么init函数就是htb_init

*最后返回创建的Qdisc

*/

if (!ops->init || (err = ops->init(sch, tca[TCA_OPTIONS])) == 0) {

if (tca[TCA_STAB]) {

stab = qdisc_get_stab(tca[TCA_STAB]);

if (IS_ERR(stab)) {

err = PTR_ERR(stab);

goto err_out4;

}

sch->stab = stab;

}

if (tca[TCA_RATE]) {

spinlock_t *root_lock;

err = -EOPNOTSUPP;

if (sch->flags & TCQ_F_MQROOT)

goto err_out4;

if ((sch->parent != TC_H_ROOT) &&

!(sch->flags & TCQ_F_INGRESS) &&

(!p || !(p->flags & TCQ_F_MQROOT)))

root_lock = qdisc_root_sleeping_lock(sch);

else

root_lock = qdisc_lock(sch);

err = gen_new_estimator(&sch->bstats, &sch->rate_est,

root_lock, tca[TCA_RATE]);

if (err)

goto err_out4;

}

qdisc_list_add(sch);

return sch;

}

err_out3:

dev_put(dev);

kfree((char *) sch - sch->padded);

err_out2:

module_put(ops->owner);

err_out:

*errp = err;

return NULL;

err_out4:

/*

* Any broken qdiscs that would require a ops->reset() here?

* The qdisc was never in action so it shouldn't be necessary.

*/

qdisc_put_stab(sch->stab);

if (ops->destroy)

ops->destroy(sch);

goto err_out3;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值