Cisco VPP KVM vhost-user

原文地址:https://blog.csdn.net/u010827484/article/details/81223105
目的:VPP作为KVM数据平面,使用vhost-user方案进行数据包通信

什么是 vhost-user

在 vhost 的方案中,由于 vhost 实现在内核中,guest 与 vhost 的通信,相较于原生的 virtio 方式性能上有了一定程度的提升,从 guest 到 kvm.ko 的交互只有一次用户态的切换以及数据拷贝。这个方案对于不同 host 之间的通信,或者 guest 到 host nic 之间的通信是比较好的,但是对于某些用户态进程间的通信,比如数据面的通信方案,openvswitch 和与之类似的 SDN 的解决方案,guest 需要和 host 用户态的 vswitch 进行数据交换,如果采用 vhost 的方案,guest 和 host 之间又存在多次的上下文切换和数据拷贝,为了避免这种情况,业界就想出将 vhost 从内核态移到用户态。这就是 vhost-user 的实现

vhost-user 的实现

vhost-user 和 vhost 的实现原理是一样,都是采用 vring 完成共享内存,eventfd 机制完成事件通知。不同在于 vhost 实现在内核中,而 vhost-user 实现在用户空间中,用于用户空间中两个进程之间的通信,其采用共享内存的通信方式。

vhost-user 基于 C/S 的模式,采用 UNIX 域套接字(UNIX domain socket)来完成进程间的事件通知和数据交互,相比 vhost 中采用 ioctl 的方式,vhost-user 采用 socket 的方式大大简化了操作。

vhost-user 基于 vring 这套通用的共享内存通信方案,只要 client 和 server 按照 vring 提供的接口实现所需功能即可,常见的实现方案是 client 实现在 guest OS 中,一般是集成在 virtio 驱动上,server 端实现在 qemu 中,也可以实现在各种数据面中,如 OVS,Snabbswitch 等虚拟交换机。

搭建环境

配置VPP

VPP作为KVM的转发平面把客户机的vhost-user接口绑定到同一个网桥,进行二层转发。VPP作为vhost-user的client,主动连接kvm。

创建VPP vhost-user虚拟接口,并绑定到指定UNIX套接字。创建两个vhost-user虚拟接口,并启动虚拟接口。

create vhost-user socket /var/run/vpp/sock1.sock
create vhost-user socket /var/run/vpp/sock2.sock
set int state VirtualEthernet0/0/0 up
set int state VirtualEthernet0/0/1 up

----
VPP删除vhost-user接口命令
delete vhost-user VirtualEthernet0/0/0

setup VPP vhost-user interface

查看vhost-user虚拟接口状态,’show hardware-interface’命令返回结果表示VPP是否识别到KVM虚拟接口,表示物理网络是否连通,因为目前KVM没有启动,所以显示状态为down。

VPP vhost-user int status

配置libvirt XML文件

Libvirt简介

Libvirt 是一组软件的汇集,提供了管理虚拟机和其它虚拟化功能(如:存储和网络接口等)的便利途径。这些软件包括:一个长期稳定的 C 语言 API、一个守护进程(libvirtd)和一个命令行工具(virsh)。Libvirt 的主要目标是提供一个单一途径以管理多种不同虚拟化方案以及虚拟化主机,包括:KVM/QEMU,Xen,LXC,OpenVZ 或 VirtualBox hypervisors

Libvirt 的一些主要功能如下:
- VM management(虚拟机管理):各种虚拟机生命周期的操作,如:启动、停止、暂停、保存、恢复和迁移等;多种不同类型设备的热插拔操作,包括磁盘、网络接口、内存、CPU等。
- Remote machine support(支持远程连接):Libvirt 的所有功能都可以在运行着 libvirt 守护进程的机器上执行,包括远程机器。通过最简便且无需额外配置的 SSH 协议,远程连接可支持多种网络连接方式。
- Storage management(存储管理):任何运行 libvirt 守护进程的主机都可以用于管理多种类型的存储:创建多种类型的文件镜像(qcow2,vmdk,raw,…),挂载 NFS 共享,枚举现有 LVM 卷组,创建新的 LVM 卷组和逻辑卷,对裸磁盘设备分区,挂载 iSCSI 共享,以及更多……
- Network interface management(网络接口管理):任何运行 libvirt 守护进程的主机都可以用于管理物理的和逻辑的网络接口,枚举现有接口,配置(和创建)接口、桥接、VLAN、端口绑定。
- Virtual NAT and Route based networking(虚拟 NAT 和基于路由的网络):任何运行 libvirt 守护进程的主机都可以管理和创建虚拟网络。Libvirt 虚拟网络使用防火墙规则实现一个路由器,为虚拟机提供到主机网络的透明访问。

