クリーム色の背景、色付き表示、高コントラスト、大きな文字のほうが読みやすいですか?配色と文字を選ぶと、すべてのページに一度で反映されます。

無料レッスン

os-kenコントローラの読み方

このレッスンのあとで: 小さな os-ken コントローラを読み、各ハンドラが何をするか言える。

60分のレッスンコマンド4件SDN のラボ:Open vSwitch、Mininet、OpenFlow コントローラーを1台の VM で

コントローラは小さなハンドラの集まり

os-ken は、OpenFlow のコントローラを Python で書くためのライブラリです。コントローラの中身は、「スイッチから知らせが届いたら、この関数を呼ぶ」という、小さな関数の集まりです。

読み方が分かれば、コントローラが何を決め、スイッチに何を書き込むかを、コードから言えます。

このレッスンのゴール

メモ

小さな os-ken コントローラを読み、各ハンドラが何をするか言える。

重要な言葉

ことばいみれい
ハンドラ知らせが届いたときに呼ばれる関数
packet-inフローのない枠を、スイッチがコントローラに送る知らせ
flow-modコントローラがスイッチにフローを書く、命令
データパスコントローラから見た、1台のスイッチdp
os-kenOpenFlow のコントローラを書く Python のライブラリ

学生が入力するセルは、このプレビューでは空白です。

スイッチの知らせごとに関数がある

os-ken では、スイッチからの知らせをイベントと呼びます。イベントごとに、@set_ev_cls の印を付けた関数を1つ書きます。

代表は2つです。スイッチがつながったとき、最初の設定をします。フローのない枠が届いたとき、packet-in で受け取って決めます。

2つのイベントと、そこでする仕事

イベントいつ起きるかよくある仕事
スイッチがつながった接続のとき、1回最初のフローを入れる
packet-inフローのない枠が届くたび行き先を決め、フローを入れる

学生が入力するセルは、このプレビューでは空白です。

ラボのコントローラの形を見る

ラボには、手を付けていないコントローラの写しが、/usr/share/sdnlab/switch.py にあります。まず、@set_ev_cls が付いた行と、関数の名前を並べます。

続いて、packet-in を受ける関数の最初の9行を見ます。ここでは読むだけで、書き換えません。

イベントの印を探す

コマンド
grep -n "set_ev_cls" /usr/share/sdnlab/switch.py

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

関数の名前を並べる

コマンド
grep -n "def " /usr/share/sdnlab/switch.py

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

packet-in の最初の9行

コマンド
sed -n 33,41p /usr/share/sdnlab/switch.py

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

出力から分かること

set_ev_cls の行は3つで、最初はインポート、残る2つが、つながったときと packet-in のイベントです。関数は4つあり、add_flow はフローを入れる道具で、あとの2つがハンドラです。

packet-in の関数は、入口のポートを msg.match から取り、枠を解いて送り主と宛先を取り出し、スイッチごとの表を開きます。

コントローラは flow-mod でフローを書く

コントローラがスイッチにフローを入れる命令を、flow-mod と呼びます。ovs-ofctl add-flow の1行と、同じ内容です。

次の例は、スイッチがつながったとき、3番のポートから入る枠をすべて捨てるフローを1つ入れます。命令を1つも付けないフローは、枠を捨てます。

フローを1つ入れる、小さなコントローラ

コード: python
from os_ken.base import app_manager
from os_ken.controller import ofp_event
from os_ken.controller.handler import CONFIG_DISPATCHER, set_ev_cls
from os_ken.ofproto import ofproto_v1_3


class GuestBlocker(app_manager.OSKenApp):
    OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]

    @set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
    def switch_connected(self, ev):
        dp = ev.msg.datapath
        parser = dp.ofproto_parser
        match = parser.OFPMatch(in_port=3)
        # 命令を1つも付けないフローは、パケットを捨てます。
        dp.send_msg(parser.OFPFlowMod(datapath=dp, priority=200, match=match, instructions=[]))

flow-mod の引数と ovs-ofctl の行

コードの引数ovs-ofctl での書き方意味
priority=200priority=200優先度
match=OFPMatch(in_port=3)in_port=33番ポートから入る枠
instructions=[]actions=drop何もしない、つまり捨てる

学生が入力するセルは、このプレビューでは空白です。

例を動かすと、1行のフローが入る

この例をラボで動かして確かめました。接続したスイッチの表に、priority=200,in_port=3 actions=drop の1行だけが入りました。

そのあと ofproto/trace で3番ポートの枠を調べると、優先度200のフローに当たり、捨てられました。コードは例で、ラボの課題のコードではありません。

予約ポートは大きな番号

アクションの出口には、普通のポート番号のほかに、特別な予約ポートがあります。全ポートに流す FLOOD や、コントローラに送る CONTROLLER です。

予約ポートの番号は、とても大きな数です。普通のポート番号と、ぶつからないようにしてあります。

予約ポートの番号を出す

コマンド
python3 -c "from os_ken.ofproto import ofproto_v1_3 as o; print(o.OFPP_CONTROLLER, o.OFPP_FLOOD, o.OFPP_NORMAL)"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

よくある間違い

注意

packet-in のハンドラは、パケットごとに毎回呼ばれる、と思いがちです。実際は、フローのない枠だけです。コントローラがフローを入れたあとの枠は、スイッチだけで運ばれ、ハンドラには来ません。

このラボとソースについて: SDN のラボ:Open vSwitch、Mininet、OpenFlow コントローラーを1台の VM で

授業で使いますか?このモジュールを学生に割り当てると、教員用ガイド、自動採点つきの課題、学生ごとのラボを使えます。