OVS DPDK vs OVS Deep Dive(十六)

背景

OvS(Open vSwitch)是雲計算平臺的重要連接組件,爲虛擬機提供網絡連,被各大雲平臺,基礎設施供應商廣泛使用,比如OpenStack, OpenNebula。vSwitch–Virtual Switch(虛擬交換機),在雲環境中扮演交換機的角色,連接VM之間、VM與物理機之間的通訊。

互聯網發展風起雲湧,行業對網絡速率的要求也是直線上升:10G -> 40G -> 100G… 傳統的OvS因爲性能限制很難跟上腳步。基於這個背景,Intel發佈了開源項目DPDK,DPDK可以加速OvS性能,可以讓內核OvS的性能提升8~9倍。那麼,爲什麼DPDK可以大幅提升OvS的性能呢?接下來的文章中會對網卡虛擬化各代演化的設計進行剝絲抽繭地分析,探究性能是如何一步一步地提高。

典型應用場景

在雲平臺數據中心中一個典型的應用場景如下:
在這裏插入圖片描述
對於這個場景有兩個通信路徑:

  • VM -> vNic -> OvS -> vNic -> VM (VM in the same host)
  • VM -> vNic ->OvS -> pNic -> OvS -> vNic -> VM(different hosts)

第一個路徑是同一臺host主機上的VM之間的互相通信,第二個則是不同主機上的VM的通信路徑,第二個路徑也包含了外部主機訪問虛擬機的路徑。

網絡開銷

那麼在這樣的雲環境下網絡性能的瓶頸在哪裏?

在傳統的內核協議棧中,當有新的數據包到來時,網卡會通過硬件中斷通知協議棧,內核的網卡驅動負責處理這個硬件的中斷,將數據包從網卡拷貝到內核開闢的緩衝區中,所以協議棧的主要處理開銷分爲中斷處理,內存拷貝,系統調用和協議處理4個方面。

  • 硬件中斷:反覆中斷用戶態內核態的上下文切換和軟中斷都會大大增加額外的開銷,並且中斷處理程序應儘可能少,只是簡單地通過PIO(Programming Input/Output Model)或DMA(DirectMemory Access)等方式協調後把數據包從網卡內存複製到內核開闢的緩衝區中。
  • 內存拷貝:數據先從網卡緩存區通過PIO或DMA方式傳送到內核開闢的緩衝區中,然後還要通過socket從內核空間複製到用戶空間,統計表明,在Linux協議棧中,數據包從內核態拷貝到用戶態所用的時間甚至佔到了數據包整個處理流程時間的57.1%。
  • 系統調用:系統調用是內核態向用戶態提供的一組API集,系統調用一般通過軟中斷來實現,會產生較大的上下文切換開銷。
  • 協議處理:主要的耗時包括校驗、計算、定時器管理、IP分片/重組、PCB連接管理、可靠傳輸機制和擁塞控制。

當千兆萬兆網絡出現後,網絡數據包的協議處理佔據着大量的CPU計算能力,網絡協議棧的處理能力容易成爲系統總體性能的瓶頸。傳統的協議棧是針對通用性設計的,由於在內核實現,應用程序無法直接訪問協議棧的地址空間,協議棧的安全性較高。

在用戶空間層上實現TCP/IP協議棧,選擇繞過內核使我們可以採用某些高級的捕獲數據包技術(如直接寫TAP字符設備或使用Libpcap捕包技術,或性能更高得多的零拷貝捕包技術,這些由於同在用戶態中具有相同的特權指令級別,所以在user_buffer和nic_buffer之間可以直接做內存映射,例如virtio application)直接在網卡和用戶空間形成通道,減少內存的複製次數。同時,可以按照自己的需求定製協議棧的協議處理流程,簡化某些冗餘的處理機制,因此,用戶態協議棧的可定製性和可擴展性都比內核態協議棧要高。Openonload是Solarflare公司開發的一個專用高性能用戶態協議棧,它運行在Linux上,並具有標準的BSD socket API接口,結合該公司開發的專用網卡設備及設備驅動程序,網絡數據包得以旁路內核態協議棧,高效地到達用戶態協議棧。

在多核CPU硬件結構中,要充分發揮計算能力,必須採用多進程執行,使得同一時刻都有一個線程(用戶線程,內核線程,硬件線程)運行在一個CPU核上。

對於用戶態協議棧的構建,可以分爲兩種模式:一種是用戶程序與協議棧分別作爲獨立的進程,互相之間通過IPC通信;另一種方式是將用戶程序和協議棧作爲一個進程空間的兩個現成實現,假如選擇系統開銷更小的線程來實現的話,用戶態無法像在內核態一樣使用中斷來進行驅動,用戶態的協議棧的數據來源也兩種(網絡數據包和socket請求),它們本質上都可以看成是消息,因此,用戶態的驅動機制可以成爲消息驅動機制。

對於基於傳統的全虛擬化網卡技術+傳統的Hypervisor+傳統的Linux內核技術實現雲環境,其中一個虛擬機到物理網卡會存在如下的性能開銷:

  • VM,在基於傳統的Hypervisor技術中VM是宿主機用戶空間的一個進程。在Linux中,一般使用TAP設備作爲虛擬網卡,TAP設備在用戶空間會有一個字符設備供虛擬機進程讀寫。
  • Hypervisor層橫跨用戶空間和內核空間,這中間會存在數據在內核空間和用戶空間的拷貝及切換。 內核網橋再訪問物理網卡。

網絡/IO虛擬化技術的演變

QEMU全虛擬化

傳統全虛擬化網卡技術下的數據包從VM到物理網卡的路徑如下圖:
在這裏插入圖片描述
傳統的KVM實現中,kvm.ko是內核的一個模塊,主要用來捕獲虛機的是上述的針對CPU、內存MMU的特權指令然後負責模擬,對I/O的模擬則是再通過用戶態的Qemu進程模擬的,Qemu負責解釋I/O指令流,並通過系統調用讓Host操作系統上的驅動去完成真正的I/O操作。這其中用戶態與內核態切換了2次,數據也需要複製2次。如下圖所示:
在這裏插入圖片描述
用戶態的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系統。

全虛擬化網卡不需要改動虛擬機操作系統,Hypervisor層直接通過軟件模擬實現一些通用操作系統都支持的常用網絡驅動,如e1000、intel82545的等。這種通用性好一些,但性能不高。

virtio

爲了提高全虛擬化網卡的效率,有人提出了用半虛擬化驅動程序——virtio。使用virtio就必須要在宿主機和虛擬機中同時安裝virtio驅動,這樣虛擬化的I/O就可以用標準的virtio標準接口來進行,虛擬化引擎也不用捕捉解釋這些I/O請求了,可以大大提高性能。

其思想是宿主機和虛擬機操作系統同時改動配合提升性能,其架構如圖4所示,前端驅動(如virtio_pci,virtio_net等)存在於虛擬機中(所以虛擬機操作系統 要改動和安裝virtio專用驅動,Linux kernel從2.6.24開始支持virtio,Window虛擬機需要額外安裝virtio的Window版驅動即可),後端驅動virtio backend存在於QEMU內核模塊中(所以宿主機操作系統也要改動),中間的virtio是隊列,virtio-ring是共享的環形緩衝區。
在這裏插入圖片描述
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(Memory mapping I/O)。
在這裏插入圖片描述
virtio的網絡數據流如圖6所示,其網絡性能仍存在兩個瓶頸:

  • 用戶態的guset進程通過virtio driver(virtio_net)訪問內核態的KVM模塊(KVM.ko),需要用戶態和內核態切換一次,數據在用戶態和內核態之間拷貝一次。
  • 內核態的KVM.ko並不能直接訪問同在內核態的TAP設備,先需要一次從內核態到用戶態的切換,再通過用戶態的QEMU進程在去訪問TAP設備在用戶態的字符設備接口,又得切換一次和進行一次數據拷貝。
    在這裏插入圖片描述

vhost-net

virtio通過共享內存減少了Guest與Qemu之間的複製數據的開銷,有沒有可能再優化一下?觀察到virtio依然存在Qemu到內核的系統調用,可以將模擬I/O的邏輯VirtIO Device也挪到內核空間,避免Qemu和內核空間的系統調用。

vhost在內核態再增加一個vhost-net.ko模塊, vhost client與vhost backend通過共享內存(virtqueues, unit socket), 文件描述符(ioeventfds),(中斷號)irqfds實現快速交換數據的機制。
在這裏插入圖片描述
vhost的架構如圖8所示,vhost實際上是兩個進程之間通過共享內存實現通信的機制,它不僅可以在兩個進程之間共享內存,還能通過unix socket在兩個進程之間傳遞共享內存的文件描述符(ioevenfds)和中斷號(irqfd),這樣實現了兩個進程之間的零拷貝(Zero Copy)。我們知道,在virtio架構中,虛擬網卡的數據緩衝區就是virtio-ring,通過vhost機制實現了數據的零拷貝。
在這裏插入圖片描述
vhost的網絡數據流如圖9所示,在內核態增加了一個vhost驅動,與virtio相比,只需要進行一次用戶態內核態切換(因爲內核態的vhost-net.ko可以直接訪問內核態的TAP設備,少了一次切換),另外,由於引入vhost技術共享了虛擬機的網卡緩衝區也省了一次數據拷貝(vhost-net.ko充當vhost backend,kvm.ko充當vhost client)。
在這裏插入圖片描述

vhost-user

vhost比virtio減少了一次切換和拷貝,那麼還有沒有可能優化,比如實現零切換和零拷貝?
接着vhost-user就被提出,如下圖所示,將驅動挪到用戶態,不走kernel,以實現零切換和零拷貝。
在這裏插入圖片描述
vhost-user是qemu 2.1版本引入的新特性,使用方式如下:

$ qemu-m 1024 -mem-path /hugetlbfs,prealloc=on,share=on \
-netdev type=vhost-user,id=net0,file=/path/to/socket\
-device virtio-net-pci,netdev=net0

vhost是一種用戶空間進程(vhost client與vhost backend)通過共享內存(virtqueues, unit socket), 文件描述符(ioeventfds), (中斷號)irqfds實現快速交換數據的機制。vhost backend是一個userspace virtioapplication, 它能繞開kernel,和同樣是usersapce的VM虛機進程直接通過共享內存實現zero-copy大大地提升性能;另一方面,kernel也會基於vhost技術爲每個vring設備分配獨立的中斷號、事件中斷、文件描述符等,並將這些通過unix socket傳給其他用戶空間進程,這樣vhost backend並能直接訪問虛機網卡的文件描述符。

一些實現了vhost backend的交換機(如snabbswitch)直接在用戶態從vhost共享的虛擬機網卡緩存區virtio-ring中把網絡數據進行讀取,然後snabbswtich又實現了SR-IOV的物理網卡驅動直接將讀到的虛擬機網絡數據送到物理網卡上,從而大大提升了性能。所以基於vhost-user或者snabbswtich的技術甚至連虛擬網卡TAP設備都省了。snabbswitch是類似於Openvswitch的虛擬交換機,區別在於snabbswitch更重視性能。首先它是一個基於vhost-user的虛擬交換機應用,具有零拷貝和不走內核的特點;其次它實現了物理網卡驅動(目前只實現了一種驅動即intel10g.lua,支持Intel 82599 10-Gigabit芯片網卡)直接調用SR-IOV的硬件網卡的Tagging,Security等功能將由Neutron軟件實現的改由硬件實現。基於這兩個特點,snabbswitch的性能相當高。

DPDK(Data Plane Development Kit)

上文聊了很多,我們可以知道vhost-user的架構性能最好。Intel針對X86架構如何快速處理數據包開源了DPDK。DPDK是一個在用戶態可以直接操作物理網卡的庫函數,它和vhost-user結合便可以實現類似於snabb switch一樣性能強勁的用戶態交換機了。2015年6月16日dpdk vhost-user ports特性合併到了ovs社區。

DPDK特性有:

  • 參考傳統NP、多核處理器報文收發處理架構;
  • X86架構上純用戶態驅動;
  • R2C( run to completion )模型;
  • 內存資源預先分配:Buffer/隊列資源;基於mempool機制、 mbuf機制 環形隊列:無鎖設計 巨頁機制:物理空間連續
  • Executionunits:不支持調度。類似deadloop方式(可綁定邏輯核); PMD驅動,通過DMA實現零拷貝,不使用中斷;
  • 支持Intel 1G/10G網卡;部分非Intel網卡支持;VIRTIO/VMWARENET3半虛擬化網卡。
  • 硬件網卡多隊列、分類、QoS及卸載功能;
  • 支持非虛擬化、虛擬化場景。

OVS DPDK架構

在這裏插入圖片描述

  • 支持輕量型協議棧;
  • 兼容virtio,vhost-net和基於DPDK的vhost-user加速技術;
  • 支持Vxlan功能、端口Bonding功能;
  • 支持OpenFlow1.0&1.3;
  • 支持Meter功能、鏡像功能;
  • 支持VM熱遷移功能;
  • 性能較內核OVS可提升8~9倍。

OvS, OvS-DPDK I/O比較

1.對傳統的OvS,依然需要在kernel態和用戶態進行切換,data path如下圖所示:
在這裏插入圖片描述
2. 而結合了DPDK的OvS的data path如下圖所示:
在這裏插入圖片描述
在2016年的美國DPDK summit中發表了DPDK OVS相對於OVS的性能測評。他通過了4種不同的場景,綜合地從throughput, IPC, Cache behavior等,可以幫助我們更好地理解OvS-DPDK在性能上的優勢。摘取了幾個結果,有興趣的同學可以看看。
在這裏插入圖片描述
在這裏插入圖片描述
綜上所述,DPDK可以極大地提高數據轉發的性能和吞吐量,可以大大雲環境的網絡性能。官方的數據是可以提高10倍性能。

DPDK can improve packet processing performance by up to ten times. DPDK software running on current generation Intel® Xeon® Processor E5-2658 v4, achieves 233 Gbps (347 Mpps) of L3 forwarding at 64-byte packet sizes.

值得注意的是,安裝DPDK時要特別注意兼容的kernel版本,ovs版本的對應,否則編譯起來會特別suffer。

原文鏈接:https://lynnapan.github.io/2017/05/05/OVS-DPDK%20VS%20OVS%20Deep%20Dive/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章