« OpenWrt (trunk 版 r36041)を MZK-W300NH2 用にビルドしてみました | トップページ | PLANEX MZK-WNH および MZK-W300NH2 で動く OpenWrt with OpenFlow 1.0 のイメージをアップロードしました(Ver.2)」 »

2013年3月22日 (金)

MZK-WNH/MZK-W300NH2 用 OpenWrt を OpenFlow 1.0 スイッチにカスタマイズする

PLANEX MZK-WNH および MZK-W300NH2 用に先日公開した OpenWrt を OpenFlow スイッチ化したのでその手順を書いておきます。

OpenWrt 用の OpenFlow 1.0 の実装には以下の Pantou を利用しました:
http://www.openflow.org/wk/index.php/Pantou_:_OpenFlow_1.0_for_OpenWRT

Pantou がサポート対象としている機種には、当たり前ですが MZK-WNH および MZK-W300NH2 は含まれていません。また、対象としている OpenWrt も BackFire と古いバージョンです。
簡単な動作確認はしていますが、MZK-WNH/MZK-W300NH2 用の OpenWrt Attitude Adjustment で動作する保証があるものではないことをあらかじめご了承ください。

■今回用いたビルド環境
  ビルド環境は、先日書いた OpenWrt の Attitude Adjustment ブランチのビルド環境です。
なので、
  OSは、Lubuntu 12.04 Desktop(i386) を使用。
 OpenWrt があるディレクトリは、 ~/openwrt/attitude_adjustment を想定。

OpenWrt のファームウェアのファイルが作成でき、入れ替えて起動できるものがすでに作成できていることが前提です。

■どういう OpenFlow スイッチができるのか?

今回作成したファームウェアにより MZK-WNH、MZK-W300NH2 が、4ポートの OpenFlow 1.0 のスイッチとして動作します。

あまり期待はしすぎないでください。
Pantou OpenFlow 1.0 がどれだけ標準に準拠しているのかは分かりません。
また、MZK-WNH/MZK-W300NH2 では、ハードウェア構成上 VLAN タグの入ったパケットが扱えないことがわかっています。
ポート単位のリンクアップ/ダウンも扱えません。
他にもまだまだあると思います。

■手順1) Pantou のソース入手

以下のようにコマンドを実行します:

cd ~/openwrt
git clone git://gitosis.stanford.edu/openflow-openwrt

するとカレントディレクトリに openflow-openwrt というディレクトリができます。

■手順2) 省略→ ブランチ作成 

公式HPにはありますが、不要なので省略します。
ブランチを作ってみたい人は以下のような感じでやるとよいと思います。

cd ~/openwrt/openflow-openwrt
git branch origin/openflow-1.0/mzkwnh
git checkout -b openflow-1.0/mzkwnh

ブランチ origin/openflow-1.0/mzkwnh は、オリジナルの状態のソース参照用。
ブランチ openflow-1.0/mzkwnh は、MZK-WNH/MZK-W300NH2 用のソース。

■手順3) Pantou を OpenWrt のビルド環境に組み込む

cd ~/openwrt/attitude_adjustment/package
ln -s ../../openflow-openwrt/openflow-1.0 .

※ 個人的な好みの理由で、公式HPでは絶対パスでシンボリックリンクしているところを相対パスにしています。

■手順4) 省略→ 設定ファイルの OpenWRT への追加

公式HPにはありますが、不要なので省略します。
公式HPの「Add basic configuration files for OpenWRT」という手順に該当します。

この手順では、OpenWrt のルートファイルシステムを作るときに、追加でコピーするファイルを指定できる仕掛けを利用して OpenFlow の各ファイルのコピーをするようにしています。
しかし、パッケージのインストール処理でそれらのファイルをコピーするようにしてあるので、この仕掛けを利用する必要がありません。
~/openwrt/attitude_adjustment/openflow-openwrt/openflow-1.0/Makefile の中の "define Package/openflow/install" の箇所がパッケージのインストール処理の箇所です。

■手順5) make menuconfig によるビルド項目カスタマイズ

cd ~/openwrt/attitude_adjustment
make menuconfig

make menuconfigを使って、openflow 自体、および前提として必要な tc のパッケージを有効にします。
また、公式HPには記載がないですが、完全に OpenFlow スイッチとして動かすことを考えると Firewall などの処理は不要なので削除します。

対象項目にカーソルを移動したらスペースキーで種別を切り替えます。各項目名の先頭に表示される「< >」のところが種別を表しています。<*> を選ぶとファームウェアに組込まれます。削除は < > の状態。<M> はコンパイルしてパッケージ形式にしますがファームウェアのイメージには含まれません。

