Trema SwitchMonitor, LearningSwitch

openflow実践入門

クラウド時代のネットワーク技術 OpenFlow実践入門 (Software Design plus)

クラウド時代のネットワーク技術 OpenFlow実践入門 (Software Design plus)

でいくつかコードを書いてみました。

環境構築は以前行ったのでこの環境で行いました。

SwitchMonitor

これは、スイッチの起動と停止を検知するためのコントローラです。 検知すると、該当スイッチの状態の出力を行います。

コントローラのコードは以下の通りです。

# switch-monitor.rb
class SwitchMonitor < Controller
    periodic_timer_event :show_switches, 10

    def start
        @switches = []
    end

    def switch_ready(datapath_id)
        @switches << datapath_id.to_hex
        info "Switch #{ datapath_id.to_hex } is UP"
    end

    def switch_disconnected(datapath_id)
        @switches -= [datapath_id.to_hex]
        info "Switch #{datapath_id.to_hex} is DOWN"
    end

    private

    def show_switches
        info "All switches = " + @switches.sort.join(",")
    end
end

スイッチが起動するとswitch_readyハンドラが呼ばれて、停止するとswitch_disconnectedハンドラが呼び出されるそうです。

また、仮想ネットワークを作るためのコードも必要なので、書いておきます。

# switch-monitor.conf
vswitch{datapath_id 0x1}
vswitch{datapath_id 0x2}
vswitch{datapath_id 0x3}

実行

trema run switch-monitor.rb -c switch-monitor.conf で実行すると以下の通りになりました。

f:id:carumisu:20150910194344j:plain

LearningSwitch

# learning-switch.rb
class LearningSwitch < Controller
    def start
        @fdb = {}
    end

    def packet_in(datapath_id, message)
        @fdb[ message.macsa ] = message.in_port
        port_no = @fdb[message.macsa]
        if port_no
            flow_mod datapath_id, message, port_no
            packet_out datapath_id, message, port_no
        else
            flood datapath_id, message
        end
    end

    private

    def flow_mod(datapath_id, message, port_no)
        send_flow_mod_add(
            datapath_id,
            :match => ExactMatch.from(message),
            :actions => SendOutPort.new(port_no)
            )
    end

    def packet_out(datapath_id, message, port_no)
        send_flow_mod_add(
            datapath_id,
            :packet_in => message,
            :actions => SendOutPort.new(port_no)
            )
    end

    def flood(datapath_id, message)
        packet_out datapath_id, message, OFPP_FLOOD
    end
end

パケットが入ってくるとpacket_inハンドラが呼び出されるそうです。 入ってきたパケットを見て、知ってるMACアドレスかの確認をしてif文分岐してますね。 知ってるアドレスならpacket_out関数で転送して、知らないアドレスならflood関数でブロードキャストするという基本的なラーニングスイッチの動きですね。

次に仮想ネットワークを作るためのファイルです。

# learning-switch.conf
vswitch("lsw"){
    datapath_id "0xabc"
}

vhost("host1"){
    ip "192.168.0.1"
    netmask "255.255.0.0"
    mac "00:00:00:01:00:01"
}

vhost("host2"){
    ip "192.168.0.2"
    netmask "255.255.0.0"
    mac "00:00:00:01:00:02"
}

link "lsw", "host1"
link "lsw", "host2"

実行

trema run learning-switch.rb -c learning-switch.conf とすると何も表示されませんが動いています。

別の端末で、お互いにパケットを送りあいます。

trema send_packets --source host1 --dest host2
trema send_packets --source host2 --dest host1

そして、

trema show_stats host1 --rx

とすると f:id:carumisu:20150910201245j:plain host1に関する情報が確認できました。