[SDN][Network]Ryu+LagopusでREST連携ルーターを動かして遊ぶ

経緯

夜眠ろうとした所、中々寝付くことができませんで・・・ために溜め込んでいたREST API連携ルーターのお触りコーナーをやってみることにしました。

過去の記事でハード構成は完了していることを前提とします。

想定している構成

Ryubookの記載を元に、想定する構成は以下の通りとしました。

どうやらrest_router.pyはこんな機能があるようです。

  • 原則ポートはtagged vlanですべてのVLAN IDに対応することが出来る
  • ブリッジは単一であるため、どこに挿しても同じポートになる
  • 任意のVLAN IDに対してIPアドレスを割り当てることが可能である
  • 任意のスタティックルートを定義することが可能である

そもそもREST APIとは何だ?

正しくは「RESTful API」と呼ぶようです。HTTP/HTTPSを通じて設定のやり取りや、処理命令をやり取りする規約のようで、つまりはHTTP/HTTPSで使われるGET/POSTなどを使用して設定を行う代物が今回使用するrest_router.pyになるのかなーと思われます。

取り敢えず起動しよう

Lagopus switchを起動します。(DPDK外してるのでオプションスイッチはこんなもん)

# lagopus -d --

ryu-managerを起動します。

# /usr/bin/python /usr/local/bin/ryu-manager --log-dir /var/log/ryu/ /usr/local/lib/ryu/app/rest_router.py

すると、Lagopus switchとryu-manager間で認識処理が行われ、スイッチはrest_routerとして起動することになります。

loading app /usr/local/lib/ryu/app/rest_router.py
loading app ryu.controller.ofp_handler
instantiating app None of DPSet
creating context dpset
creating context wsgi
instantiating app /usr/local/lib/ryu/app/rest_router.py of RestRouterAPI
instantiating app ryu.controller.ofp_handler of OFPHandler
(4169) wsgi starting up on http://0.0.0.0:8080
[RT][INFO] switch_id=0000000000000001: Set SW config for TTL error packet in.
[RT][INFO] switch_id=0000000000000001: Set ARP handling (packet in) flow [cookie=0x0]
[RT][INFO] switch_id=0000000000000001: Set L2 switching (normal) flow [cookie=0x0]
[RT][INFO] switch_id=0000000000000001: Set default route (drop) flow [cookie=0x0]
[RT][INFO] switch_id=0000000000000001: Start cyclic routing table update.
[RT][INFO] switch_id=0000000000000001: Join as router.

VLANにアドレスを加えてみる

tagged VLANに対する設定は全ポートに「すでに割り当てられてる」と考えて良いのかなと思います。一先ずは、curlを使用してPOSTすることにより、新規アドレスの追加が行なえます。

指定するURLを変えることにより、対象のスイッチやVLAN IDを指定することが可能です。

# curl -X POST -d '{"address":"<address>/<mask>"}' http://<ctrl-ip>:8080/router/<SW-ID>/<VLAN-ID>

試しに、VLAN10に対して192.168.100.7を指定するとなると、こんな感じになります。L2レイヤーではMAC学習の準備を行う感じになります。

# curl -X POST -d '{"address": "192.168.100.7/24"}' http://localhost:8080/router/0000000000000001/10

(4176) accepted ('127.0.0.1', 57572)
[RT][INFO] switch_id=0000000000000001: Set default route (drop) flow [cookie=0xa00000000]
[RT][INFO] switch_id=0000000000000001: Set host MAC learning (packet in) flow [cookie=0xa00000001]
[RT][INFO] switch_id=0000000000000001: Set IP handling (packet in) flow [cookie=0xa00000001]
[RT][INFO] switch_id=0000000000000001: Set L2 switching (normal) flow [cookie=0xa00000001]
[{"switch_id": "0000000000000001", "command_result": [{"result": "success", "vlan_id": 10, "details": "Add address [address_id=1]"}]}]127.0.0.1 - - [06/Dec/2017 02:45:04] "POST /router/0000000000000001/10 HTTP/1.1" 200 243 0.006439

同様に冒頭の図で示すようなIPアドレスをRESTルーターに対して割り当てていきます。

# curl -X POST -d '{"address": "192.168.220.7/24"}' http://localhost:8080/router/0000000000000001/20
# curl -X POST -d '{"address": "192.168.200.7/24"}' http://localhost:8080/router/0000000000000001/100

設定の参照

設定の参照は以下のとおり行います。

# curl http://localhost:8080/router/<Switch-ID>/<VLAN-ID>

※VLAN-IDやSwitch-IDは「all」にすることも可能

