Hands on vhost-net: Do. Or do not. There is no try

Vhost-net利用标准的virtio网络接口悄悄地成为了基于qemu-kvm的虚拟化环境的默认流量卸载机制。这个机制允许通过内核模块执行网络处理,解放了qemu进程,改进了网络性能。

在之前的文章里介绍了网络架构的组成:Post not found: introduction-virtio-networking-and-vhost-net [Introduction to virtio-networking and vhost-net]  同时提供了一个更加详细的解释:[Deep dive into Virtio-networking and vhost-net] 。这篇文章里我们将会提供一个详细的步骤实践性的设置一个架构。大建好之后我们能够检查主要的组件是如何工作的。

这篇文章主要面向研发人员,hackers和其他任何有兴趣学习真实的网络卸载是如何做到的。

在读完这篇文章之后(希望能够在你的PC上重建这个环境),你将会对虚拟化使用到的工具更加熟悉(比如virsh)。你将了解如何建立一个vhost-net环境并且了解到如何检查一个运行的云主机同时测试他的网络性能。

对那些需要快速建立环境并直接逆向工程的人,这里有特别的准备!https://github.com/redhat-virtio-net/virtio-hands-on 能够自动化部署环境的ansible脚本。

Setting things up

因为懒得准备原文中相同的环境,这里我用ZStack常用环境来做替代

Requirements

一个安装了CentOS Linux release 7.6.1810 (Core)的环境
使用root用户(或者有sudo权限的用户)
home目录下有25G以上的空闲空间
至少8GB的RAM
首先安装一堆依赖,建议通过ZStack iso安装可以选择Host模式,如果是专家模式需要通过,如下命令安装

1
yum --disablerepo=* --enablerepo=zstack-mn,qemu-kvm-ev-mn install libguestfs-tools qemu-kvm libvirt kernel-tools iperf3 -y

另外根据OS版本下载一个rpm包 https://pkgs.org/download/netperf

对应的Centos 7的包是 https://centos.pkgs.org/7/lux/netperf-2.7.0-1.el7.lux.x86_64.rpm.html

安装virt-install

1
yum --disablerepo=* --enablerepo=ali* install virt-install -y

接下来确保当前用户被加入了libvirt的用户组,做一下修改

1
sudo usermod -a -G libvirt $(whoami)

然后重新登录,并重启libvirt

1
systemctl restart libvirtd

Creating VM

首先下载一个镜像,可以在内部 http://192.168.200.100/mirror/diskimages/ 找一个,这里直接用的一个c76的镜像

1
wget https://archive.fedoraproject.org/pub/archive/fedora/linux/releases/30/Cloud/x86_64/images/Fedora-Cloud-Base-30-1.2.x86_64.qcow2

这是一个封装好的镜像,我们把他作为一个copy,保证以后可以继续使用,执行如下命令,创建并查一下一下image的信息是否和预期一致

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@host ~]# qemu-img create -f qcow2 -b Fedora-Cloud-Base-30-1.2.x86_64.qcow2 virtio-test1.qcow2 20G
Formatting 'virtio-test1.qcow2', fmt=qcow2 size=21474836480 backing_file=centos76.qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
[root@host ~]# qemu-img info virtio-test1.qcow2
image: virtio-test1.qcow2
file format: qcow2
virtual size: 20 GiB (21474836480 bytes)
disk size: 196 KiB
cluster_size: 65536
backing file: centos76.qcow2
Format specific information:
compat: 1.1
lazy refcounts: false
refcount bits: 16
corrupt: false

然后清理一下这个操作系统:

1
sudo virt-sysprep --root-password password:password123 --uninstall cloud-init --selinux-relabel -a virtio-test1.qcow2

这个命令会挂载文件系统,并自动做一些基础设置,让这个镜像准备好启动

我们需要把网络连接到虚拟机网络。Libvirt对网络的配置就和管理虚拟机一样,你可以通过xml文件定义一个网络,通过命令行控制他的启动和停止。

