Linux数据包NAPI处理流程

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);

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);
}

参考:

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

软中断(softirq)

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值