热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

dpdkkni,dpdkkni性能报告

DPDK是一个优秀的收发包kit,但它本身并不提供用户态协议栈,因此由将数据报文注入内核协议栈的需求,也就是KNI(KernelNICInterface)。作为用户态和内核的接口,

DPDK是一个优秀的收发包kit,但它本身并不提供用户态协议栈,因此由将数据报文注入内核协议栈的需求,也就是KNI(Kernel NIC Interface)。作为用户态和内核的接口,其因为没有系统调用和内存拷贝,因此比传统的tun/tap设备要更高效。

借用DPDK文档的一个KNI的结构图。

 

图1. kni结构图

毫无疑问,KNI必然要也需要内核模块的支持,即rte_kni.ko。其共有三个参数,分别是lo_mode,kthread_mode和carrier。

lo_mode可配置为lo_mode_none,lo_mode_fifo,和lo_mode_fifo_skb,默认为lo_mode_none。另外两个在实际产品中基本不会用到。

kthread_mode可配置为single和multiple,默认为single。

carrier可配置为off和on,默认为off。

模块初始化函数kni_init也非常简单。除了解析上面的参数配置外,比较重要的就是注册misc设备和配置lo_mode。

 

图2. kni_init

图3. kni_net_config_lo_mode

配置lo_mode,函数指针kni_net_rx_func指向不同的函数,默认是kni_net_rx_func。

通过register_pernet_subsys或者register_pernet_gen_subsys,注册了kni_net_ops,保证每个namespace都会调用kni_init_net进行初始化(初始化动作在此不介绍了)。

注册为misc设备后,其工作机制由注册的miscdevice决定,即

 

图4. kni_misc

先看open函数kni_open,

 

图5. kni_open

代码非常简单,检查保证一个namespace只能打开kni一次,打开后将kni基于namespace的私有数据赋值给打开的文件file->private_data,以便后面使用。

DPDK在初始化阶段会调用rte_kni_init,打开kni设备。

 

图6. rte_kni_init

如何使用kni设备呢?内核的kni模块,提供了ioctl的支持。

 

图7. kni_ioctl

一共两个有效的option,RTE_KNI_IOCTL_CREATE和RTE_KNI_IOCTL_RELEASE,分别对应DPDK用户态的rte_kni_alloc和rte_kni_release,即申请kni interface和释放kni interface。

在rte_kni_alloc中,关键的代码是kni_reserve_mz申请连续的物理内存,并用其作为各个ring。

图8. rte_kni_alloc

而在kni的内核实现中,

图9. kni_ioctl_create

通过phys_to_virt将ring的物理地址转成虚拟地址使用,这样就保证了KNI的用户态和内核态使用同一片物理地址,从而做到零拷贝。

然后就是注册是netdev,启动内核接收线程。

图10. kni_ioctl_create

进入kni_run_thread,

 

图11. kni_run_thread

如果KNI模块的参数指定了多线程模式,每创建一个kni设备,就创建一个内核线程。如果为单线程模式,则检查是否已经启动了kni_thread。没有的话,创建唯一的kni内核thread kni_single,有的话,则什么都不做。

不失一般性,可以看kni_thread_single的实现。

图12. kni_thread_single

在持有读锁的情况下,遍历所有的kni设备,执行接收动作。这时,根据rte_kni.ko加载时的模块参数lo_mode

的值不同,执行不同的动作。只关心实际使用的lo_mode_none模式,其处理函数为:

图13. kni_net_rx_normal(1)

检查释放队列是否还有空位,没有的话,意味着读取后的数据无法增加到释放队列,故直接返回。

从kni->rx_q读取数据到kni->pa中。没有任何报文,则直接返回。

图14. kni_net_rx_normal(2)

循环处理收到的kni数据,将数据复制到申请的skb中。

图15. kni_net_rx_normal(3)

设置skb相关参数,调用netif_rx_ni将skb传给内核协议栈处理。最后把读取的数据追加到释放队列中。

这是DPDK app向KNI设备写入数据,也就是发给内核的情况。当内核从KNI设备发送数据时,按照内核的流程处理,最终会调用到net_device_ops->ndo_start_xmit。对于KNI驱动来说,即kni_net_tx。

 

图16. kni_net_tx(1)

对skb报文长度做检查,不能超过mbuf的大小。然后检查发送队列tx_q是否还有空位,“内存队列”是否有剩余的mbuf。

 

图17. kni_net_tx(2)

从alloc_q取出一个内存块,将其转换为虚拟地址,然后将skb的数据复制过去,最后将其追加到发送队列tx_q中。

图18. kni_net_tx(3)

发送完成后,就直接释放skb并更新统计计数。

以上,是KNI在内核部分的实现,下面看看DPDK应用层如何使用KNI接口。DPDK提供了两个API rte_kni_rx_burst和rte_kni_tx_burst,用于从KNI接收报文和向KNI发送报文。

 

图19. rte_kni_rx_burst

接收报文时,从kni->tx_q直接取走所有报文。前面内核用KNI发送报文时,填充的就是这个fifo。当取走了报文后,DPDK应用层的调用kni_allocate_mbufs,负责给tx_q填充空闲mbuf,供内核使用。

rte_kni_tx_burst流程也很简单。

图20. rte_kni_tx_burst

先将要发送给KNI的报文地址转换为物理地址,然后enqueue到kni->rx_q中(内核的KNI实现也是从这个fifo中读取报文),最后调用kni_free_mbufs释放掉内核处理完的mbuf报文。

至此,DPDK的KNI原理分析完毕。


