« 2013年7月 | トップページ | 2013年10月 »

2013年8月

2013年8月10日 (土)

◆ Linux のネットワークネームスペース機能と Open vSwitch で仮想ネットワーク: STP(Spanning Tree Protocol)

Open vSwitch のスパニングツリープロトコル(Spanning Tree Protocol, STP)を有効にして動かしてみました。

動作確認環境:
   OS: Lubuntu 13.04 Desktop (i386)
   Open vSwitch: 1.9.0

■今回作成した仮想ネットワークの構成図

2台のスイッチが2本の線でつながっており、ループしている状態にしています。

Photo
念のため、ovs-vsctl show で確認してみます:

$ sudo ovs-vsctl show
dc50ed1a-4dd2-4169-89d3-fbe717480a70
    Bridge "vswitch1"
        Port "vlink1"
            Interface "vlink1"
        Port "vlinkSW1-0"
            Interface "vlinkSW1-0"
        Port "vlinkSW2-1"
            Interface "vlinkSW2-1"
        Port "vswitch1"
            Interface "vswitch1"
                type: internal
    Bridge "vswitch2"
        Port "vlinkSW2-0"
            Interface "vlinkSW2-0"
        Port "vlink2"
            Interface "vlink2"
        Port "vswitch2"
            Interface "vswitch2"
                type: internal
        Port "vlinkSW1-1"
            Interface "vlinkSW1-1"
    ovs_version: "1.9.0"

■動作テスト

(1) ネットワークを作成後、すぐに、vhost1 から vhost2(192.168.0.2) へ ping

ping に -D オプションをつけてタイムスタンプを出力するようにしてみました。最初に通信ができるようになるまで30秒弱かかっています。

$ sudo ip netns exec vhost1 ping -D 192.168.0.2
PING 192.168.0.2 (192.168.0.2) 56(84) bytes of data.
[1376076296.379297] From 192.168.0.1 icmp_seq=1 Destination Host Unreachable
[1376076296.379366] From 192.168.0.1 icmp_seq=2 Destination Host Unreachable
[1376076296.379376] From 192.168.0.1 icmp_seq=3 Destination Host Unreachable
[1376076299.379759] From 192.168.0.1 icmp_seq=4 Destination Host Unreachable
[1376076299.379797] From 192.168.0.1 icmp_seq=5 Destination Host Unreachable
[1376076299.379806] From 192.168.0.1 icmp_seq=6 Destination Host Unreachable
[1376076302.391493] From 192.168.0.1 icmp_seq=7 Destination Host Unreachable
[1376076302.391527] From 192.168.0.1 icmp_seq=8 Destination Host Unreachable
[1376076302.391535] From 192.168.0.1 icmp_seq=9 Destination Host Unreachable
   略
[1376076317.404299] From 192.168.0.1 icmp_seq=22 Destination Host Unreachable
[1376076317.404333] From 192.168.0.1 icmp_seq=23 Destination Host Unreachable
[1376076317.404342] From 192.168.0.1 icmp_seq=24 Destination Host Unreachable
[1376076320.404558] From 192.168.0.1 icmp_seq=25 Destination Host Unreachable
[1376076320.404599] From 192.168.0.1 icmp_seq=26 Destination Host Unreachable
[1376076320.404613] From 192.168.0.1 icmp_seq=27 Destination Host Unreachable
[1376076322.405310] 64 bytes from 192.168.0.2: icmp_req=28 ttl=64 time=2000 ms
[1376076322.405340] 64 bytes from 192.168.0.2: icmp_req=29 ttl=64 time=1000 ms
[1376076322.405348] 64 bytes from 192.168.0.2: icmp_req=30 ttl=64 time=0.664 ms
[1376076323.404743] 64 bytes from 192.168.0.2: icmp_req=31 ttl=64 time=0.068 ms
[1376076324.404754] 64 bytes from 192.168.0.2: icmp_req=32 ttl=64 time=0.073 ms
^C
--- 192.168.0.2 ping statistics ---
32 packets transmitted, 5 received, +27 errors, 84% packet loss, time 31023ms
rtt min/avg/max/mdev = 0.068/600.459/2000.704/800.205 ms, pipe 4

(2) ブロックされているポートの確認

