Trema/SimpleL3Switch(1)

はじめに

Trema本(クラウド時代のネットワーク技術 OpenFlow実践入門 (Software Design plus))を改めて読み返してたわけですが、結局何かしらコード書いてみないとよくわからんのだよなーと。単純に examples とか動かしてみるだけだとね…。(そういうのを出版前にやってレビュー入れたらよかったのにという話なんですが、手が回らなかったんですよ…。)

で、どうせやるなら何か使いでのある物を(使えるかどうかはともかく)作った方が良かろう、と思って考えていたわけですが、Learning Switch から初めて Simple Router に至るという流れなので、これを組み合わせて L3 Switch みたいなの作ってみようかと。

Simple Router の概要

まず src/examples にある Simple Router なんですが、これは Routed Interface のみを持つ Router なんだよね。図で書くとこんな感じ。

構成上の制限として、Simple Router が持つインタフェース=1つのネットワークセグメントに対応するようになっているので、Simple Router と複数ホストをつなごうとするとどこかでL2スイッチ的な何かが入らないといけないわけです。

Simple L3 Switch の概要。

今回作った KVM 環境はこんなかんじな訳で。

OVS 多段にしてやれば Simple Router で複数ホストつなげてやれるんだろうけど、手っ取り早く L3 Switch 的に動いてくれればこの構成のまま複数ホスト間通信(ルーティング)できるじゃないか、という単純な発想をしてみる。Simple Router がポート単位で動いているところを Learning Switch 的な動作を加えてセグメント(複数ポートのグループ)単位でパケット転送動作もしてくれればいいので、素材としては examples にもうそろっているので。

Simple L3 Switch としてこんなのを作ってみた。

  • 1スイッチ複数セグメント
  • 1セグメント複数ポート
    • VLAN によるセグメント(ブロードキャストドメイン)分割みたいなものですが、べつに VLAN を使うわけではなく、単純なポートのグルーピングだけ。
  • 1ポート1セグメント
  • L3 Interface をつけない closed なセグメントも OK (network4)

Simple Router の処理概要

整理のために Simple Router のおおざっぱなフローチャート書いてみたので載せておく。

改造ポイント

  • Segment 情報を取り扱う
    • OFPP_FLOODで全ポートに対するフラッディングしてしまうと、セグメント分割もクソもあったもんじゃないので、どのポートがどのセグメントに所属しているか、という情報を別途加えます。Flooding の際はセグメント情報からそのセグメントに所属しているポートにだけ流すようにします。
    • スイッチのポートは番号で扱われるので Simple Router の設定ファイルではポート番号を使っていますが、OVS の設定を見る上ではポート名で表示されるので、コンフィグもポート名ベースで扱えるようにします。
      • ポート名とポート番号の対応は features request で取得します。
    • Simple Router では、Controller で実現する持つ仮想的なL3インタフェースはスイッチのポートと1対1でひも付いていましたが、Simple S3 Switch ではそこに1段Segmentの情報を入れます。つまり、[L3 Interface]-[Segment]-[Port(複数)] という関係になります。
  • Simple Router では転送先の決定のために ARP Table を使っていますが、これは [IPアドレス]→[ポート番号, MACアドレス] を検索するようになっています。Simple L3 Switch ではローカルセグメントのL2データ転送を扱うため、Learning Switch の FDB 相当の機能、つまり [MACアドレス]→[ポート番号] という検索もできるようにします。
    • データとしては ARP Table が持っている情報で足りているので、Table Lookup のメソッドを増やして L2 Forwarding にも対応できるようにします。
  • Packet In のロジック変更
    • Simple Router は自分宛 (to_me?) のパケットだけ処理していれば良かったのですが、Simple L3 Switch では自分宛のパケットも処理する(L2セグメント内での転送)必要があります。
    • ARP Request (L2 Broadcast) は、Router 宛てのケースと層でないケースで処理が分離するとか、Router からの ARP Request は特定ポートに出すのではなく対応するL2セグメント内へ flooding させる必要があるなどの処理の変更が発生します。

コード

とりあえず動いたっぽいのでいったん上げてみる。*1

コードの主な変更点については次回もうちょっと解説。

*1:だめだ。GitHubの使い方とか…そもそもGitの使い方とか全然覚えてない。使うならまじめに勉強せんといかんなあ…。