概述

NAPI是linux新的网卡数据处理API,据说是由于找不到更好的名字,所以就叫NAPI(New API),在2.5之后引入。

简单来说,NAPI是综合中断方式与轮询方式的技术。

中断的好处是响应及时,如果数据量较小,则不会占用太多的CPU事件;缺点是数据量大时,会产生过多中断,而每个中断都要消耗不少的CPU时间,从而导致效率反而不如轮询高。轮询方式与中断方式相反,它更适合处理大量数据,因为每次轮询不需要消耗过多的CPU时间;缺点是即使只接收很少数据或不接收数据时,也要占用CPU时间。

NAPI是两者的结合,数据量低时采用中断,数据量高时采用轮询。平时是中断方式,当有数据到达时,会触发中断处理函数执行,中断处理函数关闭中断开始处理。如果此时有数据到达,则没必要再触发中断了,因为中断处理函数中会轮询处理数据,直到没有新数据时才打开中断。

很明显,数据量很低与很高时,NAPI可以发挥中断与轮询方式的优点,性能较好。如果数据量不稳定,且说高不高说低不低,则NAPI则会在两种方式切换上消耗不少时间,效率反而较低一些。

实现

来看下NAPI和非NAPI的区别:

  • 支持NAPI的网卡驱动必须提供轮询方法poll()。
  • 非NAPI的内核接口为netif_rx(),NAPI的内核接口为napi_schedule()。
  • 非NAPI使用共享的CPU队列softnet_data->input_pkt_queue,NAPI使用设备内存(或者设备驱动程序的接收环)。

1、NAPI设备结构

/* Structure for NAPI scheduling similar to tasklet but with weighting */struct napi_struct {/* The poll_list must only be managed by the entity which changes the* state of the NAPI_STATE_SCHED bit. This means whoever atomically* sets that bit can add this napi_struct to the per-cpu poll_list, and* whoever clears that bit can remove from the list right before clearing the bit.*/struct list_head poll_list; /* 用于加入处于轮询状态的设备队列 */unsigned long state; /* 设备的状态 */int weight; /* 每次处理的最大数量,非NAPI默认为64 */int (*poll) (struct napi_struct *, int); /* 此设备的轮询方法,非NAPI为process_backlog() */#ifdef CONFIG_NETPOLL...
#endifunsigned int gro_count;struct net_device *dev;struct list_head dev_list;struct sk_buff *gro_list;struct sk_buff *skb;
};

2、初始化

初始napi_struct实例。

void netif_napi_add(struct net_device *dev, struct napi_struct *napi,int (*poll) (struct napi_struct *, int), int weight)
{INIT_LIST_HEAD(&napi->poll_list);napi->gro_count = 0;napi->gro_list = NULL;napi->skb = NULL;napi->poll = poll; /* 设备的poll函数 */napi->weight = weight; /* 设备每次poll能处理的数据包个数上限 */list_add(&napi->dev_list, &dev->napi_list); /* 加入设备的napi_list */napi->dev = dev; /* 所属设备 */#ifdef CONFIG_NETPOLLspin_lock_init(&napi->poll_lock);napi->poll_owner = -1;
#endifset_bit(NAPI_STATE_SCHED, &napi->state); /* 设置NAPI标志位 */
}

3、调度

在网卡驱动的中断处理函数中调用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)
{/* 判断是否可以调度NAPI */if (napi_schedule_prep(n))__napi_schedule(n);
}

判断NAPI是否可以调度。如果NAPI没有被禁止,且不存在已被调度的NAPI,则允许调度NAPI,因为同一时刻只允许有一个NAPI poll instance。

/*** napi_schedule_prep - check if napi can be scheduled* @n: napi context* Test if NAPI routine is already running, and if not mark it as running.* This is used as a condition variable insure only one NAPI poll instance runs.* We also make sure there is no pending NAPI disable.*/static inline int napi_schedule_prep(struct napi_struct *n)
{return !napi_disable_pending(n) && !test_and_set_bit(NAPI_STATE_SCHED, &n->state);
}static inline int napi_disable_pending(struct napi_struct *n)
{return test_bit(NAPI_STATE_DISABLE, &n->state);
} enum {NAPI_STATE_SCHED, /* Poll is scheduled */NAPI_STATE_DISABLE, /* Disable pending */NAPI_STATE_NPSVC, /* Netpoll - don't dequeue from poll_list */
};

NAPI的调度函数。把设备的napi_struct实例添加到当前CPU的softnet_data的poll_list中,

以便于接下来进行轮询。然后设置NET_RX_SOFTIRQ标志位来触发软中断。

void __napi_schedule(struct napi_struct *n)
{unsigned long flags;local_irq_save(flags);____napi_schedule(&__get_cpu_var(softnet_data), n);local_irq_restore(flags);
}static inline void ____napi_schedule(struct softnet_data *sd, struct napi_struct *napi)
{/* 把napi_struct添加到softnet_data的poll_list中 */list_add_tail(&napi->poll_list, &sd->poll_list);__raise_softirq_irqoff(NET_RX_SOFTIRQ); /* 设置软中断标志位 */
}

4、轮询方法

NAPI方式中的POLL方法由驱动程序提供,在通过netif_napi_add()加入napi_struct时指定。

在驱动的poll()中,从自身的队列中获取sk_buff后,如果网卡开启了GRO,则会调用napi_gro_receive()处理skb,否则直接调用netif_receive_skb()。

POLL方法应该和process_backlog()大体一致,多了一些具体设备相关的部分。

5、非NAPI和NAPI处理流程对比

以下是非NAPI设备和NAPI设备的数据包接收流程对比图:

NAPI方式在上半部中sk_buff是存储在驱动自身的队列中的,软中断处理过程中驱动POLL方法调用

