10gbe時代のネットワークi/o高速化
DESCRIPTION
10GbE、40GbEなどの極めて高速な通信をサポートするNICが、PCサーバの領域でも使われるようになってきている。 このような速度の通信をソフトウェア(OS)で処理し高い性能を得るには様々な障害があり、ハードウェア・ソフトウェア両面の実装を見直す必要がある。 本セッションでは、ハードウェア・ソフトウェア両面にどのような改良が行われてきており、性能を引き出すにはどのようにこれらを使用したらよいのかについて紹介する。TRANSCRIPT
はじめに• 10GbE、40GbEなどの極めて高速な通信をサポートするNICが、PCサーバの領域でも使われるようになってきている
• このような速度の通信をソフトウェア(OS)で処理し高い性能を得るには様々な障害があり、ハードウェア・ソフトウェア両面の実装を見直す必要がある
13年6月7日金曜日
今日のトピック1. 割り込みが多すぎる
2. プロトコル処理が重い
3. 複数のCPUでパケット処理したい
4. データ移動に伴うレイテンシの削減
5. プロトコルスタックを経由しないネットワークIO
13年6月7日金曜日
1. 割り込みが多すぎるProcess(User)
Process(Kernel)
HW Intr Handler
SW Intr Handler
パケット受信
プロトコル処理
ソケット受信処理
ユーザプログラム
user buffer
inputqueue
socketqueue
パケット
システムコール
プロセス起床
ソフトウェア割り込みスケジュール
ハードウェア割り込み
ユーザ空間へコピー
13年6月7日金曜日
割り込みが多すぎる• NICの性能向上によって、一定時間に
NICが処理できるパケット数が飛躍的に増加
• 1パケット毎に割り込みが来ると、通信量が多いときにコンテキストスイッチ回数が増えすぎ性能が劣化
13年6月7日金曜日
旧来のパケット受信処理Process(User)
Process(Kernel)
HW Intr Handler
SW Intr Handler
パケット受信
プロトコル処理
ソケット受信処理
ユーザプログラム
user buffer
inputqueue
socketqueue
パケット
システムコール
プロセス起床
ソフトウェア割り込みスケジュール
ハードウェア割り込み
ユーザ空間へコピー
ハードウェア割り込み↓
受信キューにキューイング↓
ソフトウェア割り込みスケジュール
13年6月7日金曜日
旧来のパケット受信処理
• 1パケット受信するたびに割り込みを受けて処理を行っている
• 64byte frameの最大受信可能数:
• GbE:約1.5Mpps(150万)
• 10GbE:約15Mpps(1500万)
13年6月7日金曜日
割り込みを無効にする?• ポーリング方式
• NICの割り込みを禁止し、代わりにクロック割り込みを用いて定期的に受信キューをチェック
• デメリット:レイテンシが上がる・定期的にCPUを起こす必要がある
• ハイブリッド方式
• 通信量が多く連続してパケット処理を行っている時のみ割り込みを無効化してポーリングで動作
13年6月7日金曜日
NAPI(ハイブリッド方式)
Process(User)
Process(Kernel)
HW Intr Handler
SW Intr Handler
割り込み無効化
プロトコル処理
ソケット受信処理
ユーザプログラム
user buffer
socketqueue
パケット
システムコール
プロセス起床
ハードウェア割り込み
ユーザ空間へコピー
パケットパケット
ソフトウェア割り込みスケジュール
パケット受信
パケットが無くなるまで繰り返し
ハードウェア割り込み↓
割り込み無効化&ポーリング開始
↓パケットが無くなったら割り込み有効化
13年6月7日金曜日
Interrupt Coalescing
• NICがOS負荷を考慮して割り込みを間引く
• パケット数個に一回割り込む、或いは一定期間待ってから割り込む
• デメリット:レイテンシが上がる
13年6月7日金曜日
Interrupt Coalescingの効果• Intel 82599(ixgbe)でInterrupt Coalescing無効、有効(割り込み頻度自動調整)で比較
• MultiQueue, GRO, LRO等は無効化
• iperfのTCPモードで計測
interrupts throughput packets CPU%(sy+si)
無効
有効
46687 int/s 7.82 Gbps 660386 pkt/s 97.6%
7994 int/s 8.24 Gbps 711132 pkt/s 79.6%
13年6月7日金曜日
Process(User)
Process(Kernel)
HW Intr Handler
SW Intr Handler
割り込み無効化
プロトコル処理
ソケット受信処理
ユーザプログラム
user buffer
socketqueue
パケット
システムコール
プロセス起床
ハードウェア割り込み
ユーザ空間へコピー
パケットパケット
ソフトウェア割り込みスケジュール
パケット受信
パケットが無くなるまで繰り返し
2.プロトコル処理が重い
13年6月7日金曜日
プロトコル処理が重い• 特に小さなパケットが大量に届く場合にプロトコル処理でCPU時間を大量に使ってしまう
• パケット数分プロトコルスタックが呼び出される例:64byte frameの場合→理論上の最大値は1500万回/s
13年6月7日金曜日
TOE(TCP Offload Engine)
• OSでプロトコル処理するのをやめて、NICで処理する
• デメリット
• セキュリティ:TOEにセキュリティホールが生じても、OS
側から対処が出来ない
• 複雑性:OSのネットワークスタックをTOEで置き換えるにはかなり広範囲の変更が必要メーカによってTOEの実装が異なり共通インタフェース定義が困難
• Linux:サポート予定無し
13年6月7日金曜日
Checksum Offloadingの効果• Intel 82599(ixgbe)で比較
• iperfのTCPモードで計測
• MultiQueueは無効化
• ethtool -K ix0 rx off
throughput CPU%(sy+si)
無効有効
8.27 Gbps 86
8.27 Gbps 85.2
13年6月7日金曜日
LRO(Large Receive Offload)• NICが受信したTCPパケットを結合し、大きなパケットにしてからOSへ渡す
• プロトコルスタックの呼び出し回数を削減
• LinuxではソフトウェアによるLROが実装されている(GRO)
13年6月7日金曜日
LROが無い場合
• パケット毎にネットワークスタックを実行
seq 10000 seq 10001 seq 10002 seq 10003
←1500bytes→
To network stack
13年6月7日金曜日
LROが有る場合
• パケットを結合してからネットワークスタックを実行、ネットワークスタックの実行回数を削減
seq 10000 seq 10001 seq 10002 seq 10003
←1500bytes→
To network stack
big one packet
13年6月7日金曜日
GROの効果• Intel 82599(ixgbe)で比較
• MultiQueueは無効化
• iperfのTCPモードで計測
• ethtool -K ix0 gro off
packets network stack called count throughput CPU%(sy+si)
無効
有効
632139 pkt/s 632139 call/s 7.30 Gbps 97.6%
712387 pkt/s 47957 call/s 8.25 Gbps 79.6%
13年6月7日金曜日
TSO(TCP Segmentation Offload)• LROの逆
• パケットをフラグメント化せずに送信NICがパケットをMTUサイズに分割
• OSはパケット分割処理を省略出来る
• LinuxではソフトウェアによるGSO、ハードウェアによるTSO/UFOをサポート
13年6月7日金曜日
TSOの効果• Intel 82599(ixgbe)で比較
• MultiQueueは無効化
• iperfのTCPモードで計測
• ethtool -K ix0 gso off tso off
packets throughput CPU%(sy+si)
無効
有効
247794 pkt/s 2.87 Gbps 53.5%
713127 pkt/s 8.16 Gbps 26.8%
13年6月7日金曜日
3.複数のCPUでパケット処理したいcpu0
Process(User)
Process(Kernel)
HW Intr Handler
SW Intr Handler
割り込み無効化
プロトコル処理
ソケット受信処理
ユーザプログラム
user buffer
socketqueue
パケット
システムコール
プロセス起床
ハードウェア割り込み
ユーザ空間へコピー
パケットパケット
ソフトウェア割り込みスケジュール
パケット受信
パケットが無くなるまで繰り返し
cpu1
Process(User)
Process(Kernel)
HW Intr Handler
SW Intr Handler
割り込み無効化
プロトコル処理
ソケット受信処理
ユーザプログラム
user buffer
socketqueue
パケット
システムコール
プロセス起床
ハードウェア割り込み
ユーザ空間へコピー
パケットパケット
ソフトウェア割り込みスケジュール
パケット受信
パケットが無くなるまで繰り返し
13年6月7日金曜日
ソフト割り込みとは?Process(User)
Process(Kernel)
HW Intr Handler
SW Intr Handler
割り込み無効化
プロトコル処理
ソケット受信処理
ユーザプログラム
user buffer
socketqueue
パケット
システムコール
プロセス起床
ハードウェア割り込み
ユーザ空間へコピー
パケットパケット
ソフトウェア割り込みスケジュール
パケット受信
パケットが無くなるまで繰り返し
ポーリングからプロトコル処理まで→ネットワークIOの大半部分
13年6月7日金曜日
何故偏る?ソフト割り込みはNICの割り込みがかかったCPUへ
スケジュールされる↓
ポーリングからプロトコルスタックの実行までソフト割り込み内で実行される
↓NICの割り込みがかかっているCPUだけに
負荷がかかる
13年6月7日金曜日
ソフト割り込みが1つのコアに偏って性能が出ない
• memcachedなどショートパケットを大量に捌くワークロードで顕在化
• ソフトウェア割り込みを実行しているCPUがボトルネックになり、性能がスケールしなくなる
13年6月7日金曜日
解決方法• パケットを複数のCPUへ分散させてからプロトコル処理する仕組みがあれば良い
• 但し、TCPには順序保証が有るので並列に処理されるとパケットの並べ直し(リオーダ)が発生してパフォーマンスが落ちる
13年6月7日金曜日
TCP Reordering
• シーケンスナンバー通りの順序でパケットが着信していれば順にバッファへコピーしていくだけでよいが…
1 2 3 4 5 6
1 2 3 4 5 6
protocol processing
user buffer
13年6月7日金曜日
TCP Reordering1 2 4 5 3 6
1 2 3 4 5 6
protocol processing
user buffer
reorderqueue
3 4 5
• 順序が乱れているとパケットの並べ直し(リオーダ)作業が必要になる
13年6月7日金曜日
RSS(Receive Side Scaling)• CPUごとに別々の受信キューを持つNIC
(MultiQueue NICと呼ばれる)
• 受信キューごとに独立した割り込みを持つ
• 同じフローに属するパケットは同じキューへ、異なるフローに属するパケットはなるべく別のキューへ分散→パケットヘッダのハッシュ値を計算する事により宛先キューを決定
13年6月7日金曜日
MSI-X割り込み• PCI Expressでサポート
• デバイスあたり2048個のIRQを持てる
• それぞれのIRQの割り込み先CPUを選べる→1つのNICがCPUコア数分のIRQを持てる
13年6月7日金曜日
RSSによるパケット振り分け
NIC
パケットパケットパケット
ハッシュ計算
パケット着信
hash queue
ディスパッチ参照
RX Queue
#0
RX Queue
#1
RX Queue
#2
RX Queue
#3
cpu0 cpu1 cpu2 cpu3
受信処理
割り込み
受信処理
■■
01
13年6月7日金曜日
キュー選択の手順indirection_table[64] = initial_value
input[12] = {src_addr, dst_addr, src_port, dst_port}
key = toeplitz_hash(input, 12)
index = key & 0x3f
queue = indirection_table[index]
13年6月7日金曜日
RPS• RSS非対応のオンボードNICをうまくつかってサーバの性能を向上させたい
• ソフトでRSSを実装してしまおう
• ソフト割り込みの段階でパケットを各CPUへばらまく
• CPU間割り込みを使って他のCPUを稼動させる
• RSSのソフトウエアによるエミュレーション
13年6月7日金曜日
cpu3cpu2cpu1cpu0
割り込み無効化
プロトコル処理
ソケット受信処理
ユーザプログラム
user buffer
socketqueue
パケット
システムコール
プロセス起床
ハードウェア割り込み
ユーザ空間へコピー
パケットパケット
ソフトウェア割り込み
パケット受信
ハッシュ計算
ディスパッチ
プロトコル処理
ソケット受信処理
ユーザプログラム user
buffer
socketqueue
backlog#1
hash queue 参照■■
01
CPU間割り込み
backlog#2
backlog#3
13年6月7日金曜日
RPSの使い方
# echo "f" > /sys/class/net/eth0/queues/rx-0/rps_cpus
# echo 4096 > /sys/class/net/eth0/queues/rx-0/rps_flow_cnt
13年6月7日金曜日
RPS netperf resultnetperf benchmark result on lwn.net:
e1000e on 8 core Intel
Without RPS: 90K tps at 33% CPU
With RPS: 239K tps at 60% CPU
foredeth on 16 core AMD
Without RPS: 103K tps at 15% CPU
With RPS: 285K tps at 49% CPU
13年6月7日金曜日
RFSの使い方
# echo "f" > /sys/class/net/eth0/queues/rx-0/rps_cpus
# echo 4096 > /sys/class/net/eth0/queues/rx-0/rps_flow_cnt
# echo 32768 > /proc/sys/net/core/rps_sock_flow_entries
13年6月7日金曜日
RFS netperf resultnetperf benchmark result on lwn.net:
e1000e on 8 core Intel
No RFS or RPS 104K tps at 30% CPU
No RFS (best RPS config): 290K tps at 63% CPU
RFS 303K tps at 61% CPU
RPC test tps CPU% 50/90/99% usec latency StdDev
No RFS or RPS 103K 48% 757/900/3185 4472.35
RPS only: 174K 73% 415/993/2468 491.66
RFS 223K 73% 379/651/1382 315.61
13年6月7日金曜日
Accelerated RFS
• RFSをMultiQueue NICでも実現するためのNICドライバ拡張
• Linux kernelはプロセスの実行中CPUをNICドライバに通知
• NICドライバは通知を受けてフローのキュー割り当てを更新
13年6月7日金曜日
Receive Side Scalingの制限• 32bitのハッシュ値をそのまま使用していればハッシュ衝突しにくいが、Indirection Tableが小さいので少ないビット数でindex値をマスクしている→フローが多い時にハッシュ衝突する
• Accelerated RFSには不向き
13年6月7日金曜日
Flow Steering
• フローとキューの対応情報を記憶4tuple:キュー番号のような形式で設定
• RSSのような明確な共通仕様は無いが、各社の10GbEに実装されている
• Accelerated RFSはFlow Steeringを前提としている
13年6月7日金曜日
Flow Steeringで手動フィルタ設定
# ethtool --config-nfc ix00 flow-type tcp4 src-ip 10.0.0.1 dst-ip 10.0.0.2 src-port 10000 dst-port 10001 action 6
Added rule with ID 2045
13年6月7日金曜日
XPSの使い方
# echo 1 > /sys/class/net/eth0/queues/tx-0/xps_cpus
# echo 2 > /sys/class/net/eth0/queues/tx-1/xps_cpus
# echo 4 > /sys/class/net/eth0/queues/tx-2/xps_cpus
# echo 8 > /sys/class/net/eth0/queues/tx-3/xps_cpus
13年6月7日金曜日
データ移動に伴うレイテンシの削減
• プロトコル処理よりもむしろNIC↔メモリ↔CPUキャッシュの間でのデータ移動に伴うオーバヘッドの方が重いケースがある
• 特にメモリアクセスが低速
13年6月7日金曜日
Intel Data Direct I/O Technology
• NICがDMAしたパケットのデータは、最初にCPU
がアクセスした時に必ずキャッシュヒットミスを起こす ↓
• CPUのLLC(三次キャッシュ)にDMAしてしまえ!
• 新しいXeonとIntel 10GbEでサポート
• OS対応は不要(HWが透過的に提供する機能)
13年6月7日金曜日
コピーが重い
Process(User)
Process(Kernel)
HW Intr Handler
SW Intr Handler
パケット受信
プロトコル処理
ソケット受信処理
ユーザプログラム
user buffer
inputqueue
socketqueue
パケット
システムコール
プロセス起床
ソフトウェア割り込みスケジュール
ハードウェア割り込み
ユーザ空間へコピー
13年6月7日金曜日
コピーが重いがゼロコピー化は困難
• NICのDMAバッファはキュー毎に設定できるがフロー毎ではない→そもそもキューを一つのアプリで専有出来る前提でないと無理
• バッファがページサイズにアライン・アロケートされてないと無理
• パケットヘッダとペイロードが分離されてないとバッファにパケットヘッダまで書かれてしまう
13年6月7日金曜日
• (Intel I/O ATとも呼ばれる)
• NICのバッファ→アプリケーションのバッファへDMA転送
• CPU負荷を削減
• チップセットに実装
• CONFIG_NET_DMA=y in Linux
Intel QuickData Technology
13年6月7日金曜日
プロトコルスタックを経由しないネットワークIO• プロトコル処理をする必要もSocket APIである必要も無いなら、ネットワークIOはもっと速く出来る
• 特定用途向け
• プロトコル処理を必要としないアプリケーション→snort、OpenvSwitchなど
• プロトコル処理を自前で行なってでも性能を上げたいアプリケーション
13年6月7日金曜日
基本的な仕組み• 専用NICドライバと専用ライブラリを用いて、NICの受信バッファをMMAP
• パケットをポーリング
• アプリ固有のパケットに対する処理を実行NIC
RX1 RX2 RX3
Kernel Driver
AppRX1 RX2 RX3
MMAP
Packets
Polling
Do some work
13年6月7日金曜日
RAWソケット・BPF
との違い?• ゼロコピーが基本
• マルチキューの受信バッファをそのままユーザランドにエクスポートしている
• ↑により、マルチスレッド性能が高い(RAWソケット・BPFはシングルスレッド)
• 上述の機能を実現するためNICのドライバを改造
13年6月7日金曜日
Intel DPDK• 割り込みをやめてポーリングを使用しオーバヘッド削減
• 受信バッファにHugePageを使う事によりTLB missを低減
• 64 byte packetのL3フォワーディング性能(Intel資料より)
• Linux network stack:Xeon E5645 x 2 → 12.2Mpps
• DPDK:Xeon E5645 x 1 → 35.2Mpps
• DPDK : Next generation Intel Processor x 1 → 80Mpps
• OpenvSwitch対応
• 対応NIC:Intel
13年6月7日金曜日
類似の実装• PF_RING DNA
ntopの実装、Linux向けlibpcapサポート対応NIC:Intel
• NetmapFreeBSD向けの実装、一応Linux版ありlibpcap, OpenvSwitchサポート対応NIC:Intel, Realtek...
13年6月7日金曜日