DPDK2.1 linux上開發入門手冊

1引言node

  本文檔主要包含INTEL DPDK安裝和配置說明。目的是讓用戶快速的開發和運行程序。文檔描述瞭如何在不深刻細節的狀況下在linux應用開發環境上編譯和運行一個DPDK應用程序。python

1.1文檔總覽linux

  如下是DPDK文檔列表,建議按照文檔順序閱讀:ios

  • Release Note:提供版本特有信息,包括支持的型號,限制,修正的問題,一直的問題等等。也提供一些在常見問題解答中被頻繁問道的問題的大案。
  • 入門指導(Getting Started Guide(本文檔)):描述怎麼安裝和配置DPDK,目的是讓用戶快速開發和運行軟件。
  • 開發手冊(Programmer's Guide):描述:
    • 軟件架構和如何在linux環境下運行一個DPDK範例程序
    • DPDK的內容,開發系統(包括如何在DPDK根目錄下使用的編譯Makefile的指令來編譯開發庫和運用程序)和移植一個應用程序參考
    • 軟件優化和須要在新的開發環境考慮的問題。
  • 也提供了關鍵詞彙表:
    •   API手冊:提供了DPDK上的函數,數據結構和其它編程結構的詳細信息。
  • 範例使用手冊(Sample Application User Guide):描述了一系列的範例程序,每一個章節都描述了一個有特殊功能的示例,提供了編譯,運行和使用示例的操做指南。

注意:以上文檔均可以從DPDK源碼包的同一個位置上分別下載。c++

2系統必備條件shell

本章講的是編譯DPDK源碼包必須具備的環境。編程

注意:若是DPDK要用到intel的89XX系列的網卡平臺上,請先翻閱89xx網卡系列的入門手冊。ubuntu

2.1X86上BIOS先決條件緩存

  對於主要的平臺,沒有什麼特別的BIOS設置才能用DPDK的基本功能。然而總有例外的,對於HPET高精度時鐘,能源管理功能,在40g網卡上高性能的小包收發,BIOS設置須要改一下。請看第5章(其它功能的開啓)來獲取須要作哪些更改的信息。網絡

2.2編譯DPDK

注意:測試是在Fedora18上,編譯安裝指令在其它系統上可能不同。在其它linux發行版本上的測試細節請參閱DPDKrelease note。

  • GNU make
  • coreutils:cmp,sed,grep,arch
  • gcc:在686/x86_64平臺上得大於等於4.5.x版本,對於ppc_64 和x86_x32程序,建議用4.8.x版本。一些特殊的編譯標識和鏈接標示默認是打開的,會影響到性能(例如-fsatckprotector),請參閱你所使用版本的說明文檔和使用gcc -dumpspecs來查看。
  • c庫:intel的架構上要求glibc-devel.i686 / libc6-dev-i386; glibc-devel.x86_64 for 64-bit,ibm power架構則要求glibc-devel.ppc64 for 64 bit
  • linux內核源碼庫頭文件用於編譯內核模塊:kernel-devel.x86_64,kernel - devel.ppc64
  • 另外32位和64位編譯環境須要的包有:glibc.i686, libgcc.i686, libstdc++.i686 and glibc-devel.i686 for Intel i686/x86_64;glibc.ppc64, libgcc.ppc64, libstdc++.ppc64 and glibc-devel.ppc64 for IBM ppc_64;

注意:x86_32應用程序接口只支持最新的debian發行版和13.10以上版本的unbuntu。惟一支持的gcc版本是4.8+。

注意:python須要2.6或者是2.7,在dpdk安裝包中有各類各樣的幫助腳本。

可選的工具:

  •  intel C++編譯器(icc)。須要安裝一些其它的庫,本身看編譯器安裝的說明文檔吧,這個版本已經在icc 12.1上測過
  • IBM powerLinux工具鏈。這是一系列的開源開發工具和可以用到power最新linux硬件特徵的動態庫,要安裝的話看ibm的官方文檔
  • 編譯和使用基於libpcap庫的輪詢驅動須要libpcap頭文件和庫(libpcap-devel)。驅動默認是不能用的,要用的話須要在編譯時設置config文件中的CONFIG_RTE_LIBRTE_PMD_PCAP=y

2.3運行DPDK程序

要運行dpdk程序,在目標機器上須要一些本地化要求。

2.3.1系統軟件

要求:

  •   內核版本 >= 2.6.33

  當前在使用的內核版本能夠經過如下命令獲取:

  uname -r

對於在更早的內核版本上使用DPDK須要的補丁細節,能夠看DPDK的Release Notes中的DPDK FAQ。也要注意redhat 6.2和6.3使用的2.6.32內核版本須要用到全部必須得補丁。

  •   glibc >= 2.7(由於cpuset相關的操做)

  c庫版本能夠經過使用ldd -version命令獲取,一個命令使用結果例子以下:

  # ldd --version
  ldd (GNU libc) 2.14.90
  Copyright (C) 2011 Free Software Foundation, Inc.
  This is free software; see the source for copying conditions. There is NO
  warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  Written by Roland McGrath and Ulrich Drepper.

  • 內核配置

  在fedora os和其它普通的linux發行版,例如ubuntu,或者是紅帽企業版linux,供應商提供的內核配置能夠跑大部分DPDK應用。

  對於其它內核版本,要使用DPDK必須使一下選項能支持:

    • UIO支持
    • HUGETLBFS(大頁內存用到的庫)
    • PROC_PAGE_MONITOR支持
    • 要使用HPET就要求HPET和HPET_MMAP配置項能支持。看5.1章《高精度定時器(HPET)功能》細節。

2.3.2在linux上使用大頁內存

對於要緩存報文的超大內存池的內存分配必須用hugepage,(HUGETLBFS選項在當前容許的內核上必須是支持的,入2.3所說的)使用大頁來分配內存,即便只使用少數頁面,性能也是可以獲得提高的。由於用到更少的頁表緩衝條目(TLBs,高速翻譯緩存),能夠減小翻譯虛擬地址到物理地址的時間,若是不用大頁,那麼用4k的頁較高的TLB丟失率會下降性能。實際上還有一個好處就是不會被交換到磁盤上去。

獲取DPDK使用的大頁內存

分配大頁內存最好是在系統啓動時或者是在啓動後儘早,以便於申請的內存減小碎片,即內存在物理上儘可能是連續的。在內核啓動時獲取大頁內存,須要將一個參數傳遞給內核。

對於2m的頁,僅僅只須要將大頁選項發送給內核。例如,申請1024個2m的頁:

    hugepages=1024

對於其它尺寸的大頁內存,例如1g的頁,頁大小必須明確的指定,也能設置系統的默認大頁內存大小。例如申請4g大小的大內存經過4個1g內存頁的形式,須要將如下選項發給內核:

  default_hugepagesz=1G hugepagesz=1G hugepages=4

注意:在intel的架構機器上cpu支持的大頁內存的尺寸取決於CPU標識(這些標示能夠經過查看/proc/cpuinfo獲取),若是pse存在,那麼2m頁支持,pdpe1gb存在,則1g頁支持。在IBM power架構的機器上,支持16M和16G的頁。

注意:64位機器,交付時若是平臺支持那天生就支持1g頁了。

對於2個socket的NUMA系統,申請的大頁內存數在系統啓動時通常是從兩個socket上平均分配(假定兩個socket上都有足夠的內存),如上,4g就是一個socket上分出2g內存。

能夠看內核源碼樹的Documentation/kernel-parameter.txt文件獲取更多的內核選項細節。

可選項:

  2m的頁也能夠在系統啓動後申請,經過echo 內存頁數目到/sys/devices/目錄下的文件nr_hugepages中。對於單node的系統,使用一下命令獲取1024個2m內存頁:

  echo 1024 > /sys/kernel/mm/hugepages/hugepages_2048kb/nr_huge

在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的大內存頁是不可能在系統啓動以後申請分配的。

 2.3.3 linux環境下Xen Domain0支持

當前的內存管理基於linux內核的大內存頁機制,在Xen虛擬機監視器上,大頁支持無特權帳戶意味着DPDK程序是做爲一個普通用戶態程序運行。

然而,Domain0不支持大頁的,解決這個限制須要,內核模塊rte_dom0_mm加入,使得能夠經過IOCTL和MMAP來分配和映射內存。

在DPDK中打開Xen Dom0模式

默認狀況下,Xen Dom0在DPDK配置文件中是關閉的,要支持Xen Dom0就須要改變配置項CONFIG_RTE_LIBRTE_XEN_DOM0的值爲y,那這個功能在編譯時就是打開的。

此外,CONFIG_RTE_EAL_ALLOW_INV_SOCKET_ID選項也應該設爲y,避免萬一收到錯誤的socket id。

加載DPDK rte_dom0_mm模塊

在Xen Dom0上跑DPDK程序,rte_dom0_mm模塊必須帶着參數rsv_memsize選項加載入運行中的內核中。模塊能夠在DPDK目錄下的子目錄kmod中找到,加載時使用insmod命令,像下面同樣操做(假設咱們當前處於DPDK的根目錄下):

sudo insmod kmod/rte_dom0_mm.ko rsc_memsize=X

X的值能夠大於4096(MB)

配置DPDK使用的內存

在加載完rte_dom0_mm.ko內核模塊後,用戶必須配置DPDK使用的內存大小。經過echo 內存頁數目到/sys/devices/目錄下的內存大小配置文件中。使用以下命令(假設須要2048MB內存):

echo 2048 >/sys/kernel/mm/dom0_mm/memsize-mB/memsize

用戶也能夠檢查當前已經使用了多少內存:

cat /sys/kernel/mm/dom0-mm/memsize-mB/memsize_revd

Xen Domain0不支持NUMA配置,因此–socket-mem選項對它來講是沒用的。

注意:內存大小值不能大於rsv_memsize值

在Xen Domain0上跑DPDK程序

要在Xen Domain0上跑DPDK程序,必須帶上額外的選項–xen-dom0

 

3編譯DPDK源碼包

3.1安裝DPDK和查看源碼

首先,解壓壓縮包並進入DPDK目錄:

user@host:~$ unzip DPDK-<version>.zip
user@host:~$ cd DPDK-<version>
user@host:~/DPDK-<version>$ ls
app/ config/ drivers/ examples/ lib/ LICENSE.GPL LICENSE.LGPL Makefile mk/ sc

解壓的DPDK目錄下有幾個子目錄:

  • lib:DPDK庫源碼
  • drivers:DPDK PMD源碼
  • app:DPDK程序源碼(自動化測試用)
  • examples:DPDK應用程序範例源碼
  • config,tools,scripts,mk:框架相關的makefile文件,腳本,配置文件等。

3.2在目標機器環境下安裝DPDK

安裝DPDK的結果格式以下(就是在當前目錄下回出現一個新目錄,目錄名格式):

ARCH-MACHINE-EXECENV-TOOLCHAIN

  • ARCH:i686, x86_64, ppc_64
  • MACHINE:native, ivshmem, power8
  • EXECENV:linuxapp,bsdapp
  • TOOCHAIN:gcc,icc

我在redhat上的是x86_64-native-linuxapp-gcc(intel的ICC編譯器沒用過...,聽說在intel的機器上,用icc性能高一些)

生成的文件取決於32/64位安裝包和機器上的編譯器。能實現的結果能夠在DPDK/config中看到。defconfig_ prefix不必用到。

注意:提供的配置文件是根據RTE_MACHINE優化的最優選項集,在配置文件中,RTE_MACHINE配置項

被設爲native,意味着編譯軟件會自動匹配編譯的平臺。要看更多關於設置和可能值的詳細星系,請看DPDK Programmers Guide

當使用intel的C++編譯器icc,須要針對64位和32位系統分別執行下面的命令。注意shell腳本更新了PATH環境變量,所以在同一個會話中不須要再執行了。另外,確認編譯的安裝目錄由於目錄可能不同:

source /opt/intel/bin/iccvars.sh intel64

source /opt/intel/bin/iccvars.sh ia32

安裝和編譯,在DPDK根目錄下執行make install T=<target>命令。

例如,用icc編譯64位系統,執行:

make install T=x86_64-native-linuxapp-icc

用gcc編譯32位系統,命令以下:

make install T=i686-native-linuxapp-gcc

用gcc編譯64位系統:

make install T=x86_64*gcc

同時使用gcc和icc編譯64位系統:

make install T=x86_64-*

注意:通配符*表示能夠同時生成多個結果。

準備編譯而不是編譯它,例如,配置被改變了須要在編譯前make一下,使用make config T=<target>命令:make config T=x86_64-native-linuxapp-gcc

提示:任意一個使用到的內核模塊,如igb_uio,rte,必須在目標機器上同一個運行的內核上編譯。若是你的DPDK不是要裝在本機,那麼編譯前須要將RTE_KERNELDIR指向須要安裝的機器的內核版本的一個拷貝。

暈:忘了保存了........,再來一遍

一旦環境配置好了,那麼進入配置的目錄修改代碼並編譯。用戶若是要修改編譯時的配置,那麼修改安裝目錄下的.config文件。它是安裝根目錄下的config目錄中的defconfig文件的一個拷貝。

cd x86_64-native-linuxapp-gcc
vi .config
make

此外,make clean命令能夠清除以前編譯產生的文件,以便從新編譯。

3.3查看安裝完成的DPDK環境目錄

一旦編譯完成,那麼這個DPDK環境目錄包含全部的庫文件,PMD,全部DPDK應用程序須要用到了DPDK頭文件。此外,測試程序和測試PMD程序在對應的build/app目錄下,能夠用來測試。當前的kmod目錄下須要被加載到內核中的木塊。

$ ls x86_64-native-linuxapp-gcc
app build hostapp include kmod lib Makefile

3.4加載內核模塊實現DPDK用戶態IO

跑dpdk程序,對應匹配的uio模塊須要加載到運行的內核中。不少狀況下,linux內核已經有的uio_pci_generic模塊能夠提供uio能力,能夠經過如下命令加載:

sudo modprobe uio_pci_generic

相對這個正式的方式,DPDK還提供kmod子目錄下的igb_uio模塊實現這個功能。加載以下:

sudo modprobe uio

sudoi insmod kmod/igb_uio.ko

注意:對於一些缺少對中斷支持的設備,例如虛擬設備(VF),igb_uio須要用來替換uio_pci_generic。

從DPDK1.7以上版本提供VFIO支持之後,對於使用VFIO的平臺來講,用不用uio就無所謂了。

3.5在家VFIO模塊

運行一個使用VFIO的程序,vfio-pci模塊必須加載:

sudo modprobe vfio-pci

固然要使用VFIO,內核也必須支持才行。自動3.6.0內核版本以來都包含有VFIO模塊且默認都是加載的,可是最好是看看對應使用的linux發行版本的說明文檔以防萬一。

哎,用VFIO,內核和BIOS都必須支持且被配置使用IO virtualization(例如 intel@VT-d(bios裏面的一個選項)

對於非root用戶在跑dpdk程序時,應該賦予相應的權限操做VFIO。能夠經過DPDK腳原本實現(在tools目錄下,名字是setup.sh)

3.6綁定和解綁網卡從內核模塊

自從dpdk1.4版本起,dpdk程序再也不須要自動的解綁全部支持dpdk且內核驅動正在用的網卡。取而代之的是,dpdk程序要用到的網卡必須在程序運行前綁定到uio_pci_generic, igb_uio或者vfio-pci模塊。在linux內核驅動控制下的網卡都會被dpdk的pmd忽略,也不會被程序使用。

提示:dpdk將,也是默認,再也不在啓動時自動從linux內核驅動解綁每一個網卡。任意一個要被dpdk用到的網卡必須在程序運行前先從linux控制下解綁而後綁定到對應的uio_pci_generic, igb_uio or vfio-pci。

綁定網卡到uio_pci_generic, igb_uio or vfio-pci供dpdk使用,以及將網卡返回給linux系統控制,tools子目錄下叫dpdk_nic_bind.py腳本能夠提供該功能。這個腳本能夠列出當前系統內全部網卡的狀態信息,也能夠從不一樣linux驅動綁定或者解綁網卡,包括uio和vfio模塊。下面是一些展現腳本如何使用的例子。對於腳本完整的功能和參數介紹能夠經過使用腳本帶上-help或者是-usage參數。要注意的是使用dpdk_nic_bind.py腳本前須要將uio或者是vfio加載到內核中。

提示:對於使用VFIO的設備會有一些限制。主要歸結於IOMMU分組如何工做。任何虛擬設備就其自己而言均可以使用VFIO,可是對於物理設備要求綁定到VFIO,或者是其中一些綁定到VFIO而另外的不綁定到任何東西上。

若是你的設備是在一個PCI-to-PCI網橋以後,網橋將做爲設備的IOMMU組的一部分。因此當設備在網橋以後工做於VFIO,網橋驅動也必須與網橋PCI設備解綁。

提示:任何用戶可使用腳本查看網卡狀態,解綁和綁定網卡,可是須要root權限。

上面這個xen啊,vfio啊,不是很懂,翻譯的不是很清楚,也可能翻譯錯了,想搞明白仍是看原文吧。

看系統內網卡的狀態:

root@host:DPDK# ./tools/dpdk_nic_bind.py --status
Network devices using DPDK-compatible driver
============================================
0000:82:00.0 '82599EB 10-Gigabit SFI/SFP+ Network Connection' drv=uio_pci_generic unused=ixgbe
0000:82:00.1 '82599EB 10-Gigabit SFI/SFP+ Network Connection' drv=uio_pci_generic unused=ixgbe
Network devices using kernel driver
===================================
0000:04:00.0 'I350 Gigabit Network Connection' if=em0 drv=igb unused=uio_pci_generic *Active*
0000:04:00.1 'I350 Gigabit Network Connection' if=eth1 drv=igb unused=uio_pci_generic
0000:04:00.2 'I350 Gigabit Network Connection' if=eth2 drv=igb unused=uio_pci_generic
0000:04:00.3 'I350 Gigabit Network Connection' if=eth3 drv=igb unused=uio_pci_generic
Other network devices
=====================
<none>

綁定網卡eth1,04:00.1(eth1的pci號),到uio_pci_generic驅動:

root@host:DPDK# ./tools/dpdk_nic_bind.py --bind=uio_pci_generic 04:00.1

或者是用這種方式:

root@host:DPDK# ./tools/dpdk_nic_bind.py --bind=uio_pci_generic eth1

恢復設備82:00.0,綁定到原有的內核驅動:

root@host:DPDK# ./tools/dpdk_nic_bind.py --bind=ixgbe 82:00.0

4編譯和運行範例程序

本章介紹瞭如何編譯和在DPDK環境下運行程序,也指示了範例程序存在哪裏。

注意:本章的部份內容能夠在第6章描述的使用安裝腳本後操做。

4.1編譯範例程序

一旦DPDK環境建立完成(例如x86_64-nativelinuxapp-gcc),包含開發程序須要的全部的DPDK庫和頭文件。

當在linux下編譯一個基於dpdk的程序,下面的兩個參數要被導出:

RTE_SDK:指向DPDK安裝目錄

RTE_TARGET:指向DPDK目的環境目錄,就是編譯dpdk產生的目錄,例如x86_64-nativelinuxapp-gcc

下面是建立helloworld程序的例子,這個是在dpdk linux環境在運行的。這個例子能夠在${RTE_SDK}/examples目錄下找到。

這個目錄包含一個main.c文件。這個文件和dpdk目錄下的庫結合,調用各類初始化dpdk環境的函數,而後加載每一個core的入口函數(分發程序)運行。(這個我本身明白可是翻譯的不清楚,實際就是在dpdk線程上運行一個入口函數,在函數內再根據所在的邏輯核配置跑對應的功能,入rx,tx,fp)。默認編譯產生的可執行二進制文件在build目錄下。

user@host:~/DPDK$ cd examples/helloworld/
user@host:~/DPDK/examples/helloworld$ export RTE_SDK=$HOME/DPDK
user@host:~/DPDK/examples/helloworld$ export RTE_TARGET=x86_64-native-linuxapp-gcc
user@host:~/DPDK/examples/helloworld$ make
CC main.o
LD helloworld
INSTALL-APP helloworld
INSTALL-MAP helloworld.map
user@host:~/DPDK/examples/helloworld$ ls build/app
helloworld helloworld.map

注意:在上面的例子中,helloworld是在dpdk目錄框架下。然而也有可能它再也不dpdk目錄下以保證dpdk的完整。在下面的例子中,helloworl程序就是從dpdk目錄下將helloworld拷貝到一個新的目錄下:

user@host:~$ export RTE_SDK=/home/user/DPDK
user@host:~$ cp -r $(RTE_SDK)/examples/helloworld my_rte_app
user@host:~$ cd my_rte_app/
user@host:~$ export RTE_TARGET=x86_64-native-linuxapp-gcc
user@host:~/my_rte_app$ make
CC main.o
LD helloworld
INSTALL-APP helloworld
INSTALL-MAP helloworld.map

4.2運行一個範例程序

提示:uio驅動和大頁內存必須在程序運行前設置。

提示:每一個程序使用的網卡必須綁定到內核對應的驅動,實際就是咱們家在到內核的dpdk內核模塊,如igb_uio等,如3.5所寫的,這個動做也要在程序運行前執行。

程序是和dpdk目標環境下的環境抽象層庫鏈接,後者提供了每一個dpdk程序通用的一些選項。

下面是須要提供給eal的參數列表:

./rte-app -c COREMASK -n NUM [-b <domain:bus:devid.func>] [--socket-mem=MB,...] [-m MB] [-r NUM] 

EAL選項以下:

  • -c coremask:16進制的要運行的邏輯核位掩碼。注意在不一樣的平臺之間core編號可能不一樣,須要預先肯定好。
  • -n NUM:每一個處理器插槽的內存通道數
  • -b <domain:bus:devid.func>:網卡黑名單,阻止EAL使用的特殊的PCI設備,支持多個-b選項
  • -use-device:只使用特殊的網卡設備,可使用逗號分割的<[domain:]bus:devid.func>值來指定。不能喝-b一塊兒用
  • -socket-mem:從特定的socket上分配大頁內存
  • -m MB:從大頁分配內存數,不區分是那個socket。建議用-socket-mem代替這個選項
  • -r NUM:內存rank數(說實話,查了那麼多資料,仍是對這個不是很清楚啊)
  • -v:在啓動時顯示版本信息
  • -huge-dir:大頁內存掛在的目錄
  • -file-prefix:用於大頁文件的前綴名
  • -proc-type:The type of process instance進程類型(主/備吧,我猜的沒有用過多進程的)
  • -xen-dom0:支持程序在Xen Domain0上不使用大頁運行
  • -vmware-tsc-map:使用VMvare的TSC代替本地的RDTSC
  • -base-virtaddr:特定的虛擬基地址
  • -vfio-intr:VFIO使用的特定的中斷類型(即便VFIO不使用也沒有影響)

-n和-c是必須得,其它都是可選項

拷貝可執行程序到目的機器上,以下運行程序(假設每一個socket有4個內存通道,使用0-3核跑該程序):

user@target:~$ ./helloworld -c f -n 4

 注意:選項-proc-type和-file-prefix EAL用於跑多個dpdk程序,能夠看《dpdk範例程序使用手冊》中的多進程範例程序一章和dpdk開發手冊獲取更多細節。

4.2.1程序使用的邏輯核

對於dpdk程序,參數coremask是必須有的。每一個bit的掩碼都對應linxu展現的邏輯覈編號。這些邏輯覈編號對應具體得NUMA上的物理核心,不一樣的平臺會不一樣,建議在不一樣的平臺上運行不一樣的例子要考慮選擇使用的core的分佈。

運行dpdk程序初始化EAL時,會將使用的邏輯核和對應的socket打印出來。這些信息也可用經過查看/proc/cpuinfo來獲取,例如,執行 cat /proc/cpuinfo,顯示的physical id代表了每一個核所屬的cpu插槽。這個在咱們弄明白邏輯核和socket的映射關係時頗有用。

注意:更多的邏輯核分佈的拓撲結構視圖能夠經過使用lstopo獲取。在Fedora上,該命令可能安裝了,像這樣運行:

sudo yum install hwloc

./lstopo

提示:在不一樣的主板上佈局不一樣,邏輯核的分佈也會不一樣,咱們須要在選取程序使用的邏輯核以前檢查一下

4.2.2程序使用的大頁內存

在程序運行時,使用分配的數量的大頁內存(就是你分配多少就用多少了,而不是按需去整),這是在沒有指定參數-m和-socket-mem時程序在啓動時自動執行的。

若是程序使用-m和-socket-mem指定具體的內存數超出時,程序就會掛掉。然而,程序要求使用的內存比分配保留的大頁內存數小,特別是用-m選項指定時,程序也可能會掛掉。原有以下:假設如今系統在socket0和socket1上各有1024個2M的大內存頁。若是用戶申請使用128M內存,那64個頁可能不知足如下限制:

  • 內核只在soket1上給程序分配了大頁內存。萬一程序想要在socket0上建立一個對象,例如隊列或者是mempool,程序會報錯。要避免這個錯誤建議使用-socket-mem選項代替-m選項。(就是-m是內核隨機分配的內存,不知道在哪一個socket上,而-socket-mem是指定socket,咱們建立隊列,mempool是須要指定使用內存的socke,若是這個socket上內存不足就會報錯退出)
  • 這些內存頁可能在物理內存上隨機的分佈在任意一個地方,而dpdk EAL試圖分配一個在物理上連續的內存塊。在這些物理頁不連續時,萬一程序想要申請一段很大的mempool是灰報錯。

-socket-mem選擇用於在特定的socket上申請指定數目的內存頁。使用-socket-mem帶上每一個socket申請的內存數實現。例如,使用-socket-mem=0,512,意味着只在socket1上分配512m內存。一樣的,在4個socket的機器上,從socket0和socket2上分配各1g內存,參數應該是-socket-mem=1024,0,1024.在其它沒有明確指定的cpusocket上不會分配內存,如socket3.若是dpdk在每一個socket上不能申請到足夠的內存,EAL就會初始化失敗。

4.3其它的範例程序

其它的例子程序在${RTE_SDK}/examples目錄下。這些程序的建立和運行與本手冊中其它章節描述的差很少。另外就是看《dpdk範例程序使用手冊》看具體每一個程序的描述信息,編譯和執行時的特殊指令,以及一些代碼的註釋說明。

4.4另外的測試程序

除此以外,有兩個程序在庫建立時也建立了。源文件在DPDK/app下,在測試和測試pmd時調用。能夠在庫建立完成後,在build/app下找到。

測試程序提供了DPDK各類功能的多種測試。

PMD測試程序提供了一些不一樣的包收發測試和像如何使用INTEL® 82599萬兆網卡的FLow Director這類特徵的例子。

5打開其它功能

5.1高精度時鐘功能HPET

5.1.1BIOS支持

要使用HPET那麼平臺的BIOS必須是支持的,不然使用默認的TSC。通常狀況下,開機時按F2能夠進入bios設置。用戶能夠選擇HPET選項。在intel的Crystal Forest平臺的BIOS上,路徑是Advanced -> PCH-IOConfiguration -> High Precision Timer -> (Change fromDisabled to Enabled if necessary).

在系統重啓後,用下面的指令確認是否打開HPET:

# grep hpet /proc/timer_list

若是沒啥返回,HPET在BIOS上確定打開了,每次在重啓後執行上述命令。

5.1.2linux內核支持

 dpdk使用平臺的HPET經過映射時間戳計時器到用戶地址空間,諸如此類的,就須要內核的HPET_MMAP選項打開。

提示:在Fedora上,和其它的注入unbuntu發現版上,HPET的內核選項默認是關閉的。在將選項修改後在編譯內核,請經過查看發行版文檔來獲取確切的指令。

5.1.3在DPDK中打開HPET

默認狀況下,DPDK的配置文件中HPET支持選項是禁用的。要使用HPET,那麼CONFIG_RTE_LIBEAL_USE_HPET選項須要設置成y,會在編譯時使用HPET配置。

應用程序要使用rte_get_hpet_cycles() 和rte_get_hpet_hz()這兩個接口,使用HPET最爲rte_timer庫的默認時間源。API rte_eal_hpet_init()須要在程序初始化時調用。這個API的調用確認HPET是可使用,返回錯誤值則說明不能用。例如,若是內核的HPET_MMAP是關閉的。程序能夠決定採起什麼動做,若是HPET在運行時不能用。

注意:程序要使用時間API,可是明確HPET是不能用時,建議使用rte_get_timer_cycles() and rte_get_timer_hz()代替HPET相關的API。這兩個API使用的不是TSC就是HPET,取決於程序是否調用了rte_eal_hpet_init(),作了就看系統是否在運行時支持了。

5.2非root權限下運行dpdk程序

 儘管基於dpdk的程序能直接使用到網卡和其它硬件資源,只須要一點小的權限調整便可跑起來而不是做爲root用戶使用。要實現這些,文件的全部者或者是權限要調整以便確保linux用戶帳號可以使用dpdk程序:

  • 做爲大頁掛在點服務的目錄,例如:/mnt/huge
  • 在/dev下用戶態io設備文件,例如:/dev/uio0,/dev/uio1等等
  • 用戶態io sysfs配置和源文件,例如uio0:/sys/class/uio/uio0/device/config /sys/class/uio/uio0/device/resource*
  • 若是使用了HPET,/dev/hpet

注意:在一些安裝的linux上,會默認建立一個大頁的掛載點/dev/hugepages

5.3電量管理和省電功能

要用到dpdk的電源管理功能就要求該平臺的bios支持加強型intel SpeedStep®技術,不然,sys文件/sys/devices/system/cpu/cpu0/cpufreq就不會存在且cpu平率調整的電源管理也不恩可以用。查閱相關的bIOS文檔看如何實現吧

舉例說明,在一些intel平臺上,Enhanced IntelSpeedStep® Technology在BIOS的路徑是:

Advanced->Processor Configuration->Enhanced Intel SpeedStep® Tech

此外,爲了電源管理C3和C6也須要打開。C3和C6路徑以下:Advanced->Processor Configuration->Processor C3 Advanced->ProcessorConfiguration-> Processor C6

5.4使用linux的cpu核心隔離來減小上下文切換的開銷

當DPDK程序線程固定在系統的摸一個核上運行時,linux調度器可能會將其它的任務調度到該核上運行。爲了防止其它負載調度到dpdk使用的核上,須要使用linux內核參數isolcpus來將這些核從linux調度器中隔離開。

例如,若是dpdk程序跑在邏輯核2,4,6上,下面的這個參數須要加到內核選項(就是那個grub文件)中:

isolcpus=2,4,6

5.5 加載kni模塊

要跑dpdk KNI例子程序,須要額外加載一個模塊kni。在dpdk編譯目錄下的kmod中,和加載igb_uio同樣,使用ismod加載:

#insmod kmod/rte_kni.ko

注意:請看DPDK範例使用手冊的KNI示例章節。

5.6經過intel的VT-d虛擬化技術實現IOMMU直接傳輸跑dpdk

要讓linux內核支持intel® VT-d,須要打開如下內核選項:

• IOMMU_SUPPORT
• IOMMU_API
• INTEL_IOMMU

此外,要跑使用intel VT-d技術的dpdk程序,在使用igb_uio驅動時必須帶上iommu=pt參數。這會讓直接內存訪問從新映射。若是內核參數NTEL_IOMMU_DEFAULT_ON沒有設置,那麼內核參數intel_iommu=on也必須使用。這是爲了確保intel IOMMU按照預期初始化。

請注意當強制在igb_uio,vfio-pci驅動上使用iommu=pt,確實能夠同時使用iommu=pt and iommu=on。

5.740g網卡上小包的高性能處理

最新版本的固件鏡像解決了性能加強的問題,固件更新能夠獲取更高的處理性能。跟本地的intel工程師聯繫固件更新。支持固件版本FVL3E的基本驅動將在下一個dpdk版本中整合到一塊兒,當前能用到的版本是4.2.6

5.7.1 打開Extended Tag和設置Max Read Request Size

PCI的extended_tag和max_read_request_size對40g網卡的小包處理性能有巨大的影響。打開extended_tag和設置max_read_request_size爲小尺寸例如128字節會對小包的處理性能提高有恆大的幫助。

  • 大部分能夠在BIOS啓動時設置
  • 對於其它BIOS,PCI配置能夠經過使用命令setpci,或者是dpdk配置文件的特殊配置
    • pci設備的地址0xa8處bit7:5處用於設置max_read_request_size,而0xa8處的第八個bit用於開啓關閉extended_tag。能夠用lspci和setpci來讀取讀取0xa8對應的值而後回寫修改的值。
    • 在通常的linux配置文件中,下面的配置項要zuo修改:

      CONFIG_RTE_PCI_CONFIG
      CONFIG_RTE_PCI_EXTENDED_TAG
      CONFIG_RTE_PCI_MAX_READ_REQUEST_SIZE

5.7.2 使用16字節大小的rx描述符

i40e的PMD支持16和32字節大小rx描述符,16個字節能夠在小包處理性能上提供幫助。要使用16字節的須要修改配置文件中的配置項CONFIG_RTE_LIBRTE_I40E_16BYTE_RX_DESC。

5.7.3高性能和包延遲權衡

因爲硬件設計的緣由,每一個包描述符的回寫是須要網卡內部的中斷型號來實現。最小時間間隔的中斷信號能夠經過配置文件的CONFIG_RTE_LIBRTE_I40E_ITR_INTERVAL配置,編譯生效。儘管有默認配置,用戶能夠考慮性能或者是包處理延遲來調整這個參數。

6快速啓動腳本

tools目錄下的setup.sh腳本能夠幫助用戶完成如下任務:

  • 建立dpdk庫
  • 裝載和卸載dpdk igb_uio內核模塊
  • 裝載和卸載VFIO內核模塊
  • 裝載和卸載dpdk KNI內核模塊
  • 建立和刪除NUMA或非NUMA下的大頁
  • 網絡端口狀態視圖和分配dpdk使用的端口
  • 賦予非特權用戶使用VFIO的權限
  • 運行測試程序和測試pmd程序
  • 查看內存的大頁信息
  • 顯示/mnt/huge的大頁列表
  • 移除建立的dpdk庫

那些步驟完成後,用戶須要編譯本身的程序並鏈接建立的dpdk EAL庫。

6.1腳本的使用

 setup.sh腳本能夠暗轉給必定的順序使用,每一步都給說明方便用戶完成想要的任務。下面是每一步驟的簡短說明:

step1:建立dpdk庫

 最開始,用戶表虛選擇須要建立的dpdk目標類型和建立庫是用到的編譯選項。

用戶必須先有全部的連接庫,模塊,更新和編譯安裝,如前面章節中介紹的。

step2:安裝環境

用戶配置linux系統環境以支持運行dpdk程序。大頁能夠在numa或非numa系統中創建。任何存在的大頁都會被弄走。要用到的內核模塊也會在這是插入,dpdk用的網卡端口也會綁定到這個模塊。

step3:運行程序

一旦上述步驟完成,用戶可能要運行測試程序。測試程序容許用戶運行一系列的dpdk功能測試。testpmd測試程序則是測試收發包。

step4:檢查系統

這一步提供一些工具查看大頁的狀態信息

step:系統還原

最後一步是將系統還原到初始的狀態。

6.2用例

下面的步驟是展現如何使用setup.sh腳本。腳本的運行須要使用source命令,執行前腳本的一些選項提示用到的值。

提示:setup.sh腳本要運行在root權限下。

user@host:~/rte$ source tools/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-ivshmem-linuxapp-gcc
[5] x86_64-ivshmem-linuxapp-icc
[6] x86_64-native-bsdapp-clang
[7] x86_64-native-bsdapp-gcc
[8] x86_64-native-linuxapp-clang
[9] x86_64-native-linuxapp-gcc
[10] 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
Option:

 

下面是建立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驅動的示例:(感受不對,25應該按上面說的是卸載驅動啊,2.1沒用過,等後面翻譯開發手冊時再試試吧)

Option: 25
Unloading any existing DPDK UIO module
Loading DPDK UIO module

在numa系統中建立大頁的示範。在每一個node上分配1024個2m內存頁。結果就是程序應該在啓動時帶上-m 4096參數使用這些內存(實際上即便不提供-m選項,dpdk程序也會自動使用這些內存)

注意:若是顯示提示用戶刪除臨時文件,輸入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

下面是加載測試程序在一個核上跑的示例:

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>>

 

6.3應用程序

一旦用戶setup.sh腳本運行過,EAL建立了,大頁也搞好了。就能夠建立和運行本身的程序了或者是提供的例子程序。

下面是運行/exaples下的helloword程序示例,使用的是0-3核:

rte@rte-desktop:~/rte/examples$ cd helloworld/rte@rte-desktop:~/rte/examples/helloworld$ makeCC main.oLD helloworldINSTALL-APP helloworldINSTALL-MAP helloworld.maprte@rte-desktop:~/rte/examples/helloworld$ sudo ./build/app/helloworld -c 0xf -n 3[sudo] password for rte:EAL: coremask set to fEAL: Detected lcore 0 as core 0 on socket 0EAL: Detected lcore 1 as core 0 on socket 1EAL: Detected lcore 2 as core 1 on socket 0EAL: Detected lcore 3 as core 1 on socket 1EAL: Setting up hugepage memory...EAL: Ask a virtual area of 0x200000 bytesEAL: Virtual area found at 0x7f0add800000 (size = 0x200000)EAL: Ask a virtual area of 0x3d400000 bytesEAL: Virtual area found at 0x7f0aa0200000 (size = 0x3d400000)EAL: Ask a virtual area of 0x400000 bytesEAL: Virtual area found at 0x7f0a9fc00000 (size = 0x400000)EAL: Ask a virtual area of 0x400000 bytesEAL: Virtual area found at 0x7f0a9f600000 (size = 0x400000)EAL: Ask a virtual area of 0x400000 bytesEAL: Virtual area found at 0x7f0a9f000000 (size = 0x400000)EAL: Ask a virtual area of 0x800000 bytesEAL: Virtual area found at 0x7f0a9e600000 (size = 0x800000)EAL: Ask a virtual area of 0x800000 bytesEAL: Virtual area found at 0x7f0a9dc00000 (size = 0x800000)EAL: Ask a virtual area of 0x400000 bytesEAL: Virtual area found at 0x7f0a9d600000 (size = 0x400000)EAL: Ask a virtual area of 0x400000 bytesEAL: Virtual area found at 0x7f0a9d000000 (size = 0x400000)EAL: Ask a virtual area of 0x400000 bytesEAL: Virtual area found at 0x7f0a9ca00000 (size = 0x400000)EAL: Ask a virtual area of 0x200000 bytesEAL: Virtual area found at 0x7f0a9c600000 (size = 0x200000)EAL: Ask a virtual area of 0x200000 bytesEAL: Virtual area found at 0x7f0a9c200000 (size = 0x200000)EAL: Ask a virtual area of 0x3fc00000 bytesEAL: Virtual area found at 0x7f0a5c400000 (size = 0x3fc00000)EAL: Ask a virtual area of 0x200000 bytesEAL: Virtual area found at 0x7f0a5c000000 (size = 0x200000)EAL: Requesting 1024 pages of size 2MB from socket 0EAL: Requesting 1024 pages of size 2MB from socket 1EAL: 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 1hello from core 2hello from core 3hello from core 0

相關文章
相關標籤/搜索