現在位置: ホーム / みらくるブログ / #11 DPDKのパケットロスを抑制する

#11 DPDKのパケットロスを抑制する

DPDKを使って転送を行っている際、パケットロスが生じることがあります。本稿では、カーネルの割り込みなどのオーバーヘッドを削減することで、パケットロスを低減する方法を紹介します。

はじめに

これまでの記事では、次のようなパケット折り返しの評価を行ってきました。送信レートがある程度高くなるとパケットロスをすることがあります。

04-flow-1.png

例えば、筆者が使用している環境では送信レートを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を専有するように計画しました。

PMDCPU 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以外の機能の動作のために指定してあります。

11-cpu-set.png

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