$30 off During Our Annual Pro Sale. View Details »

自作パケット処理系の性能測定と可視化&改善のPDCAを回して最強のパケット処理系の作り方を学ぼ...

Takeru Hayasaka
October 27, 2023

自作パケット処理系の性能測定と可視化&改善のPDCAを回して最強のパケット処理系の作り方を学ぼう / Let's Measure the Performance of Packet Processing System with Python Tools.

Takeru Hayasaka

October 27, 2023
Tweet

More Decks by Takeru Hayasaka

Other Decks in Research

Transcript

  1. 自己紹介 - 早坂 彪流 (Hayasaka Takeru|@takemioIO) - 仙台市出身, 京都市在住 -

    Pycon初参加🐍 - 社会人3年目(25歳) - 今月誕生日でした。四捨五入したら30歳でつらいです。 - さくらインターネット に所属して、現職(BBSakura)へ出向中 - 10月で転職して1年🎊 前職は京都にあるゲーム会社 - 仕事の中身がSwitchからSwitchにSwitchすることになりネットワークに関する開発へ... - 好きな技術: eBPF, Go,Python - 趣味はSFアニメ・漫画、散財とか - ふるさと納税駆け込んだら赤字になってしまった。 - 最近今更「魔法少女リリカルなのは」を見終わった。 2 https://fr.m.wikipedia.org/wiki/Fichier:Go_gopher_mascot_bw.png
  2. なぜこの題材で喋るのか - 自作パケット処理系が最近流行っててみんな(?)やってるイメージ - 最近はいい資料もたくさんあるイメージ - 自作パケット処理系をより良いものにするためには?という情報は少ない - なので一歩目ではなく二歩目を踏み出すための資料を作りたいと思った -

    なので後から見返すと嬉しくなるように書いてみました。 よって今回の発表スタイルは、書いてあるけど説明しない事もあります。 - 普段Python🐍にお世話になってるのでコミュニティにぜひ還元したかった - Goにもお世話になってます 3 https://twitter.com/pandax381/status/1547489422954070021 最近は若者向けにTCPを作ろうインターンみたいなのがあったり 
 https://github.com/xdp-project/xdp-tutorial XDPを利用した開発のためのワークショップが行われたり 

  3. Agenda - 背景事情と背景技術 - 高速なパケット処理系を作るとは? - 処理系に関する実装の基本的な考え方を速習 - PGW-Uの性能評価実験 -

    実際のパケット処理系をPython製のツールで測定・評価をした話 - PGW-Uのチューニングと改善 - 自作パケット処理系を測定していく中で行った三つの改善の紹介 - 今後の展望とまとめ 4
  4. • BBIXとさくらインターネットの合弁会社 • 2019年8月1日設立 • ネットワークサービスのソフトウェア開発 • 親会社を通じてソフトウェアを世に出している • すべての「モノ」がつながる社会の実現に向け、プラットフォーム(OCX)

    提供を通じてネットワークサービスのクラウド化を進めてます 開発や運用をしているサービス • さくらのセキュアモバイルコネクト • さくらのショートメッセージサービス • BBIXお客様向けポータル • OCX (Open Connectivity eXchange)
  5. 基本的なLTEアーキテクチャ 11 UE eNB HSS MME PGW SGW S1-U S5

    SGi S6a LTE-Uu S1-MME UE: User Equipment eNB: eNodeB, evolved Node B MME: Mobility Management Entity HSS: Home Subscriber Server SGW: Serving-Gateway PGW: Packet Data Network-Gateway The Internet & Cloud (& Operator network S11 この辺でSIMの 認証や位置登録 この辺でモバイル網の 終端とか制御 基地局 スマホとか
  6. フルMVNOの構成 12 UE eNB HSS MME PGW SGW S1-U S8

    SGi S6a LTE-Uu S1-MME UE: User Equipment eNB: eNodeB, evolved Node B MME: Mobility Management Entity HSS: Home Subscriber Server SGW: Serving-Gateway PGW: Packet Data Network-Gateway The Internet & Cloud (& Operator network S11 MVNOが 面倒を見てる 範囲 実際にはかなり複雑ことをしています。 詳しくは3GPP TS23.401とGSMA IR88を参照 MNOが 面倒を見てる 範囲 MNO MVNO
  7. LTEアーキテクチャでGTPを見ると... 14 UE eNB HSS MME PGW SGW S1-U S5

    SGi S6a LTE-Uu S1-MME UE: User Equipment eNB: eNodeB, evolved Node B MME: Mobility Management Entity HSS: Home Subscriber Server SGW: Serving-Gateway PGW: Packet Data Network-Gateway GTPトンネル: The Internet & Cloud (& Operator network S11 GTPに含まれるTEIDと呼 ばれるIDでUEからの通 信を識別します
  8. PGWのC/U分離ついて - PGWはコントロールプレーンと呼ばれる制御信号を処理する仕組みと ユーザープレーンと呼ばれる利用者信号だけを処理する仕組みに分割できる - このような分割をC/U分離(CUPS)と呼ぶ - 詳しくは3GPP TS 23.214に定義する

    - PGWでは特に PGW-C, PGW-U と呼びます - 分割することで - キャパシティ増強が簡単で障害時も嬉しい - 機能の単純化によって、性能の最適化も実施しやすい 16
  9. LTEアーキテクチャでPGWをC/U分離すると 17 UE eNB HSS MME PGW-U SGW S1-U S5

    SGi S6a LTE-Uu S1-MME UE: User Equipment eNB: eNodeB, evolved Node B MME: Mobility Management Entity HSS: Home Subscriber Server SGW: Serving-Gateway PGW-C: Packet Data Network-Gateway Controlplane PGW-U: Packet Data Network-Gateway Userplane The Internet & Cloud (& Operator network S11 PGW-C GTPv1-Uトンネル: GTPv2-Cトンネル:
  10. PGW-Uの処理動作 - 今回紹介するPGW-Uは以下のような動きをします - Uplink: SGWから受信したGTPパケットをDecapしてInternet等の方面に送信 - Downlink: Internet等の方面から受信したパケットをGTPヘッダーでEncapし、SGW に対して送信してUEに届ける

    - 他にもUEに合わせて(==TEIDをみて) どこに送信するか・ポリシーを適用するかを決定 する 18 The Internet & Cloud (& Operator network SGW PGW-U IP TCP IP ETH GTP/ UDP IP TCP ETH Uplink => <=Downlink Encap Decap Dot1q Dot1q
  11. ここまでのまとめ - MVNOの事業をやってるよ! - MVNOはPGW, HSSの面倒を見てるよ! - PGWは... - 利用者がインターネットやクラウドに出るためのパケット交換機です

    - GTPというトンネリングプロトコルを終端してて、ハンドオーバーを実現 - ユーザーの通信はGTPに含まれるTEIDというID単位で識別されます - C/U分離が可能で、分割するとメンテやキャパの観点からいい事がある - PGW-Uのお仕事はGTPをEncap/Decapしてあげて携帯等の通信を外部まで届けること 19
  12. 自作PGW-Uの紹介 - eBPF/XDP製のPGW-U - PGW-Cからのトンネル作成リクエストをハンドルしてeBPF Mapsと呼ばれるTableに セッションデータを書き込むことでeBPFのコード上で利用可能になる - XDPを採用することで既存のLinux Protocal

    Stackと協調動作しつつ実装可能 - ARPやICMP等をカーネルにフォワードできるので本質的な必須実装だけに注力可能 - なおこのCplaneやハンドラはGo製...... - 詳しくは以下のENOG 63 の資料が参考になるので興味あればご覧ください ENOG63 モバイルネットワークのデータプレーンを XDPで作る話 https://fr.m.wikipedia.org/wiki/Fichier:Go_gopher_mascot_bw.png
  13. このセッションで話す・話さないこと - 話すこと🙆 - 私たちのXDP製自作PGW-Uを題材に、高速パケット処理系をどう測定評価するか - 高速パケット処理系の手法と定石の説明 - 特にソフトウェア上で実装されるモノにフォーカスする -

    自作パケット処理系を磨く(測定・検証)ためにPythonをどのように利活用しているか - 話さないこと󰢄 - PGW-Uやモバイル網のアーキテクチャの詳細 - どういうサービスでどういう実装やアーキテクチャになっているか - eBPF/XDPに関する細かい話 21
  14. なるべく(余計な)処理をしない事である - 高速パケット処理系というとHWベース, SWベースがある - HWベースの実装: ASIC, P4, openflow, SmartNIC…etc

    - SWベースの実装: eBPF/XDP, DPDK…etc <- 今日はこの話 - 基本的にはソフトウェアの高速化と何も変わらない - 単一コアで処理をせず(並列化)、単一コアの処理時間を短くする(高速化)が肝である - 今どきのパケット処理系では、コストや性能の観点から HWとSWを組み合わせたハイブリットな実装が主流 - HWだけならコストが高すぎて、BigTechクラスの会社じゃないとコスパが悪すぎる 一方SWだけなら思ったほど性能が出ない...😇 23 https://developer.nvidia.com/blog/choosing-the-best-dpu-based-smartnic 今日はこっちの話
  15. パケット処理の並列化技術 24 処理箇所 分散方法 利用シーン RSS: Receive Side Scaling NICレベルの処理

    Hashを取りNIC Queueに振り 分けてCPUコア へ均等に負荷分散する パケット処理の並列化 RPS: Receive Packet Steering CPUレベルでの処理 単一CPUコアで パケットに対して特定 パラメータでhashを取ってCPU コアに分散する NICでRSSに対応して ないFlowをCPUで処理 できる様に変更した パケット処理の並列化 RFS: Receive Flow Steering NICレベルでの処理 ルールにマッチした特定の パケットが任意のCPUに渡すこ とができる Cplane向けのパケットは 専用に割り当てたCPUコアで 処理することで 特別な処理を分離出来る 処理の安定化を行える - 詳しくはLinux kernelのドキュメント見てください - https://www.kernel.org/doc/Documentation/networking/scaling.txt
  16. パケット処理の並列化技術 25 処理箇所 分散方法 利用シーン RSS: Receive Side Scaling NICレベルの処理

    Hashを取りNIC Queueに振り 分けてCPUコア へ均等に負荷分散する パケット処理の並列化 RPS: Receive Packet Steering CPUレベルでの処理 単一CPUコアで パケットに対して特定 パラメータでhashを取ってCPU コアに分散する NICでRSSに対応して ないFlowをCPUで処理 できる様に変更した パケット処理の並列化 RFS: Receive Flow Steering NICレベルでの処理 ルールにマッチした特定の パケットが任意のCPUに渡すこ とができる Cplane向けのパケットは 専用に割り当てたCPUコアで 処理することで 特別な処理を分離出来る 処理の安定化を行える - 詳しくはLinux kernelのドキュメント見てください - https://www.kernel.org/doc/Documentation/networking/scaling.txt 今回はRSSだけを メインとして話します
  17. NIC RSS: Receive Side Scaling - packetのHashを取りNIC Queueに振り分け てCPUコア へ均等に負荷分散する技術

    - packetに含まれる要素N個のTupleで 一つのFlowは定義される - このFlowごとに各CPUに負荷分散することで マルチコア処理が可能になる - 動作原理はざっくり図の通り - 詳しくはLinux kernelのドキュメント見てくださ い - https://www.kernel.org/doc/Documentation/net working/scaling.txt 26 cpu0 cpu1 cpu2 cpu3 RX Queue 00 RX Queue 01 RX Queue 02 RX Queue 03 HashMask
 pkt..
 Indirection Table 0
 HashFunc
 1
 2
 …
 MSX割り込み
  18. Q.round robinにせず, なぜHashを取るの? - A. PerFlowでパケット処理をしたいから - PerFlowで処理をしないとパケットのリオーダーが起きてしまう - 例えば

    TCPには順序保証があるので、雑に並列に処理をすると 並べ直しが必要になり困ってしまう - リオーダーが起きてしまうとパフォーマンス劣化が起きてしまったり、 HoLブロッキングとか...輻輳させてしまう原因に😇 27 UE PGW-U Uplink => <=Downlink サーバー 1 2 3 4 1 2 4 3 ほな今から音楽 データ送るで! TCPで順序保証されて 流れてくる 雑な実装のPGW-Uのせいで 途中経路でバラバラにされてし まった データ並びなおさないと 中身わからんわ! 賢くないと 「データ壊れてる! もう一回送って〜」 とか...
  19. - 従来ソフトウェアにおいてのパケット処理高速化の定石は大きく分けて二つ - ProtocolStack/OSのオーバーヘッド回避のためのKernelByPass - 高いパケットレートを保つためのCPU占有のBusyPolling - 大体そこを作るのはだるいので、ほぼパケット処理フレームワークの上に作って終わり(完) - DPDK,

    netmap, XDPが大体それに当たる - ちなみにXDPは? - KernelByPassはせず、プロトコルスタックに渡す前にドライバーレベルで動作させることでオーバー ヘッドを削減している - BusyPollingは NAPI を利用して実現している - NAPIとはLinuxにおいてパケット流量のレートが上がると自動でポーリングする機能 パケット処理系の高速化技法 28
  20. XDPの処理のケースを図にすると... - 水色:XDPで処理するパス - NICドライバー上で実行されkernel内 部で処理 - 橙色:通常の処理するパス - NICドライバーを通じて整形されてプロ

    トコルスタックに渡している - コンポーネントの論理関係から XDPの方が早いことがわかる 29 Application XDP Driver NIC Protocol stack/ socket Kernel land User land Hardware
  21. 基本的な実装方針はざっくりこの辺を考えたりする - テーブル参照の数を減らす - 参照するテーブルの数をなるべく減らす&まとめる。 - テーブルの構造の最適化 - HashMapなどを利用する分にはそれなりにパフォーマンスは良い -

    Per-CPUなテーブルを積極的に利用する - CPUで共通のテーブルだとRead/Writeでロックがかかって遅くなってしまうので、 コア単位でテーブルのレプリカを分けましょう - LPM(Longest Prefix Match)などは処理が重いのでできれば使わないでおく - ちゃんとしてるところはLPMやルーティングテーブルを最適化してたり... - e.g. NTTCom Kamuee の Poptrie 余談: パケット処理系のあるあるな高速化技法 30
  22. - ハードウェアで並列化し、必要なところを可能な限り高速にCPUで処理する - 具体的には - ハードウェアベースなところでRSSを処理しておく - CPUのAffinity、Multi NIC Queueも調整しておく

    - PerFlowパケットをなるべくデータのバケツリレーされるところの最初の方で処理を行う - 細かい話をするともっと色々あるがそれはまた別の話 - CPUの性能を引き出すあれこれ - HW的にはSMTを無効にする - VPPのようにL1のIキャッシュミスを減らすとか... - NICはRSS以外に高速化でも役立つ話とか - Csumオフロード(処理系依存) - VlanのDecapなどもできるので有効化するとか... - 出てきたIFから出す方が処理が早いとか - そんなこんなを上手い事ことするといい感じのオレオレ処理系ができます。 みんなパケットの通る気持ちよさを味わおうね! つまりSW Basedな高速パケット処理系とは 31
  23. 自作PGW-Uの紹介 - eBPF/XDP製のPGW-U - PGW-Cからのトンネル作成リクエストをハンドルしてeBPF Mapsと呼ばれるTableに セッションデータを書き込むことでeBPFのコード上で利用可能になる - XDPを採用することで既存のLinux Protocal

    Stackと協調動作しつつ実装可能 - ARPやICMP等をカーネルにフォワードできるので本質的な必須実装だけに注力可能 - なおこのCplaneやハンドラはGo製...... - 詳しくは以下のENOG 63 の資料が参考になります。興味あれば参照して下さい ENOG63 モバイルネットワークのデータプレーンを XDPで作る話 https://fr.m.wikipedia.org/wiki/Fichier:Go_gopher_mascot_bw.png 再掲

  24. PGW-Uがどんなことしてるのかおさらい - PGW-Uとはインターネット等に出るためのゲートウェイ - UL: GTPv1-UをUE方面から受信し、DecapしてInternet等に投げる - DL: EthernetをInternet等から受信し、GTPv1-UでEncapしてSGWに投げる -

    UEの識別にGTPv1-Uに含むTEIDを利用している 34 The Internet & Cloud (& Operator network SGW PGW-U Uplink => <=Downlink Encap Decap IP TCP IP ETH GTP/ UDP IP TCP ETH Dot1q Dot1q
  25. 性能測定の環境とPGW-Uの設定 35 TrafficGen PGW-U(DUT) L3SW MetricServer 100G 1G - Commons

    - Xeon Platinum 8362 32C/64T/64G - Intel E810-CQDA2 100GbE 2port - Ubuntu Server - Traffic Generator - TRex v2.50 - Linux 6.1.0-1008-oem - PGW-U - Linux 6.6.0-rc4 - L3SW - Dell S5248F-ON - SONiC v4.1.0 - MetricServer - Grafana v9.5.13 - Prometheus v2.47.2 - Pushgateway v1.6.2
  26. 性能測定のプロセス 36 TrafficGen PGW-U(DUT) L3SW MetricServer 100G 1G 1. TrafficGen(TRex)からUL/DLパケットをPGW-Uに

    送り、PGW-Uで(Encap/Decapの)処理されたパ ケットをTRexで受け取る 2. TrafficGenで計測結果(rx_bps等)の結果を PushGateway に送る 3. PGW-Uにはnode exporterを導入し、処理系 自身のCPU利用率等のメトリックを収集 4. メトリックをgrafana経由で CSV形式でダウンロードし、 matplotlibとsklearnを駆使してグラフ化📈 5. グラフを眺めてみる🤔
  27. 性能測定のためのパケット生成 - TrafficGeneratorのTRexはバックエンドにDPDK製ソフトウェアを、 フロントエンドにPythonを利用しているOSS - Scapy を使って任意のパケットを生成して負荷をかけることができる - DPDKはCを書かないといけないが、Pythonでラップされててお手軽簡単で 37

    IP TCP IP ETH GTP/ UDP Dot1q IP TCP ETH Dot1q Uplink:ローミング網からインターネット等へ Downlink:インターネット等からローミング網へ hdr = Ether()/ \ Dot1Q(vlan=t_global.args.vlan_id)/ \ IP(src=t_global.args.src, dst=t_global.args.dst)/ \ UDP(dport=2152, sport=2152, chksum=0)/ \ GTP_U_Header(gtp_type="g_pdu", teid=200) hdr = Ether()/ \ Dot1Q(vlan=t_global.args.vlan_id)/ \ IP(src=t_global.args.src, dst=t_global.args.dst)/ \ TCP(sport=8080, dport=80) Uplinkでのパケット生成例 Downlinkでのパケット生成例
  28. MultiFlowを実現するためのFlow変数 - この機能でパケットをMultiFlowにすることができる - TRexはパケットの一部をランダムやインクリメンタルに変化させられる - これを応用して送信元IPを変化させることで複数クライアントを模した環境 を再現することができる 38 IP

    TCP IP ETH GTP/ UDP Dot1q IP TCP ETH Dot1q Uplink:ローミング網からインターネット等へ Downlink:インターネット等からローミング網へ # SrcIP STLVmFlowVar( name="ip_src",size=4, op="random", min_value=t_global.args.src_min, max_value=t_global.args.src_max, ) STLVmWrFlowVar(fv_name="ip_src",pkt_offset= "IP.src"), # TEID STLVmFlowVar( name="teid",size=4, op="random", min_value=t_global.args.teid_min, max_value=t_global.args.teid_max, ) STLVmWrFlowVar(fv_name="teid",pkt_offset= "GTP_U_Header.teid") SrcIP, TEIDを 変化させてmulti flowに VID, SrcIP,DstIPを 変化させてmulti flowに Uplinkでのmulti flow化の例
  29. 生成したパケットで性能測定をしてみる - 実際にTRexを利用してパケットを投げ る時にはこのような設定を 入れます - Interface portの初期化 - L2モード

    or L3モードにするのか - L2モード: Macアドレスを手動で 与えた上で動作させる仕組み - L3モード: 任意のIPアドレスでARPの解 決を自動でサポートしてくれる 設定項目が減って嬉しい - 送って戻ってきたパケットが正しいか を判断する機能は無いので、RXに来たパ ケットをDumpする必要があります 39 # クライアントインスタンスを作る c = STLClient(server = t_global.args.ip) # 投げたいパケットとそのストリームを定義 s = STLStream( packet = self.pkt_handler.create_stream(frame_size), random_seed = 0x1234, mode = STLTXCont(), ) # TRexのバックエンドアプリと接続 c.connect() # ポートの初期化とL3での動作モード設定 c.reset(ports = self.rx_ports) c.set_service_mode(ports = self.tx_ports, enabled = True) c.set_l3_mode(port = e.port, src_ipv4 = e.ipaddr, dst_ipv4 = e.gw) c.add_streams(s, ports = self.tx_ports) # 実際にリクエストが返ってきたパケットの tcpdump設定 c.start_capture(rx_ports = e.port, limit = e.capture_size) # 負荷試験をスタート c.start(ports = self.tx_ports, mult = speed, duration = duration, force=True) # リクエスト終了まで待つ c.wait_on_traffic(ports = self.rx_ports) 生成したパケットをTRexを使って投げつける例
  30. さらにアプリケーションまで見てみる - perfコマンドを使ってカーネル内部の関数がどの様に呼ばれているのかを見ること でアプリケーションでのボトルネックを探ることができる 41 sudo perf record -a -g

    -F 99 sudo perf script > perf_data.txt perl stackcollapse-perf.pl perf_data.txt|perl flamegraph.pl > flamegraph.svg DLを測定中にperfを行った結果 perfを行うコマンド例
  31. 性能測定したデータをPrometheusに渡す - 測定終了後に パラメーターを取得 Pushgatewayに送信 - Prometheus でそれを ウォッチして取得 42

    # TRexで負荷をかけた部分のデータを取得 stats = c.get_stats(self.rx_ports) if t_global.args.is_send_metric:   metrix_for_prom = "".   join([    format_metrics_for_prom(stats[port],self.labels.with_ports(port)) for port in self.rx_ports])  send_metrics(self.pushgateway_host, self.jobname, metrix_for_prom) # pushgateway にメトリックを送る def send_metrics(pushgateway_host, job_name, payload):   url = f"http://{ pushgateway_host }/metrics/job/{ job_name }"   headers = {     'Accept': '*/*',     'Host': pushgateway_host,   }   req = urllib.request.Request(url, payload.encode('utf-8'), headers)   with urllib.request.urlopen(req) as res:    body = res.read() def format_metrics_for_prom(metrics, labels):   lines = [(f'{key}') + labels.to_label() + (f' {value:.8f}') for (key, value) in metrics.items() ]   lines.append("")   return "\n".join(lines) PushGatewayにメトリックを送る例
  32. 性能測定したデータをPrometheusに渡す - 右のようなヘルパークラスを作って Labelをつける - actionとuuid,frame_sizeは入れた方が 実験をする時には便利 - 以下のように条件を入れることができて 絞り込みに便利

    43 class LabelParam():   def __init__(self, duration, multiplier, frame_size,  action):     self.duration = duration     self.multiplier = multiplier     self.uid = str(uuid.uuid4())     self.frame_size = frame_size     self.action = action   def with_ports(self, ports):     self.ports = ports     return self   def to_label(self):     items = []     for k, v in self.__dict__.items():       if v is None:          continue       items.append(f'{k}="{v}"')     return "{"+", ".join(items)+"}" PushGatewayに送るときにラベルを付ける例 Prometheusでどの回の実験だったかを こんな感じに絞り込みができて便利
  33. 必要な測定データ抽出 44 - Grafanaから欲しい範囲のデータを CSVでdumpします - Jupyter Notebook上でpandasを 使ってCSVを読み出し、 Matplotlibでグラフ化します

    import matplotlib.pyplot as plt import lib.clue as clue df = clue.get_dataframe_from_csv('raw_data/scenario-mue-32cpu-dl.csv') target = df.loc[df['dot1q'] == '999'] plt.bar(target['frame_size'], target['rx_bps']/1000/1000/1000.0, width=100.0) plt.title("32Core-DL(v4) framesize-RxGbps") plt.xlabel("frame size[byte]") plt.ylabel("Rx throughpt[Gbps]") plt.ticklabel_format(style='plain') plt.grid(True) plt.savefig("./graph/cpu32-dl-bbs-rx.png") plt.show() CSVデータからグラフを作る例 こんな感じの結果が出ます
  34. 測定データを利用したデータ分析 45 - CSVを再度読ませてsklearnを使って線 形回帰モデルを作ります - ここではCPU負荷とframesize の因果関係を元に線形回帰します correlation =

    result['framesize'].corr(result['softirq_mean']) print(f'Correlation between softirq and payload length: {correlation}') # 独立変数と従属変数を指定 X = result['framesize'].values.reshape(-1,1) Y = result['softirq_mean'] # 線形回帰モデルのインスタンスを作成 model = LinearRegression() # モデルをデータにフィット model.fit(X, Y) # 結果の係数と切片を表示 print('Coefficient (slope): ', model.coef_) print('Intercept: ', model.intercept_) # フレームサイズとソフトIRQの平均値の散布図をプロット sns.scatterplot(x='framesize', y='softirq_mean', hue='core', data=result, palette='viridis') # 回帰直線をプロット plt.title('Linear Regression Model: DLv4 Packet Framesize vs mean SoftIRQ') plt.xlabel("frame size[byte]") plt.ylabel("softirq_mean[%]") plt.ylim(-0.1, 1.1) plt.plot(X, model.predict(X), color='red') plt.grid(True) plt.savefig("./graph/all_corr_v4_dl.png") plt.show() sklearnを使って線形回帰をする例 こんな感じの結果が出ます
  35. 評価条件 - 固定 - 収容テナント数(==VLAN): 1000 - Bearer: 1000000 -

    SGW: 100 - Req/s: 100Gbps - SMTはoff, IRQ Affinityの調整済み, nic queueも調整済み - RSSも有効, CPUパフォーマンスも調整済み - 変動 - パケットサイズを64, 128, 256, 512, 1024, 1424, 3024 のパターンで試行 - さらにこれらをCPUコア数を絞った上で実行します - シングルコア性能とマルチコア性能、そしてそれらをペイロード長を 変えながら調べていくことで基本性能を評価することができます 46
  36. 測定を通じて見つけた三つの問題点 1. eBPFMapからデータが消える事例 - 大量のエントリを流した際にエントリ数が大きくなるとデータが無くなってしまってた 2. GTPv1-Uパケットの処理をマルチコア対応した事例 - RSSが効いておらずでシングルコアでの処理になってた -

    IntelのNICドライバに機能を追加してマルチコア対応させた その結果$(nproc| CPUコア数)倍の効率アップができた事例 3. checksum機能をoptoutした事例 - パケットのcheck sumの処理で遅くなってそうだったので処理性能を向上させるために実施 - ※これは先ほどの評価の後に取り組んだものです 52
  37. - eBPF Mapに対して100万エントリ叩き込んだケースで起きた話でした - BPF_MAP_TYPE_LRU_PERCPU_HASHというMapTypeを使ったことが起因 - 使ってないやつは捨ててもらって最適化してもらおうと考えたが、なんと LRUはFullになったら捨てるわけではなく、MAXのエントリサイズの数割で 削除を始めてしまう....UEが繋がらない原因がわからず悩みました -

    しかも保持エントリ数に波がある。3割保持の時もあれば、7割保持とか... - 解決方法は以下のTypeとFlagをつけることで解決 - BPF_MAP_TYPE_PERCPU_HASH - グッバイLRU… - BPF_F_NO_PREALLOC - 実行時にメモリアロケートをするフラグ。実利用分だけ使って欲しい。 ディフォルトは事前にアロケートしてしまう。 その1 eBPFMapからデータが消える事例 53
  38. GTPv1-UでMultiFlowパケットを投げるとは? - 一般的にパケットのFlowを識別するには5Tupleの情報を利用します - 5Tupleとは Srcip, Dstip, Sport, Dport, Proto

    のパラメーターの事を指します - しかし、GTPv1-Uには一般に使われる5Tupleでは負荷分散が不十分 - Srcip: SGWの数 - Dstip: 自分宛なので固定😇 - Sport,Dport,Proto: 必ずUDPで必ず 2152 というポート番号を使ってくる😇 - そこでTEIDを要素に含めることで負荷分散が十分になりPerFlowな処理ができる - UE単位でIDが付与されるため、ユーザー単位でFlowの識別が可能になる 55 GTPv1 Header Format (cf. 3GPP TS 29.281 ) ちなみにUDPとGTPv1のDumpはこんな感じ
  39. LTEアーキテクチャでGTPを見ると... 56 UE eNB HSS MME PGW SGW S1-U S5

    SGi S6a LTE-Uu S1-MME UE: User Equipment eNB: eNodeB, evolved Node B MME: Mobility Management Entity HSS: Home Subscriber Server SGW: Serving-Gateway PGW: Packet Data Network-Gateway GTPトンネル: internet (& Operator network S11 GTPに含まれるTEIDと呼 ばれるIDでUEからの通 信を識別します 再掲
  40. 余談: SGWは実際どれくらいあるのか? - SGW -> PGW の通信なので Srcip は変わるのでは?と思うが、 残念ながらそんなに各MNOはSGWを多く置いてるわけではない

    - ざっくり数十程度のオーダーのイメージ - IPアドレスの分散はそこまで期待はできない。例えばあるキャリア さんの同一エリアからいっぱいくると実質一つのIPのSGWかも...😇 57
  41. 更なるチャレンジも💪 - この結果を元にLinux kernel にパッチを出した。絶賛レビュー中 - https://patchwork.kernel.org/project/netdevbpf/patch/20231012060115.107183-1-hayatak [email protected]/ - これでRSSがGTPに対して効くので、

    モバイルのシステムがLinux上で 効率的に使えるようになって嬉しい:) - こんな感じのノリでGTPv1-UにRSSが効きます 61 ethtool -N ens3 rx-flow-hash gtpu4 sde ethtool -N ens3 rx-flow-hash gtpc4 sde パッチに関するやり取りの写真 英語のメールに心折れかけてます
  42. Checksum処理の無効化は可能だった - 3GPP TS29.281 を見てみると双方がサポートしていればチェックサムは0で 良いことになっている - つまりUDP CsumがなくてSGWが受け付けてくれるなら問題はない -

    実際に主要な会社では問題が無いという事もわかった - よって、UDP CsumをOptoutする機能を追加した - 結果としてこのケースにおいてショートパケットで 3-4Gbps ほど改善できた 63 CSumあり => CSumなし =>
  43. 今後の展望 - 実は今回のサーバースペックだと、Traffic Gen単体でショートパケットの 場合においては完璧にPGW-Uに圧力をかけ切れなかった。 今後は複数Nodeをどうにかして使って測定できないかなどを検討してる - ショートパケットで 60-80GbE までは一応出る感じだがMaxで出せていない

    - SingleにおいてULとDLの差がすごいの未解決問題 - なんですごい差があるのかわからず。Intel Vtuneとかの高性能なプロファイラで でもう少し長く睨めっこしたりすると分かるのかもと思う。もうちょっと掘り下げる課題が... - 今回測定に利用したコード類など整理や社内での調整ができたら公開したいなと 思ったりしてます - 謝辞 - 性能測定のお手伝いをしてくれた同僚の @masu-mi -san に感謝です - ぜひ整理でも手伝ってください :) 66
  44. まとめ - 自作PGW-Uを題材にパケット処理系の測定と改善の実例を紹介しました - この発表を通じて以下について伝えました - どのようにパケット処理を高速化するのか? - →パケット処理のフレームワークといくつかの定石を利用すること高速化できます -

    どのようにして測定をするのか? - →TRexとPython使って所望のパケットを大量に送信することで測定できます - どのように改善するのか? - →データ分析を行い、メトリックを観察して洞察を得ながら取り組みます - ついでにモバイル網のコンポーネントは自作可能ということもお伝えしました :) - Pythonでパケット生成から計測評価までを一貫で出来て便利でした🥳 - Let's Enjoy Python and Packet Processing! 67