Chinaunix首页 | 论坛 | 博客
  • 博客访问: 661738
  • 博文数量: 156
  • 博客积分: 4833
  • 博客等级: 上校
  • 技术积分: 1554
  • 用 户 组: 普通用户
  • 注册时间: 2007-05-21 19:36
文章分类

全部博文(156)

文章存档

2016年(2)

2013年(1)

2012年(13)

2011年(30)

2010年(46)

2009年(29)

2008年(23)

2007年(12)

分类: LINUX

2011-05-17 10:33:53

dev_init_scheduler()

 

在网卡设备的初始化函数register_netdevice()函数中调用dev_init_scheduler()函数对网卡设备的流控队列处理进行了初始化, 也就是说每个网络网卡设备的qdisc指针都不会是空的:

linux-2.6.21.7/net/sched/sch_gentric.c
1 void dev_init_scheduler(struct net_device *dev)
2 {
3     qdisc_lock_tree(dev);
4     dev->qdisc = &noop_qdisc;
5     dev->qdisc_sleeping = &noop_qdisc;
6     INIT_LIST_HEAD(&dev->qdisc_list);
7     qdisc_unlock_tree(dev);
8     dev_watchdog_init(dev);
9 }  

当然noop_qdisc中的调度是不可用的, 只进行丢包处理;网卡在激活(dev_open())时会调用dev_activate()函数重新对qdisc指针赋值,但未对qdisc_ingress 赋值:

01 void dev_activate(struct net_device *dev)
02 {
03     //
如果当前的qdisc_sleepingnoop_qdisc,重新初始化qdisc_sleeping
04     if (dev->qdisc_sleeping == &noop_qdisc) {
05         struct Qdisc *qdisc;
06         if (dev->tx_queue_len) {
07             qdisc = qdisc_create_dflt(dev, &pfifo_fast_ops,
08                     TC_H_ROOT);
09             if (qdisc == NULL) {
10                 printk(KERN_INFO "%s: activation failed\n", dev->name);
11                 return;
12             }
13             write_lock(&qdisc_tree_lock);
14             list_add_tail(&qdisc->list, &dev->qdisc_list);
15             write_unlock(&qdisc_tree_lock);
16         } else {
17             qdisc =  &noqueue_qdisc;
18         }
19         write_lock(&qdisc_tree_lock);
20         dev->qdisc_sleeping = qdisc;
21         write_unlock(&qdisc_tree_lock);
22     }
23
24     //
如果现在网线没插, 返回
25     if (!netif_carrier_ok(dev))
26         /* Delay activation until next carrier-on event */
27         return;
28
29     //
将网卡当前的qdisc赋值为qdisc_sleeping所指的qdisc
30     spin_lock_bh(&dev->queue_lock);
31     rcu_assign_pointer(dev->qdisc, dev->qdisc_sleeping);
32     if (dev->qdisc != &noqueue_qdisc) {
33         dev->trans_start = jiffies;
34         dev_watchdog_up(dev);
35     }
36     spin_unlock_bh(&dev->queue_lock);
37 }


qdisc_sleeping
用于保存在网卡起效时使用的qdisc, 因为在网卡down或网线拔除不可用时, 网卡设备的qdisc指针会指向noqueue_qdisc, qdisc操作就只是丢包, 这就是为什么在没插网线情况下也可以调用发包函数处理的原因, 结果就是直接丢包。

 

阅读(842) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~