Ryu SDN Frameworkを活用した簡易ルータ機能の作成(3) 〜Ryuアプリのユニットテスト編〜
前回、双方のPC端末間での初歩的なIPルーティングをRyuアプリとして実装してみました。
通常のプログラミングでは、ユニットテストを想定しながら実装を行っていくと思います。OpenFlowプログラミングでもユニットテストを意識しながら実装を進めていくべきです。
ところで、実際のOpenFlowスイッチ動作によるPacket-inなどイベントドリブンな挙動をユニットテストで確認するには、どうしたらよいのでしょう?
この疑問を解決するために、Ryu SDN Frameworkの内部を調査した上で、OpenFlowプログラミングのユニットテストを実施してみました。
◆Ryu SDN Frameworkの内部調査
Ryu SDN Frameworkを確認してみて、わかったことは、どうやら、RyuコントローラとOpenFlowスイッチ間でOpenFlowチャネルが開設された時点で、Datapathオブジェクトが生成され、Ryuアプリは、このDatapathオブジェクトとのやりとりを通じてOpenFlowプロトコルを制御するみたいです。
特に、OpenFlowスイッチからPacket-in等を受信した際には、DatapathオブジェクトからEventMessageを受信することにより、必要な情報授受が行われることが理解できました。
ということで、ユニットテストの実装コードにて、(通常は、Ryuアプリ動作で自動生成される)Datapathオブジェクトを、制御してあげればよいみたいです。
◆Ryuアプリ「簡易ルータ(コード名;simpleForward)」のテストシナリオ
前回のブログ記事「Ryu SDN Frameworkを活用した簡易ルータ機能の作成(2) 〜IPルーティングの初歩編〜」で動作させたRyuアプリ「簡易ルータ(コード名;simpleForward)」をユニットテストの対象としました。
TestCase2:
HOST1〜HOST2間での通信シーケンスその1(HOST1:ARP学習前)において、HOST1からICMP Echoを受信した場合
TestCase4:
HOST1〜HOST2間での通信シーケンスその2(HOST1:ARP学習済)において、HOST2から想定外のIPパケットを受信した場合
前回、HOST1〜HOST2間での通信シーケンスその2の動作を確認したところ、双方のPC端末(HOST1,HOST2)は"91.189.89.22"宛にTCP SYNパケットを送信しており、OpenFlowコントローラは、OpenFlowスイッチによるPacket-inにより同TCP SYNパケットを受信しておりました。このようなRyuアプリ作成の当初には想定していないOpenFlowコントローラ動作が判明したので、本件も、ユニットテスト化しました。
◆ユニットテスト実装コード
Ryuアプリ「簡易ルータ(コード名;simpleForward)」のユニットテスト実装コードは、こちらになります。
simpleRouter/test_SimpleForward.py at master · ttsubo/simpleRouter · GitHub
◆実際に動かしてみた
想定とおり、動作できました。ちなみに、ユニットテスト実行中のDEBUG文は、Ryuアプリ「simpleForward」で記述したものです。
$ python test_SimpleForward.py .*** Case1: HOST1からARP Request受信 *** DEBUG:SimpleForward:receive ARP Request 52:54:00:75:4e:57 => ff:ff:ff:ff:ff:ff (port1) DEBUG:SimpleForward:--------------------------------------- DEBUG:SimpleForward:eth_dst_address :ff:ff:ff:ff:ff:ff DEBUG:SimpleForward:eth_src_address :52:54:00:75:4e:57 DEBUG:SimpleForward:eth_ethertype :0x0806 DEBUG:SimpleForward:--------------------------------------- DEBUG:SimpleForward:arp_hwtype :1 DEBUG:SimpleForward:arp_proto :0x0800 DEBUG:SimpleForward:arp_hlen :6 DEBUG:SimpleForward:arp_plen :4 DEBUG:SimpleForward:arp_opcode :1 DEBUG:SimpleForward:arp_src_mac :52:54:00:75:4e:57 DEBUG:SimpleForward:arp_src_ip :192.168.0.1 DEBUG:SimpleForward:arp_dst_mac :ff:ff:ff:ff:ff:ff DEBUG:SimpleForward:arp_dst_ip :192.168.0.10 DEBUG:SimpleForward:--------------------------------------- DEBUG:SimpleForward:send ARP reply 00:00:00:00:00:01 => 52:54:00:75:4e:57 (port1) .*** Case2: HOST2のMAC未学習の時、HOST1からICMP Echoを受信 *** DEBUG:SimpleForward:receive IP packet 52:54:00:75:4e:57 => 00:00:00:00:00:01 (port1) DEBUG:SimpleForward:--------------------------------------- DEBUG:SimpleForward:eth_dst_address :00:00:00:00:00:01 DEBUG:SimpleForward:eth_src_address :52:54:00:75:4e:57 DEBUG:SimpleForward:eth_ethertype :0x0800 DEBUG:SimpleForward:--------------------------------------- DEBUG:SimpleForward:ip_version :4 DEBUG:SimpleForward:ip_header_length :5 DEBUG:SimpleForward:ip_tos :0 DEBUG:SimpleForward:ip_total_length :38 DEBUG:SimpleForward:ip_identification:0 DEBUG:SimpleForward:ip_flags :2 DEBUG:SimpleForward:ip_offset :0 DEBUG:SimpleForward:ip_ttl :64 DEBUG:SimpleForward:ip_proto :1 DEBUG:SimpleForward:ip_csum :47236 DEBUG:SimpleForward:ip_src :192.168.0.1 DEBUG:SimpleForward:ip_dst :192.168.1.1 DEBUG:SimpleForward:--------------------------------------- DEBUG:SimpleForward:Drop packet DEBUG:SimpleForward:send ARP request 00:00:00:00:00:02 => ff:ff:ff:ff:ff:ff (port2) .*** Case3: HOST1のMAC学習済の時、HOST2からARP Replyを受信 *** DEBUG:SimpleForward:receive ARP Reply 52:54:00:0b:d0:48 => 00:00:00:00:00:02 (port2) DEBUG:SimpleForward:--------------------------------------- DEBUG:SimpleForward:eth_dst_address :00:00:00:00:00:02 DEBUG:SimpleForward:eth_src_address :52:54:00:0b:d0:48 DEBUG:SimpleForward:eth_ethertype :0x0806 DEBUG:SimpleForward:--------------------------------------- DEBUG:SimpleForward:arp_hwtype :1 DEBUG:SimpleForward:arp_proto :0x0800 DEBUG:SimpleForward:arp_hlen :6 DEBUG:SimpleForward:arp_plen :4 DEBUG:SimpleForward:arp_opcode :2 DEBUG:SimpleForward:arp_src_mac :52:54:00:0b:d0:48 DEBUG:SimpleForward:arp_src_ip :192.168.1.1 DEBUG:SimpleForward:arp_dst_mac :00:00:00:00:00:02 DEBUG:SimpleForward:arp_dst_ip :192.168.1.10 DEBUG:SimpleForward:--------------------------------------- DEBUG:SimpleForward:Send Flow_mod packet for 192.168.1.1 DEBUG:SimpleForward:Send Flow_mod packet for 192.168.0.1 .*** Case4: HOST2からHOST1以外の宛先IPへのIPパケットを受信 *** DEBUG:SimpleForward:receive IP packet 52:54:00:0b:d0:48 => 00:00:00:00:00:02 (port2) DEBUG:SimpleForward:--------------------------------------- DEBUG:SimpleForward:eth_dst_address :00:00:00:00:00:02 DEBUG:SimpleForward:eth_src_address :52:54:00:0b:d0:48 DEBUG:SimpleForward:eth_ethertype :0x0800 DEBUG:SimpleForward:--------------------------------------- DEBUG:SimpleForward:ip_version :4 DEBUG:SimpleForward:ip_header_length :5 DEBUG:SimpleForward:ip_tos :0 DEBUG:SimpleForward:ip_total_length :20 DEBUG:SimpleForward:ip_identification:0 DEBUG:SimpleForward:ip_flags :2 DEBUG:SimpleForward:ip_offset :0 DEBUG:SimpleForward:ip_ttl :64 DEBUG:SimpleForward:ip_proto :1 DEBUG:SimpleForward:ip_csum :50284 DEBUG:SimpleForward:ip_src :192.168.1.1 DEBUG:SimpleForward:ip_dst :91.189.89.22 DEBUG:SimpleForward:--------------------------------------- DEBUG:SimpleForward:Drop packet DEBUG:SimpleForward:unknown ip received ! . ---------------------------------------------------------------------- Ran 5 tests in 0.013s OK
◆Github/Jenkins連携
継続的インテグレーションの予備知識を学ぶため、Github/Jenkinsと連携したユニットテストの自動化環境を構築してみました。コード・カバレッジも自動で計測できて感激しました。
http://ttsubo.github.io/simpleRouter/tree/linuxBox/tests/coverage/index.html