More Related Content Similar to Ethernetの受信処理 (20) More from Takuya ASADA (20) Ethernetの受信処理2. rcu read lock
receive_queue lock
nf_hooks nf_iterate
rcu read lock
tcp_rcv_established
tcp_v4_do_rcv
nf_hook_slow
nf_hook_thresh
___napi_schedule
__napi_schedule
e1000_intr
handle_irq
do_IRQ
common_interrupt
interrupt
get_rps_cpu
sock_queue_rcv_skb
ip_queue_rcv_skb
__udp_queue_rcv_skb
udp_queue_rcv_skb
__udp4_lib_rcv
ip_local_deliver_finish
NF_HOOK
ip_defrag
ip_rcv_finish
NF_HOOK
ip_rcv
__netif_recive_skb
process_backlog
net_rx_action
__do_softirq
netif_receive_skb
do_softirq
e1000_receive_skb
e1000_clean_rx_irq
e1000_clean
net_rx_action
__do_softirq
do_softirq
rps flow
table
backlog lock
backlog
enqueue_to_backlog
sk->sk_data_ready
fib_lookup
ip_route_input_slow
ip_route_input_common
fib
ip_mkroute_input
___napi_schedule
rps_trigger_softirq
handle_irq
do_IRQ
common_interrupt
interrupt
arch_send_call_function_single_ipi
generic_exec_single
__smp_call_function_single
net_rps_action_and_irq_enable
___napi_schedule process_backlog
NF_HOOK_THRESH
ip_route_input_noref
rt_hash_table
ip_local_deliver
ipq lock
ipq_put ip_frag_queue ip_find
udp_rcv
udp_table
__udp4_lib_lookup_skb
tcp_v4_rcv
sk->sk_data_ready
tcp_hashinfo
__inet_lookup_skb
read
sys_read
sys_read
vfs_read
file->f_op->read
sock_aio_read
do_sock_read
__sock_recvmsg_nosec
inet_recvmsg
sk_wait_data tcp_recvmsg
udp_recvmsg
__skb_recv_datagram
wait_for_packet
finish_wait
sk_receiv
e_queue
sk_backlog
3. Traditional
Network Stack
Process(User)
Process(Kernel)
SW Intr Handler
ソフトウェア割り込みスケジュール
ハードウェア割り込み
HW Intr Handler
ユーザ
プログラム
システムコール
ソケット
受信処理
プロセス起床
プロトコル処理
パケット受信
user
buffer
socket
queue
input
queue
パケット
ユーザ空間へコピー
netif_rx()
4. 旧来のパケット受信処理
Process(User)
Process(Kernel)
SW Intr Handler
ソフトウェア割り込みスケジュール
ハードウェア割り込み
HW Intr Handler
ユーザ
プログラム
システムコール
ソケット
受信処理
プロセス起床
プロトコル処理
パケット受信
user
buffer
socket
queue
input
queue
パケット
ユーザ空間へコピー
ハードウェア割り込み
↓
受信キューにキュー
イング
↓
ソフトウェア割り込
みスケジュール
13年6月7日金曜日
6. 1. 割り込みが多すぎる
Process(User)
Process(Kernel)
SW Intr Handler
ソフトウェア割り込みスケジュール
ハードウェア割り込み
HW Intr Handler
ユーザ
プログラム
システムコール
ソケット
受信処理
プロセス起床
プロトコル処理
パケット受信
user
buffer
socket
queue
input
queue
パケット
ユーザ空間へコピー
13年6月7日金曜日
8. 割り込みを無効にする?
• ポーリング方式
• NICの割り込みを禁止し、代わりにクロック割り込み
を用いて定期的に受信キューをチェック
• デメリット:レイテンシが上がる・定期的にCPUを起
こす必要がある
• ハイブリッド方式
• 通信量が多く連続してパケット処理を行っている時の
み割り込みを無効化してポーリングで動作
13年6月7日金曜日
9. NAPI(ハイブリッド方式)
Process(User)
Process(Kernel)
SW Intr Handler
パケット受信
ソフトウェア割り込みスケジュール
ハードウェア割り込み
HW Intr Handler
ユーザ
プログラム
システムコール
ソケット
受信処理
プロセス起床
プロトコル処理
割り込み無効化
user
buffer
socket
queue
パケット
ユーザ空間へコピー
パパケケッットト
パケットが無くなる
まで繰り返し
ハードウェア割り込み
↓
割り込み無効化&
ポーリング開始
↓
パケットが無くなっ
たら割り込み有効化
13年6月7日金曜日
10. NICの割り込みハンドラと
NAPI(e1000_intr)
sd = &_get_cpu_var(softnet_data)
if (napi_schedule_prep(&adapter->napi))
__napi_schedule(&adapter->napi)
→ list_add_tail(&napi->poll_list, sd->poll_list)
__raise_softirq_irqoff(NET_RX_SOFTIRQ)
// 割り込みを再開しない!
12. NAPI poll処理
(e1000_clean)
Interrupt Coalescing
• NICがOS負荷を考慮して割り込みを間
引く
• パケット数個に一回割り込む、
或いは一定期間待ってから割り込む
• デメリット:レイテンシが上がる
while (weight̶)
skb <- RX queue
napi_gro_receive(skb)
→ netif_receive_skb(skb)
→ ip_rcv()
if (RX queue.empty)
napi_complete(napi)
→ list_del(&napi->poll_list)
e1000_irq_enable()
13年6月7日金曜日
13. 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日金曜日
14. 2.プロトコル処理が重い
Process(User)
Process(Kernel)
SW Intr Handler
パケット受信
ソフトウェア割り込みスケジュール
ハードウェア割り込み
HW Intr Handler
ユーザ
プログラム
システムコール
ソケット
受信処理
プロセス起床
プロトコル処理
割り込み無効化
user
buffer
socket
queue
パケット
ユーザ空間へコピー
パパケケッットト
パケットが無くなる
まで繰り返し
13年6月7日金曜日
16. LRO
(Large Receive Offload)
• NICが受信したTCPパケットを結合し、
大きなパケットにしてからOSへ渡す
• プロトコルスタックの呼び出し回数を
削減
• LinuxではソフトウェアによるLROが実
装されている(GRO)
13年6月7日金曜日
17. LROが無い場合
To network stack
seq 10000 seq 10001 seq 10002 seq 10003
←1500bytes→
• パケット毎にネットワークスタックを
実行
13年6月7日金曜日
18. LROが有る場合
To network stack
big one packet
seq 10000 seq 10001 seq 10002 seq 10003
←1500bytes→
• パケットを結合してからネットワークスタックを
実行、ネットワークスタックの実行回数を削減
13年6月7日金曜日
19. Functions — Intel® 82599 10 GbE Controller
LRO on ixgbe(RSC)
First packet in the RSC
Header Payload-1 CRC Header Payload-2 CRC Header Rx Payload-3 CRC Header Payload-4 CRC
Packets
Large Rx
“Packet” Header
Payload-1 Payload-2 Payload-3 Payload-4
Large Rx
Buffers
Large Rx
Descriptors
NEXTP
Data Length =
whole buffer size
NEXTP
Data Length =
whole buffer size
Figure 7.41. RSC Functionality (No Header Split)
Last packet in the RSC
Header Payload-1 Payload-2 Payload-3
Large Receive example
while using Advanced
receive descriptors
(SRRCTL.DESCTYPE = 1)
Payload-4
EOP
Data Length =
partial buffer size
21. 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日金曜日
22. 3.複数のCPUでパケット処理したい
cpu0
Process(User)
Process(Kernel)
SW Intr Handler
パケット受信
ソフトウェア割り込みスケジュール
ハードウェア割り込み
HW Intr Handler
ユーザ
プログラム
システムコール
ソケット
受信処理
プロセス起床
プロトコル処理
割り込み無効化
user
buffer
socket
queue
パケット
ユーザ空間へコピー
パパケケッットト
パケットが無くなる
まで繰り返し
cpu1
Process(User)
Process(Kernel)
SW Intr Handler
パケット受信
ソフトウェア割り込みスケジュール
ハードウェア割り込み
HW Intr Handler
ユーザ
プログラム
システムコール
ソケット
受信処理
プロセス起床
プロトコル処理
割り込み無効化
user
buffer
socket
queue
パケット
ユーザ空間へコピー
パパケケッットト
パケットが無くなる
まで繰り返し
13年6月7日金曜日
27. TCP Reordering
1 2 3 4 5 6
1 2 3 4 5 6
protocol
processing
user buffer
• シーケンスナンバー通りの順序でパケットが
着信していれば順にバッファへコピーしてい
くだけでよいが…
13年6月7日金曜日
28. TCP Reordering
1 2 4 5 3 6
reorder
queue
3 4 5
1 2 3 4 5 6
protocol
processing
user buffer
• 順序が乱れているとパケットの並べ直し
(リオーダ)作業が必要になる
13年6月7日金曜日
30. RSS
(Receive Side Scaling)
• CPUごとに別々の受信キューを持つNIC
(MultiQueue NICと呼ばれる)
• 受信キューごとに独立した割り込みを持つ
• 同じフローに属するパケットは同じキューへ、
異なるフローに属するパケットはなるべく別のキュ
ーへ分散
→パケットヘッダのハッシュ値を計算する事により
宛先キューを決定
13年6月7日金曜日
31. MSI-X割り込み
• PCI Expressでサポート
• デバイスあたり2048個のIRQを持てる
• それぞれのIRQの割り込み先CPUを選べ
る
→1つのNICがCPUコア数分のIRQを持
てる
13年6月7日金曜日
32. おさらい:MultiQueue NICの割り込み
47: 7602 0 0 0 0 3 23 0 PCI-MSI-edge p1p1-TxRx-0
48: 0 7602 0 0 0 0 13 12 PCI-MSI-edge p1p1-TxRx-1
49: 12 0 7605 0 0 0 10 0 PCI-MSI-edge p1p1-TxRx-2
50: 0 12 0 7602 3 0 10 0 PCI-MSI-edge p1p1-TxRx-3
51: 0 0 12 0 7602 3 10 0 PCI-MSI-edge p1p1-TxRx-4
52: 0 0 0 20 0 7602 13 0 PCI-MSI-edge p1p1-TxRx-5
53: 0 0 0 0 12 0 7612 3 PCI-MSI-edge p1p1-TxRx-6
54: 3 0 0 0 0 13 10 7602 PCI-MSI-edge p1p1-TxRx-7
55: 0 2 0 0 0 0 2 0 PCI-MSI-edge p1p1
CPU毎に送受信キュー、キュー毎に
MSI-X割り込みを持つ
正しいsmp_affinityは固定的に決まっ
ている
複数CPUへ散らしてはならない
33. RSSによる
パケット振り分け
NIC
cpu0 cpu1 cpu2 cpu3
ハッシュ計算
パケット着信
パパケパケッケットットト
hash queue
ディスパッチ
参照
受信処理
RX
Queue
#0
RX
Queue
#1
RX
Queue
#2
RX
Queue
#3
受信処理
割り込み
■
■
0
1
13年6月7日金曜日
34. キュー選択の手順
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日金曜日
37. RPS
• RSS非対応のオンボードNICをうまくつかってサー
バの性能を向上させたい
• ソフトでRSSを実装してしまおう
• ソフト割り込みの段階でパケットを各CPUへばら
まく
• CPU間割り込みを使って他のCPUを稼動させる
• RSSのソフトウエアによるエミュレーション
13年6月7日金曜日
38. cpu0 cpu1 cpu2 cpu3
ユーザ
プログラム
システム
コール
ソケット
受信処理
プロセス起床
プロトコル処理
ディスパッチ
ハッシュ計算
パケット受信
ソフトウェア割り込み
割り込み無効化
user
buffer
socket
queue
ハードウェア割り込み
パケット
ユーザ空間へコピー
パパケケッットト
ユーザ
プログラムuser
ソケット
受信処理
プロトコル処理
buffer
socket
queue
backlog
#1
hash queue 参照0
1
■
■CPU間
割り込み
backlog
#2
backlog
#3
13年6月7日金曜日
39. 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日金曜日
40. RPSでリモートCPUへキュー
(netif_receive_skb_internal)
cpu = get_rps_cpu(skb)
→ skb_flow_dissect(skb, &keys)
hash = __flow_hash_3words(keys.dst, keys.src, keys.ports)
map = rxqueue->rps_map
cpu = map->cpus[(hash * map->len) >> 32]
enqueue_to_backlog(skb, cpu)
→ sd = &per_cpu(softnet_data, cpu)
__skb_queue_tail(&sd->input_pkt_queue, skb)
rps_ipi_queued(sd)
&__get_cpu_var(softnet_data)->rps_ipi_list = sd
net_rx_action
napi->poll
process_backlog
net_rps_action_and_irq_enable
smp_call_function_single_async
43. RPS netperf result
netperf 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日金曜日
47. 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日金曜日
49. cpu0 cpu1 cpu2 cpu3
ユーザ
プログラム
システム
コール
ソケット
受信処理
プロセス起床
プロトコル処理
ディスパッチ
ハッシュ計算
パケット受信
ソフトウェア割り込み
割り込み無効化
user
buffer
socket
queue
ハードウェア割り込み
パケット
ユーザ空間へコピー
パパケケッットト
ユーザ
プログラムuser
ソケット
受信処理
プロトコル処理
buffer
socket
queue
backlog
#1
hash queue 参照0
1
■
■CPU間
割り込み
backlog
#2
backlog
#3
13年6月7日金曜日
52. 受信処理の真っ最中に
配送先CPUを変更すると…?
• 変更前CPUと変更後CPUで同時に1つのフロー
の受信処理が実行される
• 変更後CPUの方が空いていて処理が早かった場
合、受信順序が前後する可能性がある
• TCP Reordering発生 → 遅くなる
53. 無難なタイミングで
宛先CPU変更
• システムコール側のテーブル
(rps_sock_flow_table)とパケットディスパッ
チに使うテーブル(rxqueue->rps_flow_table)
を別に持つ
• 変更元CPUのbacklogに積み残しが無いタイミ
ングで切り替えを行う
54. RFS netperf result
netperf 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日金曜日
55. Accelerated RFS
• RFSをMultiQueue NICでも実現するため
のNICドライバ拡張
• Linux kernelはプロセスの実行中CPUを
NICドライバに通知
• NICドライバは通知を受けてフローのキ
ュー割り当てを更新
13年6月7日金曜日
56. Receive Side Scalingの制限
• 32bitのハッシュ値をそのまま使用して
いればハッシュ衝突しにくいが、
Indirection Tableが小さいので少ないビッ
ト数でindex値をマスクしている
→フローが多い時にハッシュ衝突する
• Accelerated RFSには不向き
13年6月7日金曜日
57. • Disabling RSS on the fly is not allowed, and the 82599 must be reset after RSS is disabled.
• When RSS is disabled, packets are assigned an RSS output index = zero.
When multiple request queues are enabled in RSS mode, un-decodable packets are assigned an RSS
output index = zero. The 32-bit tag (normally a result of the hash function) equals zero.
Receive Side Scalingの制限
Parsed receive packet
RSS hash
7 LS
bits
32
Packet Descriptor
7
128フローしか
識別出来ない
RSS Disable or (RSS
& not decodable)
Redirection Table
128 x 4
4
0
4
RSS output index
32bitのハッシュ値のうち
4bitしか使ってない
フローが多いとハッシュ衝突する為、特定フローを
Figure 7.10. RSS Block Diagram
特定CPUへキューするのには向いていない
58. Flow Steering
• フローとキューの対応情報を記憶
4tuple:キュー番号のような形式で設定
• RSSのような明確な共通仕様は無いが、
各社の10GbEに実装されている
• Accelerated RFSはFlow Steeringを前提と
している
13年6月7日金曜日
59. Intel Ethernet
Flow Director
• Accelerated RFSガン無視
• 32kのハッシュテーブルの先にリンクドリスト
• 2つのFilter mode
• Signature Mode:ハッシュ値
最大32k個
• Perfect Match Mode:ヘッダの完全マッチ(dst-ip, dst-port,
src-ip, src-port, protocol)
最大8k個
60. following figure shows a block diagram of the flow director filters. Received flows are identified buckets by a hash function on the relevant tuples as defined by the FDIR...M registers. Each bucket organized in a linked list indicated by the hash lookup table. Buckets can have a variable length while
last filter in each bucket is indicated as a last. There is no upper limit for a linked list length during
Flow Director
programming; however, a received packet that matches a filter that exceeds the FDIRCTRL.Max-Length
reported to software (see Section 7.1.2.7.5).
Logic AND of Rx Packet tuples with
the Flexible filters Mask registers
~350
Hash
15 bit output
15 bit address
Bucket Valid First Filter PTR
Bucket Valid First Filter PTR
. . .
. . .
Flow ID Fields in “Perfect Match mode”
Hash (Signature)
15 bit output Flow ID Field in “Signature mode”
32K Filter Action
Hash Lookup Table
Shares the Rx
packet buffer memory space
Addr
0
1
2
. . .
M
Bucket Valid First Filter PTR
Bucket Valid First Filter PTR
Hash-Index = 0
Flow ID fields
Filter Action
Collision flag
Next Filter PTR
Hash-Index = 1
Flow ID fields
Filter Action
Collision flag
Next Filter PTR
Hash-Index = N
Flow ID fields
. . . Filter Action
Collision flag
Next Filter PTR
Hash-Index = N+1
Flow ID fields
Filter Action . . .
Collision flag
Next Filter PTR
Max recommended linked list length
(FDIRCTRL.Max-Length)
Hash-Index = 0
Flow ID fields
Filter Action
Collision flag
Next Filter PTR
Hash-Index = 1
Flow ID fields
Collision flag
Next Filter PTR
. . .
Bucket Valid First Filter PTR
Bucket M (linked list M)
Bucket 0 (linked list 0)
‘too long’
Linked list
Flexible Filters table - Shares the Rx packet buffer memory space
61. Linuxでの利用例#1(自
動)
送信処理
プロトコル
スタック
ソケット
システムコール
proce
ss
ドライバ
Txq
NIC
Flow
Director
Filters
フィルタ
更新
プロセスコンテキストからのパケット送出時に送信
元CPUとパケットヘッダを用いてフィルタを更新
62. Linuxでの利用例#2(手
動)
• ethtoolからフィルタをマニュアル追加
ethtool -K ntuple on
ethtool -U eth0 flow-type udp4 src-ip 0xa0a0a000
src-ip-mask 0xFFFFFF00 dst-ip 0 dst-ip-mask 0 src-port
9 src-port-mask 0 dst-port 9
ethtool -U eth0 flow-type tcp4 vlan 100 vlan-mask
0xF000 action 8
• フィルタの表示
ethtool -u eth0