« ◆【改訂】OpenFlow フレームワーク Trema 0.4 のインストール手順【0.4.7対応】 | トップページ | ◆ ポートベースVLANの作成【OpenFlow1.0をTremaの土管として使う】 »

2014年6月29日 (日)

◆ 単純なブリッジの実装その3~より完璧な土管化~【OpenFlow1.0をTremaの土管として使う】

[2014/07/27 追記。イーサネットの最少パケットサイズを確保する修正をした記事を書きました。「◆ 単純なブリッジの実装その4~Open vSwitch対策~【OpenFlow1.0をTremaの土管として使う】」]

[注意: 本記事は、OpenFlow の適切な使い方ではありません。単にパケットの出し入れの道具として利用しています。]

以前書いた記事「◆ 単純なブリッジの実装その2~複数ポート対応~【OpenFlow1.0をTremaの土管として使う】」のコードを、パケットのデータを加工して流すことにも対応できるように修正してみます。

先の記事のコードでは、パケットを送付する際、Trema の send_packet_out に引数 :packet_in を使って受信メッセージをそのまま送信データとして渡しています。仕様を確認してみましょう。
http://rubydoc.info/github/trema/trema/master/Trema/Controller:send_packet_out

packet_in (PacketIn) — default: nil
— The PacketIn object received by packet_in handler. If this option is not nil, :buffer_id,
:data, and :in_port option is set automatically
according to the value of :packet_in.

:packet_in を使うと自動で :buffer_id, :in_port, :data を設定します。

OpenFlow では、コントローラからはパケットのデータそのものを渡すのではなくスイッチ側で管理している識別子 buffer_id を渡すという仕掛けがあります。コントローラでデータを加工して送付したい場合にはこの機能は不要です。
openflow 1.0.0 仕様書の "25.3.6 Send Packet Message" には以下の説明があります:
http://archive.openflow.org/documents/openflow-spec-v1.0.0.pdf

/* uint8_t data[0]; */ /* Packet data. The length is inferred
                          from the length field in the header.
                          (Only meaningful if buffer_id == -1.) */

このカッコ書きのところがポイントです。データに変更を加えたパケットを送付するには buffer_id を指定してはいけないということです。

Trema の send_packet_out の引数 :buffer_id を確認してみると:

:buffer_id (Number) — default: 0xffffffff
— The buffer ID assigned by the datapath.
If 0xffffffff, the frame is not buffered, and
the entire frame must be passed in :data.

:buffer_id はデフォルトのままで引数 :data に指定したデータを送付します。

以上から、:packet_in を使うのではなく、:data, :in_port を指定すれば良いということがわかります。

■対策後のコード
赤字のところが変更箇所です。

class SimpleBridge3 < Controller

  def start
    @port_list = [ 1, 2, 3 ]    # all port numbers
  end

  def switch_ready( datapath_id )
    info "Switch[0x%016x] is up." % datapath_id

    send_flow_mod_add( datapath_id, :priority => 100 )

    @port_list.each do | port |
      send_flow_mod_add( datapath_id,
        :match => Match.new( :in_port => port ),
        :actions => SendOutPort.new( OFPP_CONTROLLER ) )
    end
  end

  def switch_disconnected( datapath_id )
    info "Switch[0x%016x] is disconnected." % datapath_id
  end

  def packet_in( datapath_id, message )
    return unless message.reason == Trema::PacketIn::OFPR_ACTION

    actions = [ ]
    @port_list.each do | port |
      if ( message.in_port != port )
        actions.push( SendOutPort.new( port ) )
      end
    end

    send_packet_out( datapath_id,
      :in_port => message.in_port,
      :data => message.data,

      :actions => actions )
  end

end

« ◆【改訂】OpenFlow フレームワーク Trema 0.4 のインストール手順【0.4.7対応】 | トップページ | ◆ ポートベースVLANの作成【OpenFlow1.0をTremaの土管として使う】 »

Tremaでネットワーク機器プログラミング」カテゴリの記事

コメント

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

« ◆【改訂】OpenFlow フレームワーク Trema 0.4 のインストール手順【0.4.7対応】 | トップページ | ◆ ポートベースVLANの作成【OpenFlow1.0をTremaの土管として使う】 »

最近のトラックバック

無料ブログはココログ