前言
随着网络技术的不断发展,网络带宽越来越大,网络数据流量越来越大,为了匹配网络技术的发展,诞生了大量的网络方案。
1.传统的收发报文方式都必须采用硬中断来做通讯,每次硬中断大约消耗100微秒,这还不算因为终止上下文所带来的Cache Miss。
2.数据必须从内核态用户态之间切换拷贝带来大量CPU消耗,全局锁竞争。
3.收发包都有系统调用的开销。
4.内核工作在多核上,为可全局一致,即使采用Lock Free,也避免不了锁总线、内存屏障带来的性能损耗。
5.从网卡到业务进程,经过的路径太长,有些其实未必要的,例如netfilter框架,这些都带来一定的消耗,而且容易Cache Miss。
一、DPDK是什么?
DPDK(Data Plane Development kit 数据平面开发套件),它是完全内核旁路技术产生的,跨平台的数通方案。DPDK是一个开源的,快速处理数据及数据包转发的开发平台及接口,它们可以支持在 x86、POWER 和 ARM 处理器上运行。DPDK具备丰富的库,大量的开源代码,是现在在数通领域使用比较活跃的框架。
二、方案原理
目前主流的高速数据通信方案原理,基本都是通过把网卡的数据映射到用户空间,通过bypass 的方式,在用户态进行数据处理。把网口上的存储空间直接映射数据到用户空间。此方案可以充分发挥网卡的性能和功能,例如网卡的数据流性能,转发功能。目前流行的此类型的方案主要有: netmap, pf_ring, dpdk这三种方案。netmap 支持的库比较少,功能比较原始没有依赖网络开发框架并且社区不完善。pf_ring 是商业的版本。DPDK+vpp的方案,DPDK具备丰富的库和大量的开源项目,社区比较活跃。致使DPDK迅速流行起来,目前主要是DPDK+VPP方案是很多公司采用的方案。
通过内核的方式: 每一帧数据都是从网卡copy 到协议栈,从协议栈copy 到应用程序。进行两次拷贝。 没有发挥网卡本身的特色作用。
基于网卡的数据映射到用户层空间,netmap pf_ring dpdk;
DPDK 是一个底层框架,特点体现在如下三个方面:
1> 网卡数据映射到内存的方式多样; igb_uio vfio
2>内存数据回写内核,kni 机制方式。
3> 提供了丰富的资源,cpu 亲缘性,内存池,协议数据包,acl 等库丰富。
DPDK应用
0.DPDK原理
DPDK 如何把网卡数据映射到内存
首先断开网卡和内核的关联,ifconfig ethx down. 然后bind,把网卡和dpdk 进行绑定。
1.使用场景
- 数据转发处理,例如交换机,防火墙等。
- 数据存储;
- 虚拟化方面;
3.传统网络层和dpdk网络层区别
传统linux网络层:
硬件中断—>取包分发至内核线程—>软件中断—>内核线程在协议栈中处理包—>处理完毕通知用户层
用户层收包–>网络层—>逻辑层—>业务层
dpdk网络层:
硬件中断—>放弃中断流程
用户层通过设备映射取包—>进入用户层协议栈—>逻辑层—>业务层
2. DPDK 配置
1.逻辑核分配
注意:物理cpu 卡槽数=NUMA数目=socket数目
PCI简单的理解就是内存地址,网口对应的就是网口的私有内存空间。
[root@localhost]# lscpu Architecture: x86_64 CPU op-mode(s): 32-bit, 64-bit Byte Order: Little Endian CPU(s): 24 On-line CPU(s) list: 0-23 Thread(s) per core: 2 Core(s) per socket: 6 座: 2 NUMA 节点: 2 厂商 ID: GenuineIntel CPU 系列: 6 型号: 63 型号名称: Intel(R) Xeon(R) CPU E5-2620 v3 @ 2.40GHz 步进: 2 CPU MHz: 1200.000 CPU max MHz: 3200.0000 CPU min MHz: 1200.0000 BogoMIPS: 4799.88 虚拟化: VT-x L1d 缓存: 32K L1i 缓存: 32K L2 缓存: 256K L3 缓存: 15360K NUMA 节点0 CPU: 0-5,12-17 NUMA 节点1 CPU: 6-11,18-23 Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf eagerfpu pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm epb invpcid_single intel_ppin ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid cqm xsaveopt cqm_llc cqm_occup_llc dtherm ida arat pln pts md_clear spec_ctrl intel_stibp flush_l1d NUMA 节点0 CPU: 0-5,12-17 NUMA 节点1 CPU: 6-11,18-23 此处是描述CPU核的亲缘性, 0-5,12-17 是和NUMA0=cpu0=socket0 是亲缘的, 在进行网卡绑定的时候注意逻辑核心的亲缘性。
[root@localhost]# lspci 00:00.0 Host bridge: Intel Corporation Xeon E7 v3/Xeon E5 v3/Core i7 DMI2 (rev 02) 00:01.0 PCI bridge: Intel Corporation Xeon E7 v3/Xeon E5 v3/Core i7 PCI Express Root Port 1 (rev 02) 00:02.0 PCI bridge: Intel Corporation Xeon E7 v3/Xeon E5 v3/Core i7 PCI Express Root Port 2 (rev 02) 00:02.2 PCI bridge: Intel Corporation Xeon E7 v3/Xeon E5 v3/Core i7 PCI Express Root Port 2 (rev 02) 00:03.0 PCI bridge: Intel Corporation Xeon E7 v3/Xeon E5 v3/Core i7 PCI Express Root Port 3 (rev 02) [root@localhost ~]# lspci -s 00:03.0 -vv 00:03.0 PCI bridge: Intel Corporation Xeon E7 v3/Xeon E5 v3/Core i7 PCI Express Root Port 3 (rev 02) (prog-if 00 [Normal decode]) Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx+ Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx- Latency: 0, Cache Line Size: 64 bytes Interrupt: pin A routed to IRQ 30 NUMA node: 0 Bus: primary=00, secondary=04, subordinate=04, sec-latency=0 I/O behind bridge: 00005000-00005fff Memory behind bridge: c7100000-c74fffff Prefetchable memory behind bridge: 0000000090100000-00000000904fffff Secondary status: 66MHz- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort+ <SERR- <PERR- BridgeCtl: Parity- SERR- NoISA- VGA- MAbort- >Reset- FastB2B- PriDiscTmr- SecDiscTmr- DiscTmrStat- DiscTmrSERREn- Capabilities: [40] Subsystem: Super Micro Computer Inc Device 0932 Capabilities: [60] MSI: Enable+ Count=1/2 Maskable+ 64bit- Address: fee00378 Data: 0000 Masking: 00000002 Pending: 00000000 Capabilities: [90] Express (v2) Root Port (Slot+), MSI 00 DevCap: MaxPayload 256 bytes, PhantFunc 0 ExtTag- RBE+ DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported- RlxdOrd- ExtTag- PhantFunc- AuxPwr- NoSnoop- MaxPayload 256 bytes, MaxReadReq 128 bytes DevSta: CorrErr- UncorrErr- FatalErr- UnsuppReq- AuxPwr- TransPend- LnkCap: Port #7, Speed 8GT/s, Width x16, ASPM not supported, Exit Latency L0s <512ns, L1 <16us ClockPM- Surprise+ LLActRep+ BwNot+ ASPMOptComp+ LnkCtl: ASPM Disabled; RCB 64 bytes Disabled- CommClk+ ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt- LnkSta: Speed 5GT/s, Width x8, TrErr- Train- SlotClk+ DLActive+ BWMgmt+ ABWMgmt- SltCap: AttnBtn- PwrCtrl- MRL- AttnInd- PwrInd- HotPlug- Surprise+ Slot #5, PowerLimit 25.000W; Interlock- NoCompl- SltCtl: Enable: AttnBtn- PwrFlt- MRL- PresDet- CmdCplt- HPIrq- LinkChg- Control: AttnInd Off, PwrInd Off, Power- Interlock- SltSta: Status: AttnBtn- PowerFlt- MRL- CmdCplt- PresDet+ Interlock- Changed: MRL- PresDet- LinkState- RootCtl: ErrCorrectable- ErrNon-Fatal- ErrFatal- PMEIntEna+ CRSVisible+ RootCap: CRSVisible+ RootSta: PME ReqID 0000, PMEStatus- PMEPending- DevCap2: Completion Timeout: Range BCD, TimeoutDis+, LTR-, OBFF Not Supported ARIFwd+ DevCtl2: Completion Timeout: 50us to 50ms, TimeoutDis-, LTR-, OBFF Disabled ARIFwd+ LnkCtl2: Target Link Speed: 5GT/s, EnterCompliance- SpeedDis- Transmit Margin: Normal Operating Range, EnterModifiedCompliance- ComplianceSOS- Compliance De-emphasis: -6dB LnkSta2: Current De-emphasis Level: -6dB, EqualizationComplete-, EqualizationPhase1- EqualizationPhase2-, EqualizationPhase3-, LinkEqualizationRequest- Capabilities: [e0] Power Management version 3 Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA PME(D0+,D1-,D2-,D3hot+,D3cold+) Status: D0 NoSoftRst+ PME-Enable- DSel=0 DScale=0 PME- Capabilities: [100 v1] Vendor Specific Information: ID=0002 Rev=0 Len=00c <?> Capabilities: [110 v1] Access Control Services ACSCap: SrcValid+ TransBlk+ ReqRedir+ CmpltRedir+ UpstreamFwd+ EgressCtrl- DirectTrans- ACSCtl: SrcValid- TransBlk- ReqRedir- CmpltRedir- UpstreamFwd- EgressCtrl- DirectTrans- Capabilities: [148 v1] Advanced Error Reporting UESta: DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol- UEMsk: DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol- UESvrt: DLP+ SDES+ TLP- FCP+ CmpltTO- CmpltAbrt- UnxCmplt- RxOF+ MalfTLP+ ECRC- UnsupReq- ACSViol- CESta: RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr- CEMsk: RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr+ AERCap: First Error Pointer: 00, GenCap- CGenEn- ChkCap- ChkEn- Capabilities: [1d0 v1] Vendor Specific Information: ID=0003 Rev=1 Len=00a <?> Capabilities: [250 v1] #19 Capabilities: [280 v1] Vendor Specific Information: ID=0005 Rev=3 Len=018 <?> Capabilities: [300 v1] Vendor Specific Information: ID=0008 Rev=0 Len=038 <?> Kernel driver in use: pcieport [root@localhost]# cat /proc/iomem 7984c000-79d29fff : ACPI Non-volatile Storage 79d2a000-8fffffff : reserved 80000000-8fffffff : PCI MMCONFIG 0000 [bus 00-ff] 90000000-c7ffbfff : PCI Bus 0000:00 90000000-900fffff : PCI Bus 0000:03 90000000-9001ffff : 0000:03:00.0 90020000-9003ffff : 0000:03:00.0 90040000-9005ffff : 0000:03:00.1 90060000-9007ffff : 0000:03:00.1 90080000-9009ffff : 0000:03:00.2 900a0000-900bffff : 0000:03:00.2 900c0000-900dffff : 0000:03:00.3 900e0000-900fffff : 0000:03:00.3 90100000-904fffff : PCI Bus 0000:04 90100000-901fffff : 0000:04:00.0 90200000-902fffff : 0000:04:00.0 90300000-903fffff : 0000:04:00.1 90400000-904fffff : 0000:04:00.1 c6000000-c70fffff : PCI Bus 0000:05
2.DPDK环境设置
设置环境变量 export RTE_SDK=DPDK源码的地址(export RTE_SDK=/home/share/DPDK/dpdk-19.80)
DPDK是支持跨平台的 export RTE_TARGET=目标机器运行的环境(export RTE_TARGET=x86_64-native-linux-gcc 目标机器本机运行(native))
3. DPDK大页内存
DPDK大页内存的开辟是在系统启动的时候开辟大页,大页(巨页hugpage)内存的是为了降低内存页的频繁置换。 大页默认一个是2M(512 * 4k)
4. DPDK 开发中常用到的结构体
struct rte_mbuf struct rte_mbuf struct rte_ring
5.开发注意
开辟内存池是基于socket。不同的NUMA中的内存是独立的。 mbuf是在内存池中申请。内存池是在大页内存中开辟空间。