举个例子,我们使用一个libvirt提供的叫做‘default’的网络的便利设置用如下的命令定义default网络启动并检测他已经运行

1
2
3
4
5
6
7
8
[root@host ~]# virsh net-define /usr/share/libvirt/networks/default.xml
Network default defined from /usr/share/libvirt/networks/default.xml
[root@host ~]# virsh net-start default
Network default started
[root@host ~]# virsh net-list
Name State Autostart Persistent
--------------------------------------------
default active no yes

最后我们能够使用virt-install创建虚拟机。这是一个命令行工具创建一堆操作系统需要的定义,并给出一个基础的我们可以自定义的配置:

1
virt-install --import --name virtio-test1 --ram=4096 --vcpus=2 --nographics --accelerate --network network:default,model=virtio --mac 02:ca:fe:fa:ce:01       --debug --wait 0 --console pty --disk /root/virtio-test1.qcow2,bus=virtio

这些命令用的选项特定了vCPUs的数量,还有我们虚拟机的RAM大小并且指定磁盘的路径和云主机要连接的网络。

除开虚拟机通过我们这些选项定义之外,virt-install命令也能够启动虚拟机,所以我们需要列出来:

1
2
3
4
[root@host ~]# virsh list
Id Name State
------------------------------
9 virtio-test1 running

我们的虚拟机在运行了

提醒一下,virsh是一个libvirt的命令行接口,你可以这样启动一个虚拟机:

1
virsh start virtio-test1

进入虚拟机的console:

1
virsh console virtio-test1

停止一个运行的虚拟机:

1
virsh shutdown virtio-test1

删除运行的虚拟机(不要做这个除非你想在创建一遍)

1
2
virsh undefine virtio-test1
Inspecting the guest

就像已经提到的,virt-install命令能够自动使用libvirt创建和启动云主机。每个虚拟机创建都是通过xml文件描述需要模拟的硬件设置并提交给libvirt。我们通过dump配置的内容可以看一下相关的文件。

1
2
3
4
5
6
7
8
9
10
11
12
<devices>
...
<interface type='network'>
<mac address='02:ca:fe:fa:ce:01'/>
<source network='default' bridge='virbr0'/>
<target dev='vnet0'/>
<model type='virtio'/>
<alias name='net0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
</interface>
...
</devices>

我们能够看到一个virtio设备被创建好了,并连接到网络,这堆配置里有virbr0。这个设备有PCI,bus和slot

然后通过console命令进入console

1
virsh console virtio-test1

进入guset安装一些测试依赖:

1
dnf install pciutils iperf3

然后在虚拟机里看一下,实际上虚拟PCI总线上挂了个网络设备

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@localhost ~]# lspci -s 0000:00:02.0 -v
00:02.0 Ethernet controller: Red Hat, Inc. Virtio network device
Subsystem: Red Hat, Inc. Device 0001
Physical Slot: 2
Flags: bus master, fast devsel, latency 0, IRQ 11
I/O ports at c040 [size=32]
Memory at febc0000 (32-bit, non-prefetchable) [size=4K]
Memory at febf4000 (64-bit, prefetchable) [size=16K]
Expansion ROM at feb80000 [disabled] [size=256K]
Capabilities: [98] MSI-X: Enable+ Count=3 Masked-
Capabilities: [84] Vendor Specific Information: VirtIO: <unknown>
Capabilities: [70] Vendor Specific Information: VirtIO: Notify
Capabilities: [60] Vendor Specific Information: VirtIO: DeviceCfg
Capabilities: [50] Vendor Specific Information: VirtIO: ISR
Capabilities: [40] Vendor Specific Information: VirtIO: CommonCfg
Kernel driver in use: virtio-pci

注意:lspci后面跟的地址是根据xml里面的source,bus,slot,function拼接起来的。

