手机站
网通分站
电信主站
密 码:
用户名:
当前位置 : 主页>网站运营>建站经验>列表

linux的网络设计和实现

来源:互联网 作者:west263.com 时间:2008-04-16
西部数码-全国虚拟主机10强!40余项虚拟主机管理功能,全国领先!双线多线虚拟主机南北访问畅通无阻!免费赠送企业邮局,.CN域名,自助建站480元起,免费试用7天,满意再付款! P4主机租用799元/月.月付免压金!

}
__sti();/*VY*/
}

* net/core/dev.c

/*
* Device drivers call our routines to queue packets here. We empty the
* queue in the bottom half handler.
*/
//任何的报文先存放在这里, 随后由再net_bh发给相应的网络层模块, 如 ip_input.
static struct sk_buff_head backlog;

/*
* Receive a packet from a device driver and queue it for the upper
* (protocol) levels. It always succeeds.
*/
/*
* 简单的将新到的包, 插到backlog中.
* 网卡驱动程式会调用这个函数
*/
void netif_rx(struct sk_buff *skb)
{
if(skb->stamp.tv_sec==0)
get_fast_time(&skb->stamp); //取当前的时间

/* The code is rearranged so that the path is the most
short when CPU is congested, but is still operating.
*/

if (backlog.qlen <= netdev_max_backlog) {
if (backlog.qlen) {
if (netdev_dropping == 0) {
skb_queue_tail(&backlog, skb);
mark_bh(NET_BH);
return;
}
atomic_inc(&netdev_rx_dropped);
kfree_skb(skb);
return;
}

netdev_dropping = 0;

skb_queue_tail(&backlog, skb);
mark_bh(NET_BH);
return;
}
netdev_dropping = 1;
atomic_inc(&netdev_rx_dropped);
kfree_skb(skb);
}

/*
* 网络的底半处理程式, 将报文由backlog中取出, 发给相应的网络层模块,
* 如 ip_input. 有一点请大家注意一个报文能够被多个协议层所处理. 这
* 一点很重要.
*/
void net_bh(void)
{
struct packet_type *ptype;
struct packet_type *pt_prev;
unsigned short type;
unsigned long start_time = jiffies;

NET_PROFILE_ENTER(net_bh);
/*
* Can we send anything now? We want to clear the
* decks for any more sends that get done as we
* process the input. This also minimises the
* latency on a transmit interrupt bh.
*/

if (qdisc_head.forw != &qdisc_head)
qdisc_run_queues();

/*
* Any data left to process. This may occur because a
* mark_bh() is done after we empty the queue including
* that from the device which does a mark_bh() just after
*/

/*
* While the queue is not empty..
*
* Note that the queue never shrinks due to
* an interrupt, so we can do this test without
* disabling interrupts.
*/

while (!skb_queue_empty(&backlog))
{
struct sk_buff * skb;

/* Give chance to other bottom halves to run */
if (jiffies - start_time > 1)
goto net_bh_break;

/* We have a packet. Therefore the queue has shrunk */
skb = skb_dequeue(&backlog); //从backlog中取出一个包

/*
* Bump the pointer to the next structure.
*
* On entry to the protocol layer. skb->data and
* skb->nh.raw point to the MAC and encapsulated data
*/

/* XXX until we figure out every place to modify.. */
skb->h.raw = skb->nh.raw = skb->data;

if (skb->mac.raw < skb->head || skb->mac.raw > skb->data) {
printk(KERN_CRIT "%s: wrong mac.raw ptr, proto=x\n",
skb->dev->name, skb->protocol);
kfree_skb(skb);
continue;
}

/* Fetch the packet protocol ID. */

type = skb->protocol; //这里是指网络层协议

/*
* We got a packet ID. Now loop over the "known protocols"
* list. There are two lists. The ptype_all list of taps (normally empty)
* and the main protocol list which is hashed perfectly for normal protocols.
*/

pt_prev = NULL;
for (ptype = ptype_all; ptype!=NULL; ptype=ptype->next)
{
if (!ptype->dev || ptype->dev == skb->dev) {
if(pt_prev)
{
struct sk_buff *skb2=skb_clone(skb, GFP_ATOMIC);
if(skb2)
pt_prev->func(skb2,skb->dev, pt_prev);
}
pt_prev=ptype;
}
}

for (ptype = ptype_base[ntohs(type)&15]; ptype != NULL; ptype = ptype->next)
{
if (ptype->type == type && (!ptype->dev || ptype->dev==skb->dev))
{
/*
* We already have a match queued. Deliver
* to it and then remember the new match
*/
if(pt_prev)
{
struct sk_buff *skb2;

skb2=skb_clone(skb, GFP_ATOMIC);

/*
* Kick the protocol handler. This should be fast
* and efficient code.
*/

if(skb2)
pt_prev->func(skb2, skb->dev, pt_prev);
}
/* Remember the current last to do */
pt_prev=ptype;
}
} /* End of protocol list loop */

/* Is there a last item to send to ? */

if(pt_prev)
pt_prev->func(skb, skb->dev, pt_prev);

文章整理:西部数码--专业提供域名注册虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!