Open vSwitch の Port テーブルのカラム status で状態が確認できます。出力カラムを name と status だけに絞ると出力したの以下の結果です。
今回のテストでは、vlinkSW1-0 のポートがブロックされていることが確認できます。

$ sudo ovs-vsctl -- --columns=name,status list Port
name                : "vlinkSW2-0"
status              : {stp_port_id="8001", stp_role=designated, stp_sec_in_state="433", stp_state=forwarding}

name                : "vlink1"
status              : {stp_port_id="8001", stp_role=designated, stp_sec_in_state="433", stp_state=forwarding}

name                : "vlinkSW2-1"
status              : {stp_port_id="8002", stp_role=root, stp_sec_in_state="433", stp_state=forwarding}

name                : "vlink2"
status              : {stp_port_id="8003", stp_role=designated, stp_sec_in_state="433", stp_state=forwarding}

name                : "vswitch1"
status              : {}

name                : "vlinkSW1-0"
status              : {stp_port_id="8003", stp_role=alternate, stp_sec_in_state="462", stp_state=blocking}

name                : "vlinkSW1-1"
status              : {stp_port_id="8002", stp_role=designated, stp_sec_in_state="433", stp_state=forwarding}

name                : "vswitch2"
status              : {}

(3) 切断してみる

上記で確認した結果から、vlinkSW2-0 と vlinkSW2-1 の間で通信がされていることが分かるのでこの通信を切断し、vlinkSW1-0 のブロックが解除されて vlinkSW1-0 と vlinkSW1-1 の間の通信が回復することを確認してみます。

ping を実行中に以下のコマンドでインタフェースをダウンさせて通信を切断します:

$ sudo ifconfig vlinkSW2-0 down

以下、ping の結果。回復までに約50秒かかっています。

$ sudo ip netns exec vhost1 ping -D 192.168.0.2
PING 192.168.0.2 (192.168.0.2) 56(84) bytes of data.
[1376077074.541945] 64 bytes from 192.168.0.2: icmp_req=1 ttl=64 time=0.714 ms
[1376077075.543771] 64 bytes from 192.168.0.2: icmp_req=2 ttl=64 time=0.071 ms
[1376077076.543824] 64 bytes from 192.168.0.2: icmp_req=3 ttl=64 time=0.063 ms
[1376077125.551195] From 192.168.0.1 icmp_seq=49 Destination Host Unreachable
[1376077125.551250] From 192.168.0.1 icmp_seq=50 Destination Host Unreachable
[1376077125.551258] From 192.168.0.1 icmp_seq=51 Destination Host Unreachable
[1376077125.552571] 64 bytes from 192.168.0.2: icmp_req=52 ttl=64 time=0.664 ms
[1376077126.555236] 64 bytes from 192.168.0.2: icmp_req=53 ttl=64 time=0.060 ms
[1376077127.555274] 64 bytes from 192.168.0.2: icmp_req=54 ttl=64 time=0.060 ms
[1376077128.555355] 64 bytes from 192.168.0.2: icmp_req=55 ttl=64 time=0.074 ms
[1376077129.555414] 64 bytes from 192.168.0.2: icmp_req=56 ttl=64 time=0.058 ms
^C
--- 192.168.0.2 ping statistics ---
56 packets transmitted, 8 received, +3 errors, 85% packet loss, time 55015ms
rtt min/avg/max/mdev = 0.058/0.220/0.714/0.271 ms, pipe 3

(4) ポートのステータス確認

vlinkSW1-0 のブロック状態が解除されていることが確認できます:

$ sudo ip netns exec vsudo ovs-vsctl -- --columns=name,status list Port
name                : "vlinkSW2-0"
status              : {stp_port_id="8001", stp_role=designated, stp_sec_in_state="1175", stp_state=forwarding}

name                : "vlink1"
status              : {stp_port_id="8001", stp_role=designated, stp_sec_in_state="1175", stp_state=forwarding}

name                : "vlinkSW2-1"
status              : {stp_port_id="8002", stp_role=designated, stp_sec_in_state="1175", stp_state=forwarding}

name                : "vlink2"
status              : {stp_port_id="8003", stp_role=designated, stp_sec_in_state="1175", stp_state=forwarding}

name                : "vswitch1"
status              : {}

