カスタムコントローラ登録

独自のコントローラを作成して新規に使えるようにする。


NOX コントローラのプログラミング

NOX に新しいコントローラプログラムを用意する

http://blog.bitmeister.jp/?p=2201
OpenFlowで、なんちゃって負荷分散を実装してみた[負荷分散実装編]
で、新しいコントローラプログラムを書いている。

ここのコードは無視して、とりあえず pyswitch.py をそのまま移した ylbswitch.py を用意して、これを使ってみることにする。

cd /home/hoge/nox/build/src/nox/coreapps/examples << ここで作業(nox/build/src であって nox/src ではない!)
cp pyswitch.py ylbswitch.py  << コピー
vi ylbswitch.py << 編集(pyswitch を ylbswitch に変更)

この修正では Class 名も変更する。
< class pyswitch(Component):
---
> class ylbswitch(Component):
新しいコントローラプログラムを登録する
で、これに対応するために、vi meta.json などとして定義ファイルに ylbswitch の名前を追加する。

        {
            "name": "pyswitch" ,
            "dependencies": [
                "python"
            ],
            "python": "nox.coreapps.examples.pyswitch" << 元からあった記述
        },
        {
            "name": "ylbswitch" ,
            "dependencies": [
                "python"
            ],
            "python": "nox.coreapps.examples.ylbswitch" << 赤文字全部、追加した
        }, 

この状態で NOX を
./nox_core -v -i ptcp:6633 ylbswitch 
として再起動するとちゃんと ylbswitch 名で起動することを確認した。
(なお起動すると ylbswitch.py から .pyc ファイルが作られる)
pyswitch.py の中身を読む

今回は単純なコピーだが、今後新しいコントローラを書こうと思うと関数仕様を知らなければならない。 が、あまり良いドキュメントがない。
http://noxrepo.org/~yapkke/doc/classnox_1_1lib_1_1core_1_1Component.html
あたりが NOX API リファレンスと思われるが、あまり分かりやすいとは言えない。 サンプルコードや解説を見ながら、チュートリアル的なものが必要な段階だから、か。

http://blog.bitmeister.jp/?p=2201
OpenFlowで、なんちゃって負荷分散を実装してみた[負荷分散実装編]
の「おまけ」に、少し pyswitch の解説がある。 が、関数仕様が分からないのは難しい。

が、 OpenFlowTutorialOFELIA2011 ドキュメントがなかなか良い!
http://www.openflow.org/wk/index.php/OpenFlowTutorialOFELIA2011
に説明あり。

99 行目:
inst.send_openflow(dpid, bufid, buf, openflow.OFPP_FLOOD, inport)
とあるが、FLOOD すると入力ポートにも折り返す?はずはないので、最後の引数 inport は除外ポートだよね?と思ったら、
   def send_openflow(self, dp_id, buffer_id, packet, actions,
                      inport=openflow.OFPP_CONTROLLER):
だそうで、inport は指定されれば「ソースとしてマークされたdp (datapath) を指すそうで、まあそれが除外対象なのかな?)

93 行目:
 inst.install_datapath_flow(dpid, flow, CACHE_TIMEOUT, 
                                       openflow.OFP_FLOW_PERMANENT, actions,
                                       bufid, openflow.OFP_DEFAULT_PRIORITY,
                                       inport, buf)
とあるが、この関数はまるでフロー登録だけのような顔をしているが(MAC learning スイッチの振る舞いから推して)
コードの構造的にはここでデータ送信をしないといけない。
(実際、inport と buf を引数に持つ。何故こんなモノが要るかと言えば当該データの送信のためしかない。)
仕様を見ると、
  def install_datapath_flow(self, dp_id, attrs, idle_timeout, hard_timeout,
                              actions, buffer_id=None, 
                              priority=openflow.OFP_DEFAULT_PRIORITY,
                              inport=None, packet=None):
では
inport - When packet is sent, the port on which packet came in as input,
        so that it can be omitted from any OFPP_FLOOD outputs.
とある。つまり「packet is sent」送信するつもりのとき、action が FLOOD なら inport を除外するぞと。
C++ での実装

例えば /home/hoge/nox/src/nox/coreapps/switch/switch.cc は C++ で書かれた L2 MAC learn switch 実装である。 ディレクトリが ./nox/src であって ./nox/build でないことに注意。 つまり Python の場合は build ディレクトリ以下のものを直接修正するが、C++ の場合は src ディレクトリのソースを修正して、make することで build ディレクトリ以下に反映させてから利用する。

例として switch.cc を修正した場合の操作を示す。