以下の3つの項目を <*> にします:
・ [Network] → [OpenFlow]
・ [Network] → [tc]
・ [Kernel modules] → [Network Support] → [kmod-tun]

以下の2つの項目を < > にします:
・ [Base system]→[dnsmasq]
・ [Base system]→[firewall]

■手順6) make kernel_menuconfig によるカーネルオプション変更

cd ~/openwrt/attitude_adjustment
make kernel_menuconfig

以下の項目を <*> にします:
・ [Networking support]→[Networking options]→[QoS and/or fair queueing]→[Hierarchical Token Bucket (HTB)]

■手順7) Patnou へのパッチの適用

Pantou 公式 HP にはない手順です。
openflow 用定義ファイル /etc/config/openflow ファイルで指定できる起動時オプションを追加したいので修正をしました。
修正パッチは以下においておきます:
http://ranosgrant.cocolog-nifty.com/PantouOpenFlow_1_0/pantou.diff

以下の手順でパッチをあててください:

cd ~/openwrt/openflow-openwrt
wget http://ranosgrant.cocolog-nifty.com/PantouOpenFlow_1_0/pantou.diff
patch -p0 < pantou.diff

実行時出力

$ patch -p0 < pantou.diff
patching file openflow-1.0/files/lib/openflow/ofprotocol.sh

パッチの中身

diff --git openflow-1.0/files/lib/openflow/ofprotocol.sh openflow-

1.0/files/lib/openflow/ofprotocol.sh
index 745ef3c..25b6543 100755
--- openflow-1.0/files/lib/openflow/ofprotocol.sh
+++ openflow-1.0/files/lib/openflow/ofprotocol.sh
@@ -5,11 +5,15 @@ setup_ofprotocol() {
 	local config="$1"
 	local ofctl
 	local dp
+	local fail
+	local inactivity_probe
 
 	[ -x "/usr/bin/ofprotocol" ] || ( echo "ofprotocol not executable" && return 0 )
 	config_get ofctl "$config" ofctl
 	config_get dp "$config" dp
 	config_get mode "$config" mode
+	config_get fail "$config" fail "open"
+	config_get inactivity_probe "$config" inactivity_probe "15"
 
 
 	pidfile="/var/run/ofprotocol.pid"
@@ -25,9 +29,9 @@ setup_ofprotocol() {
 		[ -z "$dp" -o -z "$ofctl" ] && echo "no controller specified" && return 1
 		if [[ "$mode" == "inband" ]]			
 		then
-			ofprotocol unix:/var/run/dp0.sock "$ofctl" --fail=open "-D" "--

pidfile=$pidfile" --listen=ptcp: --log-file="/var/log/ofprotocol.log" &
+			ofprotocol unix:/var/run/dp0.sock "$ofctl" --fail="$fail" "-D" 

"--pidfile=$pidfile" --listen=ptcp: --log-file="/var/log/ofprotocol.log" --inactivity-

probe="$inactivity_probe" &
 		else
-			ofprotocol unix:/var/run/dp0.sock "$ofctl" --fail=open "-D" "--

pidfile=$pidfile" --out-of-band --listen=ptcp: --log-file="/var/log/ofprotocol.log" &
+			ofprotocol unix:/var/run/dp0.sock "$ofctl" --fail="$fail" "-D" 

"--pidfile=$pidfile" --out-of-band --listen=ptcp: --log-file="/var/log/ofprotocol.log" 

--inactivity-probe="$inactivity_probe" &
 		fi
 		lock -u "/var/lock/ofprotocol"
 	fi

このパッチは以下のコマンドで出力しました:

cd ~/openwrt/openflow-openwrt
git diff --no-prefix

■手順8) 定義ファイルの OpenWrt への追加

こちらも Pantou 公式HPにはない手順です。
MZK-WNH/MZK-W300NH2 を OpenFlow スイッチとして動作させるためのカスタマイズをした定義ファイルを用意します。

カスタマイズ済のファイルは tar でアーカイブして、http://ranosgrant.cocolog-nifty.com/PantouOpenFlow_1_0/files.tar においておきました。

以下の手順でビルド環境に取り込んでください:

cd ~/openwrt/attitude_adjustment
wget http://ranosgrant.cocolog-nifty.com/PantouOpenFlow_1_0/files.tar
tar xvf files.tar

これで2つのファイルが生成されます。

1) files/etc/config/openflow

