KVMのVM環境でDPDK22.11のl2fwdを動かす 後編 ~DPDK入門 第20回~
今回後編では, DPDKのサンプルプログラムを改造してMACアドレスによるフィルター機能を実装する簡単な例をご紹介いたします。
KVMのVM環境でDPDK22.11のl2fwdを動かす 後編 ~DPDK入門 第20回~
はじめに
こんにちは, NTTテクノクロス株式会社の村木です。
本記事はDPDK入門「KVMのVM環境でDPDK22.11のl2fwdを動かす」の後編です。
前回前編ではDPDK22.11をベースにKVMのVM環境でサンプルアプリケーションを動かす方法までをご紹介いたしました。
今回後編では, DPDKのサンプルプログラムを改造してMACアドレスによるフィルター機能を実装する簡単な例をご紹介いたします。
前編で作成した環境をそのまま利用する前提となっておりますのでご注意いただければと思います。
本記事で紹介しているDPDKやサンプルプログラムの概要については本DPDK入門連載の以下の記事をご確認ください。
・DPDKとは? ~DPDK入門 第1回~
・DPDKのパケット処理 ~DPDK入門 第2回~

動作環境について
trafgen
を用いてl2fwd
にMACアドレスフィルタ-を追加したサンプルプログラムを実行
DPDK VMへ導入したdpdk
のサンプルプログラムl2fwd
の改造を実施します。
今回は流入するパケットのdst mac
アドレスを見て, 送信ポートの振り分けやパケット破棄の機能を追加してみたいと思います。
あわせてCALL VMで必要なtrafgen
コンフィグを準備して動作確認していきます。
送信ポートの振り分けを実施するため, 各VMにブリッジの割り当てを増やすところから実施します。
※今回の例では不要ですが, DPDKのパイプライン処理ではCPU数が処理に影響するため, VMへのCPU割当数増加の手順も実施したいと思います。

振り分け用ブリッジの追加
※一例としてCALL VMにbr_CALLtoDPDK2
を割り当てる手順を記載するが, DPDK VM側も基本的に同手順
※DPDK VMは以降の「DPDK VMのCPU数を変更(2→3へ変更)」もあわせて実施する
※ホストで実施
◯ブリッジ作成(ホストを再起動するたびに実施する必要がある)
sudo brctl addbr br_DPDKtoCALL2
◯ブリッジ立ち上げ(ホストを再起動するたびに実施する必要がある)
sudo ifconfig br_DPDKtoCALL2 up
◯VMを停止
sudo virsh shutdown CALL
Domain CALL is being shutdown
◯VMにブリッジを割り当て
→bridge
部分にbr_DPDKtoCALL2
を追記
sudo virsh edit CALL
<domain type='kvm'>
<name>CALL</name>
<uuid>6439ac13-5e55-4c4f-8e3e-b63c227869e8</uuid>
<memory unit='KiB'>2097152</memory>
<currentMemory unit='KiB'>2097152</currentMemory>
<vcpu placement='static'>2</vcpu>
~中略~
</interface>
<interface type='bridge'>
<source bridge='br_DPDKtoCALL2'/>
<model type='virtio'/>
</interface>
~中略~
</devices>
</domain>
Domain CALL XML configuration edited.
◯ブリッジ割り当て設定を反映
sudo virsh define /etc/libvirt/qemu/CALL.xml
Domain CALL defined from /etc/libvirt/qemu/CALL.xml
◯VMにブリッジが割り当てられたことを確認
sudo virsh domiflist CALL
Interface Type Source Model MAC
-------------------------------------------------------
- network default rtl8139 XX:XX:XX:XX:XX:XX
- bridge br_CALLtoDPDK virtio XX:XX:XX:XX:XX:XX
- bridge br_DPDKtoCALL virtio XX:XX:XX:XX:XX:XX
- bridge br_DPDKtoCALL2 virtio XX:XX:XX:XX:XX:XX
◯VM起動
sudo virsh start CALL
Domain CALL started
DPDK VMのCPU数を変更(2→3へ変更)
※ホストで実施
◯VMを停止
sudo virsh shutdown DPDK
Domain DPDK is being shutdown
◯DPDK VMのCPU数を変更(2→3へ変更)
sudo virsh setvcpus DPDK 3 --config --maximum
sudo virsh setvcpus DPDK 3 --config
sudo virsh dominfo DPDK
Id: -
Name: DPDK
UUID: 23532aa9-bde1-4bb7-b833-1202bdb48674
OS Type: hvm
State: shut off
CPU(s): 3
Max memory: 4194304 KiB
Used memory: 4194304 KiB
Persistent: yes
Autostart: disable
Managed save: no
Security model: apparmor
Security DOI: 0
◯VM起動
sudo virsh start DPDK
Domain DPDK started
各VMに追加したbr_DPDKtoCALL2
を割り当てIPアドレス設定
※一例としてCALL VMに割り当てたbr_DPDKtoCALL2
に10.0.3.10
を設定する手順を記載するが, DPDK VM側も設定するIPアドレス以外は基本的に同手順
※ホストで実施
◯CALL VMにSSHログイン
ssh user@192.168.122.212
※ここからCALL VMで実施
◯追加されたデバイスにIPを割り当て(ens7
が追加されたとする)
※ens2はdefault
ネットワークのデバイス
・接続プロファイルを作成
sudo nmcli connection add type ethernet ifname ens7 con-name ens7
・IPアドレスを設定
sudo nmcli connection modify ens7 ipv4.method manual ipv4.addresses 10.0.3.10/24
・デバイスに接続
sudo nmcli device connect ens7
・ens7
にIPアドレスが設定されていることを確認する
ip a
NW疎通確認
※DPDK VMで実施
◯追加した受信用ブリッジでの疎通確認
ping -I ens7 10.0.3.10
※CALL VMで実施
◯追加した受信用ブリッジでの疎通確認
ping -I ens7 10.0.3.20
VM再起動に伴うDPDKの再ビルドとドライバの追加
※DPDK VMで実施
◯DPDKのビルド/インストール
※以降, DPDK VMの作業はroot
で実施する
sudo su -
# cd /opt/dpdk-stable-22.11.4/
# meson build
# cd build
# ninja
# ninja install
◯NICのバインド
・バインド状態の確認
→Network devices using kernel driver
にNICが4つあることを確認する
# $RTE_SDK/usertools/dpdk-devbind.py --status
Network devices using kernel driver
===================================
0000:00:02.0 'Virtio network device 1000' if=ens2 drv=virtio-pci unused= *Active*
0000:00:05.0 'Virtio network device 1000' if=ens5 drv=virtio-pci unused= *Active*
0000:00:06.0 'Virtio network device 1000' if=ens6 drv=virtio-pci unused= *Active*
0000:00:07.0 'Virtio network device 1000' if=ens7 drv=virtio-pci unused= *Active*
No 'Baseband' devices detected
==============================
No 'Crypto' devices detected
============================
No 'DMA' devices detected
=========================
No 'Eventdev' devices detected
==============================
No 'Mempool' devices detected
=============================
No 'Compress' devices detected
==============================
Misc (rawdev) devices using kernel driver
=========================================
0000:00:05.0 'Virtio block device 1001' drv=virtio-pci unused=
No 'Regex' devices detected
===========================
・igb_uioのロード
# lsmod | grep uio
# modprobe uio
# insmod /opt/dpdk-stable-22.11.4/drivers/igb_uio.ko
# lsmod | grep -e Module -e 'uio'
Module Size Used by
igb_uio 16384 0
uio 20480 1 igb_uio
・バインド対象のIFのdown
# ifconfig ens5 down
# ifconfig ens6 down
# ifconfig ens7 down
・バインド状態の確認
→バインド対象のNICが非Activeであることを確認する
# $RTE_SDK/usertools/dpdk-devbind.py --status
Network devices using kernel driver
===================================
0000:00:02.0 'Virtio network device 1000' if=ens2 drv=virtio-pci unused=igb_uio *Active*
0000:00:05.0 'Virtio network device 1000' if=ens5 drv=virtio-pci unused=igb_uio
0000:00:06.0 'Virtio network device 1000' if=ens6 drv=virtio-pci unused=igb_uio
0000:00:07.0 'Virtio network device 1000' if=ens7 drv=virtio-pci unused=igb_uio
No 'Baseband' devices detected
==============================
No 'Crypto' devices detected
============================
No 'DMA' devices detected
=========================
No 'Eventdev' devices detected
==============================
No 'Mempool' devices detected
=============================
No 'Compress' devices detected
==============================
Misc (rawdev) devices using kernel driver
=========================================
0000:00:05.0 'Virtio block device 1001' drv=virtio-pci unused=igb_uio
No 'Regex' devices detected
===========================
・NICのバインド(受信用と送信用*2の3つをバインド)
→バインド時Warning: routing table indicates that interface 0000:00:05.0 is active. Not modifying
のErrorが発生した場合は対象IFがdownしていることを確認する
# $RTE_SDK/usertools/dpdk-devbind.py -b igb_uio 0000:00:05.0 0000:00:06.0 0000:00:07.0
・バインド状態の確認
→DPDK-compatible driver
にバインド対象のIFが表示されていることを確認する
# $RTE_SDK/usertools/dpdk-devbind.py --status
Network devices using DPDK-compatible driver
============================================
0000:00:05.0 'Virtio network device 1000' drv=igb_uio unused=
0000:00:06.0 'Virtio network device 1000' drv=igb_uio unused=
0000:00:07.0 'Virtio network device 1000' drv=igb_uio unused=
Network devices using kernel driver
===================================
0000:00:02.0 'Virtio network device 1000' if=ens2 drv=virtio-pci unused=igb_uio *Active*
No 'Baseband' devices detected
==============================
No 'Crypto' devices detected
============================
No 'DMA' devices detected
=========================
No 'Eventdev' devices detected
==============================
No 'Mempool' devices detected
=============================
No 'Compress' devices detected
==============================
Misc (rawdev) devices using kernel driver
=========================================
0000:00:05.0 'Virtio block device 1001' drv=virtio-pci unused=igb_uio
No 'Regex' devices detected
===========================
l2fwd
にMACアドレスフィルタ-を追加したサンプルプログラムを作成
※DPDK VMで実施
◯l2fwd_sort
のベースファイルを作成
# cd $RTE_SDK/examples/
# cp -Rp ./l2fwd ./l2fwd_sort
# cd ./l2fwd_sort
・l2fwdにMACアドレス振分を追加したl2fwd_sort
を作成
・l2fwd_mac_check
関数を追加
→m
のdst_mac
とハードコーディングの文字列を比較し, 1つ目に一致/2つ目に一致/不一致で1/2/3を返却
・l2fwd_simple_forward
にl2fwd_mac_check
の戻り値を確認するif文を追加
→一致(3以下)の場合のみ以降の処理を継続する
・l2fwd_main_loop
のprint_stats();
をコメントアウト
→l2fwd_mac_check
関数のprintf
関数がわかりやすいように既存の標準出力を非表示に修正
・l2fwd_sort
の修正
# vi ./main.c
・修正イメージ
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(c) 2010-2016 Intel Corporation
*/
/* ★中略★ */
static int
l2fwd_mac_check(struct rte_mbuf *m)
{
char str[(6 * 2) + 1] = {0};
char filter1[16] = "52540008250b";
char filter2[16] = "52540008250c";
uint8_t *eth = rte_pktmbuf_mtod(m, uint8_t * );
for (int i = 0; i < 6; i++) sprintf(&str[i * 2], "%02x", *(eth + i));
printf("出力対象1:%s \n", filter1);
printf("出力対象2:%s \n", filter2);
printf("入力対象:%s \n", str);
if(strcmp(str, filter1)==0) {
printf("転送 :OK, dst:1\n");
return 1;
} else if(strcmp(str, filter2)==0) {
printf("転送 :OK, dst:2\n");
return 2;
} else {
printf("転送 :NG\n");
return 3;
}
}
/* Simple forward. 8< */
static void
l2fwd_simple_forward(struct rte_mbuf *m, unsigned portid)
{
unsigned dst_port;
struct rte_eth_dev_tx_buffer *buffer;
/* dst_port = l2fwd_dst_ports[portid]; */
dst_port = l2fwd_mac_check(m);
if (dst_port < 3) {
if (mac_updating)
l2fwd_mac_updating(m, dst_port);
buffer = tx_buffer[dst_port];
sent = rte_eth_tx_buffer(dst_port, 0, buffer, m);
if (sent)
port_statistics[dst_port].tx += sent;
}
}
/* >8 End of simple forward. */
/* ★中略★ */
/* main processing loop */
static void
l2fwd_main_loop(void)
{
struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
struct rte_mbuf *m;
int sent;
unsigned lcore_id;
uint64_t prev_tsc, diff_tsc, cur_tsc, timer_tsc;
unsigned i, j, portid, nb_rx;
struct lcore_queue_conf *qconf;
const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S *
BURST_TX_DRAIN_US;
struct rte_eth_dev_tx_buffer *buffer;
prev_tsc = 0;
timer_tsc = 0;
lcore_id = rte_lcore_id();
qconf = &lcore_queue_conf[lcore_id];
if (qconf->n_rx_port == 0) {
RTE_LOG(INFO, L2FWD, "lcore %u has nothing to do\n", lcore_id);
return;
}
RTE_LOG(INFO, L2FWD, "entering main loop on lcore %u\n", lcore_id);
for (i = 0; i < qconf->n_rx_port; i++) {
portid = qconf->rx_port_list[i];
RTE_LOG(INFO, L2FWD, " -- lcoreid=%u portid=%u\n", lcore_id,
portid);
}
while (!force_quit) {
/* Drains TX queue in its main loop. 8< */
cur_tsc = rte_rdtsc();
/*
* TX burst queue drain
*/
diff_tsc = cur_tsc - prev_tsc;
if (unlikely(diff_tsc > drain_tsc)) {
for (i = 0; i < qconf->n_rx_port; i++) {
portid = l2fwd_dst_ports[qconf->rx_port_list[i]];
buffer = tx_buffer[portid];
sent = rte_eth_tx_buffer_flush(portid, 0, buffer);
if (sent)
port_statistics[portid].tx += sent;
}
/* if timer is enabled */
if (timer_period > 0) {
/* advance the timer */
timer_tsc += diff_tsc;
/* if timer has reached its timeout */
if (unlikely(timer_tsc >= timer_period)) {
/* do this only on main core */
if (lcore_id == rte_get_main_lcore()) {
/* print_stats(); */
/* reset the timer */
timer_tsc = 0;
}
}
}
prev_tsc = cur_tsc;
}
/* >8 End of draining TX queue. */
/* Read packet from RX queues. 8< */
for (i = 0; i < qconf->n_rx_port; i++) {
portid = qconf->rx_port_list[i];
nb_rx = rte_eth_rx_burst(portid, 0,
pkts_burst, MAX_PKT_BURST);
if (unlikely(nb_rx == 0))
continue;
port_statistics[portid].rx += nb_rx;
for (j = 0; j < nb_rx; j++) {
m = pkts_burst[j];
rte_prefetch0(rte_pktmbuf_mtod(m, void *));
l2fwd_simple_forward(m, portid);
}
}
/* >8 End of read packet from RX queues. */
}
}
/* ★中略★ */
}
l2fwd_sort
のコンパイルと実行
※DPDK VMで実施
◯l2fwd_sort
のコンパイルと実行
・l2fwdのコンパイル
# cd $RTE_SDK/examples/l2fwd_sort
# make
cc -O3 -I/usr/local/include -include rte_config.h -march=native -DALLOW_EXPERIMENTAL_API main.c -o build/l2fwd-shared -Wl,--as-needed -L/usr/local/lib64 -lrte_node -lrte_graph -lrte_pipeline -lrte_table -lrte_pdump -lrte_port -lrte_fib -lrte_ipsec -lrte_vhost -lrte_stack -lrte_security -lrte_sched -lrte_reorder -lrte_rib -lrte_dmadev -lrte_regexdev -lrte_rawdev -lrte_power -lrte_pcapng -lrte_member -lrte_lpm -lrte_latencystats -lrte_jobstats -lrte_ip_frag -lrte_gso -lrte_gro -lrte_gpudev -lrte_eventdev -lrte_efd -lrte_distributor -lrte_cryptodev -lrte_compressdev -lrte_cfgfile -lrte_bpf -lrte_bitratestats -lrte_bbdev -lrte_acl -lrte_timer -lrte_hash -lrte_metrics -lrte_cmdline -lrte_pci -lrte_ethdev -lrte_meter -lrte_net -lrte_mbuf -lrte_mempool -lrte_rcu -lrte_ring -lrte_eal -lrte_telemetry -lrte_kvargs
ln -sf l2fwd-shared build/l2fwd
・l2fwd_filterの実行(NIC番号は0-2)
# cd ./build/
# ./l2fwd -l 0-2 -n 3 -- -q 3 -p 0x07
※CALL VMで実施
◯ターミナルを3つ開く(①/②/③とする)
・ターミナル①でtrafgen
のコンフィグとしてMACアドレスを変更したものを作成する(適当なIPFIX Data Templateパケットの例)
→dst_mac
の末尾をb
からc
に修正
# cp -p ./sample_temlate.cfg ./sample_temlate_2.cfg
vi ./sample_temlate_2.cfg
#include <stddef.h>
{
/* ----- Etherframe ----- */
0x52, 0x54, 0x00, 0x08, 0x25, 0x0c, /* Dst MAC address (52:54:00:08:25:0c) */
0x52, 0x54, 0x00, 0x13, 0x4e, 0x9b, /* Src MAC address (52:54:00:13:4e:9b) */
0x08, 0x00, /* Type IP */
/* ★中略★ */
}
・ターミナル①でtrafgen
のコンフィグとしてMACアドレスを変更したものを作成する(適当なIPFIX Data Templateパケットの例)
→dst_mac
の末尾をc
からd
に修正
# cp -p ./sample_temlate_2.cfg ./sample_temlate_3.cfg
vi ./sample_temlate_3.cfg
#include <stddef.h>
{
/* ----- Etherframe ----- */
0x52, 0x54, 0x00, 0x08, 0x25, 0x0d, /* Dst MAC address (52:54:00:08:25:0d) */
0x52, 0x54, 0x00, 0x13, 0x4e, 0x9b, /* Src MAC address (52:54:00:13:4e:9b) */
0x08, 0x00, /* Type IP */
/* ★中略★ */
}
・ターミナル②でtshark
を実施しておく
sudo tshark -i ens6
・ターミナル③でtshark
を実施しておく
sudo tshark -i ens7
・ターミナル①でtrafgen
を実行(10パケット送信する)
sudo trafgen --dev ens5 -P 1 --conf ./sample_temlate.cfg --cpp -n 10
sudo trafgen --dev ens5 -P 1 --conf ./sample_temlate_2.cfg --cpp -n 10
sudo trafgen --dev ens5 -P 1 --conf ./sample_temlate_3.cfg --cpp -n 10
・ターミナル②を確認する
sample_temlate.cfg
分の10パケットだけ受信している
Running as user "root" and group "root". This could be dangerous.
Capturing on 'ens6'
1 0.000000000 10.0.1.10 → 10.0.1.20 CFLOW 86 IPFIX flow ( 44 bytes) Obs-Domain-ID=1 [Data-Template:1024]
2 0.000141704 10.0.1.10 → 10.0.1.20 CFLOW 86 IPFIX flow ( 44 bytes) Obs-Domain-ID=1 [Data-Template:1024]
3 0.000145356 10.0.1.10 → 10.0.1.20 CFLOW 86 IPFIX flow ( 44 bytes) Obs-Domain-ID=1 [Data-Template:1024]
4 0.000155847 10.0.1.10 → 10.0.1.20 CFLOW 86 IPFIX flow ( 44 bytes) Obs-Domain-ID=1 [Data-Template:1024]
5 0.000165753 10.0.1.10 → 10.0.1.20 CFLOW 86 IPFIX flow ( 44 bytes) Obs-Domain-ID=1 [Data-Template:1024]
6 0.000176537 10.0.1.10 → 10.0.1.20 CFLOW 86 IPFIX flow ( 44 bytes) Obs-Domain-ID=1 [Data-Template:1024]
7 0.000199426 10.0.1.10 → 10.0.1.20 CFLOW 86 IPFIX flow ( 44 bytes) Obs-Domain-ID=1 [Data-Template:1024]
8 0.000203575 10.0.1.10 → 10.0.1.20 CFLOW 86 IPFIX flow ( 44 bytes) Obs-Domain-ID=1 [Data-Template:1024]
9 0.000223063 10.0.1.10 → 10.0.1.20 CFLOW 86 IPFIX flow ( 44 bytes) Obs-Domain-ID=1 [Data-Template:1024]
10 0.000225516 10.0.1.10 → 10.0.1.20 CFLOW 86 IPFIX flow ( 44 bytes) Obs-Domain-ID=1 [Data-Template:1024]
^C10 packets captured
・ターミナル③を確認する
sample_temlate_2.cfg
分の10パケットだけ受信している
Running as user "root" and group "root". This could be dangerous.
Capturing on 'ens10'
1 0.000000000 10.0.1.10 → 10.0.1.20 CFLOW 86 IPFIX flow ( 44 bytes) Obs-Domain-ID=1 [Data-Template:1024]
2 0.000238089 10.0.1.10 → 10.0.1.20 CFLOW 86 IPFIX flow ( 44 bytes) Obs-Domain-ID=1 [Data-Template:1024]
3 0.000242236 10.0.1.10 → 10.0.1.20 CFLOW 86 IPFIX flow ( 44 bytes) Obs-Domain-ID=1 [Data-Template:1024]
4 0.000248309 10.0.1.10 → 10.0.1.20 CFLOW 86 IPFIX flow ( 44 bytes) Obs-Domain-ID=1 [Data-Template:1024]
5 0.000249984 10.0.1.10 → 10.0.1.20 CFLOW 86 IPFIX flow ( 44 bytes) Obs-Domain-ID=1 [Data-Template:1024]
6 0.000251082 10.0.1.10 → 10.0.1.20 CFLOW 86 IPFIX flow ( 44 bytes) Obs-Domain-ID=1 [Data-Template:1024]
7 0.000255862 10.0.1.10 → 10.0.1.20 CFLOW 86 IPFIX flow ( 44 bytes) Obs-Domain-ID=1 [Data-Template:1024]
8 0.000257195 10.0.1.10 → 10.0.1.20 CFLOW 86 IPFIX flow ( 44 bytes) Obs-Domain-ID=1 [Data-Template:1024]
9 0.000258236 10.0.1.10 → 10.0.1.20 CFLOW 86 IPFIX flow ( 44 bytes) Obs-Domain-ID=1 [Data-Template:1024]
10 0.000262584 10.0.1.10 → 10.0.1.20 CFLOW 86 IPFIX flow ( 44 bytes) Obs-Domain-ID=1 [Data-Template:1024]
^C10 packets captured
※DPDK VMで実施
◯l2fwdの画面を確認
→確認後Ctrl+C
で停止
→sample_temlate.cfg
分の10パケットが転送 :OK, dst:1
となっている
→sample_temlate_2.cfg
分の10パケットが転送 :OK, dst:2
となっている
→sample_temlate_3.cfg
分の10パケットが転送 :NG
となっている
EAL: Detected CPU lcores: 3
EAL: Detected NUMA nodes: 1
EAL: Detected shared linkage of DPDK
EAL: Multi-process socket /var/run/dpdk/rte/mp_socket
EAL: Selected IOVA mode 'PA'
EAL: Probe PCI driver: net_virtio (1af4:1000) device: 0000:00:02.0 (socket -1)
eth_virtio_pci_init(): Failed to init PCI device
EAL: Requested device 0000:00:02.0 cannot be used
EAL: Probe PCI driver: net_virtio (1af4:1000) device: 0000:00:05.0 (socket -1)
EAL: Probe PCI driver: net_virtio (1af4:1000) device: 0000:00:06.0 (socket -1)
EAL: Probe PCI driver: net_virtio (1af4:1000) device: 0000:00:07.0 (socket -1)
TELEMETRY: No legacy callbacks, legacy socket not created
MAC updating enabled
Notice: odd number of ports in portmask.
Lcore 0: RX port 0 TX port 1
Lcore 0: RX port 1 TX port 0
Lcore 0: RX port 2 TX port 2
Initializing port 0... done:
Port 0, MAC address: 52:54:00:3F:11:69
Initializing port 1... done:
Port 1, MAC address: 52:54:00:5D:80:BC
Initializing port 2... done:
Port 2, MAC address: 52:54:00:1B:E4:5E
Checking link statusdone
Port 0 Link up at Unknown FDX Autoneg
Port 1 Link up at Unknown FDX Autoneg
Port 2 Link up at Unknown FDX Autoneg
L2FWD: lcore 1 has nothing to do
L2FWD: lcore 2 has nothing to do
L2FWD: entering main loop on lcore 0
L2FWD: -- lcoreid=0 portid=0
L2FWD: -- lcoreid=0 portid=1
L2FWD: -- lcoreid=0 portid=2
出力対象1:52540008250b
出力対象2:52540008250c
入力対象:52540008250b
転送 :OK, dst:1
出力対象1:52540008250b
出力対象2:52540008250c
入力対象:52540008250b
転送 :OK, dst:1
出力対象1:52540008250b
出力対象2:52540008250c
入力対象:52540008250b
転送 :OK, dst:1
出力対象1:52540008250b
出力対象2:52540008250c
入力対象:52540008250b
転送 :OK, dst:1
出力対象1:52540008250b
出力対象2:52540008250c
入力対象:52540008250b
転送 :OK, dst:1
出力対象1:52540008250b
出力対象2:52540008250c
入力対象:52540008250b
転送 :OK, dst:1
出力対象1:52540008250b
出力対象2:52540008250c
入力対象:52540008250b
転送 :OK, dst:1
出力対象1:52540008250b
出力対象2:52540008250c
入力対象:52540008250b
転送 :OK, dst:1
出力対象1:52540008250b
出力対象2:52540008250c
入力対象:52540008250b
転送 :OK, dst:1
出力対象1:52540008250b
出力対象2:52540008250c
入力対象:52540008250b
転送 :OK, dst:1
出力対象1:52540008250b
出力対象2:52540008250c
入力対象:52540008250c
転送 :OK, dst:2
出力対象1:52540008250b
出力対象2:52540008250c
入力対象:52540008250c
転送 :OK, dst:2
出力対象1:52540008250b
出力対象2:52540008250c
入力対象:52540008250c
転送 :OK, dst:2
出力対象1:52540008250b
出力対象2:52540008250c
入力対象:52540008250c
転送 :OK, dst:2
出力対象1:52540008250b
出力対象2:52540008250c
入力対象:52540008250c
転送 :OK, dst:2
出力対象1:52540008250b
出力対象2:52540008250c
入力対象:52540008250c
転送 :OK, dst:2
出力対象1:52540008250b
出力対象2:52540008250c
入力対象:52540008250c
転送 :OK, dst:2
出力対象1:52540008250b
出力対象2:52540008250c
入力対象:52540008250c
転送 :OK, dst:2
出力対象1:52540008250b
出力対象2:52540008250c
入力対象:52540008250c
転送 :OK, dst:2
出力対象1:52540008250b
出力対象2:52540008250c
入力対象:52540008250c
転送 :OK, dst:2
出力対象1:52540008250b
出力対象2:52540008250c
入力対象:52540008250d
転送 :NG
出力対象1:52540008250b
出力対象2:52540008250c
入力対象:52540008250d
転送 :NG
出力対象1:52540008250b
出力対象2:52540008250c
入力対象:52540008250d
転送 :NG
出力対象1:52540008250b
出力対象2:52540008250c
入力対象:52540008250d
転送 :NG
出力対象1:52540008250b
出力対象2:52540008250c
入力対象:52540008250d
転送 :NG
出力対象1:52540008250b
出力対象2:52540008250c
入力対象:52540008250d
転送 :NG
出力対象1:52540008250b
出力対象2:52540008250c
入力対象:52540008250d
転送 :NG
出力対象1:52540008250b
出力対象2:52540008250c
入力対象:52540008250d
転送 :NG
出力対象1:52540008250b
出力対象2:52540008250c
入力対象:52540008250d
転送 :NG
出力対象1:52540008250b
出力対象2:52540008250c
入力対象:52540008250d
転送 :NG
^C
Signal 2 received, preparing to exit...
Closing port 0... Done
Closing port 1... Done
Closing port 2... Done
Bye...
トラブルシューティング
arp
は通っているがping
が通らない場合
※arp
も通らない時はホストで対象のブリッジがup
になっているかも確認してください。
◯事象
・DPDK VM→CALL VMへのping
(通らない)
sudo ping -I ens5 10.0.1.10
PING 10.0.1.10 (10.0.1.10) from 10.0.1.20 ens5: 56(84) bytes of data.
^C
--- 10.0.1.10 ping statistics ---
78 packets transmitted, 0 received, 100% packet loss, time 78878ms
・DPDK VM→CALL VMへのarp
(通っている)
arp -e
Address HWtype HWaddress Flags Mask Iface
192.168.122.231 ether 52:54:00:23:ec:3c C ens2
10.0.1.10 ether 52:54:00:13:4e:9b C ens5
◯対策の例→Bridge Netfilter
を無効化する
※ホストで実施
・Bridge Netfilter
が有効か確認する(1だと有効)
lsmod | grep br_netfilter
br_netfilter 24576 0
bridge 155648 1 br_netfilter
sudo sysctl net.bridge.bridge-nf-call-iptables
net.bridge.bridge-nf-call-iptables = 1
・無効にする(1→0に変更)
sudo vi /etc/sysctl.conf
・無効設定を反映
sudo sysctl -p
vm.nr_hugepages = 2048
kernel.core_pattern = /home/ntt/core
net.bridge.bridge-nf-call-iptables = 0
・無効になっていることを確認
sudo sysctl net.bridge.bridge-nf-call-iptables
net.bridge.bridge-nf-call-iptables = 0
◯設定変更後の疎通確認
・DPDK VM→CALL VMへのping
が通ることを確認する
sudo ping -I ens8 10.0.1.10 -c 4
PING 10.0.1.10 (10.0.1.10) from 10.0.1.20 ens8: 56(84) bytes of data.
64 bytes from 10.0.1.10: icmp_seq=1 ttl=64 time=1.11 ms
64 bytes from 10.0.1.10: icmp_seq=2 ttl=64 time=0.924 ms
64 bytes from 10.0.1.10: icmp_seq=3 ttl=64 time=0.710 ms
64 bytes from 10.0.1.10: icmp_seq=4 ttl=64 time=0.917 ms
--- 10.0.1.10 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3016ms
rtt min/avg/max/mdev = 0.710/0.914/1.108/0.145 ms
・CALL VM側でのtshark
(対象IFでの受信を確認)
sudo tshark -i ens8 -Y 'icmp.type==0 or icmp.type==8'
Running as user "root" and group "root". This could be dangerous.
Capturing on 'ens8'
1 0.000000000 10.0.1.20 → 10.0.1.10 ICMP 98 Echo (ping) request id=0x001e, seq=1/256, ttl=64
2 0.000056395 10.0.1.10 → 10.0.1.20 ICMP 98 Echo (ping) reply id=0x001e, seq=1/256, ttl=64 (request in 1)
3 1.001523750 10.0.1.20 → 10.0.1.10 ICMP 98 Echo (ping) request id=0x001e, seq=2/512, ttl=64
4 1.001575836 10.0.1.10 → 10.0.1.20 ICMP 98 Echo (ping) reply id=0x001e, seq=2/512, ttl=64 (request in 3)
5 2.002770950 10.0.1.20 → 10.0.1.10 ICMP 98 Echo (ping) request id=0x001e, seq=3/768, ttl=64
6 2.002828184 10.0.1.10 → 10.0.1.20 ICMP 98 Echo (ping) reply id=0x001e, seq=3/768, ttl=64 (request in 5)
7 3.015982890 10.0.1.20 → 10.0.1.10 ICMP 98 Echo (ping) request id=0x001e, seq=4/1024, ttl=64
8 3.016035895 10.0.1.10 → 10.0.1.20 ICMP 98 Echo (ping) reply id=0x001e, seq=4/1024, ttl=64 (request in 7)
^C8 packets captured
おわりに
DPDK入門 第19回に引く続き今回は入門編としてDPDKサンプルプログラム改造の例をご紹介しました。
DPDKを用いた簡易的なNW処理はDPDKのサンプルプログラムが参考になるため, ぜひ手軽に実行できる手元のKVM環境で確認いただけると幸いです。
本件に関するお問い合わせ

[著者プロフィール]
フューチャーネットワーク事業部 第一ビジネスユニット
村木 遼亮(MURAKI RYOUSUKE)