推荐阅读
  • 深入解析Android 4.4中的Fence机制及其应用
    在Android 4.4中,Fence机制是处理缓冲区交换和同步问题的关键技术。该机制广泛应用于生产者-消费者模式中,确保了不同组件之间高效、安全的数据传输。通过深入解析Fence机制的工作原理和应用场景,本文探讨了其在系统性能优化和资源管理中的重要作用。 ... [详细]
  • 在Linux系统中,网络配置是至关重要的任务之一。本文详细解析了Firewalld和Netfilter机制,并探讨了iptables的应用。通过使用`ip addr show`命令来查看网卡IP地址(需要安装`iproute`包),当网卡未分配IP地址或处于关闭状态时,可以通过`ip link set`命令进行配置和激活。此外,文章还介绍了如何利用Firewalld和iptables实现网络流量控制和安全策略管理,为系统管理员提供了实用的操作指南。 ... [详细]
  • Java Socket 关键参数详解与优化建议
    Java Socket 的 API 虽然被广泛使用,但其关键参数的用途却鲜为人知。本文详细解析了 Java Socket 中的重要参数,如 backlog 参数,它用于控制服务器等待连接请求的队列长度。此外,还探讨了其他参数如 SO_TIMEOUT、SO_REUSEADDR 等的配置方法及其对性能的影响,并提供了优化建议,帮助开发者提升网络通信的稳定性和效率。 ... [详细]
  • C++ 异步编程中获取线程执行结果的方法与技巧及其在前端开发中的应用探讨
    本文探讨了C++异步编程中获取线程执行结果的方法与技巧,并深入分析了这些技术在前端开发中的应用。通过对比不同的异步编程模型,本文详细介绍了如何高效地处理多线程任务,确保程序的稳定性和性能。同时,文章还结合实际案例,展示了这些方法在前端异步编程中的具体实现和优化策略。 ... [详细]
  • 手指触控|Android电容屏幕驱动调试指南
    手指触控|Android电容屏幕驱动调试指南 ... [详细]
  • 在CentOS 7环境中安装配置Redis及使用Redis Desktop Manager连接时的注意事项与技巧
    在 CentOS 7 环境中安装和配置 Redis 时,需要注意一些关键步骤和最佳实践。本文详细介绍了从安装 Redis 到配置其基本参数的全过程,并提供了使用 Redis Desktop Manager 连接 Redis 服务器的技巧和注意事项。此外,还探讨了如何优化性能和确保数据安全,帮助用户在生产环境中高效地管理和使用 Redis。 ... [详细]
  • 本文是Java并发编程系列的开篇之作,将详细解析Java 1.5及以上版本中提供的并发工具。文章假设读者已经具备同步和易失性关键字的基本知识,重点介绍信号量机制的内部工作原理及其在实际开发中的应用。 ... [详细]
  • 在Linux系统中避免安装MySQL的简易指南
    在Linux系统中避免安装MySQL的简易指南 ... [详细]
  • 基于Net Core 3.0与Web API的前后端分离开发:Vue.js在前端的应用
    本文介绍了如何使用Net Core 3.0和Web API进行前后端分离开发,并重点探讨了Vue.js在前端的应用。后端采用MySQL数据库和EF Core框架进行数据操作,开发环境为Windows 10和Visual Studio 2019,MySQL服务器版本为8.0.16。文章详细描述了API项目的创建过程、启动步骤以及必要的插件安装,为开发者提供了一套完整的开发指南。 ... [详细]
  • 本文介绍了如何利用Shell脚本高效地部署MHA(MySQL High Availability)高可用集群。通过详细的脚本编写和配置示例,展示了自动化部署过程中的关键步骤和注意事项。该方法不仅简化了集群的部署流程,还提高了系统的稳定性和可用性。 ... [详细]
  • 本文介绍了如何利用Struts1框架构建一个简易的四则运算计算器。通过采用DispatchAction来处理不同类型的计算请求,并使用动态Form来优化开发流程,确保代码的简洁性和可维护性。同时,系统提供了用户友好的错误提示,以增强用户体验。 ... [详细]
  • 在Cisco IOS XR系统中,存在提供服务的服务器和使用这些服务的客户端。本文深入探讨了进程与线程状态转换机制,分析了其在系统性能优化中的关键作用,并提出了改进措施,以提高系统的响应速度和资源利用率。通过详细研究状态转换的各个环节,本文为开发人员和系统管理员提供了实用的指导,旨在提升整体系统效率和稳定性。 ... [详细]
  • 本指南介绍了如何在ASP.NET Web应用程序中利用C#和JavaScript实现基于指纹识别的登录系统。通过集成指纹识别技术,用户无需输入传统的登录ID即可完成身份验证,从而提升用户体验和安全性。我们将详细探讨如何配置和部署这一功能,确保系统的稳定性和可靠性。 ... [详细]
  • 如何利用Java 5 Executor框架高效构建和管理线程池
    Java 5 引入了 Executor 框架,为开发人员提供了一种高效管理和构建线程池的方法。该框架通过将任务提交与任务执行分离,简化了多线程编程的复杂性。利用 Executor 框架,开发人员可以更灵活地控制线程的创建、分配和管理,从而提高服务器端应用的性能和响应能力。此外,该框架还提供了多种线程池实现,如固定线程池、缓存线程池和单线程池,以适应不同的应用场景和需求。 ... [详细]
  • 2012年9月12日优酷土豆校园招聘笔试题目解析与备考指南
    2012年9月12日,优酷土豆校园招聘笔试题目解析与备考指南。在选择题部分,有一道题目涉及中国人的血型分布情况,具体为A型30%、B型20%、O型40%、AB型10%。若需确保在随机选取的样本中,至少有一人为B型血的概率不低于90%,则需要选取的最少人数是多少?该问题不仅考察了概率统计的基本知识,还要求考生具备一定的逻辑推理能力。 ... [详细]
author-avatar
清潇静凌
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有