openflow 用の定義ファイル /etc/config/openflow に対して少し手を加えたもので置き換えます。
OpenFlow の Datapath ID を OpenFlow 1.0 の規格に従って MAC アドレスを指定しやすくするため少し手を加えてあります。
openflow の中身は以下です:

config ofswitch 'ofswitch0'
	option dp 'dp0'
	option ofports 'eth0.1 eth0.2 eth0.3 eth0.4'
	option ofctl 'tcp:192.168.1.10:6633'
	option mode  'outofband'

2) files/etc/uci-defaults/network

OpenWrt では、初期ブート時に /etc/config/network ファイルを作成するために /etc/uci-defaults/network というファイルが起動します。
このファイルを、OpenFlow スイッチ用の定義を作成するファイルにおきかえます。置き換え後の network ファイルは、MKZ-WNH/MZK-W300NH2 固有の定義内容です。

/etc/config/openflow ファイルの dpid (Datapath ID)の値の設定処理も入れてあります。

network の内容は、以下です:

#!/bin/sh

. /etc/functions.sh
. /lib/ramips.sh
. /lib/functions/uci-defaults.sh


[ -e /etc/config/network ] && exit 0
if [ ! -x /usr/sbin/maccalc ]; then
	echo "$0: maccalc not found!"
	exit 1
fi

lan_mac=$(ramips_get_mac_binary factory 4)
wan_mac=`/usr/sbin/maccalc add "$lan_mac" 1`

dpid=`echo "$wan_mac" | sed -e 's/://g'`
uci set openflow.ofswitch0.dpid=$dpid
uci commit openflow

touch /etc/config/network
ucidef_set_interface_loopback

ucidef_add_switch "switch0" 1 1
ucidef_add_switch_vlan "switch0" 1 "0 6t"
ucidef_add_switch_vlan "switch0" 2 "1 6t"
ucidef_add_switch_vlan "switch0" 3 "2 6t"
ucidef_add_switch_vlan "switch0" 4 "3 6t"
ucidef_add_switch_vlan "switch0" 5 "4 6t"


uci batch << EOF
set network.eth0='interface'
set network.eth0.ifname='eth0'
set network.eth0.proto='static'
set network.eth0.macaddr='$lan_mac'
EOF

ucidef_set_interface_raw "eth0_1" "eth0.1"
ucidef_set_interface_raw "eth0_2" "eth0.2"
ucidef_set_interface_raw "eth0_3" "eth0.3"
ucidef_set_interface_raw "eth0_4" "eth0.4"

uci batch << EOF
set network.eth0_5='interface'
set network.eth0_5.ifname='eth0.5'
set network.eth0_5.proto='static'
set network.eth0_5.ipaddr='192.168.1.1'
set network.eth0_5.netmask='255.255.255.0'
set network.eth0_5.macaddr='$wan_mac'
EOF

uci commit network

exit 0

■手順9) イメージのビルド

準備は以上です。あとは make するだけです。

cd ~/openwrt/attitude_adjustment
make

エラーが出るようだったら make V=99 として詳細なログを出力して確認してください。

■手順10) ファームウェアの入替え

イメージファイルのありか、ファームウェアの入替え方法などは変わりないので説明は省きます。

■ファームウェア入れ替え後の構成

接続するポートに注意してください!。今回作成したファームウェアがログイン用に受け付けるのは「Internet」というラベルのついたポートです。

1)「Internet」と書いてあるポート
  IP アドレス 192.168.1.1
  OpenFlow コントローラとの接続用です。
  ログインして設定を変更するにも使います。パスワード設定前なら telnet でパスワードなしで入れます。

  IPアドレスは、/etc/config/network ファイルで変更可能です。

2)「1」~「4」と書いてあるポート
 OpenFlow 専用ポート

3) OpenFlowコントローラ
  192.168.1.10 の TCP ポート 6633 にめがけて接続しにいきます。

  IPアドレスは、/etc/config/openflow ファイルで変更可能です。後述する OpenFlow フレームワーク Trema と接続する場合、この設定のままで大丈夫です。

4) ログファイル
 /var/log/ofprotocol.log ファイルにログが出力されます。
OpenFlowコントローラとの接続状況などが出力されています。

■簡単な動作確認

dpctl コマンドで OpenFlow のプロセスを制御できます。まずは、showサブコマンドを使ってみましょう。

