三、Hugepage配置
DPDK中,如果有多个核可能需要同时访问一个网卡,那DPDK中会为每个核准备一个单独的接收队列/发送队列,这样避免了竞争,也避免了cache一致性问题。
一般的常规页大小为4K字节,使用大页时页大小设置为2M或1G字节。修改方式如下:
Bashrc文件内添加:
非NUMA系统
Echo 1024> /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
预留了1024个2M大页,即2GB内存。
NUMA系统
Echo 1024>/sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages Echo 1024>/sys/devices/system/node/node1/hugepages/hugepages-2048kB/nr_hugepages
上述命令为每个节点各预留了1024个2M大页,即4GB内存。
/etc/fstab内添加
挂载2M大页:Nodev /mnt/huge hugetlbfs defaults 0 0 挂载1G大页:Nodev /mnt/huge_1GB hugetlbfs pagesize=1GB 0 0
3.1多线程配置
DPDK线程基于pthread接口创建,属于抢占式线程模型,受内核调度支配。通过在多核设备上创建多个线程,每个线程绑定到单独的核上,减少线程调度的开销,以提高性能。控制线程一般绑定到MASTER核上,接受用户配置,并传递配置参数给数据线程等;数据线程分布在不同核上处理数据包。
DPDK中初始化及执行任务分发示例如下图所示:
lcore初始化及执行任务分发,上图中一共使用了三个cpu核,master core负责进行任务初始化和分发,两个lcore执行任务。
3.2转发模型
DPDK转发框架分为run tocompletion模型和pipeline模型,对比图如下:
DPDK转发模型对比,DPDK run to completion模型中每个报文的生命周期只能在一个线程中出现,每个物理核都负责处理整个报文的生命周期从RX到TX。
DPDK pipeline模型中不同的工作交给不同的模块,每一个模块只单独处理特定的事务,各模块之间有输入输出,通过这些输入输出连接起来,完成复杂的网络功能.
3.3内存管理
DPDK将内存封装在Mbuf结构体内,Mbuf主要用来封装网络帧缓存,所有的应用使用Mbuf结构来传输网络帧。对网络帧封装和处理时,将网络帧元数据和帧本身存放在固定大小的同一段缓存中,网络帧元数据的一部分内容由DPDK的网卡驱动写入,结构如下图:
单帧Mbuf结构
head room用来存储和系统中其他实体交互的信息,如控制信息、帧内容、事件等。Head room长度由RTE_PKTMBUF_HEADROOM定义,默认为128.
Rte_mbuf结构对象存放在内存池中,内存池使用环形缓存区来保存空闲对象,逻辑结构如下图所示:
内存池双环形缓存区结构,当一个网络帧被网卡接收时,DPDK网卡驱动将其存储在一个高效的环形缓冲区中,同时Mbuf的环形缓存区中创建了一个Mbuf对象。Mbuf对象被创建好后,网卡驱动根据分析出的帧信息将其初始化,并将其和实际帧对象逻辑相连,对网络帧的分析处理都集中在Mbuf,仅在必要的时候访问实际网络帧。
四、性能优化
4.1收发包流程概述
DPDK中普遍采用纯轮询模式进行数据包收发,所有的收发包有关的中断在物理端口初始化的时候都会关闭。物理端口上的每一个收包队列,都会有一个对应的由收包描述符组成的软件队列来进行硬件和软件的交互。
DPDK驱动程序负责初始化好每一个收包描述符,其中包含把包缓冲内存块的物理地址填充到收包描述符对应的位置,并把对应的收包成功标志复位,通知网卡硬件把收到的包进行填充。网卡硬件将收到的包一一填充到对应的收包描述符表示的缓冲内存块中,将必要信息填充到收包描述符内,标记好收包成功标志。若一个缓冲区内存块大小不够存放一个完整数据包时,可能需要多个收包描述符来处理一个包。
针对每一个收包队列,DPDK都会有一个对应的软件线程负责轮询其中的收包描述符收包成功的标志位。当发现一个收包描述符的收包成功标志被硬件置位了,意味着有包进入网卡并且已经存储到描述符对应的缓冲区内存块中。驱动程序将解析相应的收包描述符,填充对应缓冲内存块头部,将收包缓冲内存块存放到收包函数提供的数组中,同时分配好一个新的缓冲内存块给这个描述符,以便下一次收包。
针对每一个发包队列,DPDK都有一个对应的软件线程负责设置需要发送出去的包,DPDK驱动程序负责提取发包缓冲内存块的有效信息,根据内存缓存块中包的内容来负责初始化好每一个发包描述符,驱动程序将每个包翻译为一个或者多个发包描述符内能够理解的内容,写入发包描述符。当驱动程序设置好相应的发包描述符,硬件就开始依据发包描述符内容来发包,驱动程序通过获取发包描述符内的RS发送状态位来决定发包是否结束以及对发包描述符和内存缓冲块进行回收。发包轮询就是轮询发包结束的硬件标志位,DPDK驱动程序会在发包线程内不断查询发包是否结束,网卡根据RS以写回方式通知发包结束。
4.2Burst收发包
Burst为一次完成多个数据包的收发,通过把收发包复杂的处理过程进行分解,打散成不同的相对较小的处理阶段,把相邻数据访问、相似的数据运算集中处理,尽可能减少对内存或者低一级的处理器缓存的访问次数。网卡收发包描述符一般为16字节或32字节,处理器缓存基本单位为64字节,可以存放2个或4个描述符,处理器预期机制会每次存取相邻多个缓存,若一次处理4个缓存单元,则可以更新16个描述符,Burst就可以设置为16.目前常用的Burst为32。
4.3平台优化配置
硬件:
PCIe Gen3 x 8,x16。
网卡多队列收发包,支持收包RSS时分发进多个队列。
软件:
关闭CPU以及设备的省电模式;
让内存运行在所支持的最高频率上;
内核初始化时设置好大页;
增加内核启动参数,预先指定DPDK使用的逻辑核,不被操作系统调度;
DPDK参数配置:
收包队列长度,即每个收包队列分配的收包描述符个数,反映了在软件驱动程序读取所收到包之前最大的缓存包的能力。太长占用资源,太短容易丢包,默认长度为128.
发包队列长度,即每个发包队列分配的发包描述符个数,默认长度为512.
收包队列可释放描述符数量阈值,DPDK驱动程序并没有每次收包都更新收包队列尾部索引寄存器,而是在可释放的收包描述符数量达到一个阈值时更新,设置合理,可以减少没有必要的过多收包队列尾部索引寄存器的访问。默认值为32.
发包队列可释放描述符数量阈值,通过将回写标记设置在一定间隔的发包描述符上,减少不必要的回写次数,改善性能,默认为32.
发包描述符释放阈值,当用来重新配置的发包描述符数量少于阈值时,才会启动描述符和Mbuf释放动作,设置太大释放频繁,影响性能,设置太小可用描述符少,容易丢包,默认值为32。
4.4多队列配置
DPDK中,通过将网卡的某个接收队列分配给某个核,从该队列中收到的所有报文都应当在该指定的核上处理结束,不同的核操作不同的队列。
目前可以通过RSS(接收方扩展)把数据包分配到不同的队列中,该机制根据关键字通过哈希函数计算出哈希值,再有哈希值确定队列。不同的数据包类型具有不同的关键字,例如IPv4 UDP四元组(源IP地址、目的IP地址、源端口号、目的端口号)。
另一种是Flow Director技术,根据包的字段精确匹配,查找Flow Director表项,将其分配到某个特定队列。
DPDK中可以采用RSS来负载均衡,将报文发到多个核上,同时使用Flow Director将控制报文分配到指定的队列上,使用单独的核来处理,如下图所示:
五、DPDK学习路线
这里给大家推荐零声教育全网独家的【dpdk-网络协议栈-vpp-OVS-DDos-虚拟化技术】课程体系,通过32个项目案例,2W+行手写代码,全面解析4个dpdk技术方向:
5.1DPDK网络专栏
(1)dpdk基础知识
- 1.多队列网卡,vmxnet/e1000
- 2.igb_ uio与vfio模块
- 3.kni模块
- 4.hugepage的理解
- 5.零拷贝
- 6.dpdk与netmap区别
- 7.dpdk的工作环境
(2)网络协议栈
- 1.dpdk-arp
- 2.netsh静态arp表设置
- 3.dpdk-icmp
- 4.udp协议格式分析
- 5.udp协议sendto, recvfrom实现
- 6.dpdk-ip
- 7.dpdk-tcp
- 8.tcp协议栈bind,listen, accept实现
- 9.tcp协议栈recv, send, close的实现
- 10.tcp三次握手实现
- 11.tcp四次挥手实现
- 12.tcp acknum与seqnum的确认机制实现
- 13.tcp的并发连接设计
- 14.epoll并发的实现
- 15.tcp协议栈与epoll之间的回调实现
(3)dpdk组件项目
- 1.dpdk-ac
- 2.dpdk-kni
- 3./dev/ kni的原理分析
- 4.kni_ dev的流程
- 5.kni的t缓冲区,rx缓冲区
- 6.kni的用户空间与内核空间映射
- 7.mbuf如何转化为kernel的sk_ buff
- 8.dpdk- timer
- 9.bpftrace的使用
- 10.dpdk- bpf源码流程
(4)dpdk经典项目
- 1.dpdk- dns
- 2.dpdk- gateway
- 3.dpdk-ddos熵计算源码
- 4.ddos attach检测精确度调试
- 5.ddos attach测试T具hping3
- 6.布谷鸟hash原理与使用
5.2储存技术专栏
(1)高效磁盘io读写spdk(C)
- 1.存储框架spdk,为技术栈打开扇存储的大门
- 2.spdk运行环境与vhost
- 3.NVMe与PCl的关系
- 4.手把手实现spdk_ server
- 5.nvme与pcie以及手写nvme读写操作
- 6.bdev与blob之间的关系
- 7.实现blob异步读写
- 8.blobstore的读写操作实现与rpc的关系
- 9.fio性能测试性能对比libaio,io_ uring,psync
- 10.fio plugin工作流程
- 11.fio plugin开发
(2)spdk文件系统的实现
- 1.文件系统功能拆解
- 2.spdk_ env_ init与spdk_ app init的差别
- 3.spdk_ _thread_ poll实现rpc回调
- 4.fs_ operations结构体定义
- 5.file_ operations结构体定义
- 6.dir_ operations结构体定义
- 7.syscall的hook实现
- 8.io内存管理
- 9.基数树对文件系统内存管理
- 10.spdk_ blob的open,read,write,close
- 11.测试用例与调试入口函数
(3)spdk kv存储的实现
- 1.KV存储拆解Set, Get, Mod, Del
- 2.app/.a库/so库对于kv存储的选择
- 3.bdev与blob对于kv存储的选择
- 4.kv service启动blob资源操作
- 5.kv service关闭blob资源回收
- 6.kv service接口set,get,modify,delete
- 7.kv遍历与查找实现
- 8.page存储chunk的管理
- 9.pagechunk的get与put
- 10.page单查找与多页查找
- 11.btree, artree, hashmap,radixtree, rbtree之间的选择
- 12.slab的实现
- 13.slab分配slot与释放slot
- 14.为kv加上conf文件
- 15.测试用例与性能测试
5.3安全与网关开发专栏
(1)可扩展的矢量数据包处理框架vpp(c/c++)
- 1.vpp命令详解
- 2.mac/ip转发plugin
- 3.load_ balance plugin
- 4.flowtable plugin
- 5.vpp源码之间的差异
- 6.多网卡数据接收与转发
- 7.解决plugin编译加载
- 8.vpp启动load so的流程
- 9.vpp的结构体vlib_ _main实现分析
- 10.vpp的结构体vnet_ main
- 11.vector的操作实现
- 12.vpp vcl库与LD_ PRELOAD实现分析
- 13.vcl原理讲解
- 14.vcl tcpserver实现原理
- 15.vcl tcpclient实现原理
- 16.vcl与iperf3的客户端与服务器
- 17.vcl与nginx的wrk性能测试
- 18.vcl与haproxy的性能测试
- 19.vpp 1801版本与vpp 2206版本
- 20.vpp httpserver的实现源码
- 21.vpp plugin quic源码分析
- 22.vpp plugin hs_ app的源码
- 23.vpp plugin rdma的实现分析
- 24.vpp plugin loadbalance
- 25.vpp plugin nat的源码分析
- 26.vpp host-stack tcp协议实现
- 27.vpp plugin的测试用例实现
(2)golang的网络开发框架nff-go(golang)
- 1.nff-go实现的技术原理
- 2.nff-go/low.h实现分析
- 3.nff- go数据接收的实现
- 4.nff-go数据发送的实现
- 5.ipsec协议解析与strongswan的ipsec
- 6.nff go的缺陷与不足
5.4虚拟化与云原生专栏
(1)DPDK的虚拟交换机框架OvS
- 1.ovs编译安装,ovs核心组件内容
- 2.ovs-vswitchd的工作原理
- 3.ovs-vswitchd与dpdk的关系
- 4.ovs-vsctl的网桥,网口操作
- 5.qemu-system-x86_ 64构建多子网
- 6.ovs与qemu数据流分发
- 7.ovs搭建docker跨主机通信
- 8.ovsdb server与ovsdb协议
- 9.json-rpc为控制面提供开发
- 10.ovs-tcpdump/ovs-l3ping
- 11.OvS 4种数据路径
- 12.VXL AN数据协议
- 13.ovs流量统计
(2)高性能4层负载均衡器DPVS
- 1.dpvs的技术组件与功能边界
- 2.lvs+keepalived配置高可用server
- 3.dpvs与|lvs+ keepalived的关系
- 4.dpvs.conf的配置文件
- 5.dpvs的FNat/NAT/SNAT模式
- 6.dpvs的DR模式
- 7.dpvs的tun模式
- 8.通过quagga配置ospf
- 9.dpvs的tc流控操作与源码实现
- 10.dpvs代码架构分析
- 11.dpvs测试用例ipset, tc,mempool
5.5测试工具专栏
(1)perf3
- 1.vpp vcl的perf3接口hook
- 2.perf3测网络带宽
- 3.tcp吞吐量测试
- 4.udp丢包与延迟测试
- 5.json测试结果输出
(2)TRex
- 1.TRex的运行原理
- 2.TRex与dpdk
- 3.构建TRex测试系统
- 4.t-rex -64- debug gdb调试
- 5.bg-sim- 64模拟单元测试
- 6.YAML文件编写
- 7.流编排与自动化框架
- 8.报文变量设置
(3)dpdk-pktgen
- 1.pktgen命令讲解
- 2.default.cfg配置文件分析
- 3.120M bits/s的转发速率
(4)fio
- 1.ioengine的实现
- 2.ioengine_ ops的分析
- 3.iodepth的分析
- 4.spdk_ nvme的fio分析
- 5.spdk_ bdev的fio分析
- 6.spdk_ blob的ioengine实现
- 7.psync,io_ uring, libaio性能对比
5.6性能测试专栏
(1)性能指标
- 1.吞吐量bps
- 2.拆链/建链pps
- 3.并发
- 4.最大时延
- 5.最小时延
- 6.平均时延
- 7.负载
- 8.包速fps
- 9.丢包率
(2)测试方法
- 1.测试用例
- 2.vpp sandbox
- 3.perf3灌包
- 4.rfc2544
学习后可从事开发岗位:
- 高级网络开发工程师
- DPDK开发工程师
- 云产品研发工程师
- 云基础开发工程师
- 高性能优化工程师
- SDN开发工程师
- NFV开发工程师
大家想学习DPDK高性能课程 可以扫码下面微信领取粉丝专属优惠券。
写在最后:
Dpdk作为目前在互联网越来越流行的底层技术,受到越来越多的优秀互联网公司的欢迎与使用。但对于不少程序员来说可能只是见过或是听过,并没有深入的学习和使用。