Upgrade to Pro — share decks privately, control downloads, hide ads and more …

モバイルネットワークのデータプレーンをXDPで作る話 / XDP based Mobile Network Data Plane

モバイルネットワークのデータプレーンをXDPで作る話 / XDP based Mobile Network Data Plane

Yuya Kusakabe

June 26, 2020
Tweet

More Decks by Yuya Kusakabe

Other Decks in Technology

Transcript

  1. モバイルネットワークの
    データプレーンをXDPで作る話
    2020/06/26 ENOG 63
    日下部雄也
    BBSakura Networks株式会社

    View Slide

  2. 自己紹介
    ● 日下部雄也 @higebu
    ● 2010/04~2016/07: ニフティ
    ○ IaaSの開発運用
    ● 2016/08~現在: さくらインターネット
    ○ ここからモバイルネットワークに入門した
    ● 2019/08~現在: BBSakura Networks出向
    ○ BBSakura NetworksはさくらとBBIXのジョイントベンチャー
    ○ モバイルネットワーク関連のシステムの開発、運用をやっている
    ○ 2020/04から開発本部長
    ● 普段使っているエディタはVim
    ● 北海道小樽市在住

    View Slide

  3. 目次
    ● さくらのセキュアモバイルコネクトとは
    ● 補足: さくらのクラウドのスイッチについて
    ● 構成変更について
    ● PGW-Uの中身
    ● 苦労話

    View Slide

  4. さくらのセキュアモバイルコネクトとは
    ● SIMを入れたデバイスからインターネットを経由しない
    閉域網でさくらのクラウドと通信できるサービス
    ● SIM1枚当たり13円/月
    ● 詳しくは https://www.sakura.ad.jp/services/sim/

    View Slide

  5. さくらのセキュアモバイルコネクトとは

    View Slide

  6. モバイルゲートウェイとは
    ● お客様が作成することができるGTPトンネルの終端
    ● 所属しているSIMの通信がここを通る
    ● 下記の機能がある
    ○ インターフェース(スイッチと接続する機能)
    ○ 所属しているSIMと、スイッチの先のサーバなどとの間で通信を行えるようにする
    ○ インターネット接続(NAPT)
    ○ デバイス間通信
    ○ スタティックルート
    ○ SIMルート
    ○ トラフィックコントロール(帯域制限)
    ● 機能の詳細は マニュアル 参照
    ● 以後、MGWと呼ぶ

    View Slide

  7. 補足: さくらのクラウドのスイッチについて

    View Slide

  8. 補足: さくらのクラウドのスイッチについて
    ● 実態はVLAN
    ● PR:「さくらのクラウド」のアーキテクチャは、意外なほどシンプルだった や、ENOG18発表資料
    さくらのクラウド インフラの紹介 参照
    ENOG18発表資料 さくらのクラウド インフラの紹介 P.13

    View Slide

  9. 構成変更について

    View Slide

  10. 構成変更について
    https://speakerdeck.com/higebu/20180124-sakura-secure-mobile-connect-deep-dive?slide=21
    ● 2019/12/17のメンテナンス で構成が変わってXDPベースになっている
    ● 以前の構成については2018/01/24のさくらの夕べで発表した
    ● (この発表資料を見た、とある企業から特許に関する問い合わせがあったが問題なく話は終結している)
    ● 今後もモバイル関連の技術についてもっとオープンに議論していきたいという気持ちで発表しています

    View Slide

  11. 構成変更について
    ● 2019/12/17以降の構成
    SGW
    PGW-C
    PGW-U
    さくらのクラウド上の
    スイッチたち
    インターネット
    VLAN
    VLAN
    VLAN
    VLAN IDを変換しつつ通信に必要な処理を全部やる
    ※CUPSをしてるけど間のプロトコルは標準無視して
    gRPCでやってる

    View Slide

  12. PGW-Uの中身

    View Slide

  13. MGW
    PGW-Uの中身
    mgw vrf
    vlan dummy roaming mgmt
    global vrf
    global
    default vrf
    eth0
    XDP
    vlan
    vrf
    eth1 VLAN trunkなポートに接続さ
    れている
    TC
    eBPF
    Maps
    FIB
    Table
    C-Plane
    API
    netlink(3)
    bpf(2)
    netlink(3)
    bpf(2)
    スタティックルート機能で設定し
    た経路はここに入る
    ● C-PlaneはGo製
    ● コンパネでMGWを作成すると上のMGWの中身が作成され、
    eBPF Mapsに必要な情報が書き込まれる
    ● PGWCからのトンネル作成のリクエストが来ると、
    eBPF Mapsに必要な情報が書き込まれる
    ● XDPのプログラムでは来たパケットを
    eBPF Mapsの情報を元に適切に処理して、
    XDP_DROPしたり、XDP_PASSしたり、XDP_TXしたりしている
    ● 帯域制御のためにTCも使っている
    ● dummyインターフェースはProxy ARPのため
    ○ Proxy ARPしたい経路をここに向けると、
    VLANインターフェースからの
    ARPに応答してくれるようになる
    インターネットに抜けるための
    VRF

    View Slide

  14. ここからは機能ごとのパケット処理の
    ざっくりした説明をします
    詳細はソースコードを読んでください
    ≒入社してください

    View Slide

  15. UE -> MGWに接続されたスイッチ(UL)
    ● 前提(以降のページでは書かない)
    ○ PGW-CへのCreate Session Request時に通信に必要な情報がPGW-Uに伝わっていなければならない
    ○ 必要な情報というのは、具体的にはSGWのU側のIP、PGW/SGWのU側で使うTEID、VLAN IDやVLANインターフェースのIDを含むMGWの情報
    ● 処理内容
    ○ 不要なパケットはDROPするが、LinuxにARPテーブルの管理を任せるため、ARPはPASSする(以降のページでは書かない)
    ○ TEID Aを元にeBPF Mapからトンネル情報、MGW情報を取得する
    ○ トンネル情報を元にパケットを書き換え
    ■ bpf_xdp_adjust_head()でIP/UDP/GTPヘッダの長さの分パケットのプラス方向に先頭アドレスを移動(decap)
    ■ bpf_fib_lookup()でソース/宛先MACアドレスを取得できればこれを使ってXDP_TX、取得できなければXDP_PASSする
    ● このとき参照するFIBテーブルはMGWのVRFのものなので、スタティックルート機能で設定した経路も使われる
    Ethernet 802.1q IP UDP GTP User Packet(IP) RX
    TX
    Ethernet 802.1q User Packet(IP)
    VLAN X (ローミングネットワークの
    VLAN)
    VLAN Y (MGWに接続されているスイッチの
    VLAN)
    TEID A
    XDP
    program
    eBPF
    Maps
    FIB
    Table
    bpf_fib_lookup()
    bpf_map_lookup_elem()

    View Slide

  16. MGWに接続されたスイッチ -> UE(DL)
    ● 処理内容
    ○ eBPF Mapを使って、VLAN IDからMGW情報、MGW IDとUEのIPアドレスからトンネル情報を取得する
    ○ トンネル情報を元にパケットを書き換え
    ■ bpf_xdp_adjust_head()でIP/UDP/GTPヘッダの長さの分パケットのマイナス方向に先頭アドレスを移動(encap)
    ■ トンネル情報からIP/UDP/GTPヘッダを書き込む
    ● 主にSGWのIP、GTPのTEIDを書き込む
    ■ bpf_fib_lookup()でソース/宛先MACアドレスを取得できればこれを使ってXDP_TX、取得できなければXDP_PASSする
    ● bpf_fib_lookup()で使うインターフェースはローミング用のインターフェース
    Ethernet 802.1q User Packet(IP) RX
    TX
    Ethernet 802.1q User Packet(IP)
    VLAN X (ローミングネットワークの
    VLAN)
    VLAN Y (MGWに接続されているスイッチの
    VLAN)
    TEID A
    IP UDP GTP
    宛先IPがUEのアドレス
    XDP
    program
    eBPF
    Maps
    FIB
    Table
    bpf_fib_lookup()
    bpf_map_lookup_elem()

    View Slide

  17. デバイス間通信(UL/DL)
    ● 処理内容
    ○ TEID Aを元にeBPF Mapからトンネル情報A、MGW情報を取得する
    ○ MGW IDと宛先のUEのIPアドレスからトンネル情報Bを取得する
    ■ 宛先のUEのセッションがあれば、トンネル情報Bを取得できる
    ○ トンネル情報Bを元にパケットを書き換え
    ■ 宛先IPをトンネル情報Bに入っているSGW Bのものにし、GTPのTEIDもBのものに書き換える
    ■ bpf_fib_lookup()でソース/宛先MACアドレスを取得できればこれを使ってXDP_TX、取得できなければXDP_PASSする
    ● この辺りは @takemioIO が詳しい
    Ethernet 802.1q IP UDP GTP User Packet(IP) RX
    TX
    Ethernet 802.1q User Packet(IP)
    VLAN X (ローミングネットワークの
    VLAN)
    VLAN X
    TEID A
    IP UDP GTP
    TEID B
    宛先IPが同じMGWに所属している別
    のUEのアドレス
    ソースIPは
    SGW Aのもの
    宛先IPは
    SGW Bのもの
    XDP
    program
    eBPF
    Maps
    FIB
    Table
    bpf_fib_lookup()
    bpf_map_lookup_elem()

    View Slide

  18. SIMルート(DL)
    ● 前提
    ○ SIMルートのMapが(BPF_MAP_TYPE_LPM_TRIE)あり、MGW IDをキーにしたMapのMap(BPF_MAP_TYPE_HASH_OF_MAPS)がある
    ○ SIMルートのMapはキーがIPレンジ、値がトンネル情報になっている
    ● 処理内容
    ○ eBPF Mapを使って、VLAN IDからMGW情報を取得
    ○ MGW IDからMGW毎のSIMルートMapを取得
    ○ 宛先IPを使ってSIMルートMapからトンネル情報を取得
    ○ トンネル情報を元にパケットを書き換え
    ■ ここは普通のDLと一緒
    ● 特開2019-216323
    Ethernet 802.1q User Packet(IP) RX
    TX
    Ethernet 802.1q User Packet(IP)
    VLAN X (ローミングネットワークの
    VLAN)
    VLAN Y (MGWに接続されているスイッチの
    VLAN)
    TEID A
    IP UDP GTP
    SIMルートに登録されている
    IPレンジにマッチする宛先
    IP
    XDP
    program
    eBPF
    Maps
    FIB
    Table
    bpf_fib_lookup()
    bpf_map_lookup_elem()

    View Slide

  19. UE -> インターネット(UL)
    ● 前提
    ○ conntrackテーブル(BPF_MAP_TYPE_LRU_HASH)とイベント送信用のMap(BPF_MAP_TYPE_PERF_EVENT_ARRAY)を用意しておく
    ● 処理内容
    ○ TEID Aを元にeBPF Mapからトンネル情報、MGW情報を取得する
    ○ 宛先IPがグローバルアドレスだった場合、NAPTの処理に入る
    ■ conntrackテーブルから、5タプル+方向をキーにNAPT情報を取得する
    ■ NAPT情報がなければ、グローバル側のソースポート(ICMPの場合はEcho ID)の割り当てをしつつ、NAPT情報を作成
    ● このときNAPT情報のイベントを送信をする(abuse対応で使う)
    ○ トンネル情報とNAPT情報を元にパケットを書き換え
    ■ 主にVLAN ID、ソースIP、ソースポートを書き換える
    ■ decapは普通のULと一緒だが、bpf_fib_lookup()で使うインターフェースをグローバル用のインターフェースにする
    Ethernet 802.1q IP UDP GTP IP RX
    TX
    Ethernet 802.1q
    VLAN X (ローミングネットワークの
    VLAN)
    VLAN Z (グローバルネットワークの
    VLAN)
    TEID A
    宛先IPがグローバルアドレス
    L4 Data
    IP L4 Data
    ソースIPがPGW-Uの
    グローバルアドレス
    XDP
    program
    eBPF
    Maps
    FIB
    Table
    bpf_fib_lookup()
    bpf_map_lookup_elem()
    bpf_map_update_elem()
    bpf_map_delete_elem()

    View Slide

  20. インターネット -> UE(DL)
    ● 処理内容
    ○ conntrackテーブルから所謂5タプル+方向をキーとして、NAPT情報、トンネル情報を取得する
    ○ NAPT情報、トンネル情報を元にパケットを書き換え
    ■ bpf_xdp_adjust_head()でIP/UDP/GTPヘッダの長さの分パケットのマイナス方向に先頭アドレスを移動(encap)
    ■ NAPT情報を使って、インナーパケットのIP/L4ヘッダを書き換える
    ■ トンネル情報を使って、アウターパケットのIP/UDP/GTPヘッダを書き込む
    ■ bpf_fib_lookup()でソース/宛先MACアドレスを取得できればこれを使ってXDP_TX、取得できなければXDP_PASSする
    Ethernet 802.1q RX
    TX
    Ethernet 802.1q
    VLAN X (ローミングネットワークの
    VLAN)
    VLAN Z (グローバルネットワークの
    VLAN)
    TEID A
    IP UDP GTP
    IP L4 Data
    IP L4 Data
    宛先IPがPGW-Uのグローバルアドレス
    XDP
    program
    eBPF
    Maps
    FIB
    Table
    bpf_fib_lookup()
    bpf_map_lookup_elem()
    bpf_map_update_elem()
    bpf_map_delete_elem()

    View Slide

  21. トラフィックコントロール(UL/DL)
    ● 前提
    ○ TCが有効なMGWでは、MGW情報のTCをするかどうかのフラグをオンにし、TCで使うClass IDを持たせている
    ● 処理内容
    ○ XDPプログラム
    ■ bpf_xdp_adjust_meta()でメタデータ領域を確保する
    ■ 取得したMGW情報内のTCのClass IDをメタデータ領域に書き込む
    ■ 状況に応じてパケットを書き換えてXDP_PASSする
    ○ TC
    ■ ingress側で、XDPメタデータ内のTCのClass IDをskb->markに書き込んで、bpf_redirect()
    ● iptablesでset-markするのと同じ
    ■ egress側はTC_ACT_OKするだけ
    ● この辺りは @_notchi が詳しい
    Ethernet 802.1q GTP or User Packet RX
    TX
    Ethernet 802.1q GTP or User Packet
    XDP
    program
    TC
    ingress
    cls_bpf
    TC
    egress
    cls_bpf
    bpf_redirect()

    View Slide

  22. その他
    ● 通信量カウント用のMapを用意して、SIM毎の通信量カウントをしている
    ● xdpcapを使って緊急時にパケットキャプチャをやれるようにしている
    ● 命令数が4096に制限されていて、有限ループも使えなかった時代の名残で、プログラムが 4つに分かれ
    ていて、メインのプログラムから bpf_tail_call()で呼び出している

    View Slide

  23. 苦労話

    View Slide

  24. ● Linuxのバグだと気付くのに時間がかかった
    ● VLANのパケットはskbが生成されるときにuntagされる
    ● skb_vlan_untag()で呼ばれるskb_reorder_vlan_header()でXDP metadataが置いて行かれてた
    ● 4.19以降に↓のパッチが入って直っています
    ● [v3] net: Fix missing meta data in skb with vlan packet
    XDP metadataがVLANに対応していなかった

    View Slide

  25. ● 最初は物理サーバで開発していて、だいたいできて来たので、クラウド上で動かそうと
    思ったらそもそもXDPが動かないことに気付いた
    ● virtio_netでXDPをやるにはキューをXDP用に別途用意しないといけない
    ○ [net-next,v6,0/5] XDP for virtio_net “queues must be available to dedicate to XDP”
    ● 他にも必要な機能があって、さくらのクラウドがマルチキュー対応した
    ○ サーバの仮想NICがマルチキューに対応しました
    ○ https://www.linux-kvm.org/page/Multiqueue
    ● サーバ作成時にタグとして @nic-double-queue を付けるとキューの数がCPUコア数
    *NIC数*2になる機能を作っていただいた
    ● ちなみにさくらのクラウドではvnet_hdrがオフになっているので、ethtoolでオフロードをオ
    フにしまくらなくてもXDPが使える
    さくらのクラウドがXDPに対応していなかった

    View Slide

  26. ● クラウド上でXDPは動いたけど、virtio_netでXDP metadataが使えなかった
    ● 対応させた -> [bpf-next,v6,2/2] virtio_net: add XDP meta data support
    ● qemuでVM起動するときのNICのオプションを変えるとソースのどこを通るようになるの
    かがわかるようになった(もう忘れた)
    ● 関係ない話ですが、LKMLにパッチをメールで送信するのが難しいです
    virtio_netがXDP metadataに対応していなかった

    View Slide

  27. ● SGWはエラーを返して来ていないけど通らないので、原因がわかるのに時間がかかった
    ● spare bitを1にしてしまったのが原因だった
    ○ 3GPP TS 29.060/29.281には0にしないといけないし、受け取った側は評価してはいけないと
    書いてある
    ● キャリアの設備でも仕様通りではない挙動をする設備がある。。。
    ● お客様や関係者の皆様には大変ご迷惑おかけしました
    一部キャリアの一部基地局でDLの通信が通らない事象

    View Slide

  28. C-Planeが大変という話
    ● ソフトウェアでのパケット処理あれこれ〜何故我々はロードバランサを自作するに至ったのか〜 (LINE)
    に↓のようなスライドがあって、めっちゃわかるーという気持ちになった
    ● D-Planeでなるべくややこしい処理をしないために C-Planeでお膳立てしてあげる必要がある
    ● ARPやルートの管理をLinuxに任せられるのでD-Planeはパケット処理に集中できる
    ● うちのPGW-UはCP: 8,000行、DP: 1,600行(2,900 instructions)くらいで、PGW-Cは5,000行くらい
    (自動生成コード除く)

    View Slide

  29. 終わり

    View Slide

  30. モバイルコアの開発に
    興味がある方はぜひ。。。
    http://recruit.softbank.jp/career/positions/detail/000920/

    View Slide

  31. EOF

    View Slide

  32. 参考
    ● GoでEPC
    ○ JANOG42 GoでEPC作って本番運用している話
    ● XDP
    ○ Cilium BPF and XDP Reference Guide
    ○ Suricata eBPF and XDP
    ○ Linux Documantation/bpf
    ○ Linux samples/bpf
    ○ XDP Hands-On Tutorial
    ○ BPF Features by Linux Kernel Version
    ○ Linux Observability with BPF
    ○ yunazuno.log
    ○ @IT Berkeley Packet Filter(BPF)入門
    ○ JANOG45 パケット処理の独自実装や高速化手法の 比較と実践 独自パケット処理実装方法解説( XDP)

    View Slide

  33. 参考
    ● LinuxのVRF
    ○ https://www.kernel.org/doc/Documentation/networking/vrf.txt
    ○ https://cumulusnetworks.com/blog/vrf-for-linux/
    ○ http://yunazuno.hatenablog.com/entry/2017/06/17/225917
    ● NAPT
    ○ https://tools.ietf.org/html/rfc2663
    ○ https://tools.ietf.org/html/rfc3022
    ○ https://tools.ietf.org/html/rfc6888
    ○ https://github.com/cilium/cilium/tree/master/bpf
    ○ https://github.com/torvalds/linux/tree/master/net/netfilter

    View Slide