出力結果はこうなります。実際には、括弧書きになっている箇所は1行で出力されます。

127.0.0.1 - - [06/Dec/2017 02:48:35] "GET /router/all/all HTTP/1.1" 200 411 0.000598
[{"internal_network": [{}, 
{"vlan_id": 100, "address": [{"address_id": 1, "address": "192.168.200.7/24"}]}, 
{"vlan_id": 10, "address": [{"address_id": 1, "address": "192.168.100.7/24"}]}, 
{"vlan_id": 20, "address": [{"address_id": 1, "address": "192.168.220.7/24"}]}], 
"switch_id": "0000000000000001"}]

動作確認

まず、何もしなくても・・・・というところで、ARPの学習処理等はアドレス割当を行い、Trunkポートに接続した時点で開始されています。こんなログが標準出力に出ていました。192.168.100.219は仮想ストレージの管理IP、192.168.100.202はActive DirectoryサーバのIPアドレスですね。

GARPの受信、応答としての送信が繰り返されていました。

[RT][INFO] switch_id=0000000000000001: Receive GARP from [192.168.100.219].
[RT][INFO] switch_id=0000000000000001: Send GARP (normal).
[RT][INFO] switch_id=0000000000000001: Set implicit routing flow [cookie=0xa00000001]
[RT][INFO] switch_id=0000000000000001: Receive GARP from [192.168.100.219].
[RT][INFO] switch_id=0000000000000001: Send GARP (normal).
[RT][INFO] switch_id=0000000000000001: Set implicit routing flow [cookie=0xa00000001]
[RT][INFO] switch_id=0000000000000001: Receive GARP from [192.168.100.219].
[RT][INFO] switch_id=0000000000000001: Send GARP (normal).
[RT][INFO] switch_id=0000000000000001: Set implicit routing flow [cookie=0xa00000001]
[RT][INFO] switch_id=0000000000000001: Receive ARP from an internal host [192.168.100.202].
[RT][INFO] switch_id=0000000000000001: Send ARP (normal)
[RT][INFO] switch_id=0000000000000001: Set implicit routing flow [cookie=0xa00000001]
[RT][INFO] switch_id=0000000000000001: Receive ARP from an internal host [192.168.100.202].
[RT][INFO] switch_id=0000000000000001: Send ARP (normal)
[RT][INFO] switch_id=0000000000000001: Set implicit routing flow [cookie=0xa00000001]
[RT][INFO] switch_id=0000000000000001: Receive ARP from an internal host [192.168.100.202].

L3スイッチからこのルーターのインタフェースIPアドレスに対してpingを打ってみました。

hatomugi#ping 192.168.220.7
 Pinging 192.168.220.7 with 0 bytes of data:

Reply From 192.168.220.7: icmp_seq = 0. time= 10000 usec.
Reply From 192.168.220.7: icmp_seq = 1. time <10 msec.
Reply From 192.168.220.7: icmp_seq = 2. time <10 msec.
Reply From 192.168.220.7: icmp_seq = 3. time <10 msec.

----192.168.220.7 PING statistics----
4 packets transmitted, 4 packets received, 0% packet loss
round-trip (msec) min/avg/max = <10/2/10

hatomugi#ping 192.168.100.7
 Pinging 192.168.100.7 with 0 bytes of data:

Reply From 192.168.100.7: icmp_seq = 0. time= 10000 usec.
Reply From 192.168.100.7: icmp_seq = 1. time <10 msec.
Reply From 192.168.100.7: icmp_seq = 2. time <10 msec.
Reply From 192.168.100.7: icmp_seq = 3. time <10 msec.

----192.168.100.7 PING statistics----
4 packets transmitted, 4 packets received, 0% packet loss
round-trip (msec) min/avg/max = <10/2/10

hatomugi#ping 192.168.200.7
 Pinging 192.168.200.7 with 0 bytes of data:

Reply From 192.168.200.7: icmp_seq = 0. time= 10000 usec.
Reply From 192.168.200.7: icmp_seq = 1. time <10 msec.
Reply From 192.168.200.7: icmp_seq = 2. time <10 msec.
Reply From 192.168.200.7: icmp_seq = 3. time <10 msec.

----192.168.200.7 PING statistics----
4 packets transmitted, 4 packets received, 0% packet loss
round-trip (msec) min/avg/max = <10/2/10

何れも正常に応答が帰ってきました。その際に、Ryu側からは以下の標準出力がありました。

