Atom Login Admin

Above the clouds

OpenFlowでDiffServによるQoSの実現例

written on Sunday,May 25,2014

今回は、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

Login
This entry was tagged #Ryu #OpenFlow #QoS