1.3K Views
August 27, 18
スライド概要
JANOG42 Meeting in Mie で発表した資料です。
https://www.janog.gr.jp/meeting/janog42/program/goepc
@higebu
GoでEPC作って本番運用している話 JANOG42 Meeting in Mie 発表日時:7月12日(木) 15:05~15:35(30分) 発表会場:多目的ホール 2018/7/12(木) さくらインターネット株式会社 IoTチーム (C) Copyright 1996-2018 SAKURA Internet Inc 日下部雄也
自己紹介 日下部 雄也 https://twitter.com/higebu https://github.com/higebu ● さくらインターネット2年目(2社目) ● さくらのセキュアモバイルコネクト ○ ○ HSS/PGWの開発 SIMのプロファイル作成 ● 好きなルータ ○ VyOS ● 好きな言語 ○ Go 2
この話をしようと思った理由 • EPCの実装について話せる仲間が欲しい • うちではこうしていますみたいな話が聞きたい • EPCを実装する人が増えて欲しい • 5GCではControl PlaneがOpenAPI 3.0になるらしいので、作 る人増えそう 3
アジェンダ • • • • • • • • • さくらのセキュアモバイルコネクトとは なぜ独自にHSS、PGWを作ったのか なぜGoで作ったのか 基本的なLTEのアーキテクチャ HSSの基本 Goを使ったHSSの作り方 PGWの基本 Goを使ったPGWの作り方 まとめ 4
さくらのセキュアモバイルコネクトとは • お客様のデバイスからインターネットを経由しない 閉域網でさくらのクラウドと通信できるサービス • SIM1枚当たり12円/月 • 何回でもSIMを登録解除可能で、解除中は0円 • 詳しくは https://www.sakura.ad.jp/services/sim/ 5
さくらのセキュアモバイルコネクトとは インターネット (オプション) MNO モバイルゲートウェイ さくらのSIMを入れた デバイス スイッチ サーバ 専用サーバー データセンター AWS など ネットワーク接続 オプション 6
なぜ独自にHSS、PGWを作ったのか 7
なぜ独自にHSS、PGWを作るのか • 面白いから • コスト削減 • ○億円削減 • 機能追加の自由度 • SIMルートとか • 今後も便利な機能を作っていく予定 • アンコントローラブルな箇所の削減 • 性能、品質を自分たちでコントロールできる • 何かあったとき自分たちで対応できる • 今までの常識を壊したかった 8
なぜGoで作ったのか 9
なぜGoで作ったのか • 趣味 • シンプルな言語仕様 • ネットワーク強いけどプログラミング初心者な人とかでもすぐに書けるようにな る • gofmtによる自動フォーマット • それなりに高速 • go bench でベンチマークしやすい • 豊富なサンプル • Go自体、github.com/miekg/dns 、 github.com/osrg/gobgp など 10
基本的なLTEのアーキテクチャ 11
基本的なLTEのアーキテクチャ Diameter/SCTP S6a S1-MME UE HSS S11 eNB LTE-Uu MME S1-U SGW S5 C: GTPv2-C/UDP U: GTPv1U/UDP PGW SGi Operator Network 詳細は 3GPP TS 23.401 参照 12
基本的なLTEのアーキテクチャ - ローミング VPLMN HPLMN S6a S1-MME UE HSS S11 eNB LTE-Uu MME S1-U SGW PGW S8 SGi Operator Network 詳細は 3GPP TS 23.401 と GSMA IR.88 参照 13
基本的なLTEのアーキテクチャ - 処理の流れ • 例)Attach procedure • 3GPP 23.401 5.3.2.1 E-UTRAN Initial Attach • こういう図がたくさんあるので、 これで流れを把握する 14
HSSの基本 15
HSSの基本 - プロトコル • 3GPP TS 23.401 5.1.1.9 参照 • SCTP(Stream Control Transmission Protocol) • RFC 4960 • port 3868 • Diameter • RFC 3588 • Diameterプロトコルガイド(本) Figure 5.1.1.9-1: Control Plane for S6a interface 3GPP TS 23.401 16
HSSの基本 - 保持しないといけないデータ • 3GPP TS 23.401 5.7.1 参照 • 5.7は Information Storage という章で、それぞれのコンポー ネントが何を保持しないといけないか書いてある • IMSI、MME Identity、APNなど • ここには書いていないが、AuCも実装しないといけないので、 Rand、Kiなども保存する必要がある • AuCは認証に使う • LTEのセキュリティについて詳しくは 3GPP TS 33.401 参照 17
HSSの基本 - MMEとのやり取り(S6a) • 全体の流れが23.401、動作の詳細は29.272に書いてある • 3GPP TS 23.401 の下記の章参照 • 5.3 Authentication, security and location management • 5.4 Session Management, QoS and interaction with PCC functionality • 5.5 Handover • 3GPP TS 29.272 の下記の章参照 • 5 MME – HSS (S6a) and SGSN – HSS (S6d) • 7 Protocol Specification and Implementation • ここからいろいろなドキュメントに飛ばされる。。。 18
HSSの基本 - MMEとのやり取り(S6a) • 少なくとも下記のCommandに対応する必要がある • Authentication Information • Initial Attach • Update Location • Initial Attach • Cancel Location • HSSからのDetach • Notify • MMEやSGWの変更時など • Purge UE • MME上のSubcription-Dataが消えるときに来る 19
HSSの基本 - MMEとのやり取り(S6a) • Authentication Informationでは AuC を作ってSIMの認証を する必要がある • 鍵交換アルゴリズムは Milenage(3GPP TS 35.205) • MilenageはFreeBSDに実装されていて参考になる • https://github.com/freebsd/freebsd/blob/master/contrib/wpa/src/crypto/milenage.c 20
Goを使ったHSSの作り方 21
Goを使ったHSSの作り方 - GoでSCTP • Linuxはわりと古くからSCTP使える • 詳しくは man sctp • one-to-many と one-to-one があり、 one-to-one の方はTCPと同様のAPIで 使える • one-to-many できない環境なので one-to-one を採用 • SCTPにはいろいろなパラメータがあるが、GSMA IR.88におすすめ設定が 載っている • Go本体はSCTPに対応していない • Go自体に機能追加するか、 github.com/ishidawataru/sctp を使う 22
Goを使ったHSSの作り方 - GoでSCTP
• さくらではGo自体に機能追加した
ln, err := net.Listen("sctp", ":3868")
if err != nil {
// handle error
}
• Go1.9.1時点でのソース は公開している
• GoへのPR: proposal: x/net/sctp: new package #22191
•
Go本体に追加しようとしたが、SCTPはマイナーなので golang.org/x/net に
してと言われ、さらに他のIssueの対応待ちで保留になっている
23
Goを使ったHSSの作り方 - GoでDiameter • github.com/fiorix/go-diameter を使っている • わりとメンテされているし、動く • XMLでCommand、AVPの定義を書くスタイル(つらい) • 2018/2/6に Adding Go-Diameter SCTP support and 3GPP S6a protocol support #78 というPRがマージされている • github.com/ishidawataru/sctp が使われている • さくらでは未検証 • 試してみたい気持ちはあるが、Purge-UEなど足りないCommandがある 24
Goを使ったHSSの作り方 - GoでDiameter • 正しいパケットが作れているかの確認はWiresharkでやる 25
Goを使ったHSSの作り方 - GoでDiameter • • • • • • 正しいパケットだからと言って動くとは限らない ianaの定義と被っているResult Code 足りないAVP Mbit 相手の運用上指定できない数値 なぜか通らないAVP 26
PGWの基本 27
PGWの基本 - Control Plane プロトコル • 概要は 3GPP TS 23.401 5.1.1.6 • 詳細は 3GPP TS 29.274 • GTPv2-C (2123/UDP) 3GPP TS 29.274 Figure 5.1.1.6-1: Control Plane for S5 and S8 interfaces 3GPP TS 23.401 28
PGWの基本 - User Plane プロトコル • 概要は 3GPP TS 23.401 5.2.1.1 • 詳細は 3GPP TS 29.060 • GTPv1-U (2152/UDP) Figure 5.1.2.1-1: User Plane 3GPP TS 23.401 Figure 2: Outline of the GTP Header 3GPP TS 29.060 29
PGWの基本 - 保持しないといけないデータ • リストは 3GPP TS 23.401 5.7.4 • どう使うかは 3GPP TS 29.274 • IMSI、IMEI、IPアドレスなど 30
PGWの基本 - SGWとのやり取り(S5/S8) • 全体の流れが23.401、動作の詳細は 29.274 に書いてある • 3GPP TS 23.401 の下記の章参照 • 5.3 Authentication, security and location management • 5.4 Session Management, QoS and interaction with PCC functionality • 5.5 Handover • 3GPP TS 29.274 の全部参照 • ここからいろいろなドキュメントに飛ばされる。。。 31
PGWの基本 - SGWとのやり取り(S5/S8) • Control Planeは下記の5つを実装しておけば良いはず • Echo Request/Response • • Create Session Request/Response • • SGWの変更を伴うハンドオーバーのため Delete Session Request/Response • • Attachのため Modify Bearer Request/Response • • SGWとの相互監視のため Dettachのため Delete Bearer Request/Response • PGWからベアラを削除するため 32
PGWの基本 - SGWとのやり取り(S5/S8) • User PlaneはGTPv1-Uの下記のMessage Typeに対応する 必要がある • Echo • SGWとの相互監視のため • G-PDU • UEからのパケット、UEへのパケットを通すため 33
Goを使ったPGWの作り方 34
Goを使ったPGWの作り方 - GoでGTPv2-C • GoでGTPv2-Cを実装しているOSSを見たことはない • 普通にUDPサーバ、クライアントを実装すれば良い • golang.org/pkg/net で十分 • とにかくたくさんのIE(Information Element)のパーサを書か ないといけない(つらい) 35
Goを使ったPGWの作り方 - GoでGTPv2-C • 正しいパケットを作れているかはWiresharkで確認 36
Goを使ったPGWの作り方 - GoでGTPv2-C • • • • 正しいパケットだからと言って動くとは限らない2 足りないIE Instance PCO、3GPP TS 24.008に書いてあるけど 37
Goを使ったPGWの作り方 - GoでGTPv1-U • Linux kernel 4.7以降のgtpモジュールを使うか、tunインター フェースを作って実装するのが簡単 • 現在はtunインターフェース使う方で動いている • 最近、 github.com/google/gopacket にGTPのパーサが追加 された • New protocol GTP #417 • 使ってはいないけど参考になるのでは 38
Goを使ったPGWの作り方 - GoでGTPv1-U • Linux kernel 4.7以降のgtpモジュールを使う場合 • netlink経由でgtpトンネルを作ることができる • github.com/vishvananda/netlink を使うのが簡単 • 2017/5/7から使えるようになっている • Add support for GPRS Tunnelling Protocol(GTP) #229 • サンプルコード • さくらではこれより前から実装していたので、gtpモジュールの元になった libgtpnl を参考に実装した • netlinkのデバッグは大変だが nltrace が便利だった 39
Goを使ったPGWの作り方 - GoでGTPv1-U • tunインターフェースを使う場合(流れ) • Uplink • SGWから2152/UDPに来たGTPv1-Uのパケットのペイ ロードをtunインターフェースに入れる • Downlink • tunインターフェースから読み込んだパケットをGTPv1-Uで カプセリングしてSGWに投げる 40
Goを使ったPGWの作り方 - GoでGTPv1-U • tunインターフェースを使う場合(実装) • SGW方面はただのUDPサーバ、クライアント • github.com/vishvananda/netlink でtunインターフェースを 作って読み書きする Uplink UDP socket S5/S8 PGW tun SGi Downlink 41
Goを使ったPGWの作り方 - GoでGTPv1-U
• tunインターフェースを使う場合(実装)
• github.com/vishvananda/netlink でtunインターフェース
link := &netlink.Tuntap{
LinkAttrs: netlink.LinkAttrs{Name: "gtp0"},
Mode:
netlink.TUNTAP_MODE_TUN,
Flags:
netlink.TUNTAP_DEFAULTS | netlink.TUNTAP_NO_PI,
Queues:
1,
}
if err := netlink.LinkAdd(link); err != nil {
// handle error
}
if err := netlink.LinkSetUp(link); err != nil {
// handle error
}
●
link.Fds が []*os.File になっているので、 link.Fds[0] をRead/Writeする
42
Goを使ったPGWの作り方 - GoでGTPv1-U • 性能について • 高負荷な状況ではコンテキストスイッチが問題になる • sendmmsg/recvmmsg 使うとppsが改善できる • 詳しくはCloudflare先生の How to receive a million packets per second • Goだと golang.org/x/net/ipv4 でできる • サンプルコード • GTPのルータで使っている • モバイルゲートウェイではtunインターフェース側がボトルネックになる • 今のところそこまで困っていない 43
Goを使ったPGWの作り方 - GoでGTPv1-U • 参考: さくらのクラウド上での性能測定結果 • CPU 20 core、224 GB RAM、10Gbps • 2台のサーバ間でgtpトンネルを作ってiperf(iperf 3.2) • UDP(32 byteのパケット) • gtpモジュール: ~150Kpps • Go実装: ~70Kpps • TCP • gtpモジュール: ~3Gbps • Go実装: ~1.5Gbps 44
Goを使ったPGWの作り方 - GoでGTPv1-U • 1台で数Gbps以上出す必要が出てきたら試さないといけない かなと思っているものたち • 独自カーネルモジュール • DPDK • XDP • FD.io • 他に良さそうなものがあったら教えてください 45
まとめ 46
まとめ • EPCは案外作れるので皆さんも作りましょう • 作っている方がいたら声をかけてください 47
参考資料 • • • RFC • RFC 4960 SCTP • RFC 3588 Diamter • 3GPP • 3GPP TS 23.401 • 3GPP TS 24.008 • 3GPP TS 29.272 • 3GPP TS 29.274 • 3GPP TS 33.401 • 3GPP TS 35.205 • Go • • • • github.com/ishidawataru/sctp github.com/fiorix/go-diameter github.com/vishvananda/netlink golang.org/x/net/ipv4 C • • • Milenage libgtpnl nltrace GSMA • GSMA IR.88 48
おまけ: 参考になるOSSのEPC実装 • http://www.openairinterface.org/ • CでEPC全部実装しているがSPGWになっている • 日本だと富士通さんがコアメンバー • https://github.com/travelping/ergw • ErlangでGGSN/PGW実装している • http://nextepc.org/ • CでMME,SGW,PGW,HSS,PCRFを実装している 49