Slide 1

Slide 1 text

ながらもネットワーク処理を ソフトウェアで⾃作していく話 2019.07.06 Toshiya Mabuchi 開発本部 インフラ室 ネットワーク開発グループ 転 び

Slide 2

Slide 2 text

⾃⼰紹介 • ⾺淵 俊弥 / @raibo • 開発本部 インフラ室 ネットワーク開発グループ • モンスターストライク等、 事業⽤サービスネットワークの設計/運⽤/開発 • 特定⽤途向けのネットワークデータプレーン開発 今日はこっち

Slide 3

Slide 3 text

パケット処理、好きですか︖ 1. だいすき 2. 興味ない

Slide 4

Slide 4 text

⾃社でパケット処理機能を ⾃作してる話

Slide 5

Slide 5 text

⾃社で開発するモチベーション 1. 汎⽤的な機器でネットワークを構築 • x86なLinuxサーバーで動く(すぐに交換/使いまわせる) 2. 冗⻑性の⾼さを保つ • アプライアンス+自作で冗長性の確保 3. シンプルな機能は⾃分たちで設計したい • 特定の事業にのみにフォーカスする機能は 小回りを効かせたい

Slide 6

Slide 6 text

Linux Socketの場合 NIC Rx NIC Tx NIC Kernel UserSpace Rx Ring Tx Ring Socket libsocket App sk_buff ProtocolStack IRQ Interrupt RSS syscall

Slide 7

Slide 7 text

Linux Socketを使ったパケット処理 • Pros • Linuxと各種⾔語の優れた抽象化 • 開発時もネットワークのかなりの部分を意識せず使える • 成熟したプロトコルスタックを利⽤できる • TCP等, 複雑なプロトコルに対して先⼈達の肩に乗って利⽤できる • Cons • ネットワーク処理⽤途で10Gbps~等の⼤規模な通信処理が難しい • ネットワーク処理に適⽤すると、1台当たりの処理能⼒が低い • 処理的に遅延が乗ってしまう • TCP/IPのネットワークスタック処理を⾏うからどうしても重くなる • 多段するとより顕著に遅くなる

Slide 8

Slide 8 text

なぜパフォーマンスが出ない︖遅延が乗る︖ • メモリコピーによるオーバーヘッド • 受信パケットをskbに変換し、ユーザスペースにコピーする段階等で メモリコピーが行われる • Linuxプロトコルスタック処理の重さ • IP/TCPレイヤの解釈にはそれなりの負荷がかかる ⽤途によっては、賢いプロトコルスタックは使わなくてもOK メモリコピーも最⼤限減らして、パケットのFowardに特化したい XDP, DPDK等の利用

Slide 9

Slide 9 text

⾼速パケット処理技術の概要

Slide 10

Slide 10 text

⾼速パケット処理はF1

Slide 11

Slide 11 text

XDP • eXpress Data Path • Linux Kernel Nativeなパケット処理機能 • カーネル内VMの上で動くコードを挿⼊できる機能を利⽤ (eBPF) • XDPはそのbytecodeをKernel NetworkDriverレベルの箇所に差し込む機能 • ユーザ空間からも参照/書き換えができるMAPやArrayが利⽤可能 NIC1 ELF-compiled eBPF NIC2 Management App Protocol Stack ... eBPF Map RX XDP XDP XDP_TX XDP_REDIRECT XDP_PASS r/w Queue JIT Compile UserSpace Kernel Hardware XDP_DROP r/w

Slide 12

Slide 12 text

DPDK Data Plane Development Kit • 専⽤デバイスドライバ(PMD)と開発⽤の周辺ライブラリセット • 1CPU当たり1スレッドでPolling(CPUをPollingで専有) • Hugepageによって⼤きなメモリを確保 • TLBキャッシュミス削減 • 専⽤のメモリアロケータによる⾼速な割当 • 実装⽤ライブラリも多数提供 • Checksum/decap/ACL等 • Docもかなりの充実具合 • https://doc.dpdk.org/ ApplicaKon Kernel Space NIC PMD

Slide 13

Slide 13 text

⾃社の取り組み

Slide 14

Slide 14 text

取り組んでいるもの ステートレス実装可能なもの中⼼ • Static NAT (DPDK/XDP) • グローバル ↔ プライベートIPの静的変換NAT • GRE Decap Endpoint (DPDK/XDP) • ひたすらGREをDecapする • マルチクラウド環境上でのアドレスバッティング対策 • 詳細: モンスターストライクも⽀えるデータプレーン • Tap Payload cutter & sFlow Converter (XDP) • サンプリング&解析に不要なデータを削除 • sFlow変換して別NICからFlowコレクターへ⾶ばす

Slide 15

Slide 15 text

NATの場合(XDPのパターン) • Static NAT開発 • 1:1のシンプルなIP変換 • 各NATは BPF_MAP_TYPE_PERCPU_HASH でCPU毎にテーブル管理 • GRPCによる複数台NATテーブルの管理&Stat取得 • 1台双⽅向で12Mpps(10Gbps程度)まで処理可能 Controll Server Backbone Private default Static NAT Static NAT StaKc NAT 192.0.2.0/24 ↔ 198.51.100.0/24 MAP MAP MAP MAP MAP MAP MAP MAP MAP

Slide 16

Slide 16 text

