Linux内核:从上向下分析网络层IP协议
作者:网络转载 发布时间:[ 2013/1/6 10:08:12 ] 推荐标签:
网络层的发送函数调用了设备接口层,相当于网络模型的链路层的发送函数dev_queue_xmit()
该函数的调用关系如下:
/*
* Send (or queue for sending) a packet.
*
* IMPORTANT: When this is called to resend frames. The caller MUST
* already have locked the sk_buff. Apart from that we do the
* rest of the magic.
*/
void dev_queue_xmit(struct sk_buff *skb, struct device *dev, int pri)
{
unsigned long flags;
int nitcount;
struct packet_type *ptype;
int where = 0; /* used to say if the packet should go */
/* at the front or the back of the */
/* queue - front is a retransmit try */
/* where=0 表示是刚从上层传递的新数据包;where=1 表示从硬件队列中取出的数据包*/
if (dev == NULL)
{
printk("dev.c: dev_queue_xmit: dev = NULL
");
return;
}
if(pri>=0 && !skb_device_locked(skb))//锁定该skb再进行操作,避免造成内核的不一致情况
skb_device_lock(skb); /* Shove a lock on the frame */
#ifdef CONFIG_SLAVE_BALANCING
save_flags(flags);
cli();
if(dev->slave!=NULL && dev->slave->pkt_queue < dev->pkt_queue &&
(dev->slave->flags & IFF_UP))
dev=dev->slave;
restore_flags(flags);
#endif
#ifdef CONFIG_SKB_CHECK
IS_SKB(skb);
#endif
skb->dev = dev;
/*
* This just eliminates some race conditions, but not all...
*/
if (skb->next != NULL) //这种条件似乎永远不能成立,因为发送数据包前,数据包已经从缓存队列摘下
{//以防内核代码有BUG
/*
* Make sure we haven't missed an interrupt.
*/
printk("dev_queue_xmit: worked around a missed interrupt
");
start_bh_atomic();
dev->hard_start_xmit(NULL, dev);
end_bh_atomic();
return;
}
/*
* Negative priority is used to flag a frame that is being pulled from the
* queue front as a retransmit attempt. It therefore goes back on the queue
* start on a failure.
*/
if (pri < 0) //优先级小于0表示是从硬件队列中取出的数据包
{
pri = -pri-1;
where = 1;
}
if (pri >= DEV_NUMBUFFS)
{
printk("bad priority in dev_queue_xmit.
");
pri = 1;
}
/*
* If the address has not been resolved. Call the device header rebuilder.
* This can cover all protocols and technically not just ARP either.
*/
if (!skb->arp && dev->rebuild_header(skb->data, dev, skb->raddr, skb)) {//用于ARP协议,并重建MAC帧首部
return;
}
save_flags(flags);
cli();
if (!where) {//表示是新数据包,需要将其加入设备队列中
#ifdef CONFIG_SLAVE_BALANCING
skb->in_dev_queue=1;//该数据包在设备队列
#endif
skb_queue_tail(dev->buffs + pri,skb);//将发送数据包加入硬件队列
skb_device_unlock(skb); /* Buffer is on the device queue and can be freed safely */
skb = skb_dequeue(dev->buffs + pri);//从硬件队列中取出一个数据包
skb_device_lock(skb); /* New buffer needs locking down */
#ifdef CONFIG_SLAVE_BALANCING
skb->in_dev_queue=0;
#endif
}
restore_flags(flags);
/* copy outgoing packets to any sniffer packet handlers */
if(!where)//对于新的数据包,则遍历网络层协议队列,内核支持混杂模式
{
for (nitcount= dev_nit, ptype = ptype_base; nitcount > 0 && ptype != NULL; ptype = ptype->next)
{
/* Never send packets back to the socket
* they originated from - MvS (miquels@drinkel.ow.org)
*/
if (ptype->type == htons(ETH_P_ALL) &&
(ptype->dev == dev || !ptype->dev) &&
((struct sock *)ptype->data != skb->sk))
{
struct sk_buff *skb2;
if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL)
break;
/*
* The protocol knows this has (for other paths) been taken off
* and adds it back.
*/
skb2->len-=skb->dev->hard_header_len;
ptype->func(skb2, skb->dev, ptype);//IP层函数对应func为ip_rcv(),将发送的数据回送一份给对应的网络层协议
nitcount--;//用于及时退出循环
}
}
}
start_bh_atomic();//开始原子操作
if (dev->hard_start_xmit(skb, dev) == 0) {//调用硬件的发送函数发送数据
end_bh_atomic();//结束原子操作
/*
* Packet is now solely the responsibility of the driver
*/
return;//到这里说明数据包成功发送
}
//数据包没有成功发送,进行处理,将数据包从新加入硬件队列
end_bh_atomic();
/*
* Transmission failed, put skb back into a list. Once on the list it's safe and
* no longer device locked (it can be freed safely from the device queue)
*/
cli();
#ifdef CONFIG_SLAVE_BALANCING
skb->in_dev_queue=1;
dev->pkt_queue++;
#endif
skb_device_unlock(skb);//对SKB解锁
skb_queue_head(dev->buffs + pri,skb);//这次采用头插法插入硬件发送队列
restore_flags(flags);
}
具体的硬件发送函数dev->hard_start_xmit的实现将做下篇博文中分析。
本文转自:http://blog.csdn.net/yming0221/article/details/7492423
相关推荐
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11