root@OpenWrt:/# dpctl show unix:/var/run/dp0.sock
features_reply (xid=0xdd8a589b): ver:0x1, dpid:22cf212a29
n_tables:2, n_buffers:256
features: capabilities:0xc7, actions:0xeff
 1(eth0.1): addr:00:22:cf:21:2a:28, config: 0, state:0
 2(eth0.2): addr:00:22:cf:21:2a:28, config: 0, state:0
 3(eth0.3): addr:00:22:cf:21:2a:28, config: 0, state:0
 4(eth0.4): addr:00:22:cf:21:2a:28, config: 0, state:0
get_config_reply (xid=0xba967ffb): miss_send_len=128

ポートが4つ eth0.1 ~ eth0.4 が表示されるはずです。
また、dpid には、MZK-WNH/MZK-W300NH2 の底部に貼ってあるシールの「Node ID WAN」の箇所の MAC アドレスと一致しているはずです(先頭の 00 は表示上省略されているのは気にしなくて構いません)。
OpenFlow 1.0 の規格に従って MAC アドレスを datapath id (dpid) としています。

記載箇所:
http://www.openflow.org/documents/openflow-spec-v1.0.0.pdf
"OpenFlow Switch Specification Version 1.0.0"(p.25) "5.3.1 Handshake" より:

The datapath_id field uniquely identifies a datapath. The lower 48 bits are
intended for the switch MAC address, while the top 16 bits are up to the implementer.

直訳:
datapath_id フィールドは、データパスを一意に識別します。下位48ビットはスイッチの MAC アドレスを用いることを意図しているが、上位16ビットは実装者にまかせる。

■簡単なフローエントリの確認

OpenFlow コントローラを用意しなくてもコマンドラインでフローエントリの登録ができるので以下でポート1 と 2 だけを接続してみてください。

dpctl add-flow unix:/var/run/dp0.sock idle_timeout=0,hard_timeout=0,in_port=1,actions=output:2
dpctl add-flow unix:/var/run/dp0.sock idle_timeout=0,hard_timeout=0,in_port=2,actions=output:1

フローエントリをダンプして登録されていることを確認してみます:

# dpctl dump-flows unix:/var/run/dp0.sock
stats_reply (xid=0x811a0216): flags=none type=1(flow)
  cookie=0, duration_sec=24s, duration_nsec=633000000s, table_id=1, priority=32768, n_packets=0, n_bytes=0, idle_timeout=0,hard_timeout=0,in_port=2,actions=output:1
  cookie=0, duration_sec=24s, duration_nsec=653000000s, table_id=1, priority=32768, n_packets=0, n_bytes=0, idle_timeout=0,hard_timeout=0,in_port=1,actions=output:2

これで、「1」「2」の印があるポート同士だけが通信できる状態になっています。
ケーブルを差し替えて例えば「1」と「3」にすると通信できなくなります。

dpctl コマンドの詳細は、以下のようにしてソース中の man ページを見てください:

nroff -man ~/openwrt/attitude_adjustment/build_dir/target-mipsel_r2_uClibc-0.9.33.2/openflow-1.0.0/utilities/dpctl.8 | more

■ OpenFlow コントローラとの接続確認

ここまで動いたらOpenFlow コントローラとの接続確認に挑戦してみてください。
私は、OpenFlow フレームワーク Trema を使って接続確認をしました。
Tremaについては、書籍「OpenFlow実践入門」を読んでください。

まずは ping で OpenFlow スイッチと OpenFlow コントローラの通信確認をしておいてください。

それができたら、OpenFlow フレームワーク Trema に付属するサンプルの repeater-hub あたりでまずは試してみるとよいと思います。

OpenFlow コントローラを起動したら、OpenFlow スイッチ側で tail -f /var/log/ofprotocol.log でログを監視して以下のように OpenFlow コントローラの IPアドレスで "connected" のメッセージが出たら接続完了です。

Jan 01 00:59:27|00588|rconn|INFO|tcp:192.168.1.10:6633: connected

もし、接続がなかなかできないとかすぐに切断してしまうような場合は以下のようにして openflow を再起動してみてください。

/etc/init.d/openflow restart

■ Pantou OpenFlow 1.0 のデフォルト動作の変更点について

/etc/config/openflow にて起動オプションのパラメタを変更しています。

1) option inactivity_probe '90'

デフォルトは15秒です。
Trema との接続するためには --inactivity-probe オプションを 90 秒にするように以下のブログで報告があるので採用しました。
http://trema.hatenablog.jp/entry/20120312/1331548450

2) option fail 'closed'

デフォルト値は、'open' です。
デフォルト動作は、OpenFlow コントローラとの接続失敗を繰り返したときにブリッジとして動きだす設定です。
'closed' に変更して、そのような動作をしないようにしています。

