Chinaunix首页 | 论坛 | 博客
  • 博客访问: 571587
  • 博文数量: 107
  • 博客积分: 3079
  • 博客等级: 少校
  • 技术积分: 1306
  • 用 户 组: 普通用户
  • 注册时间: 2008-11-08 00:03
个人简介

emmoblin.github.com

文章分类

全部博文(107)

文章存档

2012年(8)

2011年(15)

2010年(49)

2009年(9)

2008年(26)

分类: LINUX

2009-01-05 01:03:18

数据报在链路层的接收
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)。
阅读(1202) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~