■192.168.220.7へのping実行時
[RT][INFO] switch_id=0000000000000001: Set implicit routing flow [cookie=0x1400000001]
[RT][INFO] switch_id=0000000000000001: Receive ARP request from [192.168.220.254] to router port [192.168.220.7].
[RT][INFO] switch_id=0000000000000001: Send ARP reply to [192.168.220.254]
[RT][INFO] switch_id=0000000000000001: Receive ICMP echo request from [192.168.220.254] to router port [192.168.220.7].
[RT][INFO] switch_id=0000000000000001: Send ICMP echo reply to [192.168.220.254].
[RT][INFO] switch_id=0000000000000001: Receive ICMP echo request from [192.168.220.254] to router port [192.168.220.7].
[RT][INFO] switch_id=0000000000000001: Send ICMP echo reply to [192.168.220.254].
[RT][INFO] switch_id=0000000000000001: Receive ICMP echo request from [192.168.220.254] to router port [192.168.220.7].
[RT][INFO] switch_id=0000000000000001: Send ICMP echo reply to [192.168.220.254].
[RT][INFO] switch_id=0000000000000001: Receive ICMP echo request from [192.168.220.254] to router port [192.168.220.7].
[RT][INFO] switch_id=0000000000000001: Send ICMP echo reply to [192.168.220.254].

■192.168.100.7へのping実行時
[RT][INFO] switch_id=0000000000000001: Set implicit routing flow [cookie=0xa00000001]
[RT][INFO] switch_id=0000000000000001: Receive ARP request from [192.168.100.254] to router port [192.168.100.7].
[RT][INFO] switch_id=0000000000000001: Send ARP reply to [192.168.100.254]
[RT][INFO] switch_id=0000000000000001: Receive ICMP echo request from [192.168.100.254] to router port [192.168.100.7].
[RT][INFO] switch_id=0000000000000001: Send ICMP echo reply to [192.168.100.254].
[RT][INFO] switch_id=0000000000000001: Receive ICMP echo request from [192.168.100.254] to router port [192.168.100.7].
[RT][INFO] switch_id=0000000000000001: Send ICMP echo reply to [192.168.100.254].
[RT][INFO] switch_id=0000000000000001: Receive ICMP echo request from [192.168.100.254] to router port [192.168.100.7].
[RT][INFO] switch_id=0000000000000001: Send ICMP echo reply to [192.168.100.254].
[RT][INFO] switch_id=0000000000000001: Receive ICMP echo request from [192.168.100.254] to router port [192.168.100.7].
[RT][INFO] switch_id=0000000000000001: Send ICMP echo reply to [192.168.100.254].

■192.168.200.7へのping実行時
[RT][INFO] switch_id=0000000000000001: Receive ARP request from [192.168.200.254] to router port [192.168.200.7].
[RT][INFO] switch_id=0000000000000001: Send ARP reply to [192.168.200.254]
[RT][INFO] switch_id=0000000000000001: Receive ICMP echo request from [192.168.200.254] to router port [192.168.200.7].
[RT][INFO] switch_id=0000000000000001: Send ICMP echo reply to [192.168.200.254].
[RT][INFO] switch_id=0000000000000001: Receive ICMP echo request from [192.168.200.254] to router port [192.168.200.7].
[RT][INFO] switch_id=0000000000000001: Send ICMP echo reply to [192.168.200.254].
[RT][INFO] switch_id=0000000000000001: Receive ICMP echo request from [192.168.200.254] to router port [192.168.200.7].
[RT][INFO] switch_id=0000000000000001: Send ICMP echo reply to [192.168.200.254].
[RT][INFO] switch_id=0000000000000001: Receive ICMP echo request from [192.168.200.254] to router port [192.168.200.7].
[RT][INFO] switch_id=0000000000000001: Send ICMP echo reply to [192.168.200.254].

実際に動かしてみて

やった事自体は大したことありません。

ぶっちゃけこのルーター機能的にほとんど使い物にならないし、何より設定の保存ができないし。それこそIP振ってping打ってみましたーなレベルなんですが、久々にSDNスイッチに触ってみたのと、REST APIってなんだっけ?と言うところが復習できたのと、サンプルコンフィグの特性をチョイとかいつまんで理解ができた点で有意義だったかなと思っています。

REST APIって結構色んな所で活躍していますよね。オブジェクトストレージなんかそうだと思うし。それを活用したストレージヘッドなども最近は登場しているようで、グローバルファイルサーバなるものを構成できるとかできないとか。

こうしたAPIに舵取りを向けるか、パケットのやり取りに舵を向けるか、チョイと考えてみたいと思います。とは言えあくまで趣味の世界なので、そろそろ専門分野にも目を向け始めたほうが良いのかなーとか思ったりも。

タイトルとURLをコピーしました