name                : "vlinkSW1-0"
status              : {stp_port_id="8003", stp_role=root, stp_sec_in_state="372", stp_state=forwarding}

name                : "vlinkSW1-1"
status              : {stp_port_id="8002", stp_role=designated, stp_sec_in_state="1175", stp_state=forwarding}

name                : "vswitch2"
status              : {}

(5) 停止したインタフェースを回復させる

先ほど停止したインタフェースを回復させるとどうなるでしょう?
ping 実行中に以下のコマンドで復活させます:

$ sudo ifconfig vlinkSW2-0 up

回復したときに、少しもたつきます:

$ sudo ip netns exec vhost1 ping -D 192.168.0.2
PING 192.168.0.2 (192.168.0.2) 56(84) bytes of data.
[1376077760.643086] 64 bytes from 192.168.0.2: icmp_req=1 ttl=64 time=0.049 ms
[1376077761.642098] 64 bytes from 192.168.0.2: icmp_req=2 ttl=64 time=0.057 ms
[1376077762.643821] 64 bytes from 192.168.0.2: icmp_req=3 ttl=64 time=0.057 ms
[1376077763.645079] 64 bytes from 192.168.0.2: icmp_req=4 ttl=64 time=0.076 ms
[1376077764.645113] 64 bytes from 192.168.0.2: icmp_req=5 ttl=64 time=0.078 ms
[1376077765.645305] 64 bytes from 192.168.0.2: icmp_req=6 ttl=64 time=0.072 ms
[1376077766.689862] 64 bytes from 192.168.0.2: icmp_req=7 ttl=64 time=9.23 ms
[1376077767.853087] 64 bytes from 192.168.0.2: icmp_req=8 ttl=64 time=10.1 ms

[1376077768.669838] 64 bytes from 192.168.0.2: icmp_req=9 ttl=64 time=0.328 ms
[1376077769.668223] 64 bytes from 192.168.0.2: icmp_req=10 ttl=64 time=0.122 ms
[1376077770.667189] 64 bytes from 192.168.0.2: icmp_req=11 ttl=64 time=0.092 ms
[1376077771.666140] 64 bytes from 192.168.0.2: icmp_req=12 ttl=64 time=0.054 ms
[1376077772.666320] 64 bytes from 192.168.0.2: icmp_req=13 ttl=64 time=0.113 ms
[1376077773.666751] 64 bytes from 192.168.0.2: icmp_req=14 ttl=64 time=0.065 ms
^C
--- 192.168.0.2 ping statistics ---
14 packets transmitted, 14 received, 0% packet loss, time 13023ms
rtt min/avg/max/mdev = 0.049/1.470/10.194/3.371 ms

(6) ポートのステータス確認

再び vlinkSW1-0 がブロックされていました:

$ sudo ovs-vsctl -- --columns=name,status list Port
name                : "vlinkSW2-0"
status              : {stp_port_id="8001", stp_role=designated, stp_sec_in_state="1777", stp_state=forwarding}

name                : "vlink1"
status              : {stp_port_id="8001", stp_role=designated, stp_sec_in_state="1777", stp_state=forwarding}

name                : "vlinkSW2-1"
status              : {stp_port_id="8002", stp_role=root, stp_sec_in_state="1777", stp_state=forwarding}

name                : "vlink2"
status              : {stp_port_id="8003", stp_role=designated, stp_sec_in_state="1777", stp_state=forwarding}

name                : "vswitch1"
status              : {}

name                : "vlinkSW1-0"
status              : {stp_port_id="8003", stp_role=alternate, stp_sec_in_state="331", stp_state=blocking}

name                : "vlinkSW1-1"
status              : {stp_port_id="8002", stp_role=designated, stp_sec_in_state="1777", stp_state=forwarding}

name                : "vswitch2"
status              : {}

■今回の仮想ネットワークの作成・削除用シェルスクリプト

引数 delete で削除、add で追加です。
共通ファイル vnetcommon.sh がカレントディレクトリにおいてあることを前提としています。
赤字にしたところが STP を有効に設定している箇所です。

#!/bin/sh

. ./vnetcommon.sh

delete() {
    deleteVSwitch "vswitch1" "vswitch2"
    deleteVHost "vhost1" "vhost2"
}

