Atom Login Admin

Above the clouds

VLAN毎の帯域制御(マルチテナントな環境への応用)

written on Sunday,June 29,2014

VLAN毎の帯域制御(マルチテナントな環境への応用)

今回はRyuのrest_qosを使ってVLAN毎の帯域制御を行ってみる。
VLANによるテナント分けが行われている仮想環境を想定してテナント毎に外部ネットワーク向けのトラフィックの帯域制御を行う。

実行環境について

仮想化ソフトウェアにはXenを使用していて、あらかじめ802.1q VLAN タグに対応していて、VLAN ID 10と VLAN ID 20のサブインターフェースを作成している。
また、外部ネットワークとの接続では802.1q VLAN タグに対応したスイッチ(RouterBoard 750GL)を使用している。

以下のようなトポロジを作成する。

Xen topology

RouterBoard側には以下の設定を行う。

/interface vlan
add name=vlan10 vlan-id=10 interface=ether2
add name=vlan20 vlan-id=20 interface=ether2
/ip address
add address=10.0.0.1/24 interface=vlan10
add address=10.0.1.1/24 interface=vlan20
/ip firewall filter
add chain=forward in-interface=vlan10 action=drop out-interface=vlan20
add chain=forward in-interface=vlan20 action=drop out-interface=vlan10

DomUの起動スクリプトには以下の記述を行うことで、VLAN IDがvifに設定されるようにしている。

vm1-10

vif         = [ 'mac=00:16:3E:31:E0:37,bridge=ofbr1.10' ]

vm2-10

vif         = [ 'mac=00:16:3E:74:0A:40,bridge=ofbr2.10' ]

vm1-20

vif         = [ 'mac=00:16:3E:B5:BA:5E,bridge=ofbr1.20' ]

vm2-20

vif         = [ 'mac=00:16:3E:6E:91:97,bridge=ofbr2.20' ]

詳しくはXen Networkingを参照。

全てのDomUが起動し終えたところでOpenvSwitchの状態は以下の通りに設定する。
※Dom0への接続用、OpenFlowコントローラ接続用にofbr0が存在する。また、OVSDBへアクセスするため、6632ポートで待ち受けるように設定。OpenFlowコントローラはDom0と同じネットワークの192.168.88.101で起動する。

1a845ef1-fad2-4874-b9f8-e46548bf3662
    Manager "ptcp:6632"
    Bridge "ofbr2"
        Controller "tcp:192.168.88.101:6633"
        Port "patch1"
            Interface "patch1"
                type: patch
                options: {peer="patch0"}
        Port "vif5.0"
            tag: 10
            Interface "vif5.0"
        Port "vif6.0"
            tag: 20
            Interface "vif6.0"
        Port "ofbr2"
            Interface "ofbr2"
                type: internal
    Bridge "ofbr1"
        Controller "tcp:192.168.88.101:6633"
        Port "em1.20"
            tag: 20
            Interface "em1.20"
        Port "vif3.0"
            tag: 10
            Interface "vif3.0"
        Port "patch0"
            Interface "patch0"
                type: patch
                options: {peer="patch1"}
        Port "ofbr1"
            Interface "ofbr1"
                type: internal
        Port "em1.10"
            tag: 10
            Interface "em1.10"
        Port "vif4.0"
            tag: 20
            Interface "vif4.0"
    Bridge "ofbr0"
        Port "vif1.0"
            Interface "vif1.0"
        Port "vif2.0"
            Interface "vif2.0"
        Port "em1"
            Interface "em1"
        Port "ofbr0"
            Interface "ofbr0"
                type: internal
        Port "vif7.0"
            Interface "vif7.0"
    ovs_version: "2.1.0"

Ryuでスイッチを作成する。以下のスクリプトでシンプルなLearning Switchを作成し、rest_qosモジュールとパイプラインで処理できるようにする。

simple_l2switch.py

from ryu.base import app_manager
from ryu.controller.handler import CONFIG_DISPATCHER
from ryu.controller.handler import set_ev_cls
from ryu.controller import ofp_event
from ryu.ofproto import ofproto_v1_3

