gaocheng_cu的ChinaUnix博客
gaocheng_cu
全部博文(108)
2011年(11)
2010年(46)
2009年(29)
2008年(22)
trojans1
名侦探柯
watercol
carltrav
semiter
cxsvip
kendy_al
YUVRGB
liu77nin
分类: 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_sleeping是noop_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操作就只是丢包, 这就是为什么在没插网线情况下也可以调用发包函数处理的原因, 结果就是直接丢包。
上一篇:elf format section
下一篇:C++中const总结
登录 注册