免费注册 查看新帖 |

Chinaunix

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

[求助]netif_rx的一段代码没看明白,2.6.18.6内核的 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-03-22 15:01 |只看该作者 |倒序浏览
2.6.18.6内核, net/core/dev.c

int netif_rx(struct sk_buff *skb)函数中有下面一段:

  1.         
  2.         local_irq_save(flags);
  3.         queue = &__get_cpu_var(softnet_data);

  4.         __get_cpu_var(netdev_rx_stat).total++;
  5.         if (queue->input_pkt_queue.qlen <= netdev_max_backlog) {
  6.                 if (queue->input_pkt_queue.qlen) {                                        《==这行是做什么用的???
  7. enqueue:
  8.                         dev_hold(skb->dev);
  9.                         __skb_queue_tail(&queue->input_pkt_queue, skb);
  10.                         local_irq_restore(flags);
  11.                         return NET_RX_SUCCESS;
  12.                 }

  13.                 netif_rx_schedule(&queue->backlog_dev);
  14.                 goto enqueue;        
  15.     }
复制代码


为什么要判断if (queue->input_pkt_queue.qlen) 这一行呢,如果cpu的skb对列里面有数据包的话,下面的netif_rx_schedule(&queue->backlog_dev);就不能被执行到了。

觉得应该先把数据包加到queue对列中再调用netif_rx_schedule吧,这里实际上是先调用了netif_rx_schedule,为什么呢?

[ 本帖最后由 bekars 于 2007-3-22 15:04 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2007-03-22 15:48 |只看该作者
我觉得是因为netif_rx()并不像NAPI那样,driver把代表自己的net_dev挂到softnet_data->poll_list上,但它现在又是基于NAPI实现的了。那只好找个通用的net_dev来代表自己吧,就是softnet_data->backlog_dev。而softnet_data->input_pkt_queue.qlen为0时,说明没有包 挂到这里,也说明了没有设备(也就是softnet_data->backlog_dev)挂到poll_list上。

所以,当 有包的时候,要把backlog_dev挂上去,至于顺序,我觉得没有特别的要求。另外,你可以看一下process_backlog(),这个就是softnet_data->backlog_dev->poll()。

论坛徽章:
0
3 [报告]
发表于 2007-03-22 16:08 |只看该作者
原帖由 12013396 于 2007-3-22 15:48 发表于 2楼  
我觉得是因为netif_rx()并不像NAPI那样,driver把代表自己的net_dev挂到softnet_data->poll_list上,但它现在又是基于NAPI实现的了。那只好找个通用的net_dev来代表自己吧,就是softnet_data->backlog_de ...



现在想明白了,netif_rx_schedule(&queue->backlog_dev);是把backlog_dev挂到poll的队列上,并在netif_rx_action中调用这个队列的poll方法。
如下:

  1.         while (!list_empty(&queue->poll_list)) {
  2.                 struct net_device *dev;

  3.                 if (budget <= 0 || jiffies - start_time > 1)
  4.                         goto softnet_break;

  5.                 local_irq_enable();

  6.                 dev = list_entry(queue->poll_list.next,
  7.                                  struct net_device, poll_list);
  8.                 have = netpoll_poll_lock(dev);

  9.                 if (dev->quota <= 0 || dev->poll(dev, &budget)) {
  10.                         netpoll_poll_unlock(have);
  11.                         local_irq_disable();
  12.                         list_move_tail(&dev->poll_list, &queue->poll_list);
  13.                         if (dev->quota < 0)
  14.                                 dev->quota += dev->weight;
  15.                         else
  16.                                 dev->quota = dev->weight;
  17.                 } else {
  18.                         netpoll_poll_unlock(have);
  19.                         dev_put(dev);
  20.                         local_irq_disable();
  21.                 }
  22.         }
复制代码


如果if (dev->quota <= 0 || dev->poll(dev, &budget)) 完成了,cpu的skb队列就清空了,下次中断到来netif_rx_schedule(&queue->backlog_dev);还可以把自己加入到poll list中;如果没有完成,实际上backlog_dev还在队列中,也就没有必要再调用netif_rx_schedule(&queue->backlog_dev);了。

感觉应该是这样的。

论坛徽章:
0
4 [报告]
发表于 2007-03-25 09:25 |只看该作者
原帖由 bekars 于 2007-3-22 15:01 发表于 1楼  
2.6.18.6内核, net/core/dev.c

int netif_rx(struct sk_buff *skb)函数中有下面一段:

        
        local_irq_save(flags);
        queue = &__get_cpu_var(softnet_data);

        __ge ...


你想复杂了……

第一个包进来,此时qlen == 0,所以
           netif_rx_schedule(&queue->backlog_dev);
被调用,它完成两个重要的作用:
1、注册伪设备backlog_dev,调用其poll函数——这样做,主要是为了与NAPI兼容,大家都poll
2、激活dev的init中被安装的软中段将被激活,这样,消费者将被设置,执行队列的出队操作。

紧接着,goto一下,把这个包入队;
                goto enqueue;

可以想像,消费者是一个软中断,它的优先级低与硬中断,也就是会被硬中断中断掉,于是下一个包进来,驱动程序触发中断,再调用netif_rx,这个时候,你说的那个if(qlen)就成立了,于是执行生产者的动作:入队;

于是这边生产,那边消费,生生不息,循环不止……

论坛徽章:
0
5 [报告]
发表于 2007-03-26 09:07 |只看该作者
应是若本CPU负载很轻,先进行网卡硬件的接收,然后再处理软中断.

论坛徽章:
0
6 [报告]
发表于 2007-03-26 09:39 |只看该作者

回复 #5 AIXHP 的帖子

这跟CPU负载有什么关系??
硬中断优先级比软中断高,这就是全部

论坛徽章:
0
7 [报告]
发表于 2007-03-26 12:48 |只看该作者
应是若本CPU负载很轻,----- 先处理其它CPU的软中断的队列数据的处理,然后再处理本次的skb挂入队列,达到网络负载平衡.

[ 本帖最后由 AIXHP 于 2007-3-26 12:50 编辑 ]

论坛徽章:
0
8 [报告]
发表于 2007-06-01 11:57 |只看该作者
skb入队列之后呢?
我看sys_accept呢,发现直接从sk->accept_queue里边拿到sock
可是这个accept_queue什么时候建造的呢?

skb由netif_rx加入到sk_bff_head队列里边, 然后由谁来处理呢?

[ 本帖最后由 anhongkui 于 2007-6-1 11:59 编辑 ]

论坛徽章:
0
9 [报告]
发表于 2007-06-01 12:56 |只看该作者
上边明白了, 使用softirq

但是netif_rx添加到__get_cpu_var(softnet_data).poll_list的伪设备__get_cpu_var(soft_data).backlog_dev
不明白是什么意思??
非常迷惑

[ 本帖最后由 anhongkui 于 2007-6-1 14:00 编辑 ]
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP