linux 1.2.13 网络解析--收报分析(二层至三层过程)
2013-07-01 15:55
393 查看
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();
}
文件: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();
}
相关文章推荐
- linux 1.2.13 网络解析--收报分析(ip层处理)
- Linux网络编程之tcpdump抓包分析TCP三次握手过程
- linux 1.2.13 网络解析--入口
- 网络配置过程分析二(linux网络协议栈笔记)
- 解析Linux网络分析的三大利器(ZT)
- linux 1.2.13 网络解析--注册
- linux 网络中断分析过程
- 【linux内核2.4.26·网络】IP分片重组过程函数解析
- 网络二层与三层数据包转发过程
- 网络二层,三层的区别和寻址过程
- Linux网络编程之tcpdump抓包分析TCP三次握手过程
- Linux内核移植 part2:uboot设备树--解析过程分析
- 网络配置过程分析(linux网络协议栈笔记)
- ping命令全解析(语法、过程、结果分析、网络故障诊断)
- Linux 数据链路层接收的以太帧传递给网络层的过程分析
- 【原创】如何分析网站的网络分布和解析策略,快速指导优化用户体验(一)
- Linux 下网络协议分析器 Wireshark 使用基础
- Linux内核网络子系统数据发送模块分析(MAC802.11-OpenWRT)
- 【识记】Linux 性能调优分析图_CPU_内存_磁盘_网络
- linux网络协议栈分析笔记10-arp邻居子系统3