#11 DPDKのパケットロスを抑制する
はじめに
これまでの記事では、次のようなパケット折り返しの評価を行ってきました。送信レートがある程度高くなるとパケットロスをすることがあります。
例えば、筆者が使用している環境では送信レートを96%にして60秒間、パケットの折り返しを実行すると、送信した約8億5千万パケットのうち1760パケット(0.002%)がロスしていました。
Pktgen> set all rate 96
Pktgen> clr (カウンタリセット)
Pktgen> start 0
(60秒後)
Pktgen> stop 0
Total Rx Pkts : 0 851127744
Tx Pkts : 851129504 0
PMDのCPU専有計画
パケットロスの原因として、testpmdのPMDスレッドの実行が、他のプロセスや割り込みなどにより一定時間中断されることが考えられます。これまで、はっきりと意識していませんでしたが、あるCPUでDPDKのPMD以外が実行される要因を排除していきましょう。そのためには、PMDがアサインされるCPU番号を意識する必要があります。そこで、筆者の環境では次のように、各PMDがCPUを専有するように計画しました。
PMD | CPU ID |
---|---|
1 | 2 |
2 | 3 |
この計画を踏まえて、カーネルの起動オプションを次のように設定します。
GRUB_CMDLINE_LINUX="crashkernel=auto rhgb quiet default_hugepagesz=1G hugepagesz=1G hugepages=16 iommu=pt intel_iommu=on isolcpus=2,3 nohz_full=2,3 rcu_nocbs=2,3"
isolcpusは、指定したCPUをスケジューリングの対象から除外します。つまり、CPU2と3では、明示的に設定されたプログラム以外は実行されません。nohz_fullは、定期的なタイマ割り込みを抑止し、必要な時に動的にタイマ割り込みを使うモードにします。実際に割り込み回数を確認すると他のCPUよりCPU2と3の値が小さいことが分かります。
$ cat /proc/interrupts | grep "(LOC|CPU)"
CPU0 CPU1 CPU2 CPU3 CPU4 CPU5 CPU6 CPU7
LOC: 3514635 26125 2485 2475 12978 6819 13408 12800 Local timer interrupts
rcu_nocbsは、カーネルの同期機構RCUの動作を抑制します。CPU2と3が行うはずの処理は、rcuob, rcuosという名前のカーネルスレッドが他のCPU (下記の最左列)で行うようになります。
$ ps -eo psr,comm | grep rcuo
0 rcuob/2
1 rcuos/2
0 rcuob/3
4 rcuos/3
CPUを指定してのtestpmdの実行
CPUを指定してtestpmdを起動するには次のように入力します。
# testpmd -c 0x0e -- -i --nb-cores=2 --coremask=0x0c
-cは、testpmdが使用するCPUの指定です。0x0e (14) は、下図のようにCPU1 (2)、CPU2 (4)、CPU3 (8)の集合を意味します。CPU1は、PMD以外の機能の動作のために指定してあります。
--coremaskは、転送に使用する(すなわちPMDを実行する)CPUを指定します。0x0c (12)は、先ほど-cで指定したCPUの内、CPU2 (4)とCPU3 (8)を選択していることになります。
startコマンドで転送を開始すると、指定したとおり、CPU2と3が転送に使用されていることが分かります。(なお、今回は結果を分かりやすくするため、Port1からのみ入力していますので、実際に転送を行うのはCPU3のみです)
testpmd> start
io packet forwarding - ports=2 - cores=2 - streams=2 - NUMA support disabled, MP over anonymous pages disabled
Logical Core 2 (socket 0) forwards packets on 1 streams:
RX P=0/Q=0 (socket 0) -> TX P=1/Q=0 (socket 0) peer=02:00:00:00:00:01
Logical Core 3 (socket 0) forwards packets on 1 streams:
RX P=1/Q=0 (socket 0) -> TX P=0/Q=0 (socket 0) peer=02:00:00:00:00:00
冒頭の検証と同じく、送信レートを96%にして約60秒間パケットを転送しました。その結果、以下のとおり、パケットロスはゼロになりました。なお、手動でスタート・ストップしているため、トータルのパケット数は冒頭のそれとは若干異なります。
Total Rx Pkts : 0 852687488
Tx Pkts : 852687488 0