从 字面解释上看,D PD K 是 专 注于数据平面软件开发的套件;本质上,它是一组可以从用户空间调用的软件库,提供了一种开销更小的方法来代 替 传 统 的 L inux系 统 调 用 ,使得应用程序可以绕过内核直接和底层硬件交互.
网 络 数 据 包 不 再 通 过 内 核 ,而 是 直 接 走D PD K 的专有路径,从网卡直接到达用户空间,交由用户处理,从而将繁重的数据包过滤、数据包转发工作从内核态转至用户态.
另外,D PD K实现了多核“无锁”并行结构,使多处理器核心可以高效并行工作,并充分发挥速度 越 来 越 快 的 I/O 接 口 的 能 力 ,从而最大限度上提高网络数据包处理效率.
使 用 DPDK,将 不 能 再 用 原 来 的 L in u x内核协议栈,而 且 所 有 的 应 用 都 需 要 基 于 D PD K 提供的函数库进行重构.但由于网卡等设备的驱动程序都运行在用户层,不容易崩溃,调试方便,可以大幅降低高性能网络数据处理程序开发、调试的难度
环境
硬件环境:同方两路龙芯服务器
系统环境:loongnix
版本:dpdk-stable-18.11.2
依赖环境:
yum install numactl-devel
或
apt install libnuma-dev
sudo apt-get install libpcap0.8-dev
源码
下载官网:http://core.dpdk.org/download/
dpdk-stable-18.11.2下载链接:http://fast.dpdk.org/rel/dpdk-18.11.2.tar.xz
编译
- 解压
[root@localhost dpdk-stable-18.11.2]# ls
app buildtools config devtools doc drivers examples GNUmakefile kernel lib license MAINTAINERS Makefile meson.build meson_options.txt mk pkg README test usertools
[root@localhost dpdk-stable-18.11.2]#
[root@localhost dpdk-stable-18.11.2]#
- 配置
设置环境变量
RTE_SDK是代码顶层目录
RTE_TARGET是选择编译平台,在config下面定义,这里是64位linux系统,使用gcc编译。
x86_64如下
export RTE_SDK=/home/tools/dpdk/dpdk-stable-18.11.2
export RTE_TARGET=x86_64-native-linuxapp-gcc
mips64el如下
export RTE_SDK=/home/disk/zhubo/sw/dpdk/dpdk-stable-18.11.2
export RTE_TARGET=mips64el-native-linuxapp-gcc
使能libpcap
config/common_base 文件中的PMD_PCAP改成y
sed -ri ‘s,(PMD_PCAP=).*,\1y,’ config/common_base
加载配置文件
make config T=$RTE_TARGET
编译
DESTDIR是安装目录这里设置/home/tools/dpdk/dpdk-stable-18.11.2/destdir
make -j ( n p r o c ) i n s t a l l T = (nproc) install T= (nproc)installT=RTE_TARGET DESTDIR=/home/tools/dpdk/dpdk-stable-18.11.2/destdir
如果设置了DESTDIR的环境变量,命令行上也可以不加这个参数,上面的命令可以写成
export DESTDIR=/usr/local
make -j ( n p r o c ) i n s t a l l T = (nproc) install T= (nproc)installT=RTE_TARGET
注意:
设置了T参数没有设置DESTDIR参数或者环境变量时,是不会安装的。
如果没有T参数和DESTDIR参数或者环境变量,默认安装到/usr/local下面。
编译最后会有如下打印信息,表示安装完成。
Build complete [x86_64-native-linuxapp-gcc]
================== Installing /home/tools/dpdk/dpdk-stable-18.11.2/destdir/
Installation in /home/tools/dpdk/dpdk-stable-18.11.2/destdir/ complete
验证
静态库:在安装路径/lib
下面可以看到libdpdk.a
以及所有以librte_开头的文件
头文件在安装路径/include/dpdk
目录下
进行编译自己写的dpdk程序时,在Makefile中要加入头文件目录 I安装路径/include/dpdk
使用实例
l3fwd
编译
配置上面的环境变了后,examples/l3fwd
执行make
,配置大页内存
首先需要加载dpdk的驱动igb_uio.ko,配置大页内存的操作。
(1)加载igb_uio.ko,进入dpdk/x86_64-native-linuxapp-gcc/kmod,运行命令
modprobe uio
insmod igb_uio.ko
(2)配置大页内存:运行命令
mkdir -p /mnt/huge
mount -t hugetlbfs nodev /mnt/huge
echo 1024 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
可以通过cat /proc/meminfo
查看大页内存是否配置成功,另外也可以通过vi /etc/grub.conf来配置大页内存
./l3fwd -c fffffffffff -n4 – -p 0xf -P --config="(0,0,1)(0,1,2)(1,0,8)(1,1,9)(2,0,16)(2,1,17)(3,0,24)(3,1,25)"
参数说明:该硬件设备有四个CPU socket,使四个网口绑定到四个不同的CPU socket上,每个网口起两个队列,绑定两个CPU的核。
注意:PCI插槽对应不同的socket,如果绑错了,会导致测试性能降低
使用介绍
[14:00:51@root x86_64-native-linuxapp-gcc]#./l3fwd --help
EAL: Detected 4 lcore(s)
EAL: Detected 1 NUMA nodes
Usage: ./l3fwd [options]
EAL common options:
-c COREMASK Hexadecimal bitmask of cores to run on
-l CORELIST List of cores to run on
The argument format is <c1>[-c2][,c3[-c4],...]
where c1, c2, etc are core indexes between 0 and 128
--lcores COREMAP Map lcore set to physical cpu set
The argument format is
'<lcores[@cpus]>[<,lcores[@cpus]>...]'
lcores and cpus list are grouped by '(' and ')'
Within the group, '-' is used for range separator,
',' is used for single number separator.
'( )' can be omitted for single element group,
'@' can be omitted if cpus and lcores have the same value
-s SERVICE COREMASK Hexadecimal bitmask of cores to be used as service cores
--master-lcore ID Core ID that is used as master
--mbuf-pool-ops-name Pool ops name for mbuf to use
-n CHANNELS Number of memory channels
-m MB Memory to allocate (see also --socket-mem)
-r RANKS Force number of memory ranks (don't detect)
-b, --pci-blacklist Add a PCI device in black list.
Prevent EAL from using this PCI device. The argument
format is <domain:bus:devid.func>.
-w, --pci-whitelist Add a PCI device in white list.
Only use the specified PCI devices. The argument format
is <[domain:]bus:devid.func>. This option can be present
several times (once per device).
[NOTE: PCI whitelist cannot be used with -b option]
--vdev Add a virtual device.
The argument format is <driver><id>[,key=val,...]
(ex: --vdev=net_pcap0,iface=eth2).
--iova-mode Set IOVA mode. 'pa' for IOVA_PA
'va' for IOVA_VA
-d LIB.so|DIR Add a driver or driver directory
(can be used multiple times)
--vmware-tsc-map Use VMware TSC map instead of native RDTSC
--proc-type Type of this process (primary|secondary|auto)
--syslog Set syslog facility
--log-level=<int> Set global log level
--log-level=<type-match>:<int>
Set specific log level
-v Display version information on startup
-h, --help This help
--in-memory Operate entirely in memory. This will
disable secondary process support
EAL options for DEBUG use only:
--huge-unlink Unlink hugepage files after init
--no-huge Use malloc instead of hugetlbfs
--no-pci Disable PCI
--no-hpet Disable HPET
--no-shconf No shared config (mmap'd files)
EAL Linux options:
--socket-mem Memory to allocate on sockets (comma separated values)
--socket-limit Limit memory allocation on sockets (comma separated values)
--huge-dir Directory where hugetlbfs is mounted
--file-prefix Prefix for hugepage filenames
--base-virtaddr Base virtual address
--create-uio-dev Create /dev/uioX (usually done by hotplug)
--vfio-intr Interrupt mode for VFIO (legacy|msi|msix)
--legacy-mem Legacy memory mode (no dynamic allocation, contiguous segments)
--single-file-segments Put all hugepage memory in single files
[14:01:01@root x86_64-native-linuxapp-gcc]#
运行参数样板:
./build/l3fwd-vf [EAL options] – -p PORTMASK --config(port,queue,lcore)[,(port,queue,lcore)]
参数解释:
[EAL options] EAL选项已经在其他例子中已有说明。
-p [端口掩码 – 网卡掩码,在部署DPDK运行环境时绑定的网卡]: 十六进制表示
–config: 哪个网口哪个队列绑定到哪个逻辑核
–no-numa: 是否关闭对numa结构的识别
运行实例:
./l3fwd-vf -l 1,2 -n 4 – -p 0x3 --config="(0,0,1),(1,0,2)"
-这个实例占用的逻辑核为1,2
-启动1、2号网卡
-端口映射关系为:
0号网卡0号队列映射到1号逻辑核上;
1号网卡0号队列映射到2号逻辑核上;
运行效果如下(添加了一些提示信息):
运行
./l3fwd -c0x4 -n4 – -pf0 -L --config="(4,0,0),(5,0,0)" --parse-ptype
#LPM
$./build/l3fwd -l 1,2 -n4 – -p 0x3 -L --config="(0,0,1),(1,0,2)"
#EM
./build/l3fwd -l 1,2 -n4 – -p 0x3 -E --config="(0,0,1),(1,0,2)" --parse-ptype
也可以使用l3fwd进行一个网口的自发自收,命令:
./l3fwd -cff -n 4 – -p0x1 -P --config="(0,0,1),(0,1,2),(0,2,3),(0,3,4)"
转发分析
- l3fwd可以进行多核转发,每个逻辑核可以在不同的接口的不同队列进行收包,每个逻辑核也会在每个接口的某个队列进行发包
- l3fwd需要修改来fwd_lpm.c中的ipv4_l3fwd_lpm_route_array来设置路由表
static struct ipv4_l3fwd_lpm_route ipv4_l3fwd_lpm_route_array[] = {
{IPv4(88, 88, 88, 0), 24, 0}, // 此处为我加入的路由信息
{IPv4(99, 99, 99, 0), 24, 1}, // 此处为我加入的路由信息
{IPv4(1, 1, 1, 0), 24, 0},
{IPv4(2, 1, 1, 0), 24, 1},
{IPv4(3, 1, 1, 0), 24, 2},
{IPv4(4, 1, 1, 0), 24, 3},
{IPv4(5, 1, 1, 0), 24, 4},
{IPv4(6, 1, 1, 0), 24, 5},
{IPv4(7, 1, 1, 0), 24, 6},
{IPv4(8, 1, 1, 0), 24, 7},
};
- l3fwd需要设置下一条网关的mac地址
// 单独指定目的接口的mac
// 0:00:e0:4c:0b:01:f4
// 1:00:e0:4c:0a:fe:70
dest_eth_addr[0] = (0xf40000000000 /*<< 40*/) + (0x0100000000/* << 32*/) + (0x0b << 24) + (0x4c << 16) + (0xe0 << 8) + (0x00 << 0);
dest_eth_addr[1] = (0x700000000000/* << 40*/) + (0xfe00000000/* << 32*/) + (0x0a << 24) + (0x4c << 16) + (0xe0 << 8) + (0x00 << 0);
*(uint64_t *)(val_eth + 0) = dest_eth_addr[0];
*(uint64_t *)(val_eth + 1) = dest_eth_addr[1];
路由测试
- 拓扑:pc(88.88.88.88)---------l3fwd---------linux(99.99.99.99)
./l3fwd -c3 -n4 – -p3 -L --config="(0,0,0),(1,0,1)"