免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2751 | 回复: 7
打印 上一主题 下一主题

[转]数据报在链路层的接收 [复制链接]

论坛徽章:
3
金牛座
日期:2014-06-14 22:04:062015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:49:45
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-01-04 14:46 |只看该作者 |倒序浏览
转一位不知名的大侠写的一个笔记总结:wink: 先表示感谢!

数据报在链路层的接收
2006年12月01日 星期五 下午 01:04
    网络设备在接收到来自网络中其它主机的数据报,或本地环回接口的数据报之后,交给协议栈的netif_rx函数,该函数首先要为收到的这个skb打上当前 的时间戳(skb->tstamp成员),这个时间戳表示该数据到达的时间,它不是必选的,可以通过套接字选项SO_TIMESTAMP将其打开, 该选项打开时间戳时,会将链路层的全局变量netstamp_needed加1,netif_rx在检查到这个变量不为零时,为skb打上时间戳。     softnet_data是类型为struct softnet_data结构体的全局变量,每个CPU定义一个,它是链路层的数据接收队列,该结构体的定义如下:   
struct softnet_data {         
        struct net_device   *output_queue;
        struct sk_buff_head input_pkt_queue;
        struct list_head    poll_list;
        struct sk_buff      *completion_queue;
        struct net_device   backlog_dev;     
};     
    input_pkt_queue是skb的队列,接收到的skb全部进入该队列等待后续处理,netif_rx首先检查该队列当前的长度 input_pkt_queue.qlen,即当前排在队列中的skb的数量,当数量超过netdev_max_backlog的值时,直接丢弃新收到的 包,netdev_max_backlog在协议栈中定义的缺省值为1000,可以通过文件 /proc/sys/net/core/netdev_max_backlog进行修改。如果当前队列长度未达到上限,把新收到的skb加到这个队列中, 在加到队列之前,要确保对这个队列的接收处理已启动,如果当前队列为空,则要先调用netif_rx_schedule启动队列的处理,再把skb加到队 列中。需要注意的是softnet_data是CPU绑定的,但不是网络设备绑定的,多个网络设备收到的数据报可能存放在同一个队列中待处理。     netif_rx_schedule函数的主要作用是触发一个软中断NET_RX_SOFTIRQ,使中断处理函数net_rx_action处理接收队 列中的数据报。net_rx_action开始时会记录下系统的当前时间,然后进行处理,当处理时间持续超过1个时钟嘀嗒时,它会再触发一个中断 NET_RX_SOFTIRQ,并退出,在下一个中断中继续处理。一次中断处理除了时间上有限制,处理的数据报的数量上也有限制。     
softnet_data的成员poll_list中存放的是成员backlog_dev的地址,由netif_rx_schedule存入, backlog_dev的成员poll在系统初始化时被指向函数process_backlog,net_rx_action调用该函数进行实际的数据报 处理,process_backlog把数据报从input_pkt_queue队列中取出,传给netif_receive_skb,由 netif_receive_skb传给相应的网络层接收函数。process_backlog的处理时间也有1个时钟嘀嗒的限制,同时一次处理的数据报 的数量不得超过backlog_dev->quota和netdev_budget两个值中较小的那个值,backlog_dev-> quota由netif_rx_schedule初始化为全局变量weight_p的值,缺省为64,netdev_budget缺省为300。从代码可 以看出,process_backlog一次处理最大数据报数量为64,而net_rx_action为300。weight_p和 netdev_budget这两个值分别可以在文件/proc/sys/net/core/dev_weight和 /proc/sys/net/core/netdev_budget中查看和修改。     netif_receive_skb是链路层接收数据报的最后一站。它根据注册在全局数组ptype_all和ptype_base里的网络层数据报类型,把数据报递交给不同的网络层协议的接收函数(INET域中主要是ip_rcv和arp_rcv)。


[ 本帖最后由 dreamice 于 2009-1-4 16:49 编辑 ]

论坛徽章:
3
金牛座
日期:2014-06-14 22:04:062015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:49:45
2 [报告]
发表于 2009-01-04 14:47 |只看该作者
格式不太好,大家都凑合着看看吧,觉得写得还不错

论坛徽章:
5
摩羯座
日期:2014-07-22 09:03:552015元宵节徽章
日期:2015-03-06 15:50:392015亚冠之大阪钢巴
日期:2015-06-12 16:01:352015年中国系统架构师大会
日期:2015-06-29 16:11:2815-16赛季CBA联赛之四川
日期:2018-12-17 14:10:21
3 [报告]
发表于 2009-01-04 15:38 |只看该作者

格式不好版主就整理一下加个精华嘛

论坛徽章:
3
金牛座
日期:2014-06-14 22:04:062015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:49:45
4 [报告]
发表于 2009-01-04 16:50 |只看该作者
原帖由 T-bagwell 于 2009-1-4 15:38 发表

格式不好版主就整理一下加个精华嘛


看来不能偷懒:wink:

论坛徽章:
0
5 [报告]
发表于 2009-01-08 17:44 |只看该作者
赞一个!

论坛徽章:
0
6 [报告]
发表于 2009-01-08 19:56 |只看该作者

回复 #1 dreamice 的帖子

随便加两句:
   驱动中一般是中断接收,中断中调用netif_rx,这样就交给IP层了(以TCP/IP为例),IP层以ip_rcv接收进一步处理,只不过我们驱动程序于ip_rcv无关系了.
   发送时,ip层为了将数据交给网卡,会用dev_queue_xmit调用我们驱动程序的struct device的hard_start_xmit,在hard_start_xmit中如果不想发得太快,想停时用netif_stop_queue.重新发送用netif_start_queue(netif_start_queue和netif_stop_queue是通过struct device的stat才起作用)
    网卡发送和接收是通过软中断(共两个,一个是收,一个是发)进行的,只要我们利用netif_tx_disable将网卡的软中断关了(netif_tx_disable开放了硬件中断,所以,还是可以recv),系统就不会调用网卡驱动的发送函数了.

论坛徽章:
0
7 [报告]
发表于 2009-01-08 20:09 |只看该作者

回复 #6 whoisliang 的帖子

为什么struct device的stat能对发送有作用呢,就是因为网卡是用软中断来处理数据的,软中断启动时会测试stat,看是否为__LINK_STATE_XOFF

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
8 [报告]
发表于 2009-01-10 15:02 |只看该作者
process_backlog把数据报从input_pkt_queue队列中取出,传给netif_receive_skb,由 netif_receive_skb传给相应的网络层接收函数。

netif_receive_skb这个函数处理的数据报文中skb->data指针已经指向了ip层的头部。
该函数是算做链路层的最后呢,还是IP层的开始呢
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP