linux packet-forwarding

47
Linux におけるカーネルパケット転送 浅間 正和 @ 有限会社 銀座堂

Upload: masakazu-asama

Post on 03-Jul-2015

2.211 views

Category:

Documents


4 download

TRANSCRIPT

Page 1: Linux packet-forwarding

Linux におけるカーネルパケット転送浅間 正和 @ 有限会社 銀座堂

Page 2: Linux packet-forwarding

はじめまして?• 新潟県三条市にある地域 ISP 有限会社銀座堂でサーバ管理やネットワーク管理をしています

• 弊社では上流 ISP(OCN さんと新潟県内の ISP) や Echigo-IX(新潟県内の地域 IX) との接続に Linux(Vyatta Core) を使って BGP 接続をしています

• 2010 年頃から Linux カーネルのパケット転送処理について調べ InternetWeek で発表したりしていました

• 趣味では IETF で標準化が進められている MAP(Mapping of Address and Port with Encapsulation) というプロトコルを Linux カーネルに実装し Vyatta Core に組み込み ASAMAP という名前でオープンソースで公開したりしています

2

Page 3: Linux packet-forwarding

ASAMAP?• IPv4 over IPv6 技術のうち DS-Lite/464XLAT/MAP-E/MAP-T のキャリア側装置と顧客側装置の両方に対応

• IPv4 over IPv6 技術とはキャリア内ネットワークを極力 IPv6 のみで構築しつつ顧客ネットワークに IPv4 サービスも提供するための技術

• IPv4 ヘッダを IPv6 に書き換えるトランスレーションを用いる方法 (464XLAT/MAP-T) と IPv4 パケットを IPv6 でカプセル化する方法 (DS-Lite/MAP-E) の 2 種類に分けられ

• さらにキャリア側装置に NAPT 機能を持つ方法 (DS-Lite/464XLAT) と持たない方法 (MAP-E/MAP-T) の 2 種類に分けられる

3

MAP 対応 Vyatta (ASAMAP) 仮置き場 http://enog.jp/~masakazu/vyatta/map/

ASAMAP 開発秘話 http://www.slideshare.net/m-asama/asamap

Page 4: Linux packet-forwarding

目次• Receive Livelock と Linux NAPI • 大量のパケット受信時の問題とそれに対して Linux カーネルが取った対策

• 参考) ハードウェアによる負荷低減支援機能 • パケット転送の並列処理と RSS (Receive Side Scaling) • パケット転送処理を複数の CPU コアで並列処理するための Linux カーネルの仕組み

• 参考) RSS と NUMA • 割り込み問題再び • 参考) Intel DPDK

4

Page 5: Linux packet-forwarding

割り込みモデルとポーリング・モデル

5

NIC

CPU

① NIC が受信したパケットを受信バッファに書き込む

② NIC が割り込みで CPU に通知

③ CPU は実行中のタスクの状態を保存し割り込みハンドラを実行

② CPU は定期的に受信バッファを確認し新しいパケットが届いていたら処理する

① 受信したパケットを受信バッファに書き込む

NIC

CPU

割り込みモデル ポーリング・モデル

Page 6: Linux packet-forwarding

割り込みモデルとポーリング・モデル• 割り込みモデル • メリット • パケットの受信を CPU がすぐに気づくことが出来るので遅延が小さい

• デメリット • 割り込みによって生じるコンテキスト・スイッチは非常に重い処理なため頻繁にパケット送受信を行う環境では性能劣化を招く ❖ Receive Livelock

• ポーリング・モデル • メリット • コンテキスト・スイッチによる処理コストはかからない

• デメリット • ポーリング間隔のどこでパケットを受信するかによって遅延が変動し全体としても遅延が大きくなる

6

Page 7: Linux packet-forwarding

Receive Livelock• デッド・ロックしているわけでもないのに割り込みが溢れてしまうことで割り込みハンドラしか実行していないような状態になること

• 割り込み処理はかなり高い優先度を割り当てられているためパケット受信の際に何も考えず割り込みを発生させると他の処理を一切出来ないような状態になる

7

※1) Eliminating Receive Livelock in an Interrupt-Driven Kernel http://www.stanford.edu/class/cs240/readings/p217-mogul.pdf

1Gbps の Ethernet で 64 バイトのフレームをワイヤレートで流した際に発生する割り込みの回数

毎秒 1,488,100 回 (割り込み発生間隔 672 ナノ秒)

最近の Linux のタイマー割り込みの回数 毎秒 250 回

Page 8: Linux packet-forwarding

Linux NAPI• 割り込みモデルとポーリング・モデルのいいとこ取り • 基本的には割り込みモデルで動作 • パケットを受信した際に割り込みを無効化し処理が完了するまではポーリング・モードで動作

• 処理すべきパケットの処理が完了したら割り込みを有効化 • 2002 年 11 月にリリースされた Linux カーネル 2.4.20 の tg3 ドライバにおいて実装され順次その他の NIC ドライバでも採用

8

Page 9: Linux packet-forwarding

メモリ

Linux NAPI

9

CPU#2CPU#1

NIC#1 NIC#2

net_device 構造体他@NIC#1

softnet_data 構造体@CPU#1

net_device 構造体他@NIC#2

softnet_data 構造体@CPU#2

!TX

!RX

!TX

!RX

Page 10: Linux packet-forwarding

メモリ

Linux NAPI

10

CPU#2CPU#1

NIC#1 NIC#2

net_device 構造体他@NIC#1

softnet_data 構造体@CPU#1

net_device 構造体他@NIC#2

softnet_data 構造体@CPU#2

!TX

!RX

!TX

!RX

softnet_data 構造体は ksoftirqd カーネル・スレッドがネットワーク絡みの処理を行う際に必要とするデータ

をまとめた構造体 ksoftirqd は CPU の数だけ存在するので softnet_data 構造体も CPU の数

だけ存在する

Page 11: Linux packet-forwarding

メモリ

Linux NAPI

11

CPU#2CPU#1

NIC#1 NIC#2

net_device 構造体他@NIC#1

softnet_data 構造体@CPU#1

net_device 構造体他@NIC#2

softnet_data 構造体@CPU#2

!TX

!RX

!TX

!RX

net_device 構造体は NIC 1 つにつき 1 つ存在する構造体

通常はその直後に NIC ドライバ毎に異なる構造体がくっついていて (例えば e1000 の場合は e1000_adapter) その中には NAPI の設定のための napi_struct 構造体が含まれる

Page 12: Linux packet-forwarding

メモリ

Linux NAPI

12

CPU#2CPU#1

NIC#1 NIC#2

net_device 構造体他@NIC#1

softnet_data 構造体@CPU#1

net_device 構造体他@NIC#2

softnet_data 構造体@CPU#2

!TX

!RX

!TX

!RXNIC は受信 (RX) 用の受信バッファと

送信 (TX) 用の送信バッファを持つ 受信バッファと送信バッファは一般的にリング構造をとっておりそれぞれ NIC と CPU の間で排他制御無しで

データのやり取りを行う

Page 13: Linux packet-forwarding

メモリ

Linux NAPI

13

CPU#2CPU#1

NIC#1 NIC#2

net_device 構造体他@NIC#1

softnet_data 構造体@CPU#1

net_device 構造体他@NIC#2

softnet_data 構造体@CPU#2

!TX

!RX

!TX

!RX

パケット

(1) パケットを受信した NIC#1 はパケットを受信バッファに書き込む

Page 14: Linux packet-forwarding

メモリ

Linux NAPI

14

CPU#2CPU#1

NIC#1 NIC#2

net_device 構造体他@NIC#1

softnet_data 構造体@CPU#1

net_device 構造体他@NIC#2

softnet_data 構造体@CPU#2

!TX

!RX

!TX

!RX

パケット

(2) NIC#1 は割り込みを使って CPU#1 に通知

Page 15: Linux packet-forwarding

メモリ

Linux NAPI

15

CPU#2CPU#1

NIC#1 NIC#2

net_device 構造体他@NIC#1

softnet_data 構造体@CPU#1

net_device 構造体他@NIC#2

softnet_data 構造体@CPU#2

!TX

!RX

!TX

!RX

パケット

(3) CPU#1 は実行中のタスクの状態を保存し割り込みハンドラ

に移行する

Page 16: Linux packet-forwarding

メモリ

Linux NAPI

16

CPU#2CPU#1

NIC#1 NIC#2

net_device 構造体他@NIC#1

softnet_data 構造体@CPU#1

net_device 構造体他@NIC#2

softnet_data 構造体@CPU#2

!TX

!RX

!TX

!RX

パケット

(4) CPU#1 は NIC#1 の割り込みを無効化

Page 17: Linux packet-forwarding

メモリ

Linux NAPI

17

CPU#2CPU#1

NIC#1 NIC#2

net_device 構造体他@NIC#1

softnet_data 構造体@CPU#1

net_device 構造体他@NIC#2

softnet_data 構造体@CPU#2

!TX

!RX

!TX

!RX

パケット

(5) softnet_data 構造体の poll_list リストに NIC#1 の napi_struct 構

造体をリンクする

Page 18: Linux packet-forwarding

メモリ

Linux NAPI

18

CPU#2CPU#1

NIC#1 NIC#2

net_device 構造体他@NIC#1

softnet_data 構造体@CPU#1

net_device 構造体他@NIC#2

softnet_data 構造体@CPU#2

!TX

!RX

!TX

!RX

パケット

(6) 割り込みハンドラは終了しスケジューラが呼び出され通常はそのまま ksoftirqd カーネル・スレッドに

処理が移る

Page 19: Linux packet-forwarding

メモリ

Linux NAPI

19

CPU#2CPU#1

NIC#1 NIC#2

net_device 構造体他@NIC#1

softnet_data 構造体@CPU#1

net_device 構造体他@NIC#2

softnet_data 構造体@CPU#2

!TX

!RX

!TX

!RX

パケット

(7) ksoftirqd は softnet_data 構造体の poll_list にリンクされた

napi_struct 構造体の受信バッファからパケットを取り出し受信処理を行う

Page 20: Linux packet-forwarding

メモリ

Linux NAPI

20

CPU#2CPU#1

NIC#1 NIC#2

net_device 構造体他@NIC#1

softnet_data 構造体@CPU#1

net_device 構造体他@NIC#2

softnet_data 構造体@CPU#2

!TX

!RX

!TX

!RX

(8) 処理が終わったら NIC#1 の割り込みを有効化する

Page 21: Linux packet-forwarding

ハードウェアによる負荷低減支援機能• Ethernet Flow Control • 一時的に対向装置 (Ethernet L2 スイッチ等) に送信をやめてもらうことができる機能

• 自身の受信バッファがいっぱいになったときに対向装置に PAUSE フレームを送信することで送信を一時的にやめるようお願いする

• NIC が対応している場合ethtool -A ethX (options…)で設定することができる

• Interrupt Coalescing (Interrupt Moderation) • パケット受信時に NIC が割り込みを間引くことで OS の負担を低減させる機能

• NIC が対応している場合ethtool -C ethX (options…)で設定することができる

21

Page 22: Linux packet-forwarding

Receive Side Scaling (RSS)• 背景 • 最近のシステムでは CPU コアを複数持っているものが当たり前となっておりネットワークの処理もそれらで並列実行したい

• 仕組み • NIC 側で複数のキューを持たせる • パケットの受信時にヘッダ情報からキューを選択し対応する CPU に割り込みする

• 同一フローのパケット (IP アドレスと TCP/UDP ポート番号が同じパケット) は同じキューが選択されるためリオーダは生じない

• どの情報からキューを選択するかは変更可能 • 前提 • PCI-Express バスに接続された複数キューに対応した NIC • PCI-Express で導入された MSI/MSI-X を用いて NIC から割り込みのルーティングする必要があるため

22

Page 23: Linux packet-forwarding

Receive Side Scaling (RSS)• 受信キューと割り込み番号の対応の確認

!!!!!!!

• 受信キューと割り込み先 CPU の対応付け

23

[root@linux ~]# cat /proc/interrupts CPU0 CPU1 ... 52: 0 0 PCI-MSI-edge p1p1-TxRx-0 53: 0 0 PCI-MSI-edge p1p1-TxRx-1 54: 0 0 PCI-MSI-edge p1p1 55: 0 0 PCI-MSI-edge p1p2-TxRx-0 56: 0 0 PCI-MSI-edge p1p2-TxRx-1 57: 0 0 PCI-MSI-edge p1p2 ...

[root@linux ~]# echo 1 > /proc/irq/52/smp_affinity [root@linux ~]# echo 2 > /proc/irq/53/smp_affinity [root@linux ~]# echo 1 > /proc/irq/55/smp_affinity [root@linux ~]# echo 2 > /proc/irq/56/smp_affinity

Page 24: Linux packet-forwarding

Receive Side Scaling (RSS)• CPU の個数等の情報から自動的に IRQ の割り込み先を設定してくれる irqbalance というコマンドがある

• デーモンとして起動する場合は以下のように実行 !

• 一度だけ設定しデーモンとして起動させたくない場合は以下のように実行

24

[root@linux ~]# irqbalance

[root@linux ~]# irqbalance --oneshot

Page 25: Linux packet-forwarding

メモリ

Receive Side Scaling (RSS)

25

CPU#2CPU#1

NIC#1 NIC#2

net_device 構造体他@NIC#1

softnet_data 構造体@CPU#1

net_device 構造体他@NIC#2

softnet_data 構造体@CPU#2

!TX

!RX

!TX

!RX

Page 26: Linux packet-forwarding

メモリ

Receive Side Scaling (RSS)

26

CPU#2CPU#1

NIC#1 NIC#2

net_device 構造体他@NIC#1

softnet_data 構造体@CPU#1

net_device 構造体他@NIC#2

softnet_data 構造体@CPU#2

TX #1

TX #2

RX #1

RX #2

TX #1

TX #2

RX #1

RX #2

Page 27: Linux packet-forwarding

メモリ

Receive Side Scaling (RSS)

27

CPU#2CPU#1

NIC#1 NIC#2

net_device 構造体他@NIC#1

softnet_data 構造体@CPU#1

net_device 構造体他@NIC#2

softnet_data 構造体@CPU#2

TX #1

TX #2

RX #1

RX #2

TX #1

TX #2

RX #1

RX #2

napi_struct 構造体はキューの数だけ用意される

Page 28: Linux packet-forwarding

メモリ

Receive Side Scaling (RSS)

28

CPU#2CPU#1

NIC#1 NIC#2

net_device 構造体他@NIC#1

softnet_data 構造体@CPU#1

net_device 構造体他@NIC#2

softnet_data 構造体@CPU#2

TX #1

TX #2

RX #1

RX #2

TX #1

TX #2

RX #1

RX #2

パケット

(1) パケットを受信した NIC#1 は受信したパケットのヘッダ情報からキューを決定しそのキューの

受信バッファに書き込む

Page 29: Linux packet-forwarding

メモリ

Receive Side Scaling (RSS)

29

CPU#2CPU#1

NIC#1 NIC#2

net_device 構造体他@NIC#1

softnet_data 構造体@CPU#1

net_device 構造体他@NIC#2

softnet_data 構造体@CPU#2

TX #1

TX #2

RX #1

RX #2

TX #1

TX #2

RX #1

RX #2

パケット

(2) NIC#1 は割り込みを使って CPU#2 に通知

Page 30: Linux packet-forwarding

メモリ

Receive Side Scaling (RSS)

30

CPU#2CPU#1

NIC#1 NIC#2

net_device 構造体他@NIC#1

softnet_data 構造体@CPU#1

net_device 構造体他@NIC#2

softnet_data 構造体@CPU#2

TX #1

TX #2

RX #1

RX #2

TX #1

TX #2

RX #1

RX #2

パケット

(3) CPU#2 は実行中のタスクの状態を保存し割り込みハンドラ

に移行する

Page 31: Linux packet-forwarding

メモリ

Receive Side Scaling (RSS)

31

CPU#2CPU#1

NIC#1 NIC#2

net_device 構造体他@NIC#1

softnet_data 構造体@CPU#1

net_device 構造体他@NIC#2

softnet_data 構造体@CPU#2

TX #1

TX #2

RX #1

RX #2

TX #1

TX #2

RX #1

RX #2

パケット

(4) CPU#2 は NIC#1 の自分に対する割り込みを無効化

Page 32: Linux packet-forwarding

メモリ

Receive Side Scaling (RSS)

32

CPU#2CPU#1

NIC#1 NIC#2

net_device 構造体他@NIC#1

softnet_data 構造体@CPU#1

net_device 構造体他@NIC#2

softnet_data 構造体@CPU#2

TX #1

TX #2

RX #1

RX #2

TX #1

TX #2

RX #1

RX #2

パケット

(5) CPU#2 の softnet_data 構造体の poll_list リストに NIC#1 の RX#2 に対応する napi_struct 構

造体をリンクする

Page 33: Linux packet-forwarding

メモリ

Receive Side Scaling (RSS)

33

CPU#2CPU#1

NIC#1 NIC#2

net_device 構造体他@NIC#1

softnet_data 構造体@CPU#1

net_device 構造体他@NIC#2

softnet_data 構造体@CPU#2

TX #1

TX #2

RX #1

RX #2

TX #1

TX #2

RX #1

RX #2

パケット

(6) 割り込みハンドラは終了しスケジューラが呼び出され通常はそのまま ksoftirqd カーネル・スレッドに

処理が移る

Page 34: Linux packet-forwarding

メモリ

Receive Side Scaling (RSS)

34

CPU#2CPU#1

NIC#1 NIC#2

net_device 構造体他@NIC#1

softnet_data 構造体@CPU#1

net_device 構造体他@NIC#2

softnet_data 構造体@CPU#2

TX #1

TX #2

RX #1

RX #2

TX #1

TX #2

RX #1

RX #2

パケット

(7) ksoftirqd は softnet_data 構造体の poll_list にリンクされた

napi_struct 構造体の受信バッファからパケットを取り出し受信処理を行う

Page 35: Linux packet-forwarding

メモリ

Receive Side Scaling (RSS)

35

CPU#2CPU#1

NIC#1 NIC#2

net_device 構造体他@NIC#1

softnet_data 構造体@CPU#1

net_device 構造体他@NIC#2

softnet_data 構造体@CPU#2

TX #1

TX #2

RX #1

RX #2

TX #1

TX #2

RX #1

RX #2

(8) 処理が終わったら NIC#1 の自分に対する割り込みを有効化する

Page 36: Linux packet-forwarding

性能測定・構成

3613

性能測定・構成

Unidirectional Bidirectional

DELL PowerEdge R410!Xeon L5520 @ 2.27GHz x 2(8 cores)!Fedora 15/Linux Kernel 3.0.6(2.6.40.6)

DELL PowerEdge R410!Xeon L5520 @ 2.27GHz x 2(8 cores)!Fedora 15/Linux Kernel 3.0.6(2.6.40.6)

Spirent TestCenter Spirent TestCenter

Intel X520-SR2!10G NIC(82599EB)!SourceForge ixgbe

Intel X520-SR2!10G NIC(82599EB)!SourceForge ixgbe

128

flow

128

flow

128 flow

Loss < 0.01% Loss < 0.01%30 sec.30 sec.

Page 37: Linux packet-forwarding

RSS による性能改善 (Unidirectional)

37

0Mbps

2,000Mbps

4,000Mbps

6,000Mbps

8,000Mbps

10,000Mbps

64 128 256 512 1024 1280 1518

RSS=1,1 CPU:0,0 RSS=1,1 CPU:4,6RSS=4,4 CPU:0,2,4,6 RSS=8,8 CPU:0,1,..,7

Page 38: Linux packet-forwarding

RSS による性能改善 (Unidirectional)

38

0pps

1,000,000pps

2,000,000pps

3,000,000pps

4,000,000pps

5,000,000pps

6,000,000pps

64 128 256 512 1024 1280 1518

RSS=1,1 CPU:0,0 RSS=1,1 CPU:4,6RSS=4,4 CPU:0,2,4,6 RSS=8,8 CPU:0,1,..,7

Page 39: Linux packet-forwarding

RSS による性能改善 (Bidirectional)

39

0Mbps

4,000Mbps

8,000Mbps

12,000Mbps

16,000Mbps

20,000Mbps

64 128 256 512 1024 1280 1518

RSS=1,1 CPU:0,0 RSS=1,1 CPU:4,6RSS=4,4 CPU:0,2,4,6 RSS=8,8 CPU:0,1,..,7

Page 40: Linux packet-forwarding

RSS による性能改善 (Bidirectional)

40

0pps

1,000,000pps

2,000,000pps

3,000,000pps

4,000,000pps

5,000,000pps

6,000,000pps

64 128 256 512 1024 1280 1518

RSS=1,1 CPU:0,0 RSS=1,1 CPU:4,6RSS=4,4 CPU:0,2,4,6 RSS=8,8 CPU:0,1,..,7

Page 41: Linux packet-forwarding

NUMA とメモリの距離

41

#0

CPU ソケット#0

#2 #4 #6

メモリ・コントローラ#0

メモリ・ノード#0

#1

CPU ソケット#1

#3 #5 #7

メモリ・コントローラ#1

メモリ・ノード#1

NIC#1 NIC#2

Page 42: Linux packet-forwarding

NUMA とメモリの距離

42

#0

CPU ソケット#0

#2 #4 #6

メモリ・コントローラ#0

メモリ・ノード#0

#1

CPU ソケット#1

#3 #5 #7

メモリ・コントローラ#1

メモリ・ノード#1#0 #1 #2 #3 #4 #5 #6 #7#0 #1 #2 #3 #4 #5 #6 #7

NIC#1 NIC#2

Page 43: Linux packet-forwarding

ロス許容と性能評価

43

0Mbps

4,000Mbps

8,000Mbps

12,000Mbps

16,000Mbps

20,000Mbps

64 128 256 512 1024 1280 1518

RSS=8,8 Loss<0.01 RSS=8,8 Loss<0.1 RSS=8,8 Loss<1.0

Page 44: Linux packet-forwarding

ロス許容と性能評価

44

0pps

1,000,000pps

2,000,000pps

3,000,000pps

4,000,000pps

5,000,000pps

6,000,000pps

64 128 256 512 1024 1280 1518

RSS=8,8 Loss<0.01 RSS=8,8 Loss<0.1 RSS=8,8 Loss<1.0

Page 45: Linux packet-forwarding

割り込みモデルとポーリング・モデル (再

45

NIC

CPU

① NIC が受信したパケットを受信バッファに書き込む

② NIC が割り込みで CPU に通知

③ CPU は実行中のタスクの状態を保存し割り込みハンドラを実行

② CPU は定期的に受信バッファを確認し新しいパケットが届いていたら処理する

① 受信したパケットを受信バッファに書き込む

NIC

CPU

割り込みモデル ポーリング・モデル

Page 46: Linux packet-forwarding

参考) Intel DPDK• Intel 社がオープン・ソース (BSD ライセンス) で開発しているデータ・プレーンを開発するための SDK (Data Plane Development Kit) • http://www.dpdk.org/

• 割り込みではなくすべてポーリングでパケット処理を行う • Linux の UIO (デバイスをユーザ・ランドから直接制御するための仕組み) を用いて割り込みモードではなくポーリング・モードで動作するドライバ (PMD: Poll-Mode Driver) で NIC を制御する • 実はオープン・ソースになっていないだけで UIO でなくカーネル内で動作させるモノも存在する? • どこにも define されていないのに存在する大量の ifdef RTE_EXEC_ENV_BAREMETAL

• DMA 転送されたパケットを CPU の LLC にプリ・フェッチしていたりページ・サイズ大きくすることで TLB ミスがあまり起こらないようにしていたりと小細工も満載

46

Page 47: Linux packet-forwarding

参考) Intel DPDK

47

TRANSFORMING COMMUNICATIONS Intel Confidential 8 TRANSFORMING COMMUNICATIONS 8

IA パフォーマンスの年々の向上 iAでのPv4 レイヤー 3 フォワード性能

0

20

40

60

80

100

120

140

160

20062x2C Sossaman

2.0 GHz

20072x4C Clovertown

2.33 GHz

20082x4C Harpertown

2.33 GHz

20092x4C Nehalem

2.53 GHz

20102x6C Westmere

2.40 GHz

20111x8C Sandy Bridge

2.0 GHz

20122x8C Sandy Bridge

2.0 GHZ(PCIe* Gen2 の機器でテスト)

標準の“off-the-shelf” IAプラットフォームで魅力的な性能を提供します

* Other names and brands may be claimed as the property of others.

64B Mpps

10G

40G

100G

内蔵PCIe* コントローラー

80G 内蔵メモリーコントローラー

の登場 +

インテル® DPDK

Internet Week 2012 D1 パケットフォワーディングを支える技術 3) パケットフォワーディング高速化技術(幸村 裕子/インテル株式会社)から引用

https://www.nic.ad.jp/ja/materials/iw/2012/proceedings/d1/d1-Kohmura.pdf