netif_receive_skb()直接处理skb并提交给上层。

/*** netif_receive_skb - process receive buffer from network* @skb: buffer to process* netif_receive_skb() is the main receive data processing function.* It always succeeds. The buffer may be dropped during processing* for congestion control or by the protocol layers.* This function may only be called from softirq context and interrupts* should be enabled.* Return values (usually ignored):* NET_RX_SUCCESS: no congestion* NET_RX_DROP: packet was dropped*/int netif_receive_skb(struct sk_buff *skb)
{/* 记录接收时间到skb->tstamp */if (netdev_tstamp_prequeue)net_timestamp_check(skb);if (skb_defer_rx_timestamp(skb))return NET_RX_SUCCESS;#ifdef CONFIG_RPS...
#elsereturn __netif_receive_skb(skb);
#endif
}

__netif_receive_skb()在上篇blog中已分析过了,接下来就是网络层来处理接收到的数据包了。

原文链接:https://blog.csdn.net/zhangskd/article/details/21627963

NAPI技术--原理和实现(一)相关推荐

  1. php 伪静态 page-18.html,PHP 伪静态实现技术原理讲解

    PHP 伪静态实现技术原理讲解 发布于 2015-01-18 23:52:58 | 129 次阅读 | 评论: 0 | 来源: 网友投递 PHP开源脚本语言PHP(外文名: Hypertext Pre ...

  2. 看了极光推送技术原理的几点思考

    看了极光推送技术原理的几点思考 分类: android2012-11-26 20:50 16586人阅读 评论(18) 收藏 举报 目录(?)[+] 移动互联网应用现状 因为手机平台本身.电量.网络流 ...

  3. 秋色园QBlog技术原理解析:性能优化篇:用户和文章计数器方案(十七)

    2019独角兽企业重金招聘Python工程师标准>>> 上节概要: 上节 秋色园QBlog技术原理解析:性能优化篇:access的并发极限及分库分散并发方案(十六)  中, 介绍了 ...

  4. 详解微信域名防封的方法以及检测等工具的技术原理

    微信域名完全防封是绝对不可能的,这是必须明确的,曾经有人打折<不死域名>的概念,它不是不死,是稍微命长一点,在推广上成本更低一下,效果更好一些, 主要的技术原理是利用了腾讯云的域名安全联盟 ...

  5. NLP实践:对话系统技术原理和应用

    本文节选自电子工业出版社<自然语言处理实践:聊天机器人技术原理与应用> 作者:王昊奋&邵浩&李方圆&张凯&宋亚楠 以下是节选内容 按照技术实现,我们可将任务 ...

  6. 范成法加工matlab_光学非球面技术原理与加工技术

    光学非球面的定义 广义来说,非球面是不包括球面和平面的其他表面.从应用的角度来说,非球面可以分成轴对称的非球面.具有两个对称面的非球面.没有对称性的自由曲面. 非球面分类 通常把非球面分成二次非球面和 ...

  7. 秋色园QBlog技术原理解析:性能优化篇:数据库文章表分表及分库减压方案(十五)...

    文章回顾: 1: 秋色园QBlog技术原理解析:开篇:整体认识(一) --介绍整体文件夹和文件的作用 2: 秋色园QBlog技术原理解析:认识整站处理流程(二) --介绍秋色园业务处理流程 3: 秋色 ...

  8. 计算机书籍- 聊天机器人技术原理与应用

    去天猫看看智能鼠标 书名: 自然语言处理实践:聊天机器人技术原理与应用 作者:王昊奋 等 出版社:电子工业出版社 出版时间:2019年02月

  9. Pacbio HiFi技术原理与应用软件实例

    Pacbio HiFi技术原理与应用软件实例 原创 生信技术 生信技术 2021-06-07 13:02 收录于话题 #基因组组装3个内容 #生物信息3个内容 #生信技术3个内容 点击上方蓝字关注我们 ...

最新文章

  1. 如何采用简化方法进行需求分析
  2. java map 查找_Map 查找表操作
  3. 初学swift笔记 枚举(七)
  4. 写给找工作的朋友——最典的面试葵花宝典
  5. 此网址已被限制 此网址使用了一个通常用于网络浏览以外目的的端口。出于安全原因,Firefox 取消了该请求。
  6. Python 标准库 —— urllib(下载进度)
  7. Java的switch是否支持String作为参数,还支持哪些类型?
  8. python和Java实现斐波那契Fibonacci数列
  9. 数据结构题集c语言版考试答案,数据结构题集(C语言版)答案.pdf
  10. macOS配置使用ODB
  11. 根据图片地址检查图片格式,今日头条有效
  12. 中国数据量占全球27.8%!安防能否借机“回血”?
  13. appium原理及api
  14. 用松鼠顺利地部署您的应用程序
  15. 自顶向下与自底向上的归并排序
  16. Linux C++ 网络库 Muduo
  17. win10自带的Edge浏览器打不开PDF文件和网页的解决方法
  18. redis 缓存 2023面试题总结
  19. Matplotlib 中 y 轴显示为百分比形式的方法
  20. Spring boot PageHelper.startPage(pageIndex, pageSize)分页无效

热门文章

  1. 2020年python工资一般多少钱-2020年Python发展前景如何呢?
  2. python基础语法有哪些-python基本语法有哪些?
  3. python资料下载-python电子书学习资料打包分享百度云资源下载
  4. python培训班 费用-参加线上python培训班要多少钱?
  5. python解释器运行代码-Python如何运行程序
  6. python面试-python简单面试题
  7. head first python 第二版 中文版-Head First Python 中文版
  8. python课程与c+课程有什么不同-南通渡课少儿编程:python和C的区别是什么?
  9. 风云编程python-首页
  10. python免费课程讲解-Python快速入门免费课程