class SwitchingHub(app_manager.RyuApp):
    OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]

    def __init__(self, *args, **kwargs):
        super(SwitchingHub, self).__init__(*args, **kwargs)

    @set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
    def switch_features_handler(self, ev):
        datapath = ev.msg.datapath
        parser = datapath.ofproto_parser
        ofproto = datapath.ofproto
        out_port = ofproto.OFPP_NORMAL
        actions = [parser.OFPActionOutput(out_port)]
        match = parser.OFPMatch()
        self.add_flow(datapath, actions, match)

    def add_flow(self, datapath, actions, match):
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser
        inst = [parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,
                                         actions)]
        mod = parser.OFPFlowMod(datapath=datapath, priority=0, table_id=1,
                            match=match, instructions=inst)
        datapath.send_msg(mod)

インストール

cd ryu/; python ./setup.py install

コントローラの起動

# ryu-manager ryu.app.rest_qos ryu.app.simple_l2switch ryu.app.rest_conf_switch
loading app ryu.app.rest_qos
loading app ryu.app.simple_l2switch
loading app ryu.app.rest_conf_switch
loading app ryu.controller.ofp_handler
loading app ryu.controller.ofp_handler
loading app ryu.controller.ofp_handler
instantiating app None of DPSet
creating context dpset
instantiating app None of ConfSwitchSet
creating context conf_switch
creating context wsgi
instantiating app ryu.app.simple_l2switch of SwitchingHub
instantiating app ryu.app.rest_conf_switch of ConfSwitchAPI
instantiating app ryu.controller.ofp_handler of OFPHandler
instantiating app ryu.app.rest_qos of RestQoSAPI
(5153) wsgi starting up on http://0.0.0.0:8080/

[QoS][INFO] dpid=000038eaa7abf62f: Join qos switch.
[QoS][INFO] dpid=0000fe2b3a5e3146: Join qos switch.

Queueの設定

OVSDBのアドレスを設定

curl -X PUT -d '"tcp:192.168.88.102:6632"' http://192.168.88.101:8080/v1.0/conf/switches/000038eaa7abf62f/ovsdb_addr

curl -X PUT -d '"tcp:192.168.88.102:6632"' http://192.168.88.101:8080/v1.0/conf/switches/0000fe2b3a5e3146/ovsdb_addr

それぞれのサブインターフェースにQueueを設定する。

VLAN ID 10のサブインターフェースには以下のQueueを設定

curl -X POST -d '{"type": "linux-htb", "port_name": "em1.10", "max_rate":"1000000","queues":[{"min_rate":"100000"},{"min_rate":"500000"}]}' http://192.168.88.101:8080/qos/queue/000038eaa7abf62f

VLAN ID 20のサブインターフェースには以下のQueueを設定

curl -X POST -d '{"type": "linux-htb", "port_name": "em1.20", "max_rate":"1000000","queues":[{"min_rate":"100000"},{"min_rate":"500000"}]}' http://192.168.88.101:8080/qos/queue/000038eaa7abf62f

QoSの設定

ofbr1はDSCP値に従って出力キューを設定する。
VLAN ID 10でDSCP値が26にマッチするパケットをqueue id 1から送出する設定をおこなっている。

curl -X POST -d '{"match": {"ip_dscp": "26"}, "actions":{"queue": "1"}}' http://192.168.88.101:8080/qos/rules/000038eaa7abf62f/10

VLAN ID 20に対しても同じフローエントリを設定

curl -X POST -d '{"match": {"ip_dscp": "26"}, "actions":{"queue": "1"}}' http://192.168.88.101:8080/qos/rules/000038eaa7abf62f/20

補足だが、vm1-10、vm1-20からのトラフィックはポートに設定されているtagに従って、送出され、queue id 0より送出される。

ofbr2はフローに応じたDSCP値をマーキングするフローエントリーを設定する。
ここで注意が必要なのが、vmと直接接続されているポートからのパケットにVLANタグは付加されていないので、MAC Addressによりマッチングを行っている。