Libvirt启动虚拟机可以使用命令行带参数的方式启动虚拟机,也可是使用xml的方式编排虚拟机。本环境使用xml方式部署虚拟机。

使用libvirt XML文件启动虚拟机

1、创建libvirt xml文件:

<domain type='kvm' id='4'>
  <name>cirros1</name>
  <uuid>6b3e6847-bd57-468c-a37b-8c6e68e1e9ce</uuid>
  <memory unit='KiB'>409600</memory>
  <memoryBacking>
    <hugepages>
      <page size="2" unit="M"/>
    </hugepages>
    <source type="file"/>
    <access mode="shared"/>
    <allocation mode="immediate"/>
  </memoryBacking>
  <currentMemory unit='KiB'>409600</currentMemory>
  <vcpu placement='static'>1</vcpu>
  <os>
    <type arch='x86_64'>hvm</type>
    <boot dev='hd'/>
    <bootmenu enable='no'/>
  </os>
  <cpu mode='host-passthrough' check='none'>
    <numa>
      <cell id='0' cpus='0' memory='409600' unit='KiB' memAccess='shared'/>
    </numa>
  </cpu>
  <clock offset='utc'/>
  <on_poweroff>destroy</on_poweroff>
  <on_reboot>restart</on_reboot>
  <on_crash>restart</on_crash>
  <devices>
    <emulator>/usr/bin/qemu-system-x86_64</emulator>
    <disk type='file' device='disk'>
      <driver name='qemu' type='qcow2' cache='unsafe'/>
      <source file='/home/libvirt-xml/1_cirros-0.3.5-x86_64-disk.img'/>
      <backingStore/>
      <target dev='sda' bus='sata'/>
      <alias name='sata0-0-0'/>
      <address type='drive' controller='0' bus='0' target='0' unit='0'/>
    </disk>
    <serial type='pty'>
      <source path='/dev/pts/5'/>
      <target type='isa-serial' port='0'>
        <model name='isa-serial'/>
      </target>
      <alias name='serial0'/>
    </serial>
    <console type='pty' tty='/dev/pts/5'>
      <source path='/dev/pts/5'/>
      <target type='serial' port='0'/>
      <alias name='serial0'/>
    </console>
    <interface type='vhostuser'>
      <mac address='fa:16:3e:4f:e0:86'/>
      <source type='unix' path='/var/run/vpp/sock1.sock' mode='server'/>
      <model type='virtio'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
    </interface>
  </devices>
</domain>

主要参数解释:

name:虚拟机名字,在启动虚拟机时需要用到

memory:引导时guest虚拟机的最大内存分配。内存分配包括在启动时指定或以后热插拔的可能的附加内存设备。此值的单位由可选属性unit决定的,unit默认单位为KiB,可指定单位为KB、MB(M)、GB、TB。

memoryBacking:这个选项可以影响宿主机怎么备份虚拟机内存,这里主要用于分配大页内存。‘’指明使用page为2M大小的大页内存。没有这个选项vhost-user会启动失败,因为vhost-user使用的大页内存来分配共享内存使用。

currentMemory:虚拟机的实际内存分配。此值可以小于最大分配,以允许在运行时膨胀guest虚拟机内存。如果省略,则默认为memory元素的值。

vcpu:指明宿主机分配给虚拟cpu个数,最小为1,最大为hypervisor所限制的个数

cpu:描述虚拟机cpu分配情况。mode属性说明cpu工作模式,可指定为host-model或host-passthrough,host-model:根据物理cpu的特性,选择一个最靠近的标准cpu型号。如果没有指定cpu模式,默认使用这种模式;host-passthrough:直接将物理cpu暴露给虚拟机使用,在虚拟机上完全可以看到的就是物理cpu的型号。节点描述cpu核分配情况,指明哪些核(cpus)使用多少内存(memory),内存访问权限设置memAccess。,如果没有节点的配置vhost-user不能正常工作。

interface:虚拟机网络设置。type说明接口类型,source说明接口来源。如上所示,类型为vhostserd 接口使用’/var/run/vpp/sock1.sock’套接字,并作为vhost-user的服务端。

更多libvirt XML配置使用说明

2、使用libvirt命令定义虚拟机配置文件vm1.xml和vm2.xml,vm2.xml与vm1.xml主要区别如下:

root@ubuntu:/home/libvirt-xml# diff vm1.xml vm2.xml
2,3c2,3
<   <name>cirros1</name>
<   <uuid>6b3e6847-bd57-468c-a37b-8c6e68e1e9ce</uuid>
---
>   <name>cirros2</name>
>   <uuid>6b3e6847-bd57-468c-a37b-8c6e68e1e9ca</uuid>
52,53c52,53
<       <mac address='fa:16:3e:4f:e0:86'/>
<       <source type='unix' path='/var/run/vpp/sock1.sock' mode='server'/>
---
>       <mac address='fa:16:3e:4f:e0:88'/>
>       <source type='unix' path='/var/run/vpp/sock2.sock' mode='server'/>
root@ubuntu:/home/libvirt-xml# 

定义vm1和vm2,如果xml编写错误或有无效字段libvirt会给出相应提示:

virsh define vm1.xml
virsh define vm2.xml

查看libvirt新定义的vm需要使用virsh list –all命令查看。virsh list只能查看启动状态中(running、pause)的虚拟机。vm定义成功如下图所示,虚拟机还未启动所以ID为空,Name为XML name节点的值,表示虚拟机的名字,State表示虚拟机当前状态。

libvirt定义vm

3、使用libvirt启动vm1和vm2,启动时需要使用虚拟机Name作为虚拟机标识。

virsh start cirros1
virsh start cirros2

启动完成后,查看虚拟机状态和VPP虚拟接口状态:

VPP:使用show hardware-interface命令查看虚拟接口状态由down状态变为up状态,表示已在vhost-user模式下识别到libvirt启动的虚拟机接口

virsh list:输出vm运行状态,由’shut off’变为’running’

libvirt启动虚拟机

打通VM数据通道

1、把vpp的vhost-user虚拟接口加入同一个网桥

set interface l2 bridge VirtualEthernet0/0/0 1
set interface l2 bridge VirtualEthernet0/0/1 1

vpp添加vhost-user接口到网桥

2、登录cirros虚拟机配置IP地址,登录命令为’virsh console (VM ID) ‘,并验证网络是否正常通信。

libvirt测试网络通信

VPP 抓包

使用vhost-user方式通信的数据包VPP可以使用trace命令进行抓包,验证数据是否正常通信。

抓3个vhost-user类型的数据包命令:

trace add vhost-user-input 3

查看trace抓包数据:

show trace

vhost-user抓包数据

排错

1、使用virsh define重定义虚拟机时,需要先删除虚拟机(virsh destroy ID)

2、如果需要使用大页内存,但配置文件没有定义就会抱如下错误:(vhost-user 需要使用大页内存)

error: unsupported configuration: Shared memory mapping is supported only with hugepages

使用XML定义大页内存:

  <memoryBacking>
    <hugepages>
      <page size="2" unit="M"/>
    </hugepages>
    <source type="file"/>
    <access mode="shared"/>
    <allocation mode="immediate"/>
  </memoryBacking>

3、虚拟机内存默认是不能共享的,vhost-user需要打开内存共享功能,打开方式如下:

<numa>
  <cell id='0' cpus='0' memory='409600' unit='KiB' memAccess='shared'/>
</numa>

不用担心numa节点就必须要CPU架构是numa架构,我发现自己的虚拟机是非numa架构但还是需要加上这个节点才能正常使用vhost-user的共享内存功能,如果没有设置共享内存功能,使用 systemctl status libvirtd 命令可以看到如下警告:

Detected vhost-user interface without any shared memory, the interface might not be operational
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值