ペイロードカッター For pcap/sflow • Tapでトラブルシュートを⾏いつつ、必要ない情報はカットしたい • トラブルシュート時は所定のヘッダまで取れればOK • L4~L7以下のPacketのペイロードカットしてからユーザスペースへ • カットした部分をsFlowに変換して⾶ばす(WIP) • Flow対応してない区間でも取れる • bpf_xdp_adjust_tailでヘッドルーム縮小によってコピーしない Tap Static NAT Tap Aggregation Flow Collector .pcap XDP server Flow Dissect Payload Cutter Sampling XDP_DROP

Slide 17

Slide 17 text

作りはシンプル パケット処理部は200⾏いかない でも...考慮すべき点は結構ある

Slide 18

Slide 18 text

トラブルや課題

Slide 19

Slide 19 text

NAT実装時トラブル 謎のパケットロス • ある⽇パケットがロスし始めた ログを仕込んでも異常が観測されない • NICのFirmwareかドライバ周り? • でも試験では⼤丈夫だったけど.... ...テストサーバーとデプロイ⽤でドライバ違う...︕︕ • 試験 : ixgbe , 本番 : i40e 同じメーカーでもドライバ/ファームが違えば別機器と思うべし 適切な期間の性能試験を必ず実施しましょう

Slide 20

Slide 20 text

さらに沢⼭ハマる • 特定NICのVlan消失 • 数台のうち1つのNICで切りたい特定オフロードを切れなかった • オフロードをoffにできない(fixed)箇所はNIC毎に結構違う • 1週間でQueueが枯渇してパケットを送れなくなる • NICファームとKernel Driverの乖離が原因で 不要なパケットが溜まっていっていた... • ファームが絡むと、本当のところが明確には分からない...つらい • メニーコアマシンでXDP起動後、少しするとHang • Combinedで利⽤コアを抑制しないといけない • ⽤意できるXDP Ringの限界数は96個 • 参考: https://www.mail-archive.com/netdev@vger.kernel.org/msg246813.html

Slide 21

Slide 21 text

事前にも気を配る点は沢⼭ • 可能な限りロックを少なくしてる︖ • ロックレスなアーキテクチャを⽬指していこう • GlobalSharedな領域は減らしていこう • Affinityを意識して動かしているか︖ • NumaNodeを考慮したCPU割当してる? • CPU L2 cacheを意識した構成で使えている︖

Slide 22

Slide 22 text

気をつける点まとめ • サーバーのファームが⼊れ替え可能か確認しておくべし • 切り分けが相当しやすくなる • NICもサーバーのOEM提供だとファームが上げづらいことも • XDPはカーネルVerによって実装状況が結構違う • 実⾏時警告とかほぼ無いので、普通にパケット落ちます • ソースやPatchを確認しておこう • 例: mlx5のNIC XDP_REDIRECTは4.19~ • LinuxのKernelやドライバの知識が超重要 • NAPI/ドライバ/IRQ Balancer/numa/CPU cache/RSS/RFS等、 ある程度知らないとチューニングできない

Slide 23

Slide 23 text

まあ、様々な問題が起こるんです

Slide 24

Slide 24 text

カーネルという最高の抽象化を跨ぐには こういった問題とも向き合うことが必要

Slide 25

Slide 25 text

転ばぬ先の杖

Slide 26

Slide 26 text

テストと計測 • テスト駆動な開発 • OK/Failパターンのパケットを実装前に定義 • 実装物に関わるRFCからパケットパターンを決めて⽤意 • RFC2663, 3022, 7857 4787, 5382, 5508... • 全部通れば機能要件を概ね満たしている • 後から追加より実装上の⼿戻りも圧倒的に少ない • CircleCIで機能単位のテストを実施 • DPDK : Gtest • XDP : xdp_prog_run def test_egress_ether_vlan_ipv4_icmp_packet(self): i_pkt = Ether()/Dot1Q(vlan=10)/IP(src=”198.18.0.1", dst=”198.19.0.1")/ICMP() o_pkt = Ether()/Dot1Q(vlan=20)/IP(src=”198.18.1.1", dst=”198.19.0.1")/ICMP() self.xdp_test(self.egress, i_pkt, o_pkt, BPF.XDP_REDIRECT) ↑こんな感じで仮想的に実⾏して結果を確認可能

Slide 27

Slide 27 text

テストと計測 • 性能試験: T-Rex • Python APIを使ってシナリオ作成 • リリース毎(PR毎)に性能評価を試験 • ⾃動レポートして性能を⽐較 駄⽬な実装もこれで分かる!

Slide 28

Slide 28 text

1. 適切な利用シーン 2. 保守するというチームでの覚悟 3. リターンが見込めるケースでの利用 プロダクションに使うには、それなりのコスト(メンテ等)を支払うことになる 自社で開発するからといって必ず安く済むとは限らない でやっていかないと爆死しちゃいます 最後に...

Slide 29

Slide 29 text

まとめ • XDP/DPDK等で⾼速パケット処理開発 • 使うべき箇所と選定は⾒極めてやっていきましょう • チューニングやトラブル時にLinux Kernelや コンピュータアーキテクチャの基礎な知識は必須 • NICが違えば全く違う機器 • 同じx86でしょ︖は通⽤しない • Linuxの抽象化の隙間に潜り込むというのはそういうこと • ハマればハマるほどLinuxの深みを知ることになる

Slide 30

Slide 30 text

Thanks!