初学者也能看懂的DPDK解析( 二 )


2.Netmap仍然依赖中断通知机制 , 没完全解决瓶颈 。
3.Netmap更像是几个系统调用 , 实现用户态直接收发包 , 功能太过原始 , 没形成依赖的网络开发框架 , 社区不完善 。
那么 , 我们来看看发展了十几年的DPDK , 从Intel主导开发 , 到华为、思科、AWS等大厂商的加入 , 核心玩家都在该圈子里 , 拥有完善的社区 , 生态形成闭环 。早期 , 主要是传统电信领域3层以下的应用 , 如华为、中国电信、中国移动都是其早期使用者 , 交换机、路由器、网关是主要应用场景 。但是 , 随着上层业务的需求以及DPDK的完善 , 在更高的应用也在逐步出现 。
DPDK旁路原理:

初学者也能看懂的DPDK解析

文章插图
图片引自Jingjing Wu的文档《Flow Bifurcation on Intel® Ethe
左边是原来的方式数据从 网卡 -> 驱动 -> 协议栈 -> Socket接口 -> 业务
右边是DPDK的方式 , 基于UIO(Userspace I/O)旁路数据 。数据从 网卡 -> DPDK轮询模式-> DPDK基础库 -> 业务
用户态的好处是易用开发和维护 , 灵活性好 。并且Crash也不影响内核运行 , 鲁棒性强 。
DPDK支持的CPU体系架构:x86、ARM、PowerPC(PPC)
DPDK支持的网卡列表:https://core.dpdk.org/supported/ , 我们主流使用Intel 82599(光口)、Intel x540(电口)
关注 , 后台私信【Linux】免费试听前五节 。
四、DPDK的基石UIO
为了让驱动运行在用户态 , Linux提供UIO机制 。使用UIO可以通过read感知中断 , 通过mmap实现和网卡的通讯 。
UIO原理:
初学者也能看懂的DPDK解析

文章插图
 
要开发用户态驱动有几个步骤:
1.开发运行在内核的UIO模块 , 因为硬中断只能在内核处理
2.通过/dev/uioX读取中断
3.通过mmap和外设共享内存
五、DPDK核心优化:PMD
DPDK的UIO驱动屏蔽了硬件发出中断 , 然后在用户态采用主动轮询的方式 , 这种模式被称为PMD(Poll Mode Driver) 。
UIO旁路了内核 , 主动轮询去掉硬中断 , DPDK从而可以在用户态做收发包处理 。带来Zero Copy、无系统调用的好处 , 同步处理减少上下文切换带来的Cache Miss 。
运行在PMD的Core会处于用户态CPU100%的状态
初学者也能看懂的DPDK解析

文章插图
 
网络空闲时CPU长期空转 , 会带来能耗问题 。所以 , DPDK推出Interrupt DPDK模式 。
Interrupt DPDK:
初学者也能看懂的DPDK解析

文章插图
 
图片引自David Su/Yunhong Jiang/Wei Wang的文档《Towards Low Latency Interrupt Mode DPDK》
它的原理和NAPI很像 , 就是没包可处理时进入睡眠 , 改为中断通知 。并且可以和其他进程共享同个CPU Core , 但是DPDK进程会有更高调度优先级 。
六、DPDK的高性能代码实现
1. 采用HugePage减少TLB Miss
默认下Linux采用4KB为一页 , 页越小内存越大 , 页表的开销越大 , 页表的内存占用也越大 。CPU有TLB(Translation Lookaside Buffer)成本高所以一般就只能存放几百到上千个页表项 。如果进程要使用64G内存 , 则64G/4KB=16000000(一千六百万)页 , 每页在页表项中占用16000000 * 4B=62MB 。如果用HugePage采用2MB作为一页 , 只需64G/2MB=2000 , 数量不在同个级别 。
而DPDK采用HugePage , 在x86-64下支持2MB、1GB的页大小 , 几何级的降低了页表项的大小 , 从而减少TLB-Miss 。并提供了内存池(Mempool)、MBuf、无锁环(Ring)、Bitmap等基础库 。根据我们的实践 , 在数据平面(Data Plane)频繁的内存分配释放 , 必须使用内存池 , 不能直接使用rte_malloc , DPDK的内存分配实现非常简陋 , 不如ptmalloc 。
2. SNA(Shared-nothing Architecture)
软件架构去中心化 , 尽量避免全局共享 , 带来全局竞争 , 失去横向扩展的能力 。NUMA体系下不跨Node远程使用内存 。
3. SIMD(Single Instruction Multiple Data)
从最早的mmx/sse到最新的avx2 , SIMD的能力一直在增强 。DPDK采用批量同时处理多个包 , 再用向量编程 , 一个周期内对所有包进行处理 。比如 , memcpy就使用SIMD来提高速度 。


推荐阅读