add() {
    addVSwitch "vswitch1"
    sudo ovs-vsctl set Bridge "vswitch1" stp_enable=true

    addVSwitch "vswitch2"
    sudo ovs-vsctl set Bridge "vswitch2" stp_enable=true

    connectVSwitchToVSwitch "vswitch1" "vlinkSW1" "vswitch2"
    connectVSwitchToVSwitch "vswitch2" "vlinkSW2" "vswitch1"

    addVHost "vhost1"
    connectVHostToVSwitch "vhost1" "vlink1" "vswitch1"
    vhostExec "vhost1" ifconfig "vlink1" "192.168.0.1"

    addVHost "vhost2"
    connectVHostToVSwitch "vhost2" "vlink2" "vswitch2"
    vhostExec "vhost2" ifconfig "vlink2" "192.168.0.2"
}

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

現時点の Open vSwitch の FAQ には STP はあまりテストしていないということが書いてあり使用はおすすめしないようです。

FAQ の URL: http://git.openvswitch.org/cgi-bin/gitweb.cgi?p=openvswitch;a=blob_plain;f=FAQ;hb=HEAD

The Open vSwitch implementation of STP is not well tested. Please report any bugs you observe, but if you'd rather avoid acting as a beta tester then another option might be your best shot.

◆ 【Open vSwitchのみで OpenFlowプログラミング】VLAN ID コンバータ 改

OpenFlow コントーラを使わずに(※) Open vSwitch を OpenFlow スイッチとして使って VLAN ID を変換する機能を実装してみましたという前回の記事の最後に書いた気になった点を改善しました。OpenFlow コントローラなしの OpenFlow スイッチを仮想ネットワークに追加する addStandaloneOFSwitch を共通ファイル vnetcommon.sh に追加しました。

※OpenFlow コントローラなしで OpenFlow スイッチを使うというのは OpenFlow の仕様上はありえない構成です。でも、Open vSwitch では可能であり、お手軽に OpenFlow を試すには便利な機能だと思います。

ネットワーク構成図などは、前回記事を参照ください。

■仮想ネットワークの作成・削除シェルスクリプト

引数 delete で削除、add で追加です。
共通ファイル vnetcommon.sh がカレントディレクトリにおいてあることを前提としています。

#!/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 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() {
    addStandaloneOFSwitch "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

修正版の vnetcommon.sh コードは以下です。addStandaloneOFSwitch を追加しました。

# version: 2013-08-10

deleteVHost() {
   local host
   for host in "$@"; do
       sudo ip netns delete "$host"
   done
}

deleteVSwitch() {
   local switch
   for switch in "$@"; do
       sudo ovs-vsctl del-br "$switch"
   done
}

deleteVLink() {
   local link
   for link in "$@"; do
       sudo ip link delete "$link"
       sudo ip link delete "${link}-0"
       sudo ip link delete "${link}-1"
   done
}

addVHost() {
    local host="$1"
    sudo ip netns add "$host"
    sudo ip netns exec "$host" ifconfig lo 127.0.0.1
}

addVSwitch() {
    local switch="$1"
    sudo ovs-vsctl add-br "$switch"
}

setupVSwitchAsOpenFlowSwitch() {
    local switch="$1"
    local datapath_id="$2"

    if [ "$datapath_id" != "" ]; then
        sudo ovs-vsctl set bridge "$switch" other-config:datapath-id=`printf \"%016x\" $datapath_id`
    fi
    sudo ovs-vsctl set-fail-mode "$switch" secure
    sudo ovs-vsctl set-controller "$switch" tcp:127.0.0.1 -- \
        set controller "$switch" connection-mode=out-of-band -- \
        set controller "$switch" inactivity-probe=180 -- \
        set controller "$switch" controller-rate-limit=40000 -- \
        set controller "$switch" controller-burst-limit=20000
}

addOFSwitch() {
    addVSwitch "$1"
    setupVSwitchAsOpenFlowSwitch "$1" "$2"
}

addStandaloneOFSwitch() {
    local switch="$1"

    addVSwitch "$switch"
    sudo ovs-vsctl set-fail-mode "$switch" secure
    sudo ovs-ofctl del-flows "$switch"
}


