DPDK 安裝流程、VM 部署、官方 sample 運行。
dpdk
# xxxx 視 kernel 版本而定 (按 tab 自動補齊)
grep -i huge /boot/config-.........
grep -i huge /proc/meminfo
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
配置 hugepage (暫時配置,每次重新開機後須重新設定)
echo 1024 | sudo tee /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
# 檢查
cat /proc/meminfo | grep Huge
sudo mkdir /mnt/huge
sudo mount -t hugetlbfs nodev /mnt/huge
sudo sysctl -w vm.nr_hugepages=1024
每次開機後自動掛載(未設定成功,原因不明,每次開機後仍然執行上方暫時配置的指令)
vim /etc/fstab
# 加入
nodev /mnt/huge hugetlbfs defaults 0 0
若使用 vmware(等虛擬機),必須先使用修補檔
patch -p0 < xxx.patch
啟動並輸入要更新的檔案路徑。/home/yen/dpdk-stable-18.11.2/kernel/linux/igb_uio/igb_uio.c
安裝相關套件
sudo apt-get update
sudo apt-get install -y python libpcap-dev build-essential linux-headers-`uname -r` libnuma-dev pkg-config gcc libnuma-dev libpcre3 libpcre3-dev libssl-dev
下載 & 編譯(這邊使用的是 dpdk-18.11.2 版本)
### 下載
wget http://fast.dpdk.org/rel/dpdk-18.11.2.tar.xz
tar -xvf dpdk-18.11.2.tar.xz
### 環境變數設
export DPDK_DIR=$HOME/dpdk-stable-18.11.2
export DPDK_TARGET=x86_64-native-linuxapp-gcc
export DPDK_BUILD=$DPDK_DIR/$DPDK_TARGET
export LD_LIBRARY_PATH=$DPDK_DIR/x86_64-native-linuxapp-gcc/lib
export RTE_SDK=$HOME/dpdk-stable-18.11.2
export RTE_MACHINE="native"
export RTE_TARGET=x86_64-native-linuxapp-gcc
## 安裝
cd $DPDK_DIR && sudo make install T=$DPDK_TARGET DESTDIR=install
sudo sed -i 's/CONFIG_RTE_BUILD_SHARED_LIB=n/CONFIG_RTE_BUILD_SHARED_LIB=y/g' ${DPDK_DIR}/config/common_base
DPDK 提供的核心模組內包含了部分網路卡的驅動,利用此核心模組所提供的 API (DPDK library),可以使開發者直接控制網路卡的行為。
sudo modprobe uio
sudo modprobe vfio-pci
sudo insmod $HOME/dpdk-stable-18.11.2/x86_64-native-linuxapp-gcc/kmod/igb_uio.ko
sudo insmod $HOME/dpdk-stable-18.11.2/x86_64-native-linuxapp-gcc/kmod/rte_kni.ko kthread_mode=multiple carrier=on
# 使用 usertools 內的工具進行設定
cd $HOME/dpdk-stable-18.11.2/usertools
# 查看目前網路卡搭載的驅動狀態
sudo $HOME/dpdk-stable-18.11.2/usertools/dpdk-devbind.py --status
# 卸載指定網卡當前所搭載的驅動
sudo $HOME/dpdk-stable-18.11.2/usertools/dpdk-devbind.py -u 00:08.0
# 指定驅動與網卡做綁定
sudo $HOME/dpdk-stable-18.11.2/usertools/dpdk-devbind.py -b igb_uio 0000:00:08.0
# 最後檢查
sudo $HOME/dpdk-stable-18.11.2/usertools/dpdk-devbind.py --status
卸載 module
sudo rmmod /home/yen/dpdk-stable-18.11.2/x86_64-native-linuxapp-gcc/kmod/igb_uio.ko
sudo rmmod /home/yen/dpdk-stable-18.11.2/x86_64-native-linuxapp-gcc/kmod/rte_kni.ko
若執行 DPDK 程式出現 shared file error 等訊息,依照下列指令將編譯後的 dpdk 函式庫加入 shared file。
編輯 /etc/ld.so.conf
,加入 DPDK library。
$ sudo vim /etc/ld.so.conf
# 加入
/home/使用者名稱/dpdk-stable-18.11.2/install/lib
/home/使用者名稱/dpdk-stable-18.11.2/x86_64-native-linuxapp-gcc/lib
$ sudo ldconfig
while((1));do
echo "1. Set hugepage"
echo "2. Insert modules"
echo "3. Remove modules"
echo "4. Show NIC driver status"
echo "5. Bind NIC (ens38) with igb_uio"
echo "6. Bind NIC (ens38) with e1000"
echo "7. Set vEth0 up"
echo "U. Install dependencies"
echo "D. Remove dpdk directory and unzip again"
echo "R. Recompile DPDK package"
read -p "Action ?" n
case "$n" in
1)
echo 1024 | sudo tee /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
cat /proc/meminfo | grep Huge
sudo mount -t hugetlbfs nodev /mnt/huge
sudo sysctl -w vm.nr_hugepages=1024
;;
2)
sudo modprobe uio
sudo modprobe vfio-pci
sudo insmod /home/$(whoami)/dpdk-stable-18.11.2/x86_64-native-linuxapp-gcc/kmod/igb_uio.ko
sudo insmod /home/$(whoami)/dpdk-stable-18.11.2/x86_64-native-linuxapp-gcc/kmod/rte_kni.ko kthread_mode=multiple
carrier=on
;;
3)
sudo rmmod /home/$(whoami)/dpdk-stable-18.11.2/x86_64-native-linuxapp-gcc/kmod/igb_uio.ko
sudo rmmod /home/$(whoami)/dpdk-stable-18.11.2/x86_64-native-linuxapp-gcc/kmod/rte_kni.ko
;;
4)
sudo /home/$(whoami)/dpdk-stable-18.11.2/usertools/dpdk-devbind.py --status
;;
5)
sudo ifconfig ens38 down
sudo /home/$(whoami)/dpdk-stable-18.11.2/usertools/dpdk-devbind.py -b igb_uio 0000:02:06.0
;;
6)
sudo /home/$(whoami)/dpdk-stable-18.11.2/usertools/dpdk-devbind.py -b e1000 0000:02:06.0
sudo ifconfig ens38 up
;;
7)
sudo ip addr add 192.168.0.254/24 dev vEth0
sudo ip -6 addr add 2001:0db8:0:f101::1/64 dev vEth0
sudo ip link set vEth0 up
;;
U)
sudo apt-get update
sudo apt-get install -y python libpcap-dev build-essential linux-headers-`uname -r` libnuma-dev pkg-config gcc libnuma-dev make
;;
D)
sudo rm -rf /home/$(whoami)/dpdk-stable-18.11.2
tar -xvf dpdk-18.11.2.tar.xz
;;
R)
export DPDK_DIR=/home/$(whoami)/dpdk-stable-18.11.2
export DPDK_TARGET=x86_64-native-linuxapp-gcc
export DPDK_BUILD=$DPDK_DIR/$DPDK_TARGET
export LD_LIBRARY_PATH=$DPDK_DIR/x86_64-native-linuxapp-gcc/lib
export RTE_SDK=$HOME/dpdk-stable-18.11.2
export RTE_MACHINE="native"
export RTE_TARGET=x86_64-native-linuxapp-gcc
cd $DPDK_DIR && sudo make -j4 install T=$DPDK_TARGET DESTDIR=install
sudo sed -i 's/CONFIG_RTE_BUILD_SHARED_LIB=n/CONFIG_RTE_BUILD_SHARED_LIB=y/g' ${DPDK_DIR}/config/common_base
esac
done
sudo vim /etc/default/grub
加入 isolcpus=2,3,4
後重新開機。
這個範例程式會根據執行時選定的 core mask 啟用對應的 core,並讓每個 core 執行 hello world。
#刪除所有 export 的環境變數
#$ unset GNUPLOT_DRIVER_DIR
cd examples/helloworld/
export RTE_SDK=$HOME/dpdk-stable-18.11.2
export RTE_TARGET=x86_64-native-linuxapp-gcc
make && sudo ./build/helloworld -c 3 -n 2
-c
: core mask,3 表示啟用 core 0,1(3 = 00000011)-n
: memory channel 的數量KNI 模擬 Linux network interface 的功能,會和 kernel 做溝通,讓使用者可以操作 ethtools。
編譯&執行
cd examples/kni/
export RTE_SDK=$HOME/dpdk-stable-18.11.2
export RTE_TARGET=x86_64-native-linuxapp-gcc
make && sudo ./build/kni -c 0xf0 -n 2 -- -P -p 0x1 --config="(0,4,5)"
-c
: core mask,0xf 表示使用 core 0,1,2,3 (4 = 00001111)-n
: memory channel 的數量-P
: 混雜模式-p
: port mask,0x3 表示使用 2個 ports(兩張網卡)--config=
"(port_ID,TX_coreID,RX_coreID)"設定 vEth 網卡的 IP 並啟動
sudo ip addr add 192.168.0.254/24 dev vEth0
sudo ip -6 addr add 2001:0db8:0:f101::1/64 dev vEth0
sudo ip link set vEth0 up
sudo ip addr add 192.168.1.254/24 dev vEth1
sudo ip link set vEth1 up
設定後 ifcofig
觀察目前網路介面,經由 KNI 建立的網路經面為: vEth0
使用 tcpdump 查看流經 vEth0 的封包(ping 測試)
### 設置環境變數(找不到環境變數時就要設定一次)
export RTE_SDK=$HOME/dpdk-stable-18.11.2
export RTE_TARGET=x86_64-native-linuxapp-gcc
export nDPI_src=$HOME/nDPI
### 使用 --eth-dest 指定 port 連接目標的 MAC
make && sudo ./build/nDPIexe -c 0xf -n 4 -- -L -p 0x7 --config="(0,0,0),(1,0,1),(2,0,2)" --parse-ptyp --eth-dest=0,68:b5:99:b6:d3:5d --eth-dest=1,68:b5:99:b6:d3:75 --eth-dest=2,b4:96:91:65:62:ab -- -n2
make && sudo ./build/nDPIexe -c 0xf -n 4 -- -L -p 0x7 --config="(0,0,0),(1,0,1)" --parse-ptyp --eth-dest=0,68:b5:99:b6:d3:5d --eth-dest=1,68:b5:99:b6:d3:75 --eth-dest=2,b4:96:91:65:62:ab -- -n2
### tcpreplay
tcpprep -a bridge -i filtered/slowdownload.pcap -o processed/input.cache
tcprewrite --enet-dmac=B4:96:91:65:62:A8,B4:96:91:65:62:A9 --enet-smac=68:b5:99:b6:d3:5d,68:b5:99:b6:d3:75 --endpoints=192.168.1.100:192.168.2.100 -m1500 -i filtered/slowdownload.pcap -o processed/out.pcap -c processed/input.cache
sudo tcpreplay -l10 -t -c processed/input.cache -i enp5s0f1 -I enp4s0f1 processed/out.pcap
### tshark
tshark -n -r"packets_default.pcap" -Y "tcp.stream > 0 and tcp.stream < 100" -w tmp.pcap
### perf
ps aux | grep "nDPI" | awk 'NR==2{print $2}' | xargs sudo perf top -p
### kill process
ps aux | grep "nDPI" | awk 'NR==2{print $2}' | xargs sudo kill -9
目前連線狀況:
設定 static arp 跟 route
因為目前的轉發程式內沒有支援 ARP reply 與 ARP cache 的功能,所以需要透過設定 static ARP。
netplan 設置(路由設定參考)
client-1
network:
ethernets:
ens33:
addresses: [192.168.44.130/24]
nameservers:
addresses: [8.8.8.8,8.8.4.4]
dhcp4: no
ens38:
dhcp4: no
addresses: [192.168.0.101/24]
routes:
- to: 192.168.1.0/24
via: 192.168.0.10
version: 2
Static ARP 設置
arp -s target_IP target_MAC_addr
client_1
sudo arp -s 192.168.0.10 B4:96:91:65:62:A8
使用 tcpreplay
發送封包進行測試
tcpprep
將封包進行分流並存成 cache 檔rewrite
依據 cache 檔的分流紀錄改寫封包內容tcpreplay
將指定的 pcap 檔從指定的介面發送static uint16_t rte_eth_tx_burst( uint16_t port_id,
uint16_t queue_id,
struct rte_mbuf ** tx_pkts,
uint16_t nb_pkts
)