VLAN ID 10に所属するホスト(vm2-10)でUDP 5001ポート宛のパケットをDSCP値26でマーキングを行う。

curl -X POST -d '{"match": {"dl_src": "00:16:3E:74:0A:40", "dl_type": "IPv4", "nw_proto": "UDP", "tp_dst": "5001"}, "actions":{"mark": "26"}}' http://192.168.88.101:8080/qos/rules/0000fe2b3a5e3146

VLAN ID 20に所属するホストにはマーキングを行うエントリーは登録しない。

動作確認

外部ネットワークへのトラフィック送出を想定して、RouterBoardにPCを接続し、iperfで確認した。

vm1-10はポート5002宛に1Mbpsのトラフィックを送出

iperf -c 192.168.88.247 -b 1M -p 5002

vm2-10はポート5001宛に1Mbpsのトラフィックを送出

iperf -c 192.168.88.247 -b 1M

・結果

vm1-10からのトラフィック(マーキングなし)

[  4] local 192.168.88.247 port 5002 connected with 10.0.0.2 port 36809
[  4]  0.0- 1.0 sec   118 KBytes   964 Kbits/sec   1.124 ms    0/   82 (0%)
[  4]  1.0- 2.0 sec   119 KBytes   976 Kbits/sec   1.233 ms    0/   83 (0%)
[  4]  2.0- 3.0 sec  94.7 KBytes   776 Kbits/sec   8.750 ms    0/   66 (0%)
[  4]  3.0- 4.0 sec  18.7 KBytes   153 Kbits/sec  40.037 ms    0/   13 (0%)
[  4]  4.0- 5.0 sec  21.5 KBytes   176 Kbits/sec  50.218 ms    0/   15 (0%)
[  4]  5.0- 6.0 sec  20.1 KBytes   165 Kbits/sec  53.613 ms    0/   14 (0%)
[  4]  6.0- 7.0 sec  21.5 KBytes   176 Kbits/sec  57.246 ms    0/   15 (0%)
[  4]  7.0- 8.0 sec  21.5 KBytes   176 Kbits/sec  54.550 ms    0/   15 (0%)
[  4]  8.0- 9.0 sec  20.1 KBytes   165 Kbits/sec  55.531 ms    0/   14 (0%)
[  4]  9.0-10.0 sec  21.5 KBytes   176 Kbits/sec  57.156 ms    0/   15 (0%)
[  4] 10.0-11.0 sec  21.5 KBytes   176 Kbits/sec  56.985 ms    0/   15 (0%)
[  4] 11.0-12.0 sec  20.1 KBytes   165 Kbits/sec  58.098 ms    0/   14 (0%)
[  4] 12.0-13.0 sec  21.5 KBytes   176 Kbits/sec  55.150 ms    0/   15 (0%)
[  4] 13.0-14.0 sec  20.1 KBytes   165 Kbits/sec  55.735 ms    0/   14 (0%)
[  4] 14.0-15.0 sec  21.5 KBytes   176 Kbits/sec  58.174 ms    0/   15 (0%)
[  4] 15.0-16.0 sec  68.9 KBytes   564 Kbits/sec   5.148 ms    0/   48 (0%)
[  4] 16.0-17.0 sec   119 KBytes   976 Kbits/sec   1.503 ms    0/   83 (0%)
[  4] 17.0-18.0 sec   118 KBytes   964 Kbits/sec   2.170 ms    0/   82 (0%)
[  4] 18.0-19.0 sec   118 KBytes   964 Kbits/sec   3.362 ms    0/   82 (0%)
[  4] 19.0-20.0 sec   119 KBytes   976 Kbits/sec   1.872 ms    0/   83 (0%)
[  4]  0.0-20.8 sec  1.19 MBytes   481 Kbits/sec   1.169 ms    0/  852 (0%)

vm1-20からのトラフィック(DSCP値:26)

