DPDK Pktgen+Docker搭建VNF环境及验证

主要是搭建一个DPDK+docker的环境,然而docker上次用是在软工的时候,重新学还花了一些功夫,改日写篇docker总结好了。

最终能够运行的版本信息

注 :dpdk、pktgen是wget下载安装的,docker是apt install安装的

  • Linux kernel 4.4.0-131-generic
  • Ubuntu 16.04.5 LTS
  • dpdk-stable-16.11.1
  • pktgen-dpdk-pktgen-3.1.1
  • Docker version 17.03.2-ce

环境配置

  • 安装dpdk
  • 安装docker
  • 安装pktgen
  • 配置hugepages
    • 注意!本实验中由于我们需要使用virtio-user这种连接方式,由于实现时的一些限制导致使用vhost-user时同时最多只能使用8个hugepages无论2M还是1G大小的hugepagesize。所以这里必须使用1G大小的hugepagesize同时最多分配8个。

拓扑搭建

拓扑

预建立的简单拓扑

1
2
3
4
5
6
7
+--------+---------------+               +-------------------+---------------+
| | socket file 1 |<------------->| vhost-user port 1 | |
| +---------------+ +-------------------+ |
| host | pktgen | | testpmd | container |
| +---------------+ +-------------------+ |
| | socket file 0 |<------------->| vhost-user port 0 | |
+--------+---------------+ +-------------------+---------------+

testpmd是DPDK提供的一个通过数据包转发进行DPDK测试的工具,也是一个非常好的DPDK应用开发示例。如果想进行简单的DPDK开发实验推荐修改$RTE_SDK/app/test-pmd/iofwd.c后编译testpmd应用,之后在同一目录$RTE_SDK/app/test-pmd/下可以找到下编译后的testpmd应用。

pktgen运行在主机中,testpmd运行在容器中,两个应用之间通过建立的socket文件以及vhost-user进行通信,相当于虚拟网卡。

启动容器

创建Dockerfile

1
2
3
4
5
6
cat <<EOT >> $RTE_SDK/../Dockerfile
FROM ubuntu:latest
WORKDIR /root/dpdk
COPY dpdk /root/dpdk/.
ENV PATH "$PATH:/root/dpdk/$RTE_TARGET/app/"
EOT

使用创建的dockerfile建立docker镜像

1
2
3
cd $RTE_SDK/..
#-t为镜像名,可以以name:tag的格式来写,不加tag默认tag为latest
sudo docker build -t dpdk .

运行容器

注:这里一开始没把libnuma.so.1共享-v加进去,结果进去报错

注2:但是在后来的可跑的版本中,不加又没有关系

1
2
3
4
5
6
7
8
9
mkdir -p /tmp/virtio
# -ti 提供一个PTY交互界面并保持STDIN持续可用
# -v /dev/... 将主机的hugepages通过数据卷挂载到容器内,从而可以与主机共享hugepages
# -v /tmp/... 挂载一个数据卷到容器中用于共享virtio_user的sockets
# --privilege 不启用特权可能导致无法共享hugepages和sockets
sudo docker run -ti --rm --name=test \
-v /dev/hugepages:/dev/hugepages \
-v /tmp/virtio/:/tmp/virtio/ \
--privileged dpdk

虚拟机上的初步结果

因为硬件受限还没法添加1G的hugepage,为了测试testpmd的可用性,我暂时直接在容器中运行

1
testpmd

截图如下

启动应用

在容器中运行testpmd

1
2
3
4
5
6
7
8
9
10
11
12
# 以下命令在容器中运行
# DPDK的参数
# -l 列出所使用的CPU核
# -n 给出memory channels的数量
# --socket-mem 限制用于每个socket的内存量
# --vdev 创建vhost的socket文件用于进行网络连接,可以理解为虚拟网卡
# --file-prefix hugepages字首,用于区分所使用的hugepage
# testpmd的参数
# --forward-mode=io 对两个端口情况从一个端口进来的包直接从另一个端口发出

# 在~/dpdk文件夹下运行
./x86_64-native-linuxapp-gcc/app/testpmd -l 0-1 -n 1 --socket-mem 1024,1024 --vdev 'eth_vhost0,iface=/tmp/virtio/sock1' --vdev 'eth_vhost1,iface=/tmp/virtio/sock2' --file-prefix=test --no-pci -- -i --forward-mode=io --auto-start

在主机上运行pktgen

1
2
3
4
5
6
7
8
# 以下命令在主机中运行
# DPDK的参数同上,--vdev在这里用来连接到socket文件
# pktgen的参数
# -P 在所有端口启用混杂模式
# -m 定义CPU核到端口的绑定,在这里core5绑定到prot0,core6绑定到port1
# pktgen的运行目录应在Pktgen.lua同一文件夹下运行

sudo pktgen -l 2-6 -n 3 --socket-mem 1024,1024 --vdev='virtio_user0,path=/tmp/virtio/sock1' --vdev='virtio_user1,path=/tmp/virtio/sock2' -- -P -m "5.0,6.1"

最终结果

在pktgen中进行简单设置,并在testpmd中查看结果

1
2
3
4
Pktgen:/>set all rate 10
Pktgen:/>set 0 count 100
Pktgen:/>set 1 count 200
Pktgen:/>str

pktgen上截图

testpmd上截图

参考资料

  • https://www.sdnlab.com/20112.html
  • https://segmentfault.com/q/1010000003036379
  • http://pktgen-dpdk.readthedocs.io/en/latest/getting_started.html
  • http://www.voidcn.com/article/p-fmqewmwt-bqu.html