◆ 【Open vSwitchのみで OpenFlowプログラミング】VLAN ID コンバータ
OpenFlow コントーラを使わずに、Open vSwitch を OpenFlow スイッチとして使って VLAN ID を変換する機能を実装してみました。
Open vSwitch では、ovs-ofctl コマンドを使うことで OpenFlow スイッチとしての機能に対してフローを登録・変更・削除することができます。
動的にフローを変更する必要がなければ、このコマンドで事前に登録して動作させれば OpenFlow コントローラなしでも動かすことができそうだと思い以前作った VLAN ID を変換する例に対して試してみました。
Lubuntu 13.04 のパッケージの Open vSwitch で入る ovs-ofctl コマンドの man ページは、以下で参照できます:
http://manpages.ubuntu.com/manpages/raring/en/man8/ovs-ofctl.8.html
仮想ネットワークの構成は、以前書いた記事「◆ 【TremaでOpenFlowプログラミング】VLAN ID コンバータ」と全く一緒です。
使用した環境:
OS: Lubuntu 13.04 Desktop (i386) (※ 12.04 ではありません)
Open vSwitch: 1.9.0 (Lubuntu のパッケージでインストール)
補足:
Open vSwitch のインストールについては記事「◆ Lubuntu 13.04 に Open vSwitch をインストールした時のログ」を参照ください。
■今回の仮想ネットワークの構成図
記事「◆ 【TremaでOpenFlowプログラミング】VLAN ID コンバータ」と全く一緒です。
こんなストーリーを想定しています:
・2つの拠点があって、拠点ごとに別々に VLAN ID を管理していた。
・拠点1の VLAN ID 10, 20 の L2 ネットワークを拠点2 にも延ばす必要が生じた。
・しかし、拠点2 では VLAN ID 10, 20 は使えず、代わりに 拠点2 では LAN ID 30, 40 を割り当て、拠点間で VLAN ID を変換することにした。
・拠点1 の VLAN ID: 10 と 拠点2 の VLAN ID: 30 を接続する。
・拠点1 の VLAN ID: 20 と 拠点2 の VLAN ID: 40 を接続する。
■ 構成の確認
後述するシェルスクリプトで仮想ネットワークを作成したら OpenFlow ポートの1番が拠点1側、ポートの2番が拠点2側との接続となっていることを確認します。
$ sudo ovs-ofctl show ofs1
OFPT_FEATURES_REPLY (xid=0x1): dpid:00003670612aed45
n_tables:255, n_buffers:256
capabilities: FLOW_STATS TABLE_STATS PORT_STATS QUEUE_STATS ARP_MATCH_IP
actions: OUTPUT SET_VLAN_VID SET_VLAN_PCP STRIP_VLAN SET_DL_SRC SET_DL_DST SET_NW_SRC SET_NW_DST SET_NW_TOS SET_TP_SRC SET_TP_DST ENQUEUE
1(vlinkSW1-1): addr:06:be:3f:87:9f:18
config: 0
state: 0
current: 10GB-FD COPPER
speed: 10000 Mbps now, 100 Mbps max
2(vlinkSW2-1): addr:f6:42:dc:fe:0d:ff
config: 0
state: 0
current: 10GB-FD COPPER
speed: 10000 Mbps now, 100 Mbps max
LOCAL(ofs1): addr:36:70:61:2a:ed:45
config: PORT_DOWN
state: LINK_DOWN
speed: 100 Mbps now, 100 Mbps max
OFPT_GET_CONFIG_REPLY (xid=0x3): frags=normal miss_send_len=0
ちなみに、Lubuntu 12.04 のパッケージとしてインストールした Open vSwitch で ovs-ofctl show を実行した時はcapabilities と actions が16進数表記だったのが、今回はシンボル名に変わっていました。
■ OpenFlow コントローラ
OpenFlow コントローラ自体はありませんが、後述するスクリプトから、フローテーブルを設定している部分を以下に抜粋します:
config_ofs1() {
sudo ovs-ofctl del-flows "ofs1"
sudo ovs-ofctl add-flow "ofs1" in_port=1,dl_vlan=10,actions=mod_vlan_vid:30,output:2
sudo ovs-ofctl add-flow "ofs1" in_port=2,dl_vlan=30,actions=mod_vlan_vid:10,output:1
sudo ovs-ofctl add-flow "ofs1" in_port=1,dl_vlan=20,actions=mod_vlan_vid:40,output:2
sudo ovs-ofctl add-flow "ofs1" in_port=2,dl_vlan=40,actions=mod_vlan_vid:20,output:1
sudo ovs-ofctl add-flow "ofs1" priority=100,actions=drop
}
やっていることを文字にすると以下の通り:
・ポート1(拠点1) から来た VLAN ID: 10 のパケットなら、VLAN ID を 30 にすげかえてポート2(拠点2)へ出力。
・ポート2(拠点2) から来た VLAN ID: 30 のパケットなら、VLAN ID を 10 にすげかえてポート1(拠点1)へ出力。
・ポート1(拠点1) から来た VLAN ID: 20 のパケットなら、VLAN ID を 40 にすげかえてポート2(拠点2)へ出力。
・ポート2(拠点2) から来た VLAN ID: 40 のパケットなら、VLAN ID を 20 にすげかえてポート1(拠点1)へ出力。
・上記に当てはまらないパケットが来たら破棄する。(すべてのパケットに合致するフローエントリですが優先度 priority を他のフローエントリより下げることで「上記に当てはまらない」という動きにしています。)
先頭で、フローを削除しているのはデフォルトで登録されている actions=NORMAL のフローを削除するためです。
フローの編集を何もしていない時、ovs-ofctl dump-flow を行うと以下のような出力が得られます:
cookie=0x0, duration=5.009s, table=0, n_packets=15, n_bytes=1690, idle_age=0, priority=0 actions=NORMAL
この actions=NORMAL は、通常のスイッチとして機能するということを意味します。
■ OpenFlow スイッチのフローテーブルの確認
$ sudo ovs-ofctl dump-flows ofs1
NXST_FLOW reply (xid=0x4):
cookie=0x0, duration=223.515s, table=0, n_packets=84, n_bytes=17360, idle_age=36, priority=100 actions=drop
cookie=0x0, duration=223.54s, table=0, n_packets=4, n_bytes=308, idle_age=214, in_port=2,dl_vlan=40 actions=mod_vlan_vid:20,output:1
cookie=0x0, duration=223.57s, table=0, n_packets=4, n_bytes=308, idle_age=214, in_port=1,dl_vlan=20 actions=mod_vlan_vid:40,output:2
cookie=0x0, duration=223.621s, table=0, n_packets=4, n_bytes=308, idle_age=214, in_port=1,dl_vlan=10 actions=mod_vlan_vid:30,output:2
cookie=0x0, duration=223.596s, table=0, n_packets=4, n_bytes=308, idle_age=215, in_port=2,dl_vlan=30 actions=mod_vlan_vid:10,output:1
■ 動作確認
vhost1(192.168.0.1, 拠点1, VLAN ID: 10) から ping で vhost3(192.168.0.3, 拠点2, VLAN ID: 30) とのみ通信できることを確認:
$ sudo ip netns exec vhost1 ping -c2 192.168.0.2
PING 192.168.0.2 (192.168.0.2) 56(84) bytes of data.
From 192.168.0.1 icmp_seq=1 Destination Host Unreachable
From 192.168.0.1 icmp_seq=2 Destination Host Unreachable
--- 192.168.0.2 ping statistics ---
2 packets transmitted, 0 received, +2 errors, 100% packet loss, time 999ms
pipe 2
$ sudo ip netns exec vhost1 ping -c2 192.168.0.3
PING 192.168.0.3 (192.168.0.3) 56(84) bytes of data.
64 bytes from 192.168.0.3: icmp_req=1 ttl=64 time=0.849 ms
64 bytes from 192.168.0.3: icmp_req=2 ttl=64 time=0.060 ms
--- 192.168.0.3 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1003ms
rtt min/avg/max/mdev = 0.060/0.454/0.849/0.395 ms
$ sudo ip netns exec vhost1 ping -c2 192.168.0.4
PING 192.168.0.4 (192.168.0.4) 56(84) bytes of data.
From 192.168.0.1 icmp_seq=1 Destination Host Unreachable
From 192.168.0.1 icmp_seq=2 Destination Host Unreachable
--- 192.168.0.4 ping statistics ---
2 packets transmitted, 0 received, +2 errors, 100% packet loss, time 1010ms
pipe 2
vhost2(192.168.0.2, 拠点1, VLAN ID: 20) から ping で vhost4(192.168.0.4, 拠点2, VLAN ID: 40) とのみ通信できることを確認:
$ sudo ip netns exec vhost2 ping -c2 192.168.0.1
PING 192.168.0.1 (192.168.0.1) 56(84) bytes of data.
From 192.168.0.2 icmp_seq=1 Destination Host Unreachable
From 192.168.0.2 icmp_seq=2 Destination Host Unreachable
--- 192.168.0.1 ping statistics ---
2 packets transmitted, 0 received, +2 errors, 100% packet loss, time 1005ms
pipe 2
$ sudo ip netns exec vhost2 ping -c2 192.168.0.3
PING 192.168.0.3 (192.168.0.3) 56(84) bytes of data.
From 192.168.0.2 icmp_seq=1 Destination Host Unreachable
From 192.168.0.2 icmp_seq=2 Destination Host Unreachable
--- 192.168.0.3 ping statistics ---
2 packets transmitted, 0 received, +2 errors, 100% packet loss, time 1004ms
pipe 2
$ sudo ip netns exec vhost2 ping -c2 192.168.0.4
PING 192.168.0.4 (192.168.0.4) 56(84) bytes of data.
64 bytes from 192.168.0.4: icmp_req=1 ttl=64 time=0.809 ms
64 bytes from 192.168.0.4: icmp_req=2 ttl=64 time=0.068 ms
--- 192.168.0.4 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1009ms
rtt min/avg/max/mdev = 0.068/0.438/0.809/0.371 ms
■今回の仮想ネットワークの作成・削除シェルスクリプト
引数 delete で削除、add で追加です。
共通ファイル vnetcommon.sh がカレントディレクトリにおいてあることを前提としています。
赤字にした箇所は記事「◆ 【TremaでOpenFlowプログラミング】VLAN ID コンバータ」の仮想ネットワークのスクリプトからの変更点です。フローテーブルの設定を追加しています。また、スイッチ ofs1 は、OpenFlow コントローラの設定無しにするため addOFSwitch ではなくて addVSwitch を使って追加しています。
#!/bin/sh
. ./vnetcommon.sh
delete() {
deleteVSwitch "ofs1" "vswitch1" "vswitch2"
deleteVLink "vlinkSW1" "vlinkSW2"
deleteVHost "vhost1" "vhost2" "vhost3" "vhost4"
deleteVLink "vlink1" "vlink2" "vlink3" "vlink4"
}
config_ofs1() {
sudo ovs-ofctl del-flows "ofs1"
sudo ovs-ofctl add-flow "ofs1" in_port=1,dl_vlan=10,actions=mod_vlan_vid:30,output:2
sudo ovs-ofctl add-flow "ofs1" in_port=2,dl_vlan=30,actions=mod_vlan_vid:10,output:1
sudo ovs-ofctl add-flow "ofs1" in_port=1,dl_vlan=20,actions=mod_vlan_vid:40,output:2
sudo ovs-ofctl add-flow "ofs1" in_port=2,dl_vlan=40,actions=mod_vlan_vid:20,output:1
sudo ovs-ofctl add-flow "ofs1" priority=100,actions=drop
}
add() {
#addOFSwitch "ofs1"
addVSwitch "ofs1"
addVSwitch "vswitch1"
addVSwitch "vswitch2"
connectVSwitchToVSwitch "vswitch1" "vlinkSW1" "ofs1"
connectVSwitchToVSwitch "vswitch2" "vlinkSW2" "ofs1"
addVHost "vhost1"
connectVHostToVSwitch "vhost1" "vlink1" "vswitch1" tag=10
vhostExec "vhost1" ifconfig "vlink1" "192.168.0.1"
addVHost "vhost2"
connectVHostToVSwitch "vhost2" "vlink2" "vswitch1" tag=20
vhostExec "vhost2" ifconfig "vlink2" "192.168.0.2"
addVHost "vhost3"
connectVHostToVSwitch "vhost3" "vlink3" "vswitch2" tag=30
vhostExec "vhost3" ifconfig "vlink3" "192.168.0.3"
addVHost "vhost4"
connectVHostToVSwitch "vhost4" "vlink4" "vswitch2" tag=40
vhostExec "vhost4" ifconfig "vlink4" "192.168.0.4"
config_ofs1
}
case "$1" in
add)
sudo sh -c exit
set -x
add
;;
delete)
sudo sh -c exit
delete > /dev/null 2>&1
;;
*)
echo "usage: $0 { add | delete }"
esac
vnetcommon.sh のコードは、以前の記事の末尾を参照ください。
記事をひと通り書いてから、気が付いたのですが上記では、ovs-ofctl del-flow をするタイミングが遅いような気がします(一般論として)。del-flow するまでは普通のスイッチとして動いているので、トラブルのもとになりそう。addOFSwitch のOpenfFlow コントローラなし版を作ったほうが良いかもしれません。
[2013/08/10 追記: 上記の気になる点を修正した記事を書きました。]
« ◆ Lubuntu 13.04 に Open vSwitch をインストールした時のログ | トップページ | ◆ 【Open vSwitchのみで OpenFlowプログラミング】VLAN ID コンバータ 改 »
「OpenFlow」カテゴリの記事
- ◆ 【Open vSwitchのみで OpenFlowプログラミング】VLAN ID コンバータ 改(2013.08.10)
- ◆ 【Open vSwitchのみで OpenFlowプログラミング】VLAN ID コンバータ(2013.08.05)
- ◆ 【TremaでOpenFlowプログラミング】VLAN ID コンバータ(2013.05.12)
- ◆ Linux のネットワークネームスペース機能と Open vSwitch で仮想ネットワーク(OpenFlowスイッチとTrema)(2013.05.11)
- ◆ OpenFlow 1.0.0 メッセージと Trema API(Ruby) との対応表(2013.05.08)
「仮想ネットワーク」カテゴリの記事
- ◆ Linux のネットワークネームスペース機能と Open vSwitch で仮想ネットワーク: STP(Spanning Tree Protocol)(2013.08.10)
- ◆ 【Open vSwitchのみで OpenFlowプログラミング】VLAN ID コンバータ 改(2013.08.10)
- ◆ 【Open vSwitchのみで OpenFlowプログラミング】VLAN ID コンバータ(2013.08.05)
- ◆ 【TremaでOpenFlowプログラミング】VLAN ID コンバータ(2013.05.12)
- ◆ Linux のネットワークネームスペース機能と Open vSwitch で仮想ネットワーク(OpenFlowスイッチとTrema)(2013.05.11)
「Open vSwitch」カテゴリの記事
- ◆ Linux のネットワークネームスペース機能と Open vSwitch で仮想ネットワーク: STP(Spanning Tree Protocol)(2013.08.10)
- ◆ 【Open vSwitchのみで OpenFlowプログラミング】VLAN ID コンバータ 改(2013.08.10)
- ◆ 【Open vSwitchのみで OpenFlowプログラミング】VLAN ID コンバータ(2013.08.05)
- ◆ Lubuntu 13.04 に Open vSwitch をインストールした時のログ(2013.08.03)
- ◆ Open vSwitch の設定項目一覧や man ページのありか(2013.07.01)
「Open vSwitch のみで OpenFlow プログラミング」カテゴリの記事
- ◆ 【Open vSwitchのみで OpenFlowプログラミング】VLAN ID コンバータ 改(2013.08.10)
- ◆ 【Open vSwitchのみで OpenFlowプログラミング】VLAN ID コンバータ(2013.08.05)
この記事へのコメントは終了しました。
« ◆ Lubuntu 13.04 に Open vSwitch をインストールした時のログ | トップページ | ◆ 【Open vSwitchのみで OpenFlowプログラミング】VLAN ID コンバータ 改 »
コメント