[  3] local 192.168.88.247 port 5001 connected with 10.0.0.3 port 50619
[  3]  0.0- 1.0 sec  97.6 KBytes   800 Kbits/sec  11.031 ms    0/   68 (0%)
[  3]  1.0- 2.0 sec  97.6 KBytes   800 Kbits/sec  11.672 ms    0/   68 (0%)
[  3]  2.0- 3.0 sec  96.2 KBytes   788 Kbits/sec  11.431 ms    0/   67 (0%)
[  3]  3.0- 4.0 sec  96.2 KBytes   788 Kbits/sec   8.219 ms    0/   67 (0%)
[  3]  4.0- 5.0 sec  97.6 KBytes   800 Kbits/sec   7.873 ms    0/   68 (0%)
[  3]  5.0- 6.0 sec  96.2 KBytes   788 Kbits/sec   9.196 ms    0/   67 (0%)
[  3]  6.0- 7.0 sec  99.1 KBytes   811 Kbits/sec   9.686 ms    0/   69 (0%)
[  3]  7.0- 8.0 sec  96.2 KBytes   788 Kbits/sec   8.539 ms    0/   67 (0%)
[  3]  8.0- 9.0 sec  97.6 KBytes   800 Kbits/sec   8.609 ms    0/   68 (0%)
[  3]  9.0-10.0 sec  97.6 KBytes   800 Kbits/sec  10.628 ms    0/   68 (0%)
[  3] 10.0-11.0 sec  96.2 KBytes   788 Kbits/sec  10.084 ms    0/   67 (0%)
[  3] 11.0-12.0 sec  97.6 KBytes   800 Kbits/sec   4.338 ms    0/   68 (0%)
[  3]  0.0-12.6 sec  1.19 MBytes   796 Kbits/sec   3.898 ms    0/  852 (0%)

5001宛のマーキングされているトラフィックは最低保証帯域で送出されているのが分かる。

一方、DSCP値のマーキングを行っていないVLAN ID 20の場合

vm1-20はポート5002宛に1Mbpsのトラフィックを送出

iperf -c 192.168.88.247 -b 1M -p 5002

vm2-20はポート5001宛に1Mbpsのトラフィックを送出

iperf -c 192.168.88.247 -b 1M

・結果

vm1-20からのトラフィック

[  3] local 192.168.88.247 port 5002 connected with 10.0.1.2 port 58365
[  3]  0.0- 1.0 sec   118 KBytes   964 Kbits/sec   0.560 ms    0/   82 (0%)
[  3]  1.0- 2.0 sec   118 KBytes   964 Kbits/sec   2.018 ms    0/   82 (0%)
[  3]  2.0- 3.0 sec  81.8 KBytes   670 Kbits/sec  10.428 ms    0/   57 (0%)
[  3]  3.0- 4.0 sec  58.9 KBytes   482 Kbits/sec  12.385 ms    0/   41 (0%)
[  3]  4.0- 5.0 sec  58.9 KBytes   482 Kbits/sec  12.539 ms    0/   41 (0%)
[  3]  5.0- 6.0 sec  60.3 KBytes   494 Kbits/sec  12.502 ms    0/   42 (0%)
[  3]  6.0- 7.0 sec  58.9 KBytes   482 Kbits/sec  12.576 ms    0/   41 (0%)
[  3]  7.0- 8.0 sec  58.9 KBytes   482 Kbits/sec  12.557 ms    0/   41 (0%)
[  3]  8.0- 9.0 sec  58.9 KBytes   482 Kbits/sec  12.542 ms    0/   41 (0%)
[  3]  9.0-10.0 sec  58.9 KBytes   482 Kbits/sec  12.555 ms    0/   41 (0%)
[  3] 10.0-11.0 sec  58.9 KBytes   482 Kbits/sec  12.511 ms    0/   41 (0%)
[  3] 11.0-12.0 sec  58.9 KBytes   482 Kbits/sec  12.527 ms    0/   41 (0%)
[  3] 12.0-13.0 sec  58.9 KBytes   482 Kbits/sec  12.527 ms    0/   41 (0%)
[  3] 13.0-14.0 sec  60.3 KBytes   494 Kbits/sec  12.522 ms    0/   42 (0%)
[  3] 14.0-15.0 sec  58.9 KBytes   482 Kbits/sec  12.538 ms    0/   41 (0%)
[  3] 15.0-16.0 sec  58.9 KBytes   482 Kbits/sec  12.537 ms    0/   41 (0%)
[  3] 16.0-17.0 sec  58.9 KBytes   482 Kbits/sec  12.498 ms    0/   41 (0%)
[  3] 17.0-18.0 sec  58.9 KBytes   482 Kbits/sec  12.522 ms    0/   41 (0%)
[  3]  0.0-18.3 sec  1.19 MBytes   547 Kbits/sec  12.548 ms    0/  852 (0%)

