« ◆ OpenFlow 1.0.0 メッセージと Trema API(Ruby) との対応表 | トップページ | ◆ 【TremaでOpenFlowプログラミング】VLAN ID コンバータ »

2013年5月11日 (土)

◆ Linux のネットワークネームスペース機能と Open vSwitch で仮想ネットワーク(OpenFlowスイッチとTrema)

今回は、Open vSwitch を OpenFlow スイッチとして使ってみました。OpenFlow コントローラは、OpenFlow フレームワーク Trema を使い OpenFlow スイッチをリピーターハブとして動かしています。

今回の構成程度だと、Trema の仮想ネットワーク機能を使った方がお手軽です。ですが、このシェルスクリプトを用いた方法では今までの記事で書いてきたように VLAN や仮想ルータ、仮想スイッチを組み合わせることができるのでTrema の仮想ネットワークよりも色々なネットワーク構成が可能です。

使用した環境:
  OS: Lubuntu 12.04 Desktop (i386) (※ 13.04 ではありません)
  Trema: Trema 0.3.19

■今回作成した仮想ネットワークの構成図
2つの OpenFlow スイッチにそれぞれ1つ仮想ホストをつないだだけの簡単な構成です。
図には書いていませんが、各 OpenFlow スイッチはローカルループバック 127.0.0.1 経由で OpenFlow フレームワーク Trema と接続します。
Photo_5

仮想ホストで使うインターフェース名は、仮想スイッチ側のインターフェース名と同じ名前を使うようにしました。仮想ホスト側は独自の名前空間なのでこういうことができます。

■OpenFlowコントローラ

OpenFlow フレームワーク Trema で、OpenFlow スイッチをリピーターハブとして動作させるコントローラを動かします。ソースコードは以下:

class RepetaerHub < Controller
  def switch_ready( datapath_id )
    puts "switch #{ datapath_id.to_hex } is connected."
    send_flow_mod_add( datapath_id, :actions => SendOutPort.new( OFPP_FLOOD ))
  end
end

コントローラは仮想ネットワークを作成した後に、以下で起動します:
  trema run コントローラのソースコードのファイル

■構成の確認
OpenFlow ポートの1番が OpenFlow スイッチ間の接続、2番が仮想マシンとの接続となっていることを確認します。

vswitch1 の OpenFlow スイッチとしての情報:

$ sudo ovs-ofctl show vswitch1
OFPT_FEATURES_REPLY (xid=0x1): ver:0x1, dpid:0000000000000001
n_tables:255, n_buffers:256
features: capabilities:0xc7, actions:0xfff
1(vlinkSW1-0): addr:9a:51:e2:54:c1:69
     config:     0
     state:      0
     current:    10GB-FD COPPER
2(vlink1): addr:86:98:54:0d:32:08
     config:     0
     state:      0
     current:    10GB-FD COPPER
LOCAL(vswitch1): addr:66:40:c5:44:72:41
     config:     PORT_DOWN
     state:      LINK_DOWN
OFPT_GET_CONFIG_REPLY (xid=0x3): frags=normal miss_send_len=0

vswitch2 の OpenFlow スイッチとしての情報:

$ sudo ovs-ofctl show vswitch2
OFPT_FEATURES_REPLY (xid=0x1): ver:0x1, dpid:00008a25a0cdf842
n_tables:255, n_buffers:256
features: capabilities:0xc7, actions:0xfff
1(vlinkSW1-1): addr:1a:71:45:3a:ec:32
     config:     0
     state:      0
     current:    10GB-FD COPPER
2(vlink2): addr:7a:f8:28:27:67:f7
     config:     0
     state:      0
     current:    10GB-FD COPPER
LOCAL(vswitch2): addr:8a:25:a0:cd:f8:42
     config:     PORT_DOWN
     state:      LINK_DOWN
OFPT_GET_CONFIG_REPLY (xid=0x3): frags=normal miss_send_len=0

■ OpenFlow スイッチのフローテーブルの確認

vswitch1 のフローテーブル:

$ sudo ovs-ofctl dump-flows vswitch1
NXST_FLOW reply (xid=0x4):
cookie=0x1, duration=113.232s, table=0, n_packets=0, n_bytes=0, priority=65535 actions=FLOOD

vswitch2 のフローテーブル:

$ sudo ovs-ofctl dump-flows vswitch2
NXST_FLOW reply (xid=0x4):
cookie=0x1, duration=121.102s, table=0, n_packets=0, n_bytes=0, priority=65535 actions=FLOOD

■動作確認
vhost1 から ping で vhost2(192.168.0.2)へ通信できることを確認:

$ sudo ip netns exec vhost1 ping -c 3 192.168.0.2
PING 192.168.0.2 (192.168.0.2) 56(84) bytes of data.
64 bytes from 192.168.0.2: icmp_req=1 ttl=64 time=3.12 ms
64 bytes from 192.168.0.2: icmp_req=2 ttl=64 time=0.196 ms
64 bytes from 192.168.0.2: icmp_req=3 ttl=64 time=0.096 ms

--- 192.168.0.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2000ms
rtt min/avg/max/mdev = 0.096/1.140/3.128/1.406 ms

■今回の仮想ネットワークの作成・削除シェルスクリプト
引数 delete で削除、add で追加です。
今までのシェルスクリプトの経験から関数化して他でも使える共通部分を別ファイル vnetcommon.sh に分離しました。共通部分のファイル vnetcommon.sh はカレントディレクトリにおいてあることを前提としています。

#!/bin/sh
. ./vnetcommon.sh

delete() {
    deleteVSwitch "vswitch1" "vswitch2"
    deleteVLink "vlinkSW1"
    deleteVHost "vhost1" "vhost2"
    deleteVLink "vlink1" "vlink2"
}

add() {
    addOFSwitch "vswitch1" "0x1"
    addOFSwitch "vswitch2"
    connectVSwitchToVSwitch "vswitch1" "vlinkSW1" "vswitch2"

    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

上記で、「sudo sh -c exit」と一見無意味なことをしているのは事前に sudo のパスワード入力を済ませたかったからです。

共通ファイル vnetcommon.sh の内容は以下:

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"
}

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 "$@"
}

OpenFlow スイッチとしてのオプションは、Trema が内部的に使っているユーザースペース版 Open vSwitch の起動オプションを参考にしています。
『OpenFlow実践入門』(初版 P.195) 「仮想スイッチ」に記載されているコマンドラインオプションを参考にさせていただきました。

addOFSwitch 関数の第2引数は datapath_id ですが、省略可能です。

« ◆ OpenFlow 1.0.0 メッセージと Trema API(Ruby) との対応表 | トップページ | ◆ 【TremaでOpenFlowプログラミング】VLAN ID コンバータ »

OpenFlow」カテゴリの記事

Trema」カテゴリの記事

仮想ネットワーク」カテゴリの記事

コメント

この記事へのコメントは終了しました。

« ◆ OpenFlow 1.0.0 メッセージと Trema API(Ruby) との対応表 | トップページ | ◆ 【TremaでOpenFlowプログラミング】VLAN ID コンバータ »

最近のトラックバック

無料ブログはココログ