上記起動オプションの詳細は、以下のようにしてソース中の man ページを見てください:

nroff -man ~/openwrt/attitude_adjustment/build_dir/target-mipsel_r2_uClibc-0.9.33.2/openflow-1.0.0/secchan/ofprotocol.8 | more

■おまけ: Pantou に関して

ダウンロードしたソースを見てみると非常に少なくてどこにも OpenFlow のコードがないのが不思議でした。が、OpenFlow のソースは別のところからビルド時にダウンロードする仕掛けでした。

以下がソースツリーです:

$ cd ~/openwrt
$ tree openflow-1.0
openflow-1.0/
├── Makefile
├── files
│   ├── etc
│   │   ├── config
│   │   │   └── openflow
│   │   ├── hotplug.d
│   │   │   └── ofiface
│   │   │       └── 00-netstate
│   │   └── init.d
│   │       └── openflow
│   ├── lib
│   │   └── openflow
│   │       ├── ofinterfaces.sh
│   │       ├── ofprotocol.sh
│   │       └── ofswitch.sh
│   └── sbin
│       ├── ofdown
│       └── ofup
└── patches
    ├── 001-secchan-Fix-port-status-detection.patch
    ├── 002-BSD_cross_compile_fix.patch
    ├── 003_FLOW_ENTIES_limit.patch
    ├── 004-lib-use-bitwise-AND-when-checking-for-ARP.patch
    └── 005-Remove-hardcoded-path-for-tc.patch

10 directories, 14 files

Pantou のホームページに書いてあるように、OpenFlow部分は Standford reference の実装を使っています。

The OpenFlow module is based on the Stanford reference implementation (userspace).

files ディレクトリにはそのままインストールするファイル群、patches の下には元となるソースに対するパッチファイル群がおいてあります。

もともと OpenWrt のパッケージのビルドの仕掛けには、他からソースを持ってきてパッチをあててビルドするという仕掛けがあります。
OpenWrt のパッケージの仕掛けの詳細は以下を参照ください(英語です):
http://wiki.openwrt.org/doc/devel/packages

~/openwrt/attitude_adjustment/openflow-1.0/Makefile の以下の箇所がソースの入手元:

PKG_NAME_SHORT:=openflow
PKG_NAME:=kmod-$(PKG_NAME_SHORT)
PKG_VERSION:=1.0.0
PKG_RELEASE:=1

PKG_SOURCE:=$(PKG_NAME_SHORT)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:= http://openflowswitch.org/downloads/

今回の場合、実際にコンパイルに使っているソースや生成したオブジェクトがあるディレクトリは以下でした:
~/openwrt/attitude_adjustment/build_dir/target-mipsel_r2_uClibc-0.9.33.2/openflow-1.0.0/

ちなみに、パッケージだけコンパイルしたい場合は以下の手順です:

cd ~openwrt/attitude_adjustment
make package/openflow-1.0/compile

(情報源: http://wiki.openwrt.org/doc/howtobuild/single.package)

p.s.
以前、公開した OpenFlow 対応のファームウェアは Attitude Adjustment が trunk (開発用ブランチ) だった古いものです。
当時は、試行錯誤でつくったので手順を公開できませんでしたが、今回はできるだけ最小限の手間でビルドできる手順としました...したつもりです。

« OpenWrt (trunk 版 r36041)を MZK-W300NH2 用にビルドしてみました | トップページ | PLANEX MZK-WNH および MZK-W300NH2 で動く OpenWrt with OpenFlow 1.0 のイメージをアップロードしました(Ver.2)」 »

OpenFlow」カテゴリの記事

openwrt」カテゴリの記事

PLANEX MZK-W300NH2」カテゴリの記事

PLANEX MZK-WNH」カテゴリの記事

Trema」カテゴリの記事

コメント

コメントを書く

(ウェブ上には掲載しません)

トラックバック

この記事のトラックバックURL:
http://app.f.cocolog-nifty.com/t/trackback/1776113/50877824

この記事へのトラックバック一覧です: MZK-WNH/MZK-W300NH2 用 OpenWrt を OpenFlow 1.0 スイッチにカスタマイズする:

« OpenWrt (trunk 版 r36041)を MZK-W300NH2 用にビルドしてみました | トップページ | PLANEX MZK-WNH および MZK-W300NH2 で動く OpenWrt with OpenFlow 1.0 のイメージをアップロードしました(Ver.2)」 »

最近のトラックバック

無料ブログはココログ