vm2-20からのトラフィック

[  3] local 192.168.88.247 port 5001 connected with 10.0.1.3 port 49749
[  3]  0.0- 1.0 sec  58.9 KBytes   482 Kbits/sec  11.590 ms    0/   41 (0%)
[  3]  1.0- 2.0 sec  58.9 KBytes   482 Kbits/sec  12.471 ms    0/   41 (0%)
[  3]  2.0- 3.0 sec  58.9 KBytes   482 Kbits/sec  12.496 ms    0/   41 (0%)
[  3]  3.0- 4.0 sec  58.9 KBytes   482 Kbits/sec  12.520 ms    0/   41 (0%)
[  3]  4.0- 5.0 sec  58.9 KBytes   482 Kbits/sec  12.625 ms    0/   41 (0%)
[  3]  5.0- 6.0 sec  58.9 KBytes   482 Kbits/sec  12.547 ms    0/   41 (0%)
[  3]  6.0- 7.0 sec  58.9 KBytes   482 Kbits/sec  12.558 ms    0/   41 (0%)
[  3]  7.0- 8.0 sec  58.9 KBytes   482 Kbits/sec  12.503 ms    0/   41 (0%)
[  3]  8.0- 9.0 sec  60.3 KBytes   494 Kbits/sec  12.552 ms    0/   42 (0%)
[  3]  9.0-10.0 sec  58.9 KBytes   482 Kbits/sec  12.548 ms    0/   41 (0%)
[  3] 10.0-11.0 sec  58.9 KBytes   482 Kbits/sec  12.547 ms    0/   41 (0%)
[  3] 11.0-12.0 sec  58.9 KBytes   482 Kbits/sec  12.527 ms    0/   41 (0%)
[  3] 12.0-13.0 sec  58.9 KBytes   482 Kbits/sec  12.706 ms    0/   41 (0%)
[  3] 13.0-14.0 sec  58.9 KBytes   482 Kbits/sec  12.561 ms    0/   41 (0%)
[  3] 14.0-15.0 sec  58.9 KBytes   482 Kbits/sec  12.541 ms    0/   41 (0%)
[  3] 15.0-16.0 sec  63.2 KBytes   517 Kbits/sec   9.908 ms    0/   44 (0%)
[  3] 16.0-17.0 sec   113 KBytes   929 Kbits/sec   1.610 ms    0/   79 (0%)
[  3] 17.0-18.0 sec   112 KBytes   917 Kbits/sec   1.054 ms    0/   78 (0%)
[  3]  0.0-18.4 sec  1.19 MBytes   543 Kbits/sec   1.499 ms    0/  852 (0%)

VLAN ID 20に所属するホストでは優先度のマーキングは行っていない為、
1Mbpsの上限帯域を分け合っている事が確認できる。

このようにVLAN ID毎に優先付けのルールを行えることが確認できた。

今回の例のようにマルチテナントな環境に於いてOpenFlowコントローラから帯域制御が行えることにより、テナント毎に一定の帯域幅、柔軟な制御を提供することが可能と考えられる。

Comments

Add Comment

Login
This entry was tagged #Ryu #OpenFlow #QoS #Xen