除了典型的PCI设备信息之外(比如内存阈和功能之外,驱动还实现了基于PCI的通用virtio功能吗,并创建了一个由virtio_net驱动的网络设备,比如我们可以深入的看一下这个设备

1
2
[root@localhost ~]# readlink /sys/devices/pci0000\:00/0000\:00\:02.0/virtio0/driver
../../../../bus/virtio/drivers/virtio_net

通过命令行readlink,可以看到这个pci设备使用的是virtio_net驱动。

是这个virtio_net驱动控制了操作系统使用的网络接口的创建:

1
2
3
4
5
6
[root@localhost ~]# ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
link/ether 02:ca:fe:fa:ce:01 brd ff:ff:ff:ff:ff:ff
Inspecting the host

我们已经看过guset了,让我们再看看host。注意我们通过‘network’类型配置网络接口的默认行为是使用vhost-net

首先我们看一下vhost-net是否加载

1
2
3
4
5
[root@host ~]# lsmod | grep vhost
vhost_net 22507 1
tun 31881 4 vhost_net
vhost 48422 1 vhost_net
macvtap 22796 1 vhost_net

我们能够检查到QEMU使用了tun,kvm和vhost-net设备,同时通过检查/proc文件系统也能发现这些文件描述符被分给qemu处理了。

1
2
3
4
5
6
7
[root@host ~]# ls -lh /proc/40888/fd | grep '/dev'
lrwx------ 1 root root 64 Dec 27 22:55 0 -> /dev/null
lrwx------ 1 root root 64 Dec 27 22:55 10 -> /dev/ptmx
lrwx------ 1 root root 64 Dec 27 22:55 13 -> /dev/kvm
lr-x------ 1 root root 64 Dec 27 22:55 3 -> /dev/urandom
lrwx------ 1 root root 64 Dec 27 22:55 35 -> /dev/net/tun
lrwx------ 1 root root 64 Dec 27 22:55 37 -> /dev/vhost-net

这意味着qemu进程,不仅打开了kvm设备执行虚拟化操作,同时也创建了一个tun/tap设备和一打开了一个vhost-net设备。当然我们也能够看到一个辅助qemu的vhost内核线程也被创建出来了

1
2
3
4
5
[root@host ~]# ps -ef | grep '\[vhost'
root 40056 21741 0 09:53 pts/0 00:00:00 grep --color=auto \[vhost
root 40894 2 0 Dec27 ? 00:00:03 [vhost-40888]
[root@host ~]# pgrep qemu
40888

这个vhost内核线程的名字就是vhost-$qemu_pid

最后我们可以看到qemu进程创建的tun接口(上面通过/proc找到的)通过bridge把host和guest连在一起了。注意,虽然tap设备被挂在了qemu进程上,实际上进行tap设备读写的是vhost内核线程。

1
2
3
4
5
[root@host ~]# ip -d tuntap
virbr0-nic: tap UNKNOWN_FLAGS:800
Attached to processes:
vnet0: tap vnet_hdr
Attached to processes: qemu-kvm(40888)

OK,所以vhost已经启动并且运行了,qemu也连接到了vhost上。现在我们可以制造一些流量来看看系统的表现。

Generating traffic

如果你已经完成之前的步骤的话,你已经可以尝试通过ip地址从host发送数据到guest或者反过来。举个例子,通过iperf3测试网络性能,注意这些测试方法不是正确的benchmarks,不同的输入比如软硬件版本,不同的网络协议栈参数,会显著影响测试结果。性能吞吐量,或者是特定的使用量基准不在本文的范围之内。

首先检查guest的ip地址,执行 iperf3 server (或者任意你打算用来测试连通性的工具)

1
2
3
4
5
6
7
8
[root@localhost ~]# ip addr
...
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 02:ca:fe:fa:ce:01 brd ff:ff:ff:ff:ff:ff
inet 192.168.122.41/24 brd 192.168.122.255 scope global dynamic noprefixroute eth0
valid_lft 2808sec preferred_lft 2808sec
inet6 fe80::ca:feff:fefa:ce01/64 scope link
valid_lft forever preferred_lft forever

然后再host上运行iperf3的client:

1
2
3
4
5
[root@host ~]# iperf3 -c 192.168.122.41
Connecting to host 192.168.122.41, port 5201
[ ID] Interval Transfer Bandwidth Retr
[ 4] 0.00-10.00 sec 34.3 GBytes 29.5 Gbits/sec 1 sender
[ 4] 0.00-10.00 sec 34.3 GBytes 29.5 Gbits/sec receiver

在iperf3的输出里我们能看到一个29.5 Gbits/sec 的传输速率(主机这个网络的带宽收到很多以来的影响,不要假定会和你的环境一致)。我们可以通过 -l 参数修改包的大小来测试更多数据平面。

如果我们在iperf3测试过程中运行top命令我们能够看到vhost-$pid内核线程使用了100%的core来做包转发,同时QEMU使用了几乎两倍的cores(可以多试几次,刚好中间观察到一个200% 一个100%,注意创建guest的时候指定的qemu的vcpu数量就是2)

1
2
3
4
5
6
7
8
9
top - 10:07:24 up 7 days, 17:30,  3 users,  load average: 1.49, 0.55, 0.28
Tasks: 612 total, 2 running, 610 sleeping, 0 stopped, 0 zombie
%Cpu(s): 2.9 us, 6.6 sy, 0.0 ni, 90.4 id, 0.0 wa, 0.0 hi, 0.2 si, 0.0 st
KiB Mem : 13174331+total, 10001235+free, 4672644 used, 27058324 buff/cache
KiB Swap: 4194300 total, 4194300 free, 0 used. 12307848+avail Mem

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
40888 root 20 0 6158388 1.2g 11436 S 200.0 0.9 3:38.41 qemu-kvm
40894 root 20 0 0 0 0 R 100.0 0.0 0:58.46 vhost-40888

要测试延迟,我们使用netperf命令启动一个netperf服务,然后测试延迟。(注:需要在guest里先启动一个netserver,如何在guest安装netperf 2021.12.18 fedora安装netperf)

1
2
3
4
5
6
7
8
9
[root@host ~]# netperf -l 30 -H 192.168.122.41 -p 16604 -t TCP_RR
MIGRATED TCP REQUEST/RESPONSE TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to 192.168.122.41 () port 0 AF_INET : first burst 0
Local /Remote
Socket Size Request Resp. Elapsed Trans.
Send Recv Size Size Time Rate
bytes Bytes bytes bytes secs. per sec

16384 87380 1 1 30.00 36481.26
16384 131072

计算打开vhost-net host → guest TCP_RR延迟为 1 / 36481.26 = 0.0000274s

就像之前说的,我们进行的不是benchmark或者是吞吐测试。我们只是熟悉一下这个方法。

Extra: Disable vhost-net

就像我们看到的vhost-net是被作为默认行为的,因为带来了性能的提升。然而因为我们是来实践学习的,金庸vhost-net来看一下性能有什么不同,通过这个我们将知道qemu做了多“重”的包处理的操作,以及对性能造成了什么影响。

首先停止vm:

1
virsh shutdown virtio-test1

编辑云主机配置:

1
virsh edit virtio-test1

修改网卡配置为,增加了

1
2
3
4
5
6
7
8
9
10
11
<devices>
...
<interface type='network'>
<mac address='02:ca:fe:fa:ce:01'/>
<source network='default'/>
<model type='virtio'/>
<driver name='qemu'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
</interface>
...
</devices>

修改成功后llibvirt会显示

1
Domain virtio-test1 XML configuration not changed

然后启动云主机:

1
virsh start virtio-test1

我们可以检查一下指向/dev/vhost-net的文件描述符没了

1
2
3
4
5
6
7
[root@host ~]# ls -lh /proc/37518/fd | grep '/dev'
lrwx------ 1 root root 64 Dec 28 11:22 0 -> /dev/null
lrwx------ 1 root root 64 Dec 28 11:22 10 -> /dev/ptmx
lrwx------ 1 root root 64 Dec 28 11:22 13 -> /dev/kvm
lr-x------ 1 root root 64 Dec 28 11:22 3 -> /dev/urandom
lrwx------ 1 root root 64 Dec 28 11:22 33 -> /dev/net/tun
Analyzing the performance impact

如果我们在没有vhost-net的环境重复之前的测试,我们能看到vhost-net的线程没有在运行了

1
2
[root@host ~]# ps -ef | grep '\[vhost'
root 9076 23993 0 11:24 pts/0 00:00:00 grep --color=auto \[vhost

我们获得的性能iperf3测试结果为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[root@host ~]# iperf3 -c 192.168.122.41
Connecting to host 192.168.122.41, port 5201
[ 4] local 192.168.122.1 port 58628 connected to 192.168.122.41 port 5201
[ ID] Interval Transfer Bandwidth Retr Cwnd
[ 4] 0.00-1.00 sec 1.89 GBytes 16.2 Gbits/sec 0 2.08 MBytes
[ 4] 1.00-2.00 sec 1.78 GBytes 15.3 Gbits/sec 0 2.19 MBytes
[ 4] 2.00-3.00 sec 1.82 GBytes 15.6 Gbits/sec 0 2.37 MBytes
[ 4] 3.00-4.00 sec 1.82 GBytes 15.7 Gbits/sec 0 2.47 MBytes
[ 4] 4.00-5.00 sec 1.73 GBytes 14.8 Gbits/sec 0 2.61 MBytes
[ 4] 5.00-6.00 sec 1.80 GBytes 15.4 Gbits/sec 0 2.64 MBytes
[ 4] 6.00-7.00 sec 1.82 GBytes 15.6 Gbits/sec 0 2.64 MBytes
[ 4] 7.00-8.00 sec 1.81 GBytes 15.6 Gbits/sec 0 2.69 MBytes
[ 4] 8.00-9.00 sec 2.33 GBytes 20.0 Gbits/sec 0 2.81 MBytes
[ 4] 9.00-10.00 sec 2.32 GBytes 19.9 Gbits/sec 0 2.93 MBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bandwidth Retr
[ 4] 0.00-10.00 sec 19.1 GBytes 16.4 Gbits/sec 0 sender
[ 4] 0.00-10.00 sec 19.1 GBytes 16.4 Gbits/sec receiver

iperf Done.

可以看到传输速度从上面的29.5 Gbits/sec掉到了16.4 Gbits/sec

在通过top命令检查,我们可以发现qemu对CPU的使用,峰值会变得很高(这个需要多测试一下,是一个浮动的范围,关掉vhost-net之后大概是150% ~ 260%左右,之前开vhost-net的时候最高也就200%)

1
2
3
4
5
6
7
8
top - 11:27:10 up 7 days, 18:50,  3 users,  load average: 0.57, 0.36, 0.29
Tasks: 617 total, 3 running, 614 sleeping, 0 stopped, 0 zombie
%Cpu(s): 3.8 us, 4.0 sy, 0.0 ni, 91.7 id, 0.5 wa, 0.0 hi, 0.1 si, 0.0 st
KiB Mem : 13174331+total, 10047221+free, 3931432 used, 27339668 buff/cache
KiB Swap: 4194300 total, 4194300 free, 0 used. 12381579+avail Mem

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
37518 root 20 0 6605056 514392 11372 R 242.9 0.4 1:02.22 qemu-kvm

如果我们再比较一下两种不同网络架构下的TCP和UDP的延迟,我们可以看到vhost-net对两种形式的性能都有一致的提升

记录一下关闭vhoset-net之后的测试结果

关闭vhost-net的host → guest TCP_RR测试

1
2
3
4
5
6
7
8
9
[root@host ~]# netperf -l 30 -H 192.168.122.41 -p 16604 -t TCP_RR
MIGRATED TCP REQUEST/RESPONSE TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to 192.168.122.41 () port 0 AF_INET : first burst 0
Local /Remote
Socket Size Request Resp. Elapsed Trans.
Send Recv Size Size Time Rate
bytes Bytes bytes bytes secs. per sec

16384 87380 1 1 30.00 27209.58
计算延迟为 1/27209.58 = 0.0000367s

关闭vhost-net的host → guest UDP_RR测试

1
2
3
4
5
6
7
8
[root@host ~]# netperf -l 30 -H 192.168.122.41 -p 16604 -t UDP_RR
MIGRATED UDP REQUEST/RESPONSE TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to 192.168.122.41 () port 0 AF_INET : first burst 0
Local /Remote
Socket Size Request Resp. Elapsed Trans.
Send Recv Size Size Time Rate
bytes Bytes bytes bytes secs. per sec

212992 212992 1 1 30.00 27516.04

计算延迟为 1/27516.04=0.0000363s

打开vhost-net的host → guest UDP_RR测试

1
2
3
4
5
6
7
8
[root@host ~]# netperf -l 30 -H 192.168.122.41 -p 16604 -t UDP_RR
MIGRATED UDP REQUEST/RESPONSE TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to 192.168.122.41 () port 0 AF_INET : first burst 0
Local /Remote
Socket Size Request Resp. Elapsed Trans.
Send Recv Size Size Time Rate
bytes Bytes bytes bytes secs. per sec

212992 212992 1 1 30.00 37681.20

计算延迟为 1/37681.20 = 0.0000265s

同样的测试一下guest→host方向的流量延迟,这里不列代码只记录测试结果

打开vhost-net guest→host TCP_RR 1/36030.14 = 0.0000278s

打开vhost-net guest→host UDP_RR 1/37690.97 = 0.0000265s

关闭vhost-net guest→host TCP_RR 1/26697.53 = 0.0000375s

关闭vhost-net guest→host UDP_RR 1/25850.89 = 0.0000387s

结果如下表

使用strace统计系统调用,关闭vhost-net,测试iperf3的情况

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@host ~]# strace -c -p 37518 # 进程的pid,统计结束后用ctrl+c结束
strace: Process 37518 attached
^Cstrace: Process 37518 detached
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
41.63 1.137491 8 141188 2775 read
28.66 0.783060 6 135331 ioctl
27.16 0.742136 6 121757 writev
2.40 0.065491 8 8380 ppoll
0.13 0.003653 6 594 275 futex
0.01 0.000243 5 50 write
0.00 0.000020 20 1 clone
0.00 0.000012 3 4 sendmsg
0.00 0.000008 4 2 rt_sigprocmask
------ ----------- ----------- --------- --------- ----------------
100.00 2.732114 407307 3050 total

打开vhost-net之后的iperf3测试时strace qemu的结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@host ~]# strace -c -p 27346
strace: Process 27346 attached
^Cstrace: Process 27346 detached
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
99.96 6.819794 131150 52 ppoll
0.02 0.001416 10 136 write
0.01 0.000862 13 66 futex
0.00 0.000341 9 39 read
0.00 0.000083 10 8 sendmsg
0.00 0.000022 22 1 clone
0.00 0.000016 8 2 rt_sigprocmask
------ ----------- ----------- --------- --------- ----------------
100.00 6.822534 304 total

另外一个好方法就是看qmue发送了多少IOCTLs到KVM。因为每次I/O事件都需要qemu处理,qemu需要发送IOCTL给KVM来切换回VMX noroot的guest模式。我们可以通过strace分析qemu在每个syscall上花费的时间。根据上面两次strace的结果可以看到没打开vhost-net的情况,存在很多ioctl的调用,而打开vhost之后基本上只有ppoll。

Conclusions

在这篇文章里面我们完整了提供了一个创建一个QEMU + vhost-net的虚拟机,检查guest和host来理解这个架构的输入输出。我们也展示了性能是如何变化的。这个系列也到此为止。从 Introduction to virtio-networking and vhost-net 的总览到技术视角深入理解的 Deep dive into Virtio-networking and vhost-net 详细的解释了这些组件,现在展示完了如果配置,希望这些内容呢能够提供足够的资源给IT专家,架构师以及研发人员理解这个技术并开始和他一起工作。

下一个话题将会涉及 Userland networking and DPDK