今回は、OpenFlow ControllerのRyuに新たに追加されたRESTモジュールのrest_qos.pyを使用したQoSの動作確認を行った。
※rest_qos.pyは現在ポート単位でQueueの設定ができないので修正を加えている。rest_qos.pyこちらを使用して頂きたい。
環境構築
以下のようなトポロジをMininet上に構築する。また、帯域制御が必要になるシナリオとして、h1に接続しているs1のインターフェースの帯域幅を1Mbpsと仮定する。
[h1] - 1Mbps - [s1] - [s2] - [h2]
h1:172.16.20.10/24
h2:172.16.10.10/24
以下のコマンドでトポロジを構築する。
mininet@mininet-vm:~$ sudo mn --topo linear,2 --controler remote
OpenFlow1.3に設定する
mininet@mininet-vm:~$ sudo ovs-vsctl set Bridge s1 protocols=OpenFlow13
mininet@mininet-vm:~$ sudo ovs-vsctl set Bridge s2 protocols=OpenFlow13
各ホストに割り当てられているIPアドレスを削除し、IPアドレスを設定する。
host: h1
mininet> h1 ip addr del 10.0.0.1/8 dev h1-eth0
mininet> h1 ip addr add 172.16.20.10/24 dev h1-eth0
host: h2
mininet> h2 ip addr del 10.0.0.2/8 dev h2-eth0
mininet> h2 ip addr add 172.16.10.10/24 dev h2-eth0
実行例
まず、今回のネットワーク構成ではホストが疎通を行う為にルータが必要になるので、rest_routerを使用する。
rest_qosはパイプライン処理を想定する動作となっているので、rest_routerのフローエントリをtable_id:1へ登録するようにする。
mininet@mininet-vm:~$ sed '/OFPFlowMod(/,/)/s/0, cmd/1, cmd/' ryu/app/rest_router.py > ryu/app/qos_rest_router.py
Ryuコントローラを起動する。
mininet@mininet-vm:~/ryu$ PYTHONPATH=. bin/ryu-manager --verbose ryu/app/rest_qos.py ryu/app/qos_rest_router.py ryu/app/rest_conf_switch.py
Queueの設定を行う。
OVSDBのマネージャ接続ポートは6632で待ち受けているので、rest_conf_switchで登録を行う。
mininet@mininet-vm:~$ sudo ovs-vsctl set-manager ptcp:6632
mininet@mininet-vm:~$ curl -X PUT -d '"tcp:127.0.0.1:6632"' http://localhost:8080/v1.0/conf/switches/0000000000000001/ovsdb_addr
今回のシナリオはAF PHB(AF1のみ)を使った最低帯域保証を想定している。
QueueはAF11に50%(500Kbps)、AF12に30%(300Kbps)、AF13に10%(100Kbps)の帯域保証、残りはBest Effortとする。queuesの配列はそれぞれ添字となる0〜3がqueue_idに紐づいている。
mininet@mininet-vm:~$ curl -X POST -d '{"port_name": "s1-eth1", "type": "linux-htb", "max_rate":"1000000", "queues":[{"min_rate":"100000"},{"min_rate":"500000"},{"min_rate":"300000"},{"min_rate":"100000"}]}' {http://localhost:8080/qos/queue/0000000000000001}
キューイングのルールを設定する。
mininet@mininet-vm:~$ curl -X POST -d '{"match": {"ip_dscp": "10"}, "actions":{"queue": "1"}}' {http://localhost:8080/qos/rules/0000000000000001}
mininet@mininet-vm:~$ curl -X POST -d '{"match": {"ip_dscp": "12"}, "actions":{"queue": "2"}}' {http://localhost:8080/qos/rules/0000000000000001}
mininet@mininet-vm:~$ curl -X POST -d '{"match": {"ip_dscp": "14"}, "actions":{"queue": "3"}}' {http://localhost:8080/qos/rules/0000000000000001}
ルータの設定
ルータにアドレスを設定する。
ルータs1
mininet@mininet-vm:~$ curl -X POST -d '{"address":"172.16.20.1/24"}' http://localhost:8080/router/0000000000000001
mininet@mininet-vm:~$ curl -X POST -d '{"address":"172.16.30.10/24"}' http://localhost:8080/router/0000000000000001
ルータs2
mininet@mininet-vm:~$ curl -X POST -d '{"address":"172.16.10.1/24"}' http://localhost:8080/router/0000000000000002
mininet@mininet-vm:~$ curl -X POST -d '{"address":"172.16.30.1/24"}' http://localhost:8080/router/0000000000000002
ルータにデフォルトルートを設定する。
ルータs1
mininet@mininet-vm:~$ curl -X POST -d '{"gateway": "172.16.30.1"}' http://localhost:8080/router/0000000000000001
ルータs2
mininet@mininet-vm:~$ curl -X POST -d '{"gateway": "172.16.30.10"}' http://localhost:8080/router/0000000000000002
各ホストにデフォルトゲートウェイを設定する。
host: h1
mininet> h1 ip route add default via 172.16.20.1
host: h2
mininet> h2 ip route add default via 172.16.10.1
疎通確認
mininet> h1 ping 172.16.10.10 -c 3
PING 172.16.10.10 (172.16.10.10) 56(84) bytes of data.
64 bytes from 172.16.10.10: icmp_req=1 ttl=62 time=124 ms
64 bytes from 172.16.10.10: icmp_req=2 ttl=62 time=0.212 ms
64 bytes from 172.16.10.10: icmp_req=3 ttl=62 time=0.049 ms
疎通確認がとれた
トラフィックを流す。
iperfを使って実際に確認してみる。
ルータs1にUDP 5001ポート宛のパケットにDSCP値をマークするエントリを登録する。
mininet@mininet-vm:~$ curl -X POST -d '{"match": {"dl_type": "IPv4", "nw_proto": "UDP", "tp_dst": "5001"}, "actions":{"mark": "10"}}' {http://localhost:8080/qos/rules/0000000000000002}
mininet@mininet-vm:~$ curl -X POST -d '{"match": {"dl_type": "IPv4", "nw_proto": "UDP", "tp_dst": "5002"}, "actions":{"mark": "12"}}' {http://localhost:8080/qos/rules/0000000000000002}
mininet@mininet-vm:~$ curl -X POST -d '{"match": {"dl_type": "IPv4", "nw_proto": "UDP", "tp_dst": "5003"}, "actions":{"mark": "14"}}' {http://localhost:8080/qos/rules/0000000000000002}
iperfの設定
host: h1(1)
mininet> h1 iperf -s -u -i 1 -p 5001 > /tmp/h1-1.log &
host: h1(2)
mininet> h1 iperf -s -u -i 1 -p 5002 > /tmp/h1-2.log &
host: h1(3)
mininet> h1 iperf -s -u -i 1 -p 5003 > /tmp/h1-3.log &
host: h1(4)
mininet> h1 iperf -s -u -i 1 -p 5004 > /tmp/h1-4.log &
iperfでトラフィックを流す
host: h2(1)
mininet> h2 iperf -c 172.16.20.10 -i 1 -t 40 -u -p 5001 -b 600K &
host: h2(2)
mininet> h2 iperf -c 172.16.20.10 -i 1 -t 40 -u -p 5002 -b 600K &
host: h2(3)
mininet> h2 iperf -c 172.16.20.10 -i 1 -t 40 -u -p 5003 -b 600K &
host: h2(4)
mininet> h2 iperf -c 172.16.20.10 -i 1 -t 40 -u -p 5004 -b 600K &
結果
mininet@mininet-vm:~$ cat /tmp/h1-1.log
~~ 省略 ~~
[ 3] 0.0-49.2 sec 2.86 MBytes 488 Kbits/sec 4.751 ms 0/ 2042 (0%)
mininet@mininet-vm:~$ cat /tmp/h1-2.log
~~ 省略 ~~
[ 3] 0.0-66.2 sec 2.86 MBytes 363 Kbits/sec 12.761 ms 0/ 2042 (0%)
mininet@mininet-vm:~$ cat /tmp/h1-3.log
~~ 省略 ~~
[ 3] 0.0-86.4 sec 2.30 MBytes 223 Kbits/sec 96.778 ms 402/ 2042 (20%)
mininet@mininet-vm:~$ cat /tmp/h1-4.log
[ 3] 0.0-74.1 sec 1.87 MBytes 211 Kbits/sec 102.600 ms 711/ 2042 (35%)
このとおり期待通りの動作となった。
今回はRyuのREST APIであるQoSモジュールを実際に使用して動作確認してみたが、例のようなシンプルな帯域制御であれば、実現可能であることが分かった。
更にOpenFlowならではの柔軟な制御など考えてみたいところである。
ただ、課題としては優先度を考慮した制御ができないことである。OpenFlowの仕様にはqueue_idが優先度を示すというような記述はあったのだが、あくまでも実装依存といったところだろうか。また、例としてAFの1クラスしか使用していないが大規模なネットワークのDSドメインにOpenFlowを使用した時に等価なPHBが行えるかなど(というかQoSについてまだまだ勉強が足りない。。)今後も考察していきたい。
Comments
Add Comment