一.网络设备转发报文
网络设备(路由器、交换机、媒体网关、SBC、PS网关等)需要在瞬间进行大量的报文收发,因此在传统的网络设备上,往往能够看到专门的NP(Network Process)处理器,有的用FPGA,有的用ASIC。这些专用器件通过内置的硬件电路(或通过编程形成的硬件电路)高效转发报文,只有需要对报文进行深度处理的时候才需要CPU干涉。
二.实际应用场景中遇到网络报文转发时的性能瓶颈
但在公有云、NFV等应用场景下,基础设施以CPU为运算核心,往往不具备专用的 NP 处理器,操作系统也以通用 Linux 为主,网络数据包的收发处理路径如下图所示:
在虚拟化环境中,路径则会更长
由于包处理任务存在内核态与用户态的切换,以及多次的内存拷贝,系统消耗变大,以CPU为核心的系统存在很大的处理瓶颈。为了提升在通用服务器(COTS)的数据包处理效能,Intel推出了服务于IA(Intel Architecture)系统的DPDK技术。
三.DPDK原理解释
DPDK 是 Data Plane Development Kit的缩写。简单说,DPDK 应用程序运行在操作系统的 User Space,利用自身提供的数据平面库来收发包处理,绕过了 Linux 内核协议栈对数据包处理过程,以提升报文处理效率。
DPDK是一组lib库和工具包的集合。最简单的架构描述如下图所示:
上图蓝色部分是DPDK的主要组件(更全面更权威的DPDK架构可以参考Intel官网),简单解释一下:
- PMD:Pool Mode Driver,轮询模式驱动,通过非中断,以及数据帧进出应用缓冲区内存的零拷贝机制,提高发送/接受数据帧的效率
- 流分类:Flow Classification,为N元组匹配和LPM(最长前缀匹配)提供优化的查找算法
- 环队列:Ring Queue,针对单个或多个数据包生产者、单个数据包消费者的出入队列提供无锁机制,有效减少系统开销
- MBUF缓冲区管理:分配内存创建缓冲区,并通过建立MBUF对象,封装实际数据帧,供应用程序使用
- EAL:Environment Abstract Layer,环境抽象(适配)层,PMD初始化、CPU内核和DPDK线程配置/绑定、设置HugePage大页内存等系统初始化
DPDK拦截中断,不触发后续中断流程,并绕过协议栈,通过UIO技术将网卡收到的报文拷贝到应用层处理,报文不再经过内核协议栈。减少了中断,DPDK的包全部在用户控件使用内存池管理,内核控件与用户空间的内存交互不用进行拷贝,只做控制权转移,减少报文拷贝过程,提高报文的转发效率。
DPDK核心技术如下:
(1)通过UIO技术将报文拷贝到应用空间处理
(2)通过大页内存,降低cache miss ,提高命中率,进而cpu访问速度
(3)通过CPU亲和性,绑定网卡和线程到固定的core,减少cpu任务切换
(4)通过无锁队列,减少资源竞争
这么说可能还有一点点抽象,再总结一下DPDK的核心思想:
- 用户态模式的PMD驱动,去除中断,避免内核态和用户态内存拷贝,减少系统开销,从而提升I/O吞吐能力
- 用户态有一个好处,一旦程序崩溃,不至于导致内核完蛋,带来更高的健壮性
- HugePage,通过更大的内存页(如1G内存页),减少TLB(Translation Lookaside Buffer,即快表) Miss,Miss对报文转发性能影响很大
- 多核设备上创建多线程,每个线程绑定到独立的物理核,减少线程调度的开销。同时每个线程对应着独立免锁队列,同样为了降低系统开销
- 向量指令集,提升CPU流水线效率,降低内存等待开销
下图简单描述了DPDK的多队列和多线程机制:
DPDK将网卡接收队列分配给某个CPU核,该队列收到的报文都交给该核上的DPDK线程处理。存在两种方式将数据包发送到接收队列之上:
- RSS(Receive Side Scaling,接收方扩展)机制:根据关键字,比如根据UDP的四元组<srcIP><dstIP><srcPort><dstPort>进行哈希
- Flow Director机制:可设定根据数据包某些信息进行精确匹配,分配到指定的队列与CPU核
当网络数据包(帧)被网卡接收后,DPDK 网卡驱动将其存储在一个高效缓冲区中,并在MBUF缓存中创建MBUF对象与实际网络包相连,对网络包的分析和处理都会基于该MBUF,必要的时候才会访问缓冲区中的实际网络包