Trema/FlowStatsおためし

ちょっと思うところあって、Controller から各スイッチのフロー情報を取得してみる、という処理のテストをしてみた。

コード

class FlowDumper < Controller
  oneshot_timer_event :send_message_to_all_switches, 5

  def start
    @switches = []
  end

  def switch_ready dpid
    puts "[FlowDumper::switch_ready] DPID: #{dpid}"
    @switches << dpid
    send_output_flow_mod dpid, 1, 2
    send_output_flow_mod dpid, 2, 1
  end

  def stats_reply dpid, message
    puts "[FlowDumper::stats_reply]"

    puts "stats of dpid:#{dpid}"
    puts "* transaction id: #{message.transaction_id}"
    puts "* flags: #{message.type}"
    puts "* type: #{message.type}"

    if message.type == Trema::StatsReply::OFPST_FLOW
      message.stats.each do |each|
        puts "* stats:"
        puts "  * length: #{each.length}"
        puts "  * table_id: #{each.table_id}"
        puts "  * match: #{each.match.to_s}"
        puts "  * duration_sec: #{each.duration_sec}"
        puts "  * duration_nsec: #{each.duration_nsec}"
        puts "  * priority: #{each.priority}"
        puts "  * idle_timeout: #{each.idle_timeout}"
        puts "  * hard_timeout: #{each.hard_timeout}"
        puts "  * cookie: #{each.cookie.to_hex}"
        puts "  * packet_count: #{each.packet_count}"
        puts "  * byte_count: #{each.byte_count}"
        puts "  * actions:"
        each.actions.each do |action|
          puts "    * #{action.to_s}:"
        end
      end
    end
  end

  private

  def send_output_flow_mod dpid, in_port, out_port
    send_flow_mod_add(
      dpid,
      :idle_timeout => 0,
      :match => Match.new(:in_port => in_port),
      :actions => SendOutPort.new(out_port)
    )
  end

  def send_message_to_all_switches
    puts "[FlowDumper::send_message_to_all_switches]"
    @switches.each do |each|
      puts "send FlowStatsRequest to dpid:#{each}"
      send_message(
        each,
        FlowStatsRequest.new(
          :match => Match.new()
        )
      )
    end
  end

end

テスト

  • トポロジ
    • 上のコードはこのトポロジにあわせてフローをハードコードしちゃってます。
vswitch("sw1") { dpid "0x1" }
vswitch("sw2") { dpid "0x2" }

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

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

link "sw1", "sw2"
link "host1", "sw1"
link "host2", "sw2"
  • コントローラ側の出力
stereocat@oftest04:~/training/ruby_flow_dumper$ sudo trema run flow_dumper.rb -c flow_dumper.conf
[FlowDumper::switch_ready] DPID: 1
[FlowDumper::switch_ready] DPID: 2
[FlowDumper::send_message_to_all_switches]
send FlowStatsRequest to dpid:1
send FlowStatsRequest to dpid:2
[FlowDumper::stats_reply]
stats of dpid:1
* transaction id: 618135557
* flags: 1
* type: 1
* stats:
  * length: 96
  * table_id: 0
  * match: wildcards = 0x3820fe(dl_src|dl_dst|dl_type|dl_vlan|dl_vlan_pcp|nw_proto|nw_tos|nw_src(32)|nw_dst(32)|tp_src|tp_dst), in_port = 1, dl_src = 00:00:00:00:00:00, dl_dst = 00:00:00:00:00:00, dl_vlan = 0, dl_vlan_pcp = 0, dl_type = 0, nw_tos = 0, nw_proto = 0, nw_src = 0.0.0.0/0, nw_dst = 0.0.0.0/0, tp_src = 0, tp_dst = 0
  * duration_sec: 4
  * duration_nsec: 54000000
  * priority: 65535
  * idle_timeout: 0
  * hard_timeout: 0
  * cookie: 0x24d8000000000001
  * packet_count: 0
  * byte_count: 0
  * actions:
    * Trema::SendOutPort: port_number=2, max_len=65535:
* stats:
  * length: 96
  * table_id: 0
  * match: wildcards = 0x3820fe(dl_src|dl_dst|dl_type|dl_vlan|dl_vlan_pcp|nw_proto|nw_tos|nw_src(32)|nw_dst(32)|tp_src|tp_dst), in_port = 2, dl_src = 00:00:00:00:00:00, dl_dst = 00:00:00:00:00:00, dl_vlan = 0, dl_vlan_pcp = 0, dl_type = 0, nw_tos = 0, nw_proto = 0, nw_src = 0.0.0.0/0, nw_dst = 0.0.0.0/0, tp_src = 0, tp_dst = 0
  * duration_sec: 4
  * duration_nsec: 54000000
  * priority: 65535
  * idle_timeout: 0
  * hard_timeout: 0
  * cookie: 0x24d8000000000002
  * packet_count: 0
  * byte_count: 0
  * actions:
    * Trema::SendOutPort: port_number=1, max_len=65535:
[FlowDumper::stats_reply]
stats of dpid:2
* transaction id: 618135558
* flags: 1
* type: 1
* stats:
  * length: 96
  * table_id: 0
  * match: wildcards = 0x3820fe(dl_src|dl_dst|dl_type|dl_vlan|dl_vlan_pcp|nw_proto|nw_tos|nw_src(32)|nw_dst(32)|tp_src|tp_dst), in_port = 1, dl_src = 00:00:00:00:00:00, dl_dst = 00:00:00:00:00:00, dl_vlan = 0, dl_vlan_pcp = 0, dl_type = 0, nw_tos = 0, nw_proto = 0, nw_src = 0.0.0.0/0, nw_dst = 0.0.0.0/0, tp_src = 0, tp_dst = 0
  * duration_sec: 4
  * duration_nsec: 22000000
  * priority: 65535
  * idle_timeout: 0
  * hard_timeout: 0
  * cookie: 0x24d8000000000003
  * packet_count: 0
  * byte_count: 0
  * actions:
    * Trema::SendOutPort: port_number=2, max_len=65535:
* stats:
  * length: 96
  * table_id: 0
  * match: wildcards = 0x3820fe(dl_src|dl_dst|dl_type|dl_vlan|dl_vlan_pcp|nw_proto|nw_tos|nw_src(32)|nw_dst(32)|tp_src|tp_dst), in_port = 2, dl_src = 00:00:00:00:00:00, dl_dst = 00:00:00:00:00:00, dl_vlan = 0, dl_vlan_pcp = 0, dl_type = 0, nw_tos = 0, nw_proto = 0, nw_src = 0.0.0.0/0, nw_dst = 0.0.0.0/0, tp_src = 0, tp_dst = 0
  * duration_sec: 4
  * duration_nsec: 22000000
  * priority: 65535
  * idle_timeout: 0
  * hard_timeout: 0
  * cookie: 0x24d8000000000004
  * packet_count: 0
  * byte_count: 0
  * actions:
    * Trema::SendOutPort: port_number=1, max_len=65535:
  • trema dumpflows によるフロー情報の取得
stereocat@oftest04:~/training/ruby_flow_dumper$ sudo trema dump_flows sw1
NXST_FLOW reply (xid=0x4):
 cookie=0x1, duration=73.234s, table=0, n_packets=0, n_bytes=0, priority=65535,in_port=1 actions=output:2
 cookie=0x2, duration=73.234s, table=0, n_packets=0, n_bytes=0, priority=65535,in_port=2 actions=output:1
stereocat@oftest04:~/training/ruby_flow_dumper$ sudo trema dump_flows sw2
NXST_FLOW reply (xid=0x4):
 cookie=0x1, duration=76.842s, table=0, n_packets=0, n_bytes=0, priority=65535,in_port=1 actions=output:2
 cookie=0x2, duration=76.842s, table=0, n_packets=0, n_bytes=0, priority=65535,in_port=2 actions=output:1
stereocat@oftest04:~/training/ruby_flow_dumper$ 

テスト結果について

とりあえずこんな感じでフロー情報がとれるな、というのを確認してみました。それはそれとしていいんだけど、cookie の値が trema コマンドで出すのとコントローラから flow stats request して出すのとで違うな…。raw のと switch daemon 経由で cookie 変換した物とになってるのか?