linux 1.2.13 网络解析--收报分析(二层至三层过程)

linux 内核版本 1.2.13

文件:net/inet/dev.c 


1.

/*
 * Receive a packet from a device driver and queue it for the upper
 * (protocol) levels.  It always succeeds. This is the recommended 
 * interface to use.
 */
void netif_rx(struct sk_buff *skb)  //
skb在上一步工作中,已经部分初始化
{
static int dropping = 0;
/*
*Any received buffers are un-owned and should be discarded
*when freed. These will be updated later as the frames get
*owners.
*/
skb->sk = NULL;
skb->free = 1;
if(skb->stamp.tv_sec==0)
skb->stamp = xtime;
/*
*Check that we aren't overdoing things.
*/
if (!backlog_size)
  dropping = 0;
else if (backlog_size > 300)
dropping = 1;
if (dropping) 
{
kfree_skb(skb, FREE_READ);
return;
}
/*
*Add it to the "backlog" queue. 
*/
#ifdef CONFIG_SKB_CHECK
IS_SKB(skb);
#endif
skb_queue_tail(&backlog,skb);//加入接收对列
backlog_size++;
/*
*If any packet arrived, mark it for processing after the
*hardware interrupt returns.
*/
mark_bh(NET_BH);
return;
}

//中断上半部完成

/*
 * When we are called the queue is ready to grab, the interrupts are
 * on and hardware can interrupt and queue to the receive queue a we
 * run with no problems.
 * This is run as a bottom half after an interrupt handler that does
 * mark_bh(NET_BH);
 */
 
void net_bh(void *tmp)
{
struct sk_buff *skb;
struct packet_type *ptype;
struct packet_type *pt_prev;
unsigned short type;
/*
* Atomically check and mark our BUSY state. 
*/

if (set_bit(1, (void*)&in_bh))
return;
/*
* Can we send anything now? We want to clear the
* decks for any more sends that get done as we
* process the input.
*/

dev_transmit();
 
/*
* 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
*/


cli();

/*
* While the queue is not empty
*/ 
while((skb=skb_dequeue(&backlog))!=NULL)  
//抽取队列数据
{
/*
*We have a packet. Therefore the queue has shrunk
*/
  backlog_size--;
sti();
      /*
*Bump the pointer to the next structure.
*This assumes that the basic 'skb' pointer points to
*the MAC header, if any (as indicated by its "length"
*field).  Take care now!
*/
skb->h.raw = skb->data + skb->dev->hard_header_len;
skb->len -= skb->dev->hard_header_len;
      /*
*Fetch the packet protocol ID.  This is also quite ugly, as
*it depends on the protocol driver (the interface itself) to
*know what the type is, or where to get it from.  The Ethernet
*interfaces fetch the ID from the two bytes in the Ethernet MAC
*header (the h_proto field in struct ethhdr), but other drivers
*may either use the ethernet ID's or extra ones that do not
*clash (eg ETH_P_AX25). We could set this before we queue the
*frame. In fact I may change this when I have time.
*/
type = skb->dev->type_trans(skb, skb->dev);//获得二层协议类型
/*
*We got a packet ID.  Now loop over the "known protocols"
*table (which is actually a linked list, but this will
*change soon if I get my way- FvK), and forward the packet
*to anyone who wants it.
*
*[FvK didn't get his way but he is right this ought to be
*hashed so we typically get a single hit. The speed cost
*here is minimal but no doubt adds up at the 4,000+ pkts/second
*rate we can hit flat out]
*/
pt_prev = NULL;
for (ptype = ptype_base; ptype != NULL; ptype = ptype->next) 
{
if ((ptype->type == type || ptype->type == htons(ETH_P_ALL)) && (!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);  //根据type类型,找到三层入口并执行 如:ip_packet_type.ip_rcv
}
/* 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);//根据type类型,找到三层入口并执行 如:ip_packet_type.ip_rcv
/*
*Has an unknown packet has been received ?
*/ 
else
kfree_skb(skb, FREE_WRITE);
/*
*Again, see if we can transmit anything now. 
*[Ought to take this out judging by tests it slows
*us down not speeds us up]
*/
dev_transmit();
cli();
  }/* End of queue loop */
  /*
  *We have emptied the queue
  */
  in_bh = 0;
sti();
/*
*One last output flush.
*/
 
dev_transmit();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值