这周为了提高网络压测的压力,尝试了一下VPP,初次接触,好多东西不是很理解。但不管怎么样,先安装起来跑跑,积累一点初步的认识吧。
我的验证环境如下:
- 虚拟化:kvm,创建两台4核4G的虚拟机;
- 操作系统:Ubuntu 20.04
- VPP版本:22.06
- DPDK版本:19.11.12
只是很粗浅的尝试,如果你也正好是入门选手,希望对你有帮助。
创建虚拟机
我平时主要是用vagrant创建虚拟机,这次也不例外。Vagrant文件如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
# Defaults for config options defined in CONFIG
$num_instances ||= 2
$hostname_prefix ||= "vpp"
$libvirt_nested ||= false
$vm_cpus ||= 4
$vm_memory ||= 4096
$subnet1_prefix ||= "172.18.10"
$subnet1_startip ||= 30
$subnet2_prefix ||= "172.18.11"
$subnet2_startip ||= 30
Vagrant.configure("2") do |config|
config.vm.box_check_update = false
config.vm.box = "generic/ubuntu2004"
# copy files into vm
config.vm.synced_folder ".", "/vagrant", type: "rsync", disabled: true
(1..$num_instances).each do |i|
config.vm.define vm_name = "%s-%01d" % [$hostname_prefix, i] do |node|
node.vm.hostname = vm_name
node.vm.provider :libvirt do |lv|
lv.nested = $libvirt_nested
lv.cpu_mode = "host-model"
lv.cpus = $vm_cpus
lv.memory = $vm_memory
lv.disk_bus = 'scsi'
end
# network
eth1ip = "#{$subnet1_prefix}.#{i+$subnet1_startip}"
eth1net = "net-#{$subnet1_prefix}"
node.vm.network :private_network, :ip => eth1ip, :libvirt__network_name => eth1net
eth2ip = "#{$subnet2_prefix}.#{i+$subnet2_startip}"
eth2net = "net-#{$subnet2_prefix}"
node.vm.network :private_network, :ip => eth2ip, :libvirt__network_name => eth2net
end
end
end
|
通过上面的vagrant up
我们就可以创建两台ubuntu 20.04的虚拟机。具体如下:
1
2
3
4
5
6
7
|
# 拉起虚拟机
$ vagrant up
...
# 注意:如果你缺少ubuntu 20.04的镜像,需要保证机器可以联网
# 创建成功后,通过下面的命令可以登录虚拟机
$ vagrant ssh vpp-1
$ vagrant ssh vpp-2
|
安装VPP
创建好了虚拟机之后,接下来就是安装vpp软件了。对于常见的系统,FD.io社区都有编译好的二进制安装文件,我们就直接用编译好的安装文件安装即可。具体如下:
1
2
3
4
5
6
7
8
9
|
# 配置软件源
$ curl -s https://packagecloud.io/install/repositories/fdio/release/script.deb.sh | sudo bash
# 创建日志文件及目录(缺少这步会导致启动失败,当然也可以通过修改配置文件解决)
$ mkdir -p /var/log/vpp
$ touch /var/log/vpp/vpp.log
# 安装vpp
$ apt install -y dpdk vpp vpp-plugin-core vpp-plugin-dpdk vpp-dev vpp-plugin-devtools net-tools
|
若无异常,到此就安装完成了,接下来就是配置了。
配置VPP
DPDK相关配置
我们创建的虚拟机有三张网卡,其中第一张是用来管理的,其他两张是用来测试。VPP可以使用DPDK作为数据面,因此,我们需要先配置DPDK,修改网卡的驱动。首先,通过DPDK提供的工具看看现在网卡的状态。
1
2
3
4
5
6
7
8
9
10
11
|
$ dpdk-devbind.py -s
Network devices using DPDK-compatible driver
============================================
Network devices using kernel driver
===================================
0000:00:05.0 'Virtio network device 1000' if=eth0 drv=virtio-pci unused=vfio-pci,uio_pci_generic *Active*
0000:00:06.0 'Virtio network device 1000' if=eth1 drv=virtio-pci unused=vfio-pci,uio_pci_generic *Active*
0000:00:07.0 'Virtio network device 1000' if=eth2 drv=virtio-pci unused=vfio-pci,uio_pci_generic *Active*
...
|
上面的输出可以看到,有三张Virtio的网卡,现在都是在使用内核驱动,不是DPDK兼容的驱动。我们需要修改一下,如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
# 加载dpdk兼容的uio_pci_generic驱动
$ modprobe uio_pci_generic
## 去掉eth1的ip地址,否则后面操作会失败
$ ifconfig eth1 0 up
$ dpdk-devbind.py -b uio_pci_generic 0000:00:06.0
# 若无错误提示,就是成功了,用同样的方法,设置eth2
$ ifconfig eth2 0 up
$ dpdk-devbind.py -b uio_pci_generic 0000:00:07.0
$ dpdk-devbind.py -s ## 再次查看网卡的驱动情况
Network devices using DPDK-compatible driver
============================================
0000:00:06.0 'Virtio network device 1000' drv=uio_pci_generic unused=vfio-pci
0000:00:07.0 'Virtio network device 1000' drv=uio_pci_generic unused=vfio-pci
Network devices using kernel driver
===================================
0000:00:05.0 'Virtio network device 1000' if=eth0 drv=virtio-pci unused=vfio-pci,uio_pci_generic *Active*
|
注意:每块网卡的PCI地址不一样,具体内容以dpdk-devbind.py -s
的输出为准。
修改之后,通过ifconfig -a
应该看不到eth1和eth2两张网卡了,但它们可以被VPP使用。
VPP配置文件
VPP默认的配置文件路径是/etc/vpp/startup.conf
,我对其内容做了一下简化,如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
$ cat /etc/vpp/startup.conf
unix {
nodaemon
log /var/log/vpp/vpp.log
full-coredump
cli-listen /run/vpp/cli.sock
gid vpp
startup-config /etc/vpp/setup-interface.txt
}
api-trace {
on
}
api-segment {
gid vpp
}
socksvr {
default
}
cpu {
main-core 0
}
dpdk {
dev 0000:00:06.0 {
name eth1
}
dev 0000:00:07.0 {
name eth2
}
}
|
上面的配置文件中,除了dpdk部分及startup-config
,其他的都是默认配置。我们可以把一些接口的配置信息放到startup-config
中,这样整个配置文件不会太复杂。startup-config
具体的内容如下:
1
2
3
4
5
6
|
$ cat /etc/vpp/setup-interface.txt
set interface state eth1 up
set interface state eth2 up
set interface ip address eth1 172.18.10.31/24
set interface ip address eth2 172.18.11.31/24
|
上面的配置,是给激活VPP的两个网口eth1和eth2,并给它们配置IP地址。
配置完成后,我们可以重启vpp,并查看其状态。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
$ systemctl restart vpp
$ systemctl status vpp
$ vppctl
_______ _ _ _____ ___
__/ __/ _ \ (_)__ | | / / _ \/ _ \
_/ _// // / / / _ \ | |/ / ___/ ___/
/_/ /____(_)_/\___/ |___/_/ /_/
## 查看接口的IP地址
vpp# show int addr
eth1 (up):
L3 172.18.10.31/24
eth2 (up):
L3 172.18.11.31/24
local0 (dn):
vpp#
|
网络测试
安装同样的方法,配置两台虚拟机(注意:IP地址不要重了)。
测试连通性
我们在vpp-1这台虚拟机上ping下vpp-2看看。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
root@vpp-1:~$ vppctl ping 172.18.10.32
116 bytes from 172.18.10.32: icmp_seq=1 ttl=64 time=.1754 ms
116 bytes from 172.18.10.32: icmp_seq=2 ttl=64 time=.0893 ms
116 bytes from 172.18.10.32: icmp_seq=3 ttl=64 time=.1191 ms
116 bytes from 172.18.10.32: icmp_seq=4 ttl=64 time=.2431 ms
116 bytes from 172.18.10.32: icmp_seq=5 ttl=64 time=.1220 ms
Statistics: 5 sent, 5 received, 0% packet loss
root@vpp-1:~$ vppctl ping 172.18.11.32
116 bytes from 172.18.11.32: icmp_seq=2 ttl=64 time=.1408 ms
116 bytes from 172.18.11.32: icmp_seq=3 ttl=64 time=.1069 ms
116 bytes from 172.18.11.32: icmp_seq=4 ttl=64 time=.0985 ms
116 bytes from 172.18.11.32: icmp_seq=5 ttl=64 time=.1252 ms
Statistics: 5 sent, 4 received, 20% packet loss
|
从上面的结果可以看出,两个IP都是可达的。
测试带宽
下面我们再用iperf3跑跑带宽测试。为了使用VPP里面提供的网口,iperf3需要加载libvcl_ldpreload.so这个动态链接库,来替换部分网络编程接口。
此外,我们还需要配置一下VCL,具体如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
# 添加VCL的配置文件
$ cat > /etc/vpp/vcl.conf << EOF
vcl {
rx-fifo-size 4000000
tx-fifo-size 4000000
app-scope-local
app-scope-global
api-socket-name /run/vpp/api.sock
use-mq-eventfd
}
EOF
$ export VCL_CONFIG=/etc/vpp/vcl.conf
$ export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libvcl_ldpreload.so
$ iperf3 -s --bind 172.18.10.31 # 启动服务端
|
用同样的方法,我们在vpp-2上启动客户端,发起测试。
1
2
3
|
$ export VCL_CONFIG=/etc/vpp/vcl.conf
$ export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libvcl_ldpreload.so
$ iperf3 -c 172.18.10.31 -p 5201 -t 30 # 启动客户端,测试30秒
|
初步测试来看,性能并不好。不知道是不是跑在虚拟机中的原因,比直接跑iperf3测试出来的带宽低很多。