Intel DPDK: Intel Data Plane Development Kit
使用linux socket进行开发存在如下一些性能瓶颈:
copy_from/to_user,TLB miss
下图为sk_buffer结构:
该图是linux内核协议栈草图:
结论:标准的数据面只是用于通用环境
一个Ipv4 LPM查看仅需一次内存访问。
kernel version >=2.6.33
glibc >= 2.7
kernel configuration :
Uio support
Hugetlbfs support
…
编译安装:
app/ config/ examples/ lib/ LICENSE.GPL LICENSE.LGPL Makefile mk/ scripts/ tools/
lib:Intel dpdk库源码
config,tools,mk,scipts:架构相关配置,makefiles,脚本
examples 目录提供了大量例程:
make install T=i686-native-linuxapp-gcc
T指定编译目标环境,格式:ARCH-MACHINE-EXECENV-TOOLCHAIN
ARCH can be: i686, x86_64
MACHINE can be: native, ivshmem
EXECENV can be: linuxapp, bsdapp
TOOLCHAIN can be: gcc, icc
设置环境变量RTE_SDK为DPDK安装目录 RTE_TARGET指定目标环境
进入example目录
# export RTE_SDK=$HOME/DPDK
# export RTE_TARGET=x86_64-native-linuxapp-gcc
# make
sudo modprobe uio
sudo insmod kmod/igb_uio.ko
通过DPDK提供的工具解绑网卡默认驱动,并绑定DPDK驱动
./tools/dpdk_nic_bind.py –u eth1
./tools/dpdk_nic_bind.py --bind=igb_uio 04:00.1 /eth1
# echo 1024 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
# mkdir /mnt/huge
# mount -t hugetlbfs nodev /mnt/huge
./build/l2fwd [EAL options] -- -p PORTMASK [-q NQ] -T PERIOD
EAL 参数:
例程执行:
环境抽象层: Environment Abstraction Layer
内存管理: rte_malloc
Ring队列管理: rte_ring
内存池管理: rte_mempool
数据包缓存管理: rte_mbuf
轮询模式网卡驱动: PMD
算法库: rte_hash,rte_lpm
IP stack库及工具: rte_net
定时器、日志及调试功能 .etc
下图是DPDK应用的架构图:
各组件之间依赖关系:
相关库的描述如下:
环境适应层(EAL)提供了一套API,主要用于系统的初始化,获取核心数量和线程等配置信息, 发现外围设备互连(PCI)设备,设置超大页面,留出与高速缓存相应的内存、缓冲区和描述符环,初始化轮询模式驱动程序(PMD) ,并在其他核心上生成线程,后续任务交由这些线程去做。
EAL 层的主要工作:
- Intel DPDK loading and launching
- Support for multi-process and multi-thread execution types
- Core affinity / assignment procedures
- System memory allocation / de-allocation
- Atomic / lock operations
- Time reference
- PCI bus access
- Trace and debug functions
- CPU feature identification
- Interrupt handling
- alarm operations
DPDK应用程序在开始执行时,都需要调用EAL层初始化函数:rte_eal_init(argc, argv)
该函数执行流程如下:
EAL 初始化函数中内存初始化主要工作:
eal_hugepage_info_init()
rte_eal_memory_init()->rte_eal_hugepage_init
rte_eal_memzone_init
DPDK应用程序所分配的内存都是在hugepage上分配,以上函数通过hugetlbfs,将预留的hugepage按照物理地址连续性,是否在相同socket等性质,组装成 memseg,后续当应用程序使用内存时,就会从这些memseg中,根据需要分配内存的大小来划分一块称为 memzone的区域,供应用程序使用。
DPDK应用程序主要的内存分配操作有两个,一个是通过malloc函数分配内存,另一种是分配mbuf。两者底层都使用了memzone。
提供malloc-like API在memzone上分配任意大小的内存。DPDK应用程序分配内存时,不是在程序栈上分配,而是通过其自身实现的malloc,在hugepage上分配。
接口:
void * rte_malloc(const char *type, size_t size, unsigned align)
void * rte_malloc_socket(const char *type, size_t size, unsigned align, int socket)
split_elem(elem, new_elem)
join_elem(elem, next)
该机制对内存的管理类似内核伙伴关系算法,freehead用于管理空闲空间,按空闲空间大小分为不同等级。当需要内存时,就从适合的级别寻找空闲空间,从尾部将该空间分为两部分,后半部供应用程序使用,前半部放入级别较低的空心空间队列。 当释放内存时,会顺便检查其伙伴是否已经空闲,如果是,则将其合并,放入级别更高的空闲列表。
相关阅读:Intel DPDK 简介(下篇)
网易云大礼包:https://www.163yun.com/gift
本文来自网易实践者社区,经作者刘长伟授权发布