# cd /home/hoge/nox/build
# make -j 5
で、正しく switch ディレクトリ以下が make されたことを確認。
ここから。
Making all in switch
make[8]: Entering directory `/home/hoge/nox/build/src/nox/coreapps/switch'
make  all-am
make[9]: Entering directory `/home/hoge/nox/build/src/nox/coreapps/switch'
/bin/sh ../../../../libtool  --tag=CXX   --mode=compile g++ -DHAVE_CONFIG_H -I. -I../../../../../src/nox/coreapps/switch -I../../../..  -DPKGDATADIR=\"/usr/local/share/nox\" -DPKGLIBDIR=\"/usr/local/bin/nox/coreapps/switch\" -DPKGLOCALSTATEDIR=\"/usr/local/var/nox\" -DPKGSYSCONFDIR=\"/usr/local/etc/nox\" -include ../../../../config.h -I ../../../../../src/include -I../../../../../src/include/openflow -I/usr/include -D_GNU_SOURCE=1   -D_REENTRANT -D__STDC_LIMIT_MACROS=1 -D__STDC_FORMAT_MACROS=1 -D__STDC_CONSTANT_MACROS=1 -D_GLIBCXX_CONCEPT_CHECKS=1 -D_GLIBCXX_DEBUG=1 -D_GLIBCXX_DEBUG_PEDANTIC=1 -I../../../../../src/nox  -fno-omit-frame-pointer -fno-strict-aliasing -Wall -Wno-sign-compare -Winit-self -Wformat-nonliteral -Wformat-security -g -O2 -MT switch_la-switch.lo -MD -MP -MF .deps/switch_la-switch.Tpo -c -o switch_la-switch.lo `test -f 'switch.cc' || echo '../../../../../src/nox/coreapps/switch/'`switch.cc
libtool: compile:  g++ -DHAVE_CONFIG_H -I. -I../../../../../src/nox/coreapps/switch -I../../../.. -DPKGDATADIR=\"/usr/local/share/nox\" -DPKGLIBDIR=\"/usr/local/bin/nox/coreapps/switch\" -DPKGLOCALSTATEDIR=\"/usr/local/var/nox\" -DPKGSYSCONFDIR=\"/usr/local/etc/nox\" -include ../../../../config.h -I ../../../../../src/include -I../../../../../src/include/openflow -I/usr/include -D_GNU_SOURCE=1 -D_REENTRANT -D__STDC_LIMIT_MACROS=1 -D__STDC_FORMAT_MACROS=1 -D__STDC_CONSTANT_MACROS=1 -D_GLIBCXX_CONCEPT_CHECKS=1 -D_GLIBCXX_DEBUG=1 -D_GLIBCXX_DEBUG_PEDANTIC=1 -I../../../../../src/nox -fno-omit-frame-pointer -fno-strict-aliasing -Wall -Wno-sign-compare -Winit-self -Wformat-nonliteral -Wformat-security -g -O2 -MT switch_la-switch.lo -MD -MP -MF .deps/switch_la-switch.Tpo -c ../../../../../src/nox/coreapps/switch/switch.cc  -fPIC -DPIC -o .libs/switch_la-switch.o
mv -f .deps/switch_la-switch.Tpo .deps/switch_la-switch.Plo
/bin/sh ../../../../libtool --tag=CXX   --mode=link g++ -fno-omit-frame-pointer -fno-strict-aliasing -Wall -Wno-sign-compare -Winit-self -Wformat-nonliteral -Wformat-security -g -O2 -module -export-dynamic  -o switch.la -rpath /usr/local/bin/nox/coreapps/switch switch_la-switch.lo  
libtool: link: rm -fr  .libs/switch.la .libs/switch.lai .libs/switch.so .libs/switch.so.0 .libs/switch.so.0.0.0
libtool: link: g++ -shared -nostdlib /usr/lib/gcc/x86_64-redhat-linux/4.4.4/../../../../lib64/crti.o /usr/lib/gcc/x86_64-redhat-linux/4.4.4/crtbeginS.o  .libs/switch_la-switch.o   -L/usr/lib/gcc/x86_64-redhat-linux/4.4.4 -L/usr/lib/gcc/x86_64-redhat-linux/4.4.4/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-redhat-linux/4.4.4/../../.. -lstdc++ -lm -lc -lgcc_s /usr/lib/gcc/x86_64-redhat-linux/4.4.4/crtendS.o /usr/lib/gcc/x86_64-redhat-linux/4.4.4/../../../../lib64/crtn.o    -Wl,-soname -Wl,switch.so.0 -o .libs/switch.so.0.0.0
libtool: link: (cd ".libs" && rm -f "switch.so.0" && ln -s "switch.so.0.0.0" "switch.so.0")
libtool: link: (cd ".libs" && rm -f "switch.so" && ln -s "switch.so.0.0.0" "switch.so")
libtool: link: ( cd ".libs" && rm -f "switch.la" && ln -s "../switch.la" "switch.la" )
make[9]: Leaving directory `/home/hoge/nox/build/src/nox/coreapps/switch'
make[8]: Leaving directory `/home/hoge/nox/build/src/nox/coreapps/switch'
ここまで。

この状態で問題となると思われる switch.cc の生成物のタイムスタンプを確認。
もともと、
# pwd
/home/hoge/nox/build
# ls -l src/nox/coreapps/switch/
total 36
-rw-r--r--. 1 root root 26391 2011-07-19 19:50 Makefile
lrwxrwxrwx. 1 root root    48 2011-07-19 19:52 meta.json -> ../../../../../src/nox/coreapps/switch/meta.json
-rw-r--r--. 1 root root   925 2011-07-19 19:52 switch.la
-rw-r--r--. 1 root root   287 2011-07-19 19:52 switch_la-switch.lo
# 
だったものが、以下に変更された。
# ls -l src/nox/coreapps/switch/
total 36
-rw-r--r--. 1 root root 26391 2011-07-19 19:50 Makefile
lrwxrwxrwx. 1 root root    48 2011-07-19 19:52 meta.json -> ../../../../../src/nox/coreapps/switch/meta.json
-rw-r--r--. 1 root root   925 2011-07-21 22:18 switch.la
-rw-r--r--. 1 root root   287 2011-07-21 22:18 switch_la-switch.lo
# 

これで nox を起動する際に switch を指定してやれば動作確認が出来る。
./nox_core -v -i ptcp:6633 switch  

以上で NOX 上で新しいコントローラを実装し、利用する方法が分かった。



Yutaka Yasuda (yasuda [ at ] ylb.jp)