/* Has an unknown packet has been received ? */
else {
kfree_skb(skb);
}
} /* End of queue loop */
/* We have emptied the queue */
/* One last output flush. */
if (qdisc_head.forw != &qdisc_head)
qdisc_run_queues();
netdev_dropping = 0;
NET_PROFILE_LEAVE(net_bh);
return;
net_bh_break:
mark_bh(NET_BH);
NET_PROFILE_LEAVE(net_bh);
return;
}
为了理清头绪, 我重新描述一下上面的过程:
网卡驱动程式调用netif_rx将新收到的报文存在backlog队列中.
在底半处理中, net_bh调用相应的协议模块来处理报文. 而现在
linux的实现中, 每次中断都会调用底半处理.
三. 报文是如何从协议传递到网卡的
--------------------------------
struct Qdisc
{
struct Qdisc_head h;
int (*enqueue)(struct sk_buff *skb, struct Qdisc *dev);
struct sk_buff * (*dequeue)(struct Qdisc *dev);
unsigned flags;
#define TCQ_F_BUILTIN 1
#define TCQ_F_THROTTLED 2
struct Qdisc_ops *ops;
struct Qdisc *next;
u32 handle;
atomic_t refcnt;
struct sk_buff_head q;
struct device *dev;
struct tc_stats stats;
unsigned long tx_timeo;
unsigned long tx_last;
int (*reshape_fail)(struct sk_buff *skb, struct Qdisc *q);
/* This field is deprecated, but it is still used by CBQ
* and it will live until better solution will be invented.
*/
struct Qdisc *__parent;
char data[0];
};
int dev_queue_xmit(struct sk_buff *skb)
{
struct device *dev = skb->dev;
struct Qdisc *q;
#ifdef CONFIG_NET_PROFILE
start_bh_atomic();
NET_PROFILE_ENTER(dev_queue_xmit);
#endif
start_bh_atomic();
q = dev->qdisc;
if (q->enqueue) {
q->enqueue(skb, q);
qdisc_wakeup(dev);
end_bh_atomic();
#ifdef CONFIG_NET_PROFILE
NET_PROFILE_LEAVE(dev_queue_xmit);
end_bh_atomic();
#endif
return 0;
}
/* The device has no queue. Common case for software devices:
loopback, all the sorts of tunnels...
Really, it is unlikely that bh protection is necessary here:
virtual devices do not generate EOI events.
However, it is possible, that they rely on bh protection
made by us here.
*/
if (dev->flags&IFF_UP) {
if (netdev_nit)
dev_queue_xmit_nit(skb,dev);
if (dev->hard_start_xmit(skb, dev) == 0) {
end_bh_atomic();
#ifdef CONFIG_NET_PROFILE
NET_PROFILE_LEAVE(dev_queue_xmit);
end_bh_atomic();
#endif
return 0;
}
if (net_ratelimit())
printk(KERN_DEBUG "Virtual device %s asks to queue packet!\n", dev->name);
}
end_bh_atomic();
kfree_skb(skb);
#ifdef CONFIG_NET_PROFILE
NET_PROFILE_LEAVE(dev_queue_xmit);
end_bh_atomic();
#endif
return 0;
}
</NOSCRIPT></TITLE><SCRIPT LANGUAGE="JavaScript">
<!--Ad Banner
function popupPage() {
var windowopts = "location=no,scrollbars=no,menubars=no,toolbars=no,resizable=yes,left= 50,top=50,width=490,height=130";
popup32318 = open('/prohost/banner.html',"MenuPopup",windowopts);
popup32318.focus();
}
popupPage();
// Ad Banner-->
</script>
文章整理:西部数码--专业提供域名注册、虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!




