当前位置:   article > 正文

Linux数据包NAPI处理流程_非nap适用

非nap适用

Linux数据包NAPI处理流程

1. 概念

  1. NAPI:linux新的网卡数据包处理API,采用新的数据包处理流程。
  2. round-robin:轮询调度调度算法。
  3. 硬中断:由外设产生,主要是用来通知通过操作系统外设发生变化。比如当网卡收到数据包的时候,就会产生一个硬中断。
  4. 软中断:为了满足实时性需要,中断处理应该是越快越好,当中断发生时,硬中断处理那些用时间短的工作,而时间较长的任务放在硬中断之后处理,也就是有软中断完成。软中断是有系统调用中断指令产生的,不是硬件设备触发的。

2. 非NAPI与NAP处理流程的区别

非NAPI的数据包处理流程:采用的是中断方式,即网卡收到数据包就触发一个中断,然后交由中断处理程序进行处理。

  • 优势:响应及时,如果数据量较小,则不会占用太多的CPU事件。

  • 劣势:数据量大时,会产生过多中断,而每个中断都要消耗不少的CPU时间。

NAPI的数据包处理流程:采用的是综合中断方式和轮询方式。即,当网卡收到一个数据包时,产生一个中断,触发中断处理函数,NAPI方式中断处理函数会关闭中断,然后通过驱动

  • 优势:数据量大或者数据量小的时候,使用中断或者轮询的方式,数据包处理效率都非常高。

  • 劣势:数据流量不稳定时,则NAPI则会在两种方式切换上消耗不少时间,效率反而较低一些。对于上层应用来说,系统不能在接收到每个数据包时可以及时的去处理,随着传输速度的增加,累计的数据包将耗费大量内存;另外采用NAPI所造成的另一个问题就是对大的数据包处理比较困难,原因是大包处理更费时。NAPI技术适用于高速率的短数据包的处理。

3. NAPI处理数据包流程图

  1. 网卡收包产生中断,调用驱动处理函数,驱动处理函数会根据网络设备是否支持NAPI调用不通的内核处理函数,netif_rx和napi_schedule为内核入口函数。

  2. enqueue_to_backlog和__napi_schedule都通过____napi_schedule函数(通过调用__raise_softirq_irqoff(NET_RX_SOFTIRQ))激触发软中断,但是区别是加入poll_list的回调函数不同,enqueue_to_backlog的回调函数为process_backlog,而__napi_schedule的回调函数为napi_struct中的poll函数,该方法由驱动提供,在通过netif_napi_add加入napi_struct时制定。

netif_rx

netif_rx是内核接收数据包的入口。

/**
 *  netif_rx    -   post buffer to the network code
 *  @skb: buffer to post
 *
 *  This function receives a packet from a device driver and queues it for
 *  the upper (protocol) levels to process.  It always succeeds. The buffer
 *  may be dropped during processing for congestion control or by the
 *  protocol layers.
 *
 *  return values:
 *  NET_RX_SUCCESS  (no congestion)
 *  NET_RX_DROP     (packet was dropped)
 *
 */

int netif_rx(struct sk_buff *skb)
{
    int ret;

    /* if netpoll wants it, pretend we never saw it */
    if (netpoll_rx(skb))
        return NET_RX_DROP;

    if (netdev_tstamp_prequeue)
        net_timestamp_check(skb);

    trace_netif_rx(skb);
#ifdef CONFIG_RPS
    {
        struct rps_dev_flow voidflow, *rflow = &voidflow;
        int cpu;

        preempt_disable();
        rcu_read_lock();

        cpu = get_rps_cpu(skb->dev, skb, &rflow);
        if (cpu < 0)
            cpu = smp_processor_id();

        ret = enqueue_to_backlog(skb, cpu, &rflow->last_qtail);

        rcu_read_unlock();
        preempt_enable();
    }
#else
    {
        unsigned int qtail;
        ret = enqueue_to_backlog(skb, get_cpu(), &qtail);
        put_cpu();
    }
#endif
    return ret;
}
EXPORT_SYMBOL(netif_rx);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54

napi_schedule

在网卡驱动的中断处理函数中调用napi_schedule来使用NAPI

/**
 *  napi_schedule - schedule NAPI poll
 *  @n: napi context
 *
 * Schedule NAPI poll routine to be called if it is not already
 * running.
 */
static inline void napi_schedule(struct napi_struct *n)
{
    if (napi_schedule_prep(n))
        __napi_schedule(n);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

参考:

数据包接收系列 — NAPI的原理和实现

软中断(softirq)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/252934
推荐阅读
相关标签
  

闽ICP备14008679号