connectVSwitchToVSwitch() {
    local switch1="$1"
    local link="$2"
    local switch2="$3"

    sudo ip link add name "${link}-0" type veth peer name "${link}-1"

    sudo ip link set "${link}-0" up
    sudo ovs-vsctl add-port "$switch1" "${link}-0"

    sudo ip link set "${link}-1" up
    sudo ovs-vsctl add-port "$switch2" "${link}-1"
}

connectVHostToVSwitch() {
    local host="$1"
    local link="$2"
    local switch="$3"
    local opt="$4"

    sudo ip link add name "${link}" type veth peer name "${link}-1"

    sudo ip link set "${link}-1" netns "$host"
    sudo ip netns exec "$host" ip link set "${link}-1" name "${link}"
    sudo ip netns exec "$host" ifconfig "${link}" up

    sudo ip link set "${link}" up
    sudo ovs-vsctl add-port "$switch" "${link}" $opt
}

vhostExec() {
    sudo ip netns exec "$@"
}

2013年8月 5日 (月)

◆ 【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 を接続する。

Photo
■ 構成の確認
後述するシェルスクリプトで仮想ネットワークを作成したら 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 追記: 上記の気になる点を修正した記事を書きました。]

2013年8月 3日 (土)

◆ Lubuntu 13.04 に Open vSwitch をインストールした時のログ

今更ながらですが、Lubuntu 13.04 Desktop (i386) に、Open vSwitch のパッケージをインストールしたのでログを残しておきます。
Open vSwitch のバージョンは 1.9.0 でした。
インストールは以下のコマンドで行いました:

  sudo apt-get install openvswitch-switch

Lubuntu 12.04 Desktop (i386) に入れた時と違ってカーネルモジュールの処理がなくなっています。Lubuntu 13.04  だと Linux カーネルのバージョンがあがって、Open vSwitch のカーネルモジュールが Linux のカーネルに取り込まれたバージョンになったからですね。

$ sudo apt-get install openvswitch-switch
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています                
状態情報を読み取っています... 完了
以下の特別パッケージがインストールされます:
  openvswitch-common
提案パッケージ:
  ethtool openvswitch-datapath-module
以下のパッケージが新たにインストールされます:
  openvswitch-common openvswitch-switch
アップグレード: 0 個、新規インストール: 2 個、削除: 0 個、保留: 0 個。
2,502 kB のアーカイブを取得する必要があります。
この操作後に追加で 5,912 kB のディスク容量が消費されます。
続行しますか [Y/n]? y
取得:1 http://jp.archive.ubuntu.com/ubuntu/ raring/main openvswitch-common i386 1.9.0-0ubuntu1 [725 kB]
取得:2 http://jp.archive.ubuntu.com/ubuntu/ raring/main openvswitch-switch i386 1.9.0-0ubuntu1 [1,777 kB]
2,502 kB を 5秒 で取得しました (460 kB/s)       
以前に未選択のパッケージ openvswitch-common を選択しています。
(データベースを読み込んでいます ... 現在 134896 個のファイルとディレクトリがインストールされています。)
(.../openvswitch-common_1.9.0-0ubuntu1_i386.deb から) openvswitch-common を展開しています...
以前に未選択のパッケージ openvswitch-switch を選択しています。
(.../openvswitch-switch_1.9.0-0ubuntu1_i386.deb から) openvswitch-switch を展開しています...
man-db のトリガを処理しています ...
ureadahead のトリガを処理しています ...
ureadahead will be reprofiled on next reboot
openvswitch-common (1.9.0-0ubuntu1) を設定しています ...
openvswitch-switch (1.9.0-0ubuntu1) を設定しています ...
 * Inserting openvswitch module
 * /etc/openvswitch/conf.db does not exist
 * Creating empty database /etc/openvswitch/conf.db
 * Starting ovsdb-server
 * Configuring Open vSwitch system IDs
 * Starting ovs-vswitchd
ureadahead のトリガを処理しています ...

サービスを確認してみます:

$ service openvswitch-switch status
ovsdb-server is running with pid 2468
ovs-vswitchd is running with pid 2477

2つ running が表示されます。

« 2013年7月 | トップページ | 2013年10月 »

最近のトラックバック

無料ブログはココログ