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

Cybozu Lab Youth 12th Enigamict

Enigamict
March 31, 2023
96

Cybozu Lab Youth 12th Enigamict

Enigamict

March 31, 2023
Tweet

Transcript

  1. 自己紹介 • Twitter & GitHub (@Enigamict) • 好きな事 ◦ Network

    ▪ Routing Protocol(BGP etc…)やLinux Network ▪ Segment Routing Mobile Network eBPF etc…
  2. 経路について & Routing Protocolとは • TCP/IPのインターネット上で、ユーザーが目的のネットワークにたどり着くためにはその宛先に関す る情報をルーティングテーブルに追加して通信をする事が可能になります。 ◦ 宛先に関する情報は経路情報と呼ばれます。 ◦

    経路情報は一般的にIPv4 address IPv6 addressなどでやりとりが行われます。(例外もある) • Routing Protocolは経路情報を自動的に処理し、経路情報の交換を円滑にするために作ら れた通信プロトコルになります。
  3. 設計と実装 • メッセージ交換の通信の手法として、 unixドメインソケットという方法を使用します。 ◦ 各プロセスがソケットを通じてメッセージのやり取りを行い、 ZebraではRouting Software側を Zserverと呼び、命令を出す側をZclientと呼びます ◦

    unix ドメイン間のメッセージ交換は単純なバイナリデータで通信を行います。 BGP OSPF IS-IS CLI … Routing Software unix domain send msg [0x01 0x01 0x01 0x01 ….] socket unix domain recv msg [0x01 0x01 0x01 0x01 ….]
  4. 設計と実装 • 経路テーブルに該当する経路を登録したい場合、 Linux kernelに対して「この経路を追加する」という命令 が必要になります。 ◦ Netlinkはユーザー空間とカーネル空間のやりとりを行う事が出来る Linux kernelのサブシステムと

    して存在しており、対応したメッセージを送信する事で Kernelに対し、経路の操作を行う事が出来ま す。 ◦ Netlinkに関する記事: https://eniyo0.hatenablog.com/entry/2022/11/23/180135 Routing Software BGP: 1.1.1.1/32… Linux Kernel Netlink msg 0240: 00 00 00 00 00 00 00 00 2c 00 00 00 18 00 01 06 0250: 00 00 00 00 00 00 00 00 02 20 00 00 fe 03 00 01 0260: 00 00 00 00 08 00 01 00 01 01 01 01 08 00 05 00 0270: 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00
  5. 設計と実装 • Server側の実装 ◦ メッセージをdecodeしたり、クライアントを受け付けるためのイベント駆動型の実装は Zebraの実装を元にGoで 簡易な実装。 ◦ Clientの受け付け(msgの受信とparse)またメッセージの送信を行う処理を Main

    Threadにし、Sub Threadは Clientに対してメッセージの送受信をServer側のコアな処理として機能しています。 ◦ NeburaはGoroutineを使用してMain Threadの処理をClientの受付、msgのparseとし、Sub Threadは実際 に受け取ったデータを元にNetlink msgの送信を行います。 Zebra(Server) process main thread void zserv_event() { case accept } sub thread voidzserv_client_event () { case read …. } Nebura(Server) process main thread for{ n.lis.Accept() n.MsgRead() …. } fn MsgRead() { go n.ClientSendEvent() } sub thread ClientSendEvent() { for{ select { case e := <-n.ceventChan: } } }
  6. 設計と実装 • Client側の実装 ◦ Client側の実装としては、unix domain socketによる接続を行いGoのInterfaceの実装を生かしたメッセージ の作成を行っています。 ◦ Bodyをメッセージを書き込むInterfaceとして定義し、各ヘッダーが持つ構造体ごとの

    writeTo()を作成する事で 設計しやすく、違いを持てるようにしています。 Nebura(Client) process type Body interface { writeTo() ([]byte, error) } type ApiHeader struct { Len uint16 Type uint8 Body Body } func (api *ApiHeader) writeTo() func (n *NclientRouteAdd) writeTo() … ↓ sendNclientAPI() { api := &ApiHeader{ … Body: body, } buf, _ := api.writeTo() }
  7. 設計と実装 • Server側の処理 ◦ 以下の経路情報の登録を Netlinkを通じて可能にしています。 (cgoで実装) ▪ IPv4 IPv6

    prefix (IPv6は未完成) ▪ Segment Routing(Single sidのみ) ▪ Segment Routing end action(END.DX4) ◦ 遅延など発生させる事が出来る TraficContorolの実装も行っています。 (cgo) ▪ TC netem ◦ またeBPFの仕様を利用した特別なパケット処理を行う事が出来る機能をメッセージを通じて登録出 来るようにしました。 (GoのNetlink lib & eBPF lib) ▪ XDP ◦ Zebraとの通信も可能です。 (FRRなら8.1以上ならおそらく動くはず ...) ▪ SendHello(Zebraに対してHello msgを送信し、経路元がどこから来ているかを判別してくれる) ▪ RouteAdd(経路の追加(IPv4のみ)、細かい調整は出来ていません ...)
  8. 簡単に動かしてみる • GoBGPからの経路を実際に登録 ◦ BGP peer up ◦ 経路を受け取れる状態にする 仮BGP

    10.0.0.1/24 GoBGP 10.0.0.2/24 2023/03/27 03:15:09 BGP State: Conect 2023/03/27 03:15:09 BGP Peer Listen... 2023/03/27 03:15:09 Listen addr 10.0.0.2... 2023/03/27 03:15:09 BGP State: Active 2023/03/27 03:15:09 BGP Open Recv... 2023/03/27 03:15:09 BGP KeepAlive Recv... 2023/03/27 03:15:09 State Estab... Nebura Zebra
  9. 簡単に動かしてみる • GoBGPからの経路を実際に登録 ◦ BGP UPDATE MSG ◦ 経路情報を受け取って、 Neburaにメッセージを送信

    仮BGP 10.0.0.1/24 GoBGP 10.0.0.2/24 023/03/27 03:24:52 Nebura Conect... 2023/03/27 03:24:52 Send buf [0 14 2 32 1 1 1 8 24 10 0 0 2 0]... Nebura Zebra
  10. Nebura hdr • Len(2byte uint16) + Type code(1byte uint8)のシンプルなヘッダー構造 ◦

    Nserver側で受け取るとLenの長さから全体のヘッダーの長さを取得 ◦ Type codeはNclientからの命令で、Typeを読み取って処理を行う Len(2byte) Type(1byte) Data hdr… Type code : 0x01(IPv4) : 0x02(IPv6) ….
  11. 簡単に動かしてみる • GoBGPからの経路を実際に登録 ◦ Nebura clientの受け付け ◦ Clientごとにメッセージを処理する 仮BGP 10.0.0.1/24

    Nebura(Server) 2023/03/27 03:24:45 Nebura Server start... 2023/03/27 03:24:52 Nebura Accept... 2023/03/27 03:25:31 Msg Read...
  12. 簡単に動かしてみる • GoBGPからの経路を実際に登録 ◦ Nebura msgの処理とNetlink msgの送信 ◦ メッセージのTypeによって駆動する。Netlinkメッセージを送信 仮BGP

    10.0.0.1/24 Nebura(Server) RIB SHOW BGP: 1.1.1.8/32 via 10.0.0.2 0000: 3c 00 00 00 18 00 05 05 … 0010: 02 20 00 00 fe ba 00 01 … 0020: 01 01 01 08 08 00 05 00 … 0030: 65 00 00 00 08 00 0f 00 … 0, Success func (n NservMsgSend) NecliEvent(ns *Nserver) error { switch n.api.Type { case IPv4RouteAdd: NetlinkSendRouteAdd(n.data) case IPv6RouteAdd: NetlinkSendIPv6RouteAdd(n.data) ….. )}
  13. 今後の展開とまとめ • 細かい経路情報の処理や未完成の部分を完成させる。 ◦ 所々の実装はまだ完璧ではない ... • GoBGPなどといったOSSを使用して、本格的なRouting Softwareとして機能させる。 ◦

    仮BGPの検証ではなく、大きなソフトウェアとの連携を行う事で機能改善を行う • 機能面の強化 ◦ 監視機能や可視化機能などを実装する ◦ もっと面白い事を募集...
  14. まとめ • 私は一年間ラボユース研究生として活動し、得られたものはとても多かった。 ◦ コードの読み方書き方をプロから教えてもらえる ▪ コードに対する考え方が変わり、コードの書き方から読み方を意識するようになっ た。また難しいOSSのコードが読めるようになったりした。 ◦ 自分の希望で最初はCSの基礎から教えてもらった

    ▪ データ構造などをみっちり教えてもらった (asmなどもいっぱい読んだ) ▪ スレッドプログラミングにどっぷりハマった • 非同期ランタイムに興味を持った • 特にプロに教えてもらうmemory orderingの勉強はとても楽しかった。 ◦ 低レイヤはとっても楽しい ◦ 最初から作りたいソフトウェアを作るのではなくて、作るまでの過程のサポートも行ってく れる。 光成さん、本当にありがとうございました。
  15. END