Release 17.02.0node
目錄python
Linux環境下DPDK入門... 1linux
1 引言... 2c++
2 資料集... 2shell
3 系統需求... 2ubuntu
3.1 x86平臺的先決條件BIOS設置... 2性能優化
3.2 編譯DPDK. 3服務器
3.3 運行DPDK程序... 3數據結構
4 編譯DPDK源碼... 5架構
4.1 安裝DPDK和瀏覽源碼... 5
4.2 安裝DPDK目標(target)開發環境... 6
4.3 瀏覽安裝好的DPDK環境target. 6
4.4 加載DPDK用戶態IO模塊... 7
4.5 加載VFIO模塊... 7
4.6 從內核模塊綁定和解綁網卡... 7
5 編譯和運行例子程序... 8
5.1 編譯例子程序... 8
5.2 運行例子程序... 9
5.2.1 程序使用的邏輯核... 9
5.2.2 程序使用的大頁內存... 10
5.3 其它例子程序... 10
5.4 其它的測試程序... 10
6 開啓其它功能... 10
6.1 高精度定時器(HPET)功能... 10
6.1.1 BIOS支持... 10
6.1.2 linux內核支持... 11
6.2 非root用戶運行DPDK程序... 11
6.3 電源管理和省電功能... 11
6.4 使用DPDK的CPU親和性減小上下文切換的開銷... 12
6.5 加載DPDK KNI內核模塊... 12
6.6 使用linux IOMMU透傳來在INTEL VT-d虛擬化環境下運行DPDK. 12
6.7 40G網口高性能小包處理... 12
6.7.1 使用16個字節的RX描述符... 12
6.7.2 高性能和報文時延間的均衡... 12
7 快速安裝啓動腳本... 12
7.1 腳本結構... 13
7.2 用例... 13
7.3 應用程序... 15
8 怎麼在intel平臺上得到網卡的最好性能... 17
8.1 硬件和內存需求... 17
8.1.1 網卡需求... 18
8.1.2 BIOS設置... 18
8.1.3 Linux內核啓動參數... 18
8.2 運行DPDK前的配置... 18
8.3 獲取intel網卡的最好性能例子... 19
文檔是安裝配置DPDK操做說明,旨在幫助客戶快速上手和運行程序。文檔介紹了在linux開發環境下如何編譯和運行DPDK程序,可是並不深刻細節。
以前曾經嘗試着翻譯來着,當時由於要離職,一時興起就想着翻譯,翻譯的太爛,如今從新翻譯,一方面是方便新入職的同事可以快速入門,另一方面是如今工做的須要,還有一方面是學習KVM想休息一下,看內存那塊弄得頭昏腦脹,並且後面的例子會涉及到虛擬話那塊的。下一個將翻譯樣例那本書(以及在本身機器上運行可能遇到的問題),同時會參雜着介紹開發者手冊中的一些我的理解。
下面列出了全部DPDK文檔資料的建議讀取順序:
l 版本說明:提供了各個版本相關的信息,包括支持的特性,限制,修復的bug,出現的問題等等。也對頻繁提到的問題以FAQ的方式作了回答。
l 入門手冊(本文的):講述瞭如何安裝配置DPDK;意在幫助開發者快速上手和運行程序。
l 開發者手冊:
n 軟件架構和(經過例子)在linux環境下使用它
n DPDK的內容包括構建系統(包括在DPDK根目錄下構建開發環境和程序使用的命令)和移植程序指南。
n 在已有軟件和要新開發的軟件中須要考慮到的優化。
還提供了一個專有術語表。
l API索引:提供了DPDK函數,數據結構和其它開發用到的結構體的詳細信息。
l 範例用戶手冊:介紹了一系列的範例程序。每個章節介紹一個程序,展現程序的特殊功能,說明如何編譯,運行和使用範例程序。
本章介紹了編譯DPDK須要的安裝包。
注意:若是DPDK要運行在intel 89xx系統通信芯片平臺,請翻閱對應該系列的linux入門手冊。
對於主流的平臺,使用DPDK的基本功能並不須要專門的BIOS設置,然而,對於額外的功能像HPET(高精度定時器),電量管理功能,以及在40G網卡上高性能小包處理,須要修改BIOS設置。修改設置的詳細信息見第六章。
須要的工具:
注意:已經在Fedora18上測試運行過,在其它系統上安裝命令和須要的安裝包可能不同,要知道其它版本linux發行版測試詳細的細節,請查看DPDK版本說明。
l GNU make
l coreutils:cmp,sed,grep,arch,等等。
l gcc:4.9版本或者是全部平臺帶的更新的版本。在一些gcc版本中,不少特殊的編譯標誌和連接標誌默認是打開的,會影響到性能(好比,-fstatck-protector)。請查閱對應版本的文檔和執行gcc –dumpspecs。
l libc hreaders,一般打包成gcc-multilib(intel 64位架構上是glibc-devel.i686/libc6-dev-i386;glibc-devel.x86_64/libc6-dev,IBM power架構則是glibc-devel.ppc64)
l 編譯內核模塊須要的內核頭文件和源文件(kernel-devel.x86_64;kernel-devel.ppc64)
l 在64位機器上編譯32位程序而外須要的庫:
n glibc.i686, libgcc.i686, libstdc++.i686 and glibc-devel.i686 for Intel i686/x86_64;
n glibc.ppc64, libgcc.ppc64, libstdc++.ppc64 and glibc-devel.ppc64 for IBM ppc_64;
注意:x86_x32 ABI庫旨在ubuntu13.10以上版本或者最新Debian版本上支持。只支持gcc4.9+版本。
l python,要使用dpdk安裝包中各類幫助腳本必需的python版本2.7+或者是3.2+。
其它的工具:
l intel編譯器icc:須要安裝額外的庫。在編譯器安裝文檔看中icc安裝說明。
l IBM powerlinux高級工具鏈:這是一系列的開源開發工具和運行時庫,可以讓用戶用到IBM最新的power硬件特性。要安裝的話看IBM的官方安裝文檔。
l libpcap頭文件和庫(libpcap-devel)編譯和使用基於libpcap的輪詢驅動。這個驅動默認是禁用的,能夠經過修改編譯時的配置文件參數CONFIG_RTE_LIBRTE_PMD_PCAP=y來打開。
l libarchive頭文件和庫在單元測試用打開源文件用到。
要運行DPDK程序,在目的機器上須要一些定製化的東西。
要求:
l 內核版本>=2.6.34:經過命令uname –r查看內核版本號
l glibc>=2.7(要用到cpuset特性):能夠經過命令ldd –version命令查看gcc版本號
l 內核配置
在Fedora操做系統和其它通用發行版,例如Ubuntu,紅帽企業版linux,發行商提供的內核配置基本能夠跑絕大多數DPDK程序。
對於在其它內核上構建DPDK,下面幾個選項須要能支持:
n UIO(用戶態IO)
n HUGETLBFS(大頁內存)
n PROC_PAGE_MONITOR支持
n HPET和HPET_MMAP配置項必須打開,若是用到HPET,具體細節看第六章。
對於大的報文內存池內存分配,大頁內存是必須的。(前一章說過運行的內核必須支持大頁內存)。使用大頁內存來分配,即便是小部分頁要用到,性能也可以獲得提高。減小了TLBmiss,對應就減小了虛擬地址轉物理地址的時間。使用小頁4K內存頁,很高頻率的TLBmiss發生會致使性能低下。
申請大頁給DPDK使用
大頁內存的分配最好是在系統啓動時或者是儘可能在系統啓動後越早越好,這樣能夠減小分配的物理內存頁物理地址碎片化。申請大頁內存須要在內核啓動時傳遞一個命令行參數。
對於2MB內存頁,分配1024個2MB內存頁參數以下:
hugepages=1024
其它尺寸的大內存頁,例如1G頁,必須指定申請的內存頁個數和默認內存頁的大小。例如分配4個1G的內存頁,須要指定的參數以下:
default_hugepagesz=1G hugepagesz=1G hugepages=4
注意:大頁內存的尺寸是CPU支持的大小來決定的。intel的機器上經過查看CPU flags來查看支持的大頁內存尺寸。好比pse 表明支持2MB的內存頁,pdpe1gb表明支持1G內存頁。在IBM power架構機器上,支持大頁內存尺寸爲16MB和16GB。
注意:對於64位的應用,若是平臺支持,建議使用1G內存頁。
在雙插槽的NUMA系統中,申請的大頁內存通常會平均在兩個socket上分配(假定兩個socket都有足夠的內存)。
能夠看linux內核源碼樹中Documentation/kernel-parameters.txt獲取更多內核選項的細節。
備選項:
對於2M的頁,能夠在系統啓動後申請分配。echo想要分配的大頁內存頁個數到/sys/devices目錄下的nr_hugepages文件。對於單NUMA(非NUMA)節點的系統,以下命令所示(假設須要1024個2M頁):
echo 1024 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
在一個NUMA機器上,分別在不一樣node上分配指定數目的內存頁:
echo 1024 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages
echo 1024 > /sys/devices/system/node/node1/hugepages/hugepages-2048kB/nr_hugepages
注意:1G的內存頁在系統啓動後是沒法申請。
DPDK使用大頁
一旦申請到大頁內存,要想其被DPDK使用到,執行如下步驟:
mkdir /mnt/huge
mount -t hugetlbfs nodev /mnt/huge
要想是掛載即便是重啓也永久有效,須要把下面一行加到/etc/fstab文件中:
nodev /mnt/huge hugetlbfs defaults 0 0
1GB內存頁,必須在掛載的時候將內存頁的大小做爲參數指定:
nodev /mnt/huge_1GB hugetlbfs pagesize=1GB 0 0
現有的內存管理基於linux內核的大頁機制。在Xen虛擬機管理器上,大頁內存對非特權域(DomainU)的支持意味着DPDK在客戶機上能夠像普通機器上同樣跑。
然而,特權域(domain0)並不支持大頁內存。須要插入新的內核模塊rte_dom0_mm以便繞過這個限制來申請和映射大頁內存,經過ioctl來申請,mmap來映射。
開啓DPDK對Xen Dom0支持
默認狀況下,Xen Dom0模式支持在DPDK的build配置文件中是禁用的。要想支持Xen Dom0,配置項CONFIG_RTE_LIBRTE_XEN_DOM0須要在編譯時改爲y。
此外,配置項CONFIG_RTE_EAL_ALLOW_INV_SOCKET_ID也必須置成y,以防萬一收到錯誤的socket ID。
加載rte_dom0_mm模塊
要在Xen Dom0中跑dpdk程序,rte_dom0_mm模塊必須帶上rsv_memsize參數加載到運行的內核中。能夠在編譯的DPDK目標目錄的子目錄中找到該模塊。該模塊的加載以下使用insmod命令(假設當前處於DPDK編譯的目標目錄下):
sudo insmod kmod/rte_dom0_mm.ko rsv_memsize=X
X的值能夠大於4095MB。
配置DPDK使用的內存
在rte_dom0_mm.ko模塊加載完成後,用戶必須配置DPDK使用的內存。將須要的內存大小echo到/sys/devices/目錄下的memsize文件中便可。使用以下命令(假設須要2048MB內存):
echo 2048 > /sys/kernel/mm/dom0-mm/memsize-mB/memsize
用戶也能夠檢查已經使用了多少內存:
cat /sys/kernel/mm/dom0-mm/memsize-mB/memsize_rsvd
Xen Dom0不支持NUMA配置,因此參數--socket-mem對於Xen Dom0是無效的。
注意:內存大小值不能超過rsv_memsize值。
在Xen Domain0中運行DPDK程序
要跑DPDK程序須要額外提供一個命令行參數--xen-dom0。
注意:本章寫的部分安裝過程也能夠經過後續<快速安裝腳本>一章中描述的腳本實現。
首先,解壓壓縮包並移動到解壓的DPDK源碼目錄:
tar xJf dpdk-<version>.tar.xz
cd dpdk-<version>
DPDK包含如下幾個子目錄:
l lib:DPDK庫的源碼
l drivers:DPDK輪詢驅動的源碼
l app:DPDK應用程序的源碼(自動化測試)
l examples:DPDK應用程序樣例源碼
l config,buildtools,mk:框架相關的Makefiles,腳本和配置文件
DPDK target格式是:
ARCH-MACHINE-EXECENV-TOOLCHAIN
詳解:
l ARCH 能夠是:i686,x86_64,ppc_64
l MACHINE 能夠是:native,power8
l EXECENV 能夠是:linuxapp,bsdapp
l TOOLCHAIN 能夠是:gcc,icc
將要被安裝的target環境取決於要安裝的機器上的包是32位仍是64位。能夠編譯產生的target在DPDK/config目錄下定義了。不要用defconfig_前綴,就是編譯的時候不要帶上這個前綴。
注意:配置文件是RTE_MACHINE下的最優配置集合。在配置文件中,RTE_MACHINE被定義爲native,意味着這是針對本機環境下最佳優化的編譯。對於這些設置的更多信息,能夠採用的值,看DPDK開發者手冊。
當使用ICC編譯器時,下面的命令分別對應32位和64位環境使用。注意這個shell腳本更新$PATH環境變量,所以換個會話就失效了。編譯安裝的目錄多是不一樣的:
source /opt/intel/bin/iccvars.sh intel64
source /opt/intel/bin/iccvars.sh ia32
安裝和生成target,在DPDK的根目錄下使用make install T=<target> 命令。
例如,使用icc編譯64位target:
make install T=x86_64-native-linuxapp-icc
使用gcc編譯32位的:
make install T=i686-native-linuxapp-gcc
只是作建立target的準備,而不是編譯,例如,在編譯以前須要手動修改配置文件的,使用命令make config T=<target>:
make config T=x86_64-native-linuxapp-gcc
警告:
任何內核模塊,好比igb_uio,kni等,必須編譯時的內核和要運行時的內核一致。若是DPDK不是在編譯產生的目標機器上運行, RTE_KERNELDIR環境變量必須指向要運行target機器對應內核版本。
一旦目標環境建立完成,用戶可能須要進入目標環境目錄,修改源碼並從新編譯。用戶也可能修改編譯時的DPDK配置項,經過編輯build目錄下的.config文件(這個文件是從頂層目錄的config目錄下defconfig文件拷貝到本地來的):
cd x86_64-native-linuxapp-gcc
vi .config
make
此外,make clean命令能夠清除全部以前編譯留下的文件。
一旦target建立完成就包含全部的苦,包括輪詢驅動,和用戶程序編譯須要的DPDK環境頭文件。此外,test和testpmd程序在build/app目錄下建立完成,可用於測試。kmod目錄下包含須要加載到內核中的幾個內核模塊。
運行DPDK程序,一個合適的uio模塊須要加載到運行中的內核。在不少例子中,標準的uio_pci_generic LINUX內核模塊能夠提供用戶態驅動能力。該模塊加載以下:
sudo modprobe uio_pci_generic
和上述不一樣的是,DPDK提供了igb_uio模塊來實現(在kmod目錄下):
sudo modprobe uio
sudo insmod kmod/igb_uio.ko
注意:對於缺少對傳統中斷支持的設備,好比VF設備,igb_uio模塊可能須要被uio_pci_generic替換掉。
在DPDK1.7以前版本提供了對VFIO的支持,在支持VFIO的平臺上UIO就不是必須的了。
使用VFIO的DPDK應用程序,vfiopci模塊必須加載:
sudo modprobe vfio-pci
須要注意的是要使用VFIO,你的內核必須支持才行。VFIO內核模塊在LINUX內核3.6.0版本以後就囊括經來了,默認是有的。然而,請翻閱linux發行版文檔肯定一下。
使用VFIO,BIOS和內核都必須支持,BIOS須要打開支持虛擬化的配置選項(例如Intel® VT-d).
在非特權用戶下運行DPDK程序,要正確的操做VFIO,須要創建正確的權限設置。這個能夠經過DPDK安裝腳本實現(dpdk-setup.sh,位於usertools目錄下)
在1.4版本,DPDK程序再也不自動解綁全部支持DPDK的網口,當網口綁定在內核驅動上且正在運行時。取而代之的是,DPDK程序在運行前,必須將使用的全部網口綁定到uio_pci_generic,igb_uio或者是vfio-pci模塊上。任何linux控制下的網口將被DPDK輪詢驅動忽略,不能被DPDK程序使用。
警告:DPDK默認再也不在啓動時自動解綁內核驅動管理的網口。任何PDDK程序使用的網口必須在程序運行前解除linux控制,綁定到對應的驅動上(uio_pci_generic,igb_uio或者是vfio-pci).
將綁定到DPDK的網口解綁並交給linux控制,可使用usertool子目錄下的dpdk_nic_bind.py腳本。這個腳本能夠展現當前系統中全部網口的狀態,能夠將其從不一樣的內核模塊間解綁和綁定,包括uio和vfio模塊。下面是使用腳本的例子。要想獲取腳本的所有使用描述和參數,能夠帶上—help或者是—usage參數啓動腳本。注意,uio或者是vfio內核模塊須要在運行dpdk-nic-bind.py腳本以前加載到內核中。
查看系統中全部網口的狀態:
./usertools/dpdk-devbind.py --status
Network devices using DPDK-compatible driver
============================================
0000:82:00.0 '82599EB 10-GbE NIC' drv=uio_pci_generic unused=ixgbe
0000:82:00.1 '82599EB 10-GbE NIC' drv=uio_pci_generic unused=ixgbe
Network devices using kernel driver
===================================
0000:04:00.0 'I350 1-GbE NIC' if=em0 drv=igb unused=uio_pci_generic *Active*
0000:04:00.1 'I350 1-GbE NIC' if=eth1 drv=igb unused=uio_pci_generic
0000:04:00.2 'I350 1-GbE NIC' if=eth2 drv=igb unused=uio_pci_generic
0000:04:00.3 'I350 1-GbE NIC' if=eth3 drv=igb unused=uio_pci_generic
Other network devices
=====================
<none>
綁定設備eth1,「04:00.1」到uio_pci_generic驅動上:
./usertools/dpdk-devbind.py --bind=uio_pci_generic 04:00.1
或者是:
./usertools/dpdk-devbind.py --bind=uio_pci_generic eth1
恢復設備82:00.0到原始的內核驅動上:
./usertools/dpdk-devbind.py --bind=ixgbe 82:00.0
本章講的是怎麼在DPDK環境下編譯和運行程序。也指出了樣例程序保存在哪裏。
注意:本章寫的部分安裝過程也能夠經過後續<快速安裝腳本>一章中描述的腳本實現。
DPDK目標環境目錄建立完成(例如x86_64-native-linuxapp-gcc),就包含了建立一個dpdk應用程序須要的庫和頭文件。
當在linux DPDK環境下編譯程序,下面兩個環境遍歷必須export:
l RTE_SDK 指向DPDK編譯安裝目錄即target所在目錄
l RTE_TARGET 指向DPDK target目錄名
下面展現的是運行在linux DPDK環境下的例子helloworld。能夠在$RTE_SDK/examples目錄下找到。
目錄下包含main.c文件,默認編譯生成的二進制文件在build目錄下:
cd examples/helloworld/
export RTE_SDK=$HOME/DPDK
export RTE_TARGET=x86_64-native-linuxapp-gcc
make
CC main.o
LD helloworld
INSTALL-APP helloworld
INSTALL-MAP helloworld.map
ls build/app
helloworld helloworld.map
注意:在上面的例子中,helloworld是在DPDK框架目錄中,爲了保證DPDK框架的完整性,能夠把helloworld移動到外部。在下面的例子中,helloworld被拷貝到一個新目錄中從新編譯。
export RTE_SDK=/home/user/DPDK
cp -r $(RTE_SDK)/examples/helloworld my_rte_app
cd my_rte_app/
export RTE_TARGET=x86_64-native-linuxapp-gcc
make
CC main.o
LD helloworld
INSTALL-APP helloworld
INSTALL-MAP helloworld.map
警告:必須在運行DPDK程序前安裝好UIO驅動和大頁內存。
警告:任何進程使用的網口在程序啓動以前必須綁定到適當的內核模塊上,如以前<從內核模塊上綁定和解綁網卡>章節所述。
程序必須連接DPDK target環境EAL(環境抽象層)庫,這個庫提供了每個DPDK程序通用的選項。
下面是能夠傳遞給EAL的參數列表:
./rte-app -c COREMASK [-n NUM] [-b <domain:bus:devid.func>] \
[--socket-mem=MB,...] [-m MB] [-r NUM] [-v] [--file-prefix] \
[--proc-type <primary|secondary|auto>] [-- xen-dom0]
EAL參數以下:
l -c COREMASK:要使用CPU core16進制掩碼。注意core編號在不一樣的平臺不同,須要事先肯定好。
l -n NUM:每一個處理器socket的內存通道數
l -b <domain:bus:devid.func>:網口黑名單,EAL不能使用的PCI設備(能夠同時存在多個-b選項)
l --socket-mem:在指定socket上分配大頁內存
l -m MB:指定分配大大頁內存數,不限處理器的socket。加以使用—socket-mem代替這個參數。
l -r NUM:內存的rank數
l -v:顯示程序版本號
l --huge-dir:大頁內存的掛載點
l --file-prefix:大頁內存文件的前綴
l --proc-type:進程類型
l --xen-dom0:支持程序在Xen Domain0中非大頁內存下運行
l --vmware-tsc-map:使用VMware TSC代替本地的RDTSC
l --base-virtaddr :指定虛擬地址的基址
l --vfio-intr:指定VFIO使用的中斷類型(若是不是用VFIO則無效)
-c是必須的,其它都是可選的。
運行例子程序(假設該平臺每一個處理器socket有4個內存通道,有4個cpu核,且程序都使用上):
./helloworld -c f -n 4
注意:--proc-type和—file-prefix EAL參數用於DPDK多進程。能夠查閱DPDK範例程序一書中多進程章節和DPDK開發手冊獲取更多細節。
CPU核掩碼參數是DPDK程序必須帶上的。掩碼的每一個bit位表明linux顯示的每一個邏輯核的編號。不一樣的平臺之間,邏輯覈編號和邏輯覈編號與NUMA socket的映射關係是不一樣的,因此建議在選在使用核以前先弄清楚該平臺的核分佈。
在初始化DPDK 環境抽象層時,會打印出要使用的邏輯核以及其所在的socket。這些信息也能夠經過查看/proc/cpuinfo文件來知道,例如,執行 cat /proc/cpuinfo。每一個邏輯核的物理ID屬性代表其屬於哪一個CPU socket。
注意:邏輯核分佈視圖能夠經過使用linux工具lstopo獲取。在Fedora系統中,可使用下面的命令安裝使用:
sudo yum install hwloc
./lstopo
警告:邏輯核的分佈在不一樣的主板上是不同的,在選擇使用的核以前要檢查一下。
運行DPDK程序,建議大頁內存用多少就分配多少。若是沒有傳入-m或者是—socket-mem參數,DPDK程序在啓動時自動完成。
若是實際使用的內存超過了傳入參數值指定的值,程序將失敗並退出。然而,若是用戶要申請使用的內存小於預先分配的內存大小,特別是使用了-m選項時,程序自身也會失敗。假定系統在socket0和socket1上各預先分配有1024個2MB內存頁,用戶請求使用128MB內存,64個頁可能不符合要求:
l 內核給予應用程序分配的大頁內存都在socket1上。這種狀況下,若是應用程序試圖在socket0上建立一個對象,好比一個無鎖隊列或者是內存池,程序會失敗。要避免這種問題,建議使用—socket-mem選項代替-m選項。
l 那些大頁內存在物理上是分佈在各處的,然而DPDK EAL試圖分配在物理地址上連續的一段內存,而可能現有的內存頁不是連續的,這種情形下,應用程序沒法申請大的內存池而失敗。
socket-mem選項能夠在指定的socket上分配指定大小的內存頁。要想作到這個,就得在這個選項後面接上要在各個socket上分配內存大小,例如:--socket-mem=0,512,就是在socket1上分配512MB內存。同理,在4socket的系統中,只在socket0和2上各分配1GB內存:--socket-mem=1024,0,1024。某一個CPUsocket上沒有內存分配,那麼就不須要顯式的引用,例如前面socket3就是。若是不能在指定的socket上分配到足夠的內存,EAL初始化失敗。
其它的例子程序在$RTE_SDK./example目錄下。這些程序的編譯和運行方式與本文中以前章節介紹的差很少。此外,能夠查閱DPDK範例程序手冊,該手冊介紹了在編譯和執行程序時的特殊命令參數,以及代碼的說明。
另外,有兩個額外的測試程序在DPDK庫建立的時候編譯出來。源碼在DPDK/app目錄下,名爲test和testpmd。DPDK目標庫建立完成,那麼就能夠在build/app目錄中找到。
l test程序提供了DPDK各類函數的特定測試。
l testpmd程序提供了一些不一樣的報文吞吐測試和特性,例如如何使用intel82599萬兆網卡的Flow Director(引流)特性。
要使用HPET必須BIOS中支持,不然默認採用TSC。通常狀況下,在系統啓動的時候按F2鍵能夠進入BIOS。用戶能夠開啓HPET選項。在intel的Crystal Forest平臺BIOS上,路徑是Advanced -> PCH-IO Configuration -> High Precision Timer -> (Change from Disabled to Enabled if necessary).
在已經啓動的系統中,下面的命令能夠查看HPET是否開啓:
grep hpet /proc/timer_list
若是返回爲空,那麼必須重啓機器並在BIOS中開啓HPET(重複上述的指令)。
DPDK經過將時間戳計數器映射處處理器地址空間來利用平臺的HPET,如此須要HPET_MMAP內核配置項支持。
警告:在Fedora系統和其餘通用linux發行版,例如ubuntu,HPET_MMAP內核選項是默認關閉的。帶此參數從新編譯內核,請查閱發行版文檔瞭解相關操做。
在DPDK中使用HPET
默認狀況下,DPDK編譯配置文件中HPET選項是關閉的。要使用HPET,CONFIG_RTE_LIBEAL_USE_HPET配置項必須改爲y,須要在編譯時修改參數。
程序使用rte_get_hpet_cycles()和rte_get_hpet_hz()接口調用,在程序初始化時調用rte_eal_hpet_init()接口來將HPET做爲rte_timer庫的默認時間源。這個接口將確保HPET可用,若是不可用則返回錯誤值。例如,若是HPET_MMAP內核不支持。那麼程序能夠針對支持或者是不支持而決定採起什麼動做。
注意:若是程序須要時間API,可是HPET不支持,建議採用rte_get_timer_cycles()和rte_get_timer_hz()接口代替HPET接口。這個通用接口既可使用TSC,也可使用HPET做爲時間源,取決因而否在程序啓動是調用rte_eal_hpet_init()接口,若是調用了的話,系統是否支持。
儘管程序經過DPDK可以直接使用網口和硬件資源,可是這些程序若是是做爲普通用戶而不是root用戶,那麼須要作一些小的權限調整。要實現這個,下面這些linux系統文件的全部者和權限必須調整,以便普通linux用戶也能在使用DPDK的時候訪問它們:
l 全部的大頁內存掛載點目錄,例如/mnt/huge
l 在/dev目錄下的用戶態IO設備文件,/dev/uio0,/dev/uio1,等等。
l 用戶態IO系統文件配置和資源文件,例如uio0:
/sys/class/uio/uio0/device/config
/sys/class/uio/uio0/device/resource
l 若是要使用HPET,文件/dev/hpet
注意:在一些linux系統上安裝時,/dev/hugepages會默認做爲大頁內存的掛載點建立。
若是要使用DPDK的電源管理功能,那麼必須在平臺BIOS中開啓加強型INTEL SpeedStep(步進?)技術開關。不然,系統文件/sys/devices/system/cpu/cpu0/cpufreq不會存在,且基於CPU主頻調節的電源管理就沒法使用。查閱相關的BIOS文檔肯定這些設置如何訪問。
例如,在一些INTEL平臺BIOS是不一致的,加強型INTEL SpeedStep技術的路徑是:
Advanced
-> Processor Configuration
-> Enhanced Intel SpeedStep® Tech
此外,要開啓電源管理C3和C6也同樣要打開。C3和C6在一樣的BIOS平臺:
Advanced
-> Processor Configuration
-> Processor C3 Advanced
-> Processor Configuration
-> Processor C6
當一些線程被DPDK程序使用時,這些線程每個會被固定到系統中的一個邏輯核心上(一個線程對應一個邏輯核心),對於linux調度器來講,也有可能會在這些核心上運行其餘任務。爲了阻止調度器將其餘任務調度到DPDK使用的核心上,須要使用內核參數isolcpus來將這些核心從Linux調度器中隔離開來.
例如,DPDK程序使用邏輯核性2,4,6運行程序,下面的這個選項須要加到內核啓動參數中:
isolcpus=2,4,6
要運行DPDK KNI例子程序,須要額外加載一個內核模塊(kni模塊)到運行的linux內核中。能夠在DPDK target目錄下的kmod目錄中找到。同理如加載igb_uio模塊,加載kni也是經過ismod命令來(假設咱們當前處於DPDK target目錄下):
insmod kmod/rte_kni.ko
要在linxu內核中開啓intel VT-d,一系列的內核配置項須要設置:
l IOMMU_SUPPORT
l IOMMU_API
l INTEL_IOMMU
此外,要在intel VT-d虛擬化環境下運行DPDK,當使用igb_uio驅動時,必須設置內核參數iommu=pt。這個是主機中DMAR(DMA Remapping(DMA地址重映射)透傳的結果。INTEL_IOMMU_DEFAULT_ON在內核中也沒有設置,內核參數inte_iommu=on必須使用。這能夠確保intel IOMMU按照指望被初始化。
請注意,使用igb_uio驅動時必須使用iommu=pt參數,而vfio-pci驅動則是使用iommu=pt和iommu=on兩者均可以運行。
在最新版本的固件鏡像中,性能加強的問題解決了,固件更新能夠獲取更高的性能。用戶須要檢查本地的intel網卡驅動版本。用戶須要查閱DPDK版本說明文檔肯定這個版本對應的網卡i40E驅動版本。
i40e輪詢驅動支持16和32字節的RX描述符大小,而16個字節的可以提供更高的小包處理性能。須要在配置文件中修改CONFIG_RTE_LIBRTE_I40E_16BYTE_RX_DESC參數爲使用16個字節的RX描述符。
因爲硬件設計的緣由,每一個報文描述符的回寫須要在網卡內產生一箇中斷信號。最小的中斷間隔須要在編譯時修改配置文件中的CONFIG_RTE_LIBRTE_I40E_ITR_INTERVAL參數。儘管有默認配置,用戶能夠根據本身的實際狀況,看是更在意性能仍是時延來調優這個參數。
dpdk-setup.sh腳本,在usertools子目錄下,能夠幫助用戶執行下面的任務:
l 編譯DPDK庫
l 插入和移走DPDK IGB_UIO內核模塊
l 插入和移走VFIO內核模塊
l 插入和移走DPDK KNI內核模塊
l 建立和刪除NUMA和非NUMA下的大頁內存
l 網口狀態試圖展現和分配網口給DPDK程序使用
l 爲使用VFIO的非特權用戶分配權限
l 運行test和testpmd程序
l 展現在meminfo中的大頁信息
l 列出/mnt/huge中的大頁
l 刪除建立的DPDK庫
dpdk-setup.sh腳本是用戶按照用戶的執行命令邏輯順序來組織起來的一系列的步驟。每個步每一步都提供了一些提示信息幫助用戶完成要求的任務。下面是每一步的簡單概述。
step 1:編譯DPDK庫
最開始,用戶必須選擇一個DPDK target,匹配類型和編譯選項,以便生成正確的庫。
用戶必須按照前面章節所述,將全部須要的庫,模塊,更新和編譯須要的東西安裝好。
step2:安裝環境
用戶配置DPDK程序運行所需的linux環境。大頁內存的創建。任何已存的大頁內存會被移除。DPDK用到的內核模塊也在這步中插入,DPDK程序使用的網卡接口也綁定到對應的模塊。
step3:運行程序
用戶可能須要在上面步驟完成後運行test程序。test程序容許執行一系列的DPDK功能測試。testpmd支持收發包相關的測試。
step4:檢查系統
這步提供了一些工具來檢查系統的大頁內存狀態。
step5:系統還原
最後一步是恢復系統到原有的狀態。
下面是一些使用dpdk-setup.sh腳本的用例。這個腳本應該使用source命令來運行。
警告:腳本須要在root權限下運行。
source usertools/dpdk-setup.sh
------------------------------------------------------------------------
RTE_SDK exported as /home/user/rte
------------------------------------------------------------------------
Step 1: Select the DPDK environment to build
------------------------------------------------------------------------
[1] i686-native-linuxapp-gcc
[2] i686-native-linuxapp-icc
[3] ppc_64-power8-linuxapp-gcc
[4] x86_64-native-bsdapp-clang
[5] x86_64-native-bsdapp-gcc
[6] x86_64-native-linuxapp-clang
[7] x86_64-native-linuxapp-gcc
[8] x86_64-native-linuxapp-icc
------------------------------------------------------------------------
Step 2: Setup linuxapp environment
------------------------------------------------------------------------
[11] Insert IGB UIO module
[12] Insert VFIO module
[13] Insert KNI module
[14] Setup hugepage mappings for non-NUMA systems
[15] Setup hugepage mappings for NUMA systems
[16] Display current Ethernet device settings
[17] Bind Ethernet device to IGB UIO module
[18] Bind Ethernet device to VFIO module
[19] Setup VFIO permissions
------------------------------------------------------------------------
Step 3: Run test application for linuxapp environment
------------------------------------------------------------------------
[20] Run test application ($RTE_TARGET/app/test)
[21] Run testpmd application in interactive mode ($RTE_TARGET/app/testpmd)
------------------------------------------------------------------------
Step 4: Other tools
------------------------------------------------------------------------
[22] List hugepage info from /proc/meminfo
------------------------------------------------------------------------
Step 5: Uninstall and system cleanup
------------------------------------------------------------------------
[23] Uninstall all targets
[24] Unbind NICs from IGB UIO driver
[25] Remove IGB UIO module
[26] Remove VFIO module
[27] Remove KNI module
[28] Remove hugepage mappings
[29] Exit Script
選項:
下面是展現選擇建立x86_64-native-linuxapp-gcc DPDK庫的例子:
Option: 9
================== Installing x86_64-native-linuxapp-gcc
Configuration done
== Build lib
...
Build complete
RTE_TARGET exported as x86_64-native-linuxapp-gcc
下面是展現插入DPDK UIO驅動的例子:
Option: 25
Unloading any existing DPDK UIO module
Loading DPDK UIO module
下面的選擇是展現建立NUMA系統下的大頁內存。分別在兩個node上各分配1024個2MB內存頁。那麼程序就須要系統-m 4096參數來訪問這兩塊內存。(若是沒有提供-m參數,那麼程序會自動執行)。
注意:若是提示移除臨時文件,輸入y。
Option: 15
Removing currently reserved hugepages
mounting /mnt/huge and removing directory
Input the number of 2MB pages for each node
Example: to have 128MB of hugepages available per node,
enter '64' to reserve 64 * 2MB pages on each node
Number of pages for node0: 1024
Number of pages for node1: 1024
Reserving hugepages
Creating /mnt/huge and mounting as hugetlbfs
下面是展現選擇加載test程序到一個邏輯核上運行:
Option: 20
Enter hex bitmask of cores to execute test app on
Example: to execute app on cores 0 to 7, enter 0xff
bitmask: 0x01
Launching app
EAL: coremask set to 1
EAL: Detected lcore 0 on socket 0
...
EAL: Master core 0 is ready (tid=1b2ad720)
RTE>>
一旦用戶運行dpdk-setup.sh腳本,編譯EAL庫,創建好大頁內存(加入使用的是linxu EAL目標),用戶可能接着會去編譯和運行本身的程序或者是例子程序。
在/examples目錄下的例子提供瞭解DPDK操做的好的起點。下面的命令展現了helloworld程序是怎麼編譯和運行的。如同上述章節建議的,<程序使用的邏輯核心>,邏輯核心在平臺上的分佈應該在選擇程序使用的邏輯核掩碼時肯定好。
cd helloworld/
make
CC main.o
LD helloworld
INSTALL-APP helloworld
INSTALL-MAP helloworld.map
sudo ./build/app/helloworld -c 0xf -n 3
[sudo] password for rte:
EAL: coremask set to f
EAL: Detected lcore 0 as core 0 on socket 0
EAL: Detected lcore 1 as core 0 on socket 1
EAL: Detected lcore 2 as core 1 on socket 0
EAL: Detected lcore 3 as core 1 on socket 1
EAL: Setting up hugepage memory...
EAL: Ask a virtual area of 0x200000 bytes
EAL: Virtual area found at 0x7f0add800000 (size = 0x200000)
EAL: Ask a virtual area of 0x3d400000 bytes
EAL: Virtual area found at 0x7f0aa0200000 (size = 0x3d400000)
EAL: Ask a virtual area of 0x400000 bytes
EAL: Virtual area found at 0x7f0a9fc00000 (size = 0x400000)
EAL: Ask a virtual area of 0x400000 bytes
EAL: Virtual area found at 0x7f0a9f600000 (size = 0x400000)
EAL: Ask a virtual area of 0x400000 bytes
EAL: Virtual area found at 0x7f0a9f000000 (size = 0x400000)
EAL: Ask a virtual area of 0x800000 bytes
EAL: Virtual area found at 0x7f0a9e600000 (size = 0x800000)
EAL: Ask a virtual area of 0x800000 bytes
EAL: Virtual area found at 0x7f0a9dc00000 (size = 0x800000)
EAL: Ask a virtual area of 0x400000 bytes
EAL: Virtual area found at 0x7f0a9d600000 (size = 0x400000)
EAL: Ask a virtual area of 0x400000 bytes
EAL: Virtual area found at 0x7f0a9d000000 (size = 0x400000)
EAL: Ask a virtual area of 0x400000 bytes
EAL: Virtual area found at 0x7f0a9ca00000 (size = 0x400000)
EAL: Ask a virtual area of 0x200000 bytes
EAL: Virtual area found at 0x7f0a9c600000 (size = 0x200000)
EAL: Ask a virtual area of 0x200000 bytes
EAL: Virtual area found at 0x7f0a9c200000 (size = 0x200000)
EAL: Ask a virtual area of 0x3fc00000 bytes
EAL: Virtual area found at 0x7f0a5c400000 (size = 0x3fc00000)
EAL: Ask a virtual area of 0x200000 bytes
EAL: Virtual area found at 0x7f0a5c000000 (size = 0x200000)
EAL: Requesting 1024 pages of size 2MB from socket 0
EAL: Requesting 1024 pages of size 2MB from socket 1
EAL: Master core 0 is ready (tid=de25b700)
EAL: Core 1 is ready (tid=5b7fe700)
EAL: Core 3 is ready (tid=5a7fc700)
EAL: Core 2 is ready (tid=5affd700)
hello from core 1
hello from core 2
hello from core 3
hello from core 0
本章是在INTEL平臺上DPDK程序得到高性能的一步步引導。
要最好的性能最好是使用intel至強系列服務器,例如Ivy Bridge,Haswell或者是更新的架構的服務器。
確保每個內存通道至少有一個內存DIMM插入,且內存的大小至少4GB。注意:這個在性能上有最直接的影響。
你能夠檢查內存配置經過dmidecode命令,以下:
dmidecode -t memory | grep Locator
Locator: DIMM_A1
Bank Locator: NODE 1
Locator: DIMM_A2
Bank Locator: NODE 1
Locator: DIMM_B1
Bank Locator: NODE 1
Locator: DIMM_B2
Bank Locator: NODE 1
...
Locator: DIMM_G1
Bank Locator: NODE 2
Locator: DIMM_G2
Bank Locator: NODE 2
Locator: DIMM_H1
Bank Locator: NODE 2
Locator: DIMM_H2
Bank Locator: NODE 2
上面的輸出展現了總共8個內存通道,每一個通道有2個DIMM。
也能夠經過dmidecode命令肯定內存的頻率:
dmidecode -t memory | grep Speed
Speed: 2133 MHz
Configured Clock Speed: 2134 MHz
Speed: Unknown
Configured Clock Speed: Unknown
Speed: 2133 MHzConfigured Clock Speed: 2134 MHz
Speed: Unknown
...
Speed: 2133 MHz
Configured Clock Speed: 2134 MHz
Speed: Unknown
Configured Clock Speed: Unknown
Speed: 2133 MHz
Configured Clock Speed: 2134 MHz
Speed: Unknown
Configured Clock Speed: Unknown
上述輸出代表內存爲2133MHz的DDR4內存。和前面的信息結合起來能夠肯定每一個內存通道有一根內存條。
使用DPDK支持的高端網卡,好比INTEL XL710 40GBE。
確保每個網卡刷入了最新版本的固件。
使用PCIe Gen3插槽,例如Gen3 x8或者是Gen3 x16,由於PCIe Gen2插槽沒法提供足夠的寬帶,2X10Gbe或者是更高。能夠經過使用lspci命令檢查PCI插槽的使用信息:
lspci -s 03:00.1 -vv | grep LnkSta
LnkSta: Speed 8GT/s, Width x8, TrErr- Train- SlotClk+ DLActive- ...
LnkSta2: Current De-emphasis Level: -6dB, EqualizationComplete+ ...
當擦汗如網卡到PCI插槽時總要檢查說明信息,例如CPU0或者是CPU1鏈接到的是哪一個socket上。
多考慮一下NUMA。若是你使用2個或者是更多的不一樣的網口,最好確保這些網卡在一樣的CPU socket上。如何肯定看下面的例子。
下面是推薦的BIOS設置項。不一樣的平臺上可能有不一樣的BIOS名稱,因此下面主要是做爲參考:
下面是GRUB啓動參數建議設置:
default_hugepagesz=1G hugepagesz=1G hugepages=8
isolcpus=2,3,4,5,6,7,8
iommu=pt intel_iommu=on
下面的shell命令有助於編譯和配置DPDK。
# Build DPDK target.
cd dpdk_folder
make install T=x86_64-native-linuxapp-gcc -j
# Get the hugepage size.
awk '/Hugepagesize/ {print $2}' /proc/meminfo
# Get the total huge page numbers.
awk '/HugePages_Total/ {print $2} ' /proc/meminfo
# Unmount the hugepages.
umount `awk '/hugetlbfs/ {print $2}' /proc/mounts`
# Create the hugepage mount folder.
mkdir -p /mnt/huge
# Mount to the specific folder.
mount -t hugetlbfs nodev /mnt/huge
cd dpdk_folder
usertools/cpu_layout.py
# List all the NICs with PCI address and device IDs.
lspci -nn | grep Eth
舉例說明,假設輸出是這樣的:
82:00.0 Ethernet [0200]: Intel XL710 for 40GbE QSFP+ [8086:1583]
82:00.1 Ethernet [0200]: Intel XL710 for 40GbE QSFP+ [8086:1583]
85:00.0 Ethernet [0200]: Intel XL710 for 40GbE QSFP+ [8086:1583]
85:00.1 Ethernet [0200]: Intel XL710 for 40GbE QSFP+ [8086:1583]
檢查PCI設備所述的NUMA節點ID:
cat /sys/bus/pci/devices/0000\:xx\:00.x/numa_node
一般狀況下,0x:00.x是位於socket0上,8x:00.x位於socket1上。注意:爲了得到更高的性能,確保cpu核心和網卡在一樣的socket上。例如上面的85:00.0在socket1上,那麼它被socket1上的核心使用能得到最好的性能。
# Bind ports 82:00.0 and 85:00.0 to dpdk driver
./dpdk_folder/usertools/dpdk-devbind.py -b igb_uio 82:00.0 85:00.0
# Check the port driver status
./dpdk_folder/usertools/dpdk-devbind.py –status
查看dpdk-devbind.py –help獲取更多細節。
下面是運行DPDK3層轉發例子:l3fwd程序,使用intel服務器平臺和intelXL710網卡獲的高性能。對於特殊的40GbE午那個卡的配置請查閱i40e網卡手冊。
這個例子展現的是在兩個INTELXL710 40GbE網口下得到的最好性能。
82:00.0 Ethernet [0200]: Intel XL710 for 40GbE QSFP+ [8086:1583]
85:00.0 Ethernet [0200]: Intel XL710 for 40GbE QSFP+ [8086:1583]
./l3fwd -c 0x3c0000 -n 4 -w 82:00.0 -w 85:00.0 \
-- -p 0x3 --config '(0,0,18),(0,1,19),(1,0,20),(1,1,21)'
這表明着程序使用core18轉發port0的隊列0,core19轉發port0的隊列1,core20轉發port1的隊列0,core21轉發port1的隊列1。
a) 在發包器上建立一個流
b) 設置以太網II類型爲0x8000