VLAN毎の帯域制御(マルチテナントな環境への応用)
今回はRyuのrest_qosを使ってVLAN毎の帯域制御を行ってみる。
VLANによるテナント分けが行われている仮想環境を想定してテナント毎に外部ネットワーク向けのトラフィックの帯域制御を行う。
実行環境について
仮想化ソフトウェアにはXenを使用していて、あらかじめ802.1q VLAN タグに対応していて、VLAN ID 10と VLAN ID 20のサブインターフェースを作成している。
また、外部ネットワークとの接続では802.1q VLAN タグに対応したスイッチ(RouterBoard 750GL)を使用している。
以下のようなトポロジを作成する。
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