• 网络数据包收发流程(二):不配置NAPI的情况


    一、no NAPI 数据结构

    不配置NAPI的时候,网络设备不使用自己的napi_struct结构,
    所有网络设备驱动都使用同一个napi_struct,即cpu私有变量__get_cpu_var(softnet_data).backlog

    每当收到数据包时,网络设备驱动会把__get_cpu_var(softnet_data).backlog挂到__get_cpu_var(softnet_data).poll_list上面。


    所以软中断里net_rx_action遍历cpu私有变量__get_cpu_var(softnet_data).poll_list时,
    上面挂的napi_struct只有一个

    二、内核启动时的准备工作

    也是在net_dev_init中,初始化了cpu私有变量的napi_struct,即所有网络设备驱动使用的napi_struct

    __init net_dev_init()
    {
        //每个CPU都有一个私有变量 _get_cpu_var(softnet_data)
        //
    _get_cpu_var(softnet_data).poll_list很重要,软中断中需要遍历它的

        for_each_possible_cpu(i) {
            struct softnet_data *queue;
            queue = &per_cpu(softnet_data, i);
            skb_queue_head_init(&queue->input_pkt_queue); // 不配置NAPI时,才使用这个接收队列
            queue->completion_queue = NULL;

            INIT_LIST_HEAD(&queue->poll_list);
            queue->backlog.poll = process_backlog;        // poll钩子函数初始化
            queue->backlog.weight = weight_p;             //

        }
        open_softirq(NET_TX_SOFTIRQ, net_tx_action, NULL); //在软中断上挂网络接收handler
        open_softirq(NET_RX_SOFTIRQ, net_rx_action, NULL); //在软中断上挂网络发送handler

    }

    三、中断里接受以太网包

    TSEC的接收中断处理函数

    gfar_receive

    {
        gfar_write(&priv->regs->ievent, IEVENT_RX_MASK);
    #ifdef CONFIG_GFAR_NAPI
        // test_and_set当前net_device的napi_struct.state 为 NAPI_STATE_SCHED
        // 在软中断里调用 net_rx_action 会检查状态 napi_struct.state
        if (netif_rx_schedule_prep(dev, &priv->napi)) { 
            tempval = gfar_read(&priv->regs->imask);            
            tempval &= IMASK_RX_DISABLED;
            gfar_write(&priv->regs->imask, tempval);   
            // 将当前net_device的 napi_struct.poll_list 挂到
            // CPU私有变量 &__get_cpu_var(softnet_data).poll_list 上,并触发软中断
            // 所以,在软中断中调用 net_rx_action 的时候,就会执行当前net_device的
            // napi_struct.poll()钩子函数,即 gfar_poll()
            __netif_rx_schedule(dev, &priv->napi);  
        }

    #else
        gfar_clean_rx_ring(dev, priv->rx_ring_size);
    #endif
    }

    gfar_clean_rx_ring  
      
    -->gfar_process_frame 

          -->初始化了skb->dev,这样在软中断里才能判断这个数据包来自哪里
          -->RECEIVE(skb) // 调用netif_rx(skb)


    #ifdef CONFIG_GFAR_NAPI
    #define RECEIVE(x) netif_receive_skb(x)
    #else
    #define RECEIVE(x) netif_rx(x)
    #endif

    netif_rx(skb)
    {

       queue = &__get_cpu_var(softnet_data);
       __skb_queue_tail(&queue->input_pkt_queue, skb); //将skb放到接收队列(在net_dev_init初始化)中
       napi_schedule(&queue->backlog); //将cpu私有变量的的napi_struct挂到cpu私有变量的poll_list上
                                       //test_and_set napi_struct.state为 NAPI_STATE_SCHED
                                       //触发网络接收软中断
    }

    软中断net_rx_action中调用poll钩子函数

    虽说软中断里也遍历cpu私有变量的poll_list,事实上poll_list现在只挂一个napi_struct结构
    即cpu私有变量的backlog成员(它在net_dev_init中初始化),所以现在调用的poll钩子函数就是process_backlog了

    static int process_backlog(struct napi_struct *napi, int quota)
    {
        struct softnet_data *queue = &__get_cpu_var(softnet_data);
        napi->weight = weight_p;
        do {
            struct sk_buff *skb;
            struct net_device *dev;

            local_irq_disable();
            skb = __skb_dequeue(&queue->input_pkt_queue); //从接收队列中取出skb,
            if (!skb) {                                   //这些skb是在netif_rx中进入队列的
                __napi_complete(napi);
                local_irq_enable();
                break;
            }
            local_irq_enable();
            dev = skb->dev;
            netif_receive_skb(skb);     //进入协议协议栈
            dev_put(dev);
        } while (++work < quota && jiffies == start_time);
        return work;
    }

    转载自http://blog.chinaunix.net/uid-24148050-id-473352.html

  • 相关阅读:
    IDEA的database插件无法链接mysql的解决办法(08001错误)
    window.location.href传参/传值汇总
    toggleClass() 方法
    File file=new File ()
    MultipartFile接口
    @RequestParam注解字参数详解
    在微信下载的浏览器判断问题
    JS可控制的图片自动循环播放查看效果
    PHP接口的声明与引用
    js时间
  • 原文地址:https://www.cnblogs.com/CasonChan/p/5166224.html
Copyright © 2020-2023  润新知