DPDK support for vhost-user
转载:http://blog.csdn.net/quqi99/article/details/47321023
X86体系早期没有在硬件设计上对虚拟化提供支持,因此虚拟化完全通过软件实现。一个典型的做法是通过优先级压缩(Ring Compression)和二进制代码翻译(Binary Translation)相结合,VMM在特权级ring 0, Guest操作系统在非特权级ring 1, Guest应用程序在ring 3。由于Guest操作系统工作在非特权级ring 1中,这样当它执行特权指令时就会触发异常,由VMM截获异常并采用软件方式模拟指令并返回。但由于X86体系在设计之初没有考虑虚拟化,所以一小部分特权指令在ring 1下没有引发异常,所以需要对操作系统的二进制代码进行扫描,一旦发现不友好的指令,将就其换成支持虚拟化的指令块,这些指令块与VMM合作访问受限的虚拟资源,或者显式地触发异常让VMM进一步处理。这种打补丁的方式很难在构架上保证其完整性。于是,下层的硬件加入了虚拟化功能,硬件截获操作系统对敏感指令的执行或者对敏感资源的访问后通过异常的方式报告给VMM,这样就解决了虚拟化的问题。Intel VTx技术是这一方向的代表,它引入了一个新的特殊执行模式用于运行虚拟机,这个模式会将特权指令统统截取并报告给VMM,VMM本身工作在正常模式下,在接收到处理的报告后,通过对目标指令的解码,找到相应的虚拟化模块进行模拟。
对于内存的虚拟化则需要用硬件实现从GVA(Guest Virtual Address)到GPA(Guest Physical Address)再到HPA(Host Physical Address)的两次地址转换。传统非虚拟化的操作系统只通过硬件MMU完成一次从GVA到GPA的虚拟化。
在I/O的虚拟化方面,VTd技术在北桥引入DMA重映射硬件来提供设备重映射和设备直接分配的功能。设备所有的DMA传输都会被DMA重映射硬件截取,然后根据设备对应的I/O页表,对DMA中的地址进行转换,使设备只能访问特定的内存。这样,设备就可以直接分配给Guest机使用,驱动提供给设备的GPA经过重映射,变为HPA,使得DMA操作得以完成。
在网络虚拟化方面,VTd技术可以将一个物理网卡直接分配给一个虚机使用,但扩展性差,因为一台服务支持的PCI设备数是有限的,远远不能满足越来越来的Guest机数量。因此SRIOV(Single
Root I/O Virtualization)被引入来解决这个问题。SRIOV是PCIe(PCI
Express)规范的一个扩展,定义了本质上可以共享的设备。它允许一个PCIe设备,通过是网卡,为每个与其相连的客户机复制一份资源(例如内存资源、中断和DMA数据流),使得数据处理不再依赖VMM。
在GPU虚拟化方面,如XenGT,它是由Intel在Xen基础上开发的GPU虚拟化开源方案。客户机操作系统不需要任何改动,特权操作会被Xen截获,并且转发到中介(Mediator),中介为每个客户机创建一个GPU上下文(Context),并且在其中模拟特权操作。
1, 普通虚拟化
传统的KVM实现中,kvm.ko是内核的一个模块主要用来捕获虚机的是上述的针对CPU、内存MMU的特权指令然后负责模拟,对I/O的模拟则是再通过用户态的Qemu进程模拟的,Qemu负责解释I/O指令流,并通过系统调用让Host操作系统上的驱动去完成真正的I/O操作。这其中用户态与内核态切换了两次,数据也需要复制。
用户态的Qemu在启动Guest操作系统时,可以先通过KVM在用户态的字符接口/dev/kvm获取Guest的地址空间(fd_vm)
和KVM本身(fd_kvm),然后通过fd_vm将Guest的物理空间mmap到Qemu进程的虚拟空间(虚机就是一个进程,虚机进程的用户虚拟空间就是Guest的物理空间,映射之后Qemu的虚拟设备就可以很方便的存取Guest地址空间里的数据了),并根据配置信息创建vcpu[N]线程(对虚机来说,虚机进程的线程对应着Guest的处理器),然后Qemu将操作fd_vcpu[N]在自己的进程空间mmap一块KVM的数据结构区域(即下图的shared,包括:Guest的IO信息,如端口号,读写方向,内存地址)。该数据结构用于Qemu和kvm.ko交互,Qemu通过它调用虚拟设备注册的回调函数来模拟设备的行为,并将Guest IO的请求换成系统请求发给Host系统。
图中vm-exit代表处理器进入host模式,执行kvm和Qemu的逻辑。vm-entry代表处理器进入Guest模式,执行整个Guest系统的逻辑。Qemu通过三个文件描述符同kvm.ko交互,然后kvm.ko通过vmcs这个数据结构同处理器交互,最终达到控制Guest系统的效果。其中fd_kvm主要用于Qemu同KVM本身的交互,比如获取KVM的版本号,创建地址空间、vcpu等。fd_vcpu主要用于控制处理器的模式切换,设置进入Guest
mode前的处理器状态等等(内存寻址模式,段寄存器、控制寄存器、指令指针等),同时Qemu需要通过fd_vcpu来mmap一块KVM的数据结构区域。fd_vm主要用于Qemu控制Guest的地址空间,向Guest注入虚拟中断等。
2, VirtIO
VirtIO通过共享内存的方式为Guest和Qemu提供了高速的硬盘与网络I/O通道(因为Guest的地址空间早就mmap到Qemu的进程空间)。VirtIO只需要增加VirtIO
Driver和VirtIO Device即可直接读写共享内存。如下图,Guest
VirtIO驱动通过访问port地址空间向Qemu的VirtIO设备发送IO发起消息。而设备通过读写irqfd或者IOCTL
fd_vm将I/O的完成情况通知给Guest的驱动。irqfd和ioeventfd是KVM为用户程序基于内核eventfd机制提供的通知机制,以实现异步的IO处理(这样发起IO请求的vcpu将不会阻塞)。之所以使用PIO而不是MMIO,是因为KVM处理PIO的速度快于MMIO。
3, vhost
VirtIO通过共享内存减小了Guest与Qemu之间数据复制的开销,但Qemu到内核的系统调用还是跑不了。有必要将模拟I/O的逻辑将VirtIO Device挪到内核空间避免系统调用。
vhost在内核态再增加一个vhost-net.ko模块, vhost client与vhost backend通过共享内存(virtqueues, unit socket), 文件描述符(ioeventfds), (中断号)irqfds实现快速交换数据的机制。
4, vhost-user
vhost使用了内核态TCP/IP栈导致从Guest到kvm.ko仍然有一个用户态内核态的切换以及数据的拷贝。一些用户态栈议栈如openonload直接在用户态实现网卡驱动再实现BSD兼容的socket接口供上层应用使用,vhost-user(需要将vhost-backend移到用户态)的共享内存技术用于将这些用户态网络设备(又如snabb switch)和用户态的Guest连接起来
5, DPDK support for vhost-user [3]
DPDK便是一个在用户态可以直接操作物理网卡的库函数,它和vhost-user结合便可以实现类似于snabb
switch一样性能强劲的用户态交换机了。2015年6月16日dpdk vhost-user ports特性合并到了ovs社区[1],
dpdkvhostuser port将创建unix socket将虚机的virtio-net虚拟网卡的网卡缓冲区共享给物理机上的ovs
port设备。
理论部分结束,下面开始安配置配置dpdk + vhost-user
1, sudo apt-get install fuse libfuse-dev dh-autoreconf openssl libssl-dev
Git clone git://dpdk.org/dpdk
2, 检查硬件网卡是否支持dpdk,在lib/librte_eal/common/include/rte_pci_dev_ids.h文件中搜索0x153A能搜到。
hua@hua-ThinkPad-T440p:/bak/OpenStack$ sudo lspci -nn|grep Ethernet
00:19.0 Ethernet controller [0200]: Intel Corporation Ethernet Connection I217-LM [8086:153a] (rev 04)
3, 修改文件config/common_linuxapp
CONFIG_RTE_BUILD_COMBINE_LIBS=y #产生单个库文件
CONFIG_RTE_LIBRTE_VHOST=y #enable对vhost的支持
4, 编译,安装。DPDK IVSHMEM可以在host-to-guest或guest-to-guest之间采用零拷贝技术
make config T=x86_64-ivshmem-linuxapp-gcc
make install T=x86_64-ivshmem-linuxapp-gcc
5, 编译eventfd模块
cd $DPDK/lib/librte_vhost/eventfd_link/
make
sudo insmod eventfd_link.ko
6, uio提供了用户态驱动开发的框架, dpdk中的uid驱动需要定期去poll/select
/dev/uioX检查设备是否有中断产生。uio也是通过mmap将设备的内存映射到用户空间,当然用户态也可以通过/sys/class/uio/uioX/maps/mapX来实现对设备内存的访问,所以发送和接受数据是通过操作设备的内存来完成的。
DPDK除了可以使用uio驱动,还可以使用VFIO驱动。VFIO是用户态的PCI设备驱动开发的框架,它向用户态提供访问硬件设备的接口,也向用户态提供配置IOMMU的接口。它需要内核与BIOS的支持。
sudo modprobe uio
sudo insmod x86_64-ivshmem-linuxapp-gcc/kmod/igb_uio.ko
$ sudo ./tools/dpdk_nic_bind.py --status
Network devices using DPDK-compatible driver
============================================
<none>
Network devices using kernel driver
===================================
0000:00:19.0 'Ethernet Connection I217-LM' if=eth0 drv=e1000e unused=igb_uio *Active*
Other network devices
=====================
<none>
$ sudo ./tools/dpdk_nic_bind.py --force --bind=igb_uio eth0
$ sudo tools/dpdk_nic_bind.py -u 0000:00:19.0 # 恢复
7, 大页支持,添加/etc/default/grub后执行update-grub
(centos是执行:grub2-mkconfig --output=/boot/grub2/grub.cfg),
通过mount一个大页文件系统,然后通过mmap的文件映射,使得该文件系统中的内存操作实现大页调度,从而解决TLB shrashing的问题。
GRUB_CMDLINE_LINUX=iommu=pt intel_iommu=on default_hugepagesz=1G hugepagesz=1G hugepages=8
之后mount它,mount -t hugetlbfs -o pagesize=1G none /dev/hugepages
8, 编译ovs
git clone https://github.com/openvswitch/ovs.git
cd ovs && ./boot.sh
./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var
--with-dpdk=/bak/openstack/dpdk/x86_64-ivshmem-linuxapp-gcc/
--enable-ssl
但报错“cannot link with dpdk”,无法继续了。
opendp是一个基于DPDK的用户态协议栈,当需要三层VPN或者NAT时或者其他应用时需要它,https://github.com/opendp/dpdk-odp/wiki
DPDK support for vhost-user的更多相关文章
- 译文:ovs+dpdk中的“vHost User NUMA感知”特性
本文描述了"vHost User NUMA感知"的概念,该特性的测试表现,以及该特性为ovs+dpdk带来的性能提升.本文的目标受众是那些希望了解ovs+dpdk底层细节的人,如果 ...
- ovs+dpdk numa感知特性验证
0.介绍 本测试是为了验证这篇文章中提到的DPDK的NUMA感知特性. 简单来说,在ovs+dpdk+qemu的环境中,一个虚拟机牵涉到的内存共有三部分: DPDK为vHost User设备分配的De ...
- DPDK在OpenStack中的实现
随着云计算与大数据的快速发展,其对数据中心网络的性能和管理提出了更高的要求,但传统云计算架构存在多个I/O瓶颈,由于云平台基本上是采用传统的X86服务器加上虚拟化方式组建,随着40G.100G高速网卡 ...
- VNF网络性能提升解决方案及实践
VNF网络性能提升解决方案及实践 2016年7月 作者: 王智民 贡献者: 创建时间: 2016-7-20 稳定程度: 初稿 修改历史 版本 日期 修订人 说明 1.0 20 ...
- vyatta的fork开源版本
https://www.reddit.com/r/networking/comments/3dvwfy/who_here_is_using_vyos/ Vyatta came in two flavo ...
- OVS 总体架构、源码结构及数据流程全面解析
在前文「从 Bridge 到 OVS」中,我们已经对 OVS 进行了一番探索.本文决定从 OVS 的整体架构到各个组件都进行一个详细的介绍. OVS 架构 OVS 是产品级的虚拟交换机,大量应用在生产 ...
- vyatta的fork开源版本vyos
vyatta的fork开源版本vyos 来源: https://www.reddit.com/r/networking/comments/3dvwfy/who_here_is_using_vyos/ ...
- SRS之RTMP的TCP线程(即监听线程)
本文分析的是 SRS 针对 rtmp 的端口建立的 tcp 线程.具体建立过程: SRS之监听端口的管理:RTMP RTMP 的 TCP 线程中各个类之间 handler 的关系图 1. RTMP之T ...
- DPDK之(八)——vhost库
转:http://www.cnblogs.com/danxi/p/6652725.html vhost库实现了一个用户空间的virtio net server,允许用户直接处理virtio ring队 ...
随机推荐
- 六大利器助Java程序开发事半功倍
实用的开发工具对于Java程序开发者来说,工作起来事半功倍.本文中小编将为大家列举包括开发环境.分析测试.代码保护等实用工具. 开发环境 Sonarqube Sonarqube是一个开源平台,是一款代 ...
- 【MS SQL】查看任务执行进度
原文:[MS SQL]查看任务执行进度 备份或还原数据库时,我一般是用MS SQL工具向导来进行,由于工具向导没有显示任务执行过程的状态, 如果数据库比较大执行时间较长的话,对任务啥时候执行完成比较迷 ...
- shell脚本中执行另一个shell脚本
分类: 可以在一个shell脚本中执行另一个shell脚本(或非可执行文件,主要用于取得一些变量的值),方法是: . 文件名(包括路径) 或 变量=文件名(包括路径) . $变量 注意,圆点后面有 ...
- AngularJS Change Path Without Reloading
To change path URL with AngularJS, $location.path() is passed the new URL as a parameter, and the pa ...
- 最短路径 dijkstra
最短路径 dijkstra #include <stdio.h> #include <string.h> #include <limits.h> #define M ...
- 【转】几点 iOS 开发技巧
[译] 几点 iOS 开发技巧 原文:iOS Programming Architecture and Design Guidelines 原文来自破船的分享 原文作者是开发界中知晓度相当高的 Mug ...
- 使用反射机制实现jQuery调用ashx类中的指定方法
使用反射机制实现jQuery调用ashx类中的指定方法 近期用asp.net做个小网站,但又不喜欢使用asp.net的服务器端控件,经过一番思量后确定前端采用原始的html.后台采用Linq to ...
- springMVC3学习(三)--handlerMapping和handlerAdapter
基本结构和 springMVC3学习(一)--框架搭建 差不多,这里不再用Annotation注解的方式 以下只说明需要修改的部分: 1.在Spring配置文件中配置HandlerMapping.Ha ...
- spring redis入门
小二,上菜!!! 1. 虚拟机上安装redis服务 下载tar包,wget http://download.redis.io/releases/redis-2.8.19.tar.gz. 解压缩,tar ...
- 解决中文乱码( jsp表单提交中文时出现乱码)
有三种方法: 1.建立一个filter中文解决乱码 2.Struts2在struts.xml中修改默认的编码设定 3.用Spring解决中文乱码 4.直接在jsp中修改解决 1.建立一个filter解 ...