trema 0.4.5 → 0.4.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +4 -4
  3. data/Guardfile +8 -0
  4. data/Rakefile +2 -1
  5. data/bin/trema +4 -0
  6. data/cruise.rb +1 -1
  7. data/features/core/switch_manager.feature +2 -2
  8. data/features/examples/message.vendor-action.feature +2 -2
  9. data/features/examples/message.vendor-stats-request.feature +20 -0
  10. data/features/trema_commands/kill.feature +4 -0
  11. data/features/trema_commands/killall.feature +1 -0
  12. data/features/trema_commands/run.feature +20 -1
  13. data/ruby/trema/command/run.rb +4 -0
  14. data/ruby/trema/default_openflow_channel_port.rb +26 -0
  15. data/ruby/trema/dsl/configuration.rb +2 -1
  16. data/ruby/trema/open-vswitch.rb +2 -4
  17. data/ruby/trema/stats-reply.c +10 -1
  18. data/ruby/trema/stats-request.c +34 -1
  19. data/ruby/trema/vendor-stats-reply.rb +6 -2
  20. data/ruby/trema/version.rb +1 -1
  21. data/spec/trema/dsl/runner_spec.rb +1 -1
  22. data/spec/trema/dsl/syntax_spec.rb +1 -1
  23. data/spec/trema/shell/vswitch_spec.rb +1 -1
  24. data/spec/trema/stats-reply_spec.rb +2 -1
  25. data/spec/trema/stats-request_spec.rb +11 -0
  26. data/src/examples/cbench_switch/cbench-switch.rb +1 -0
  27. data/src/examples/cbench_switch/cbench_switch.c +1 -1
  28. data/src/examples/openflow_message/vendor-action.rb +4 -4
  29. data/src/examples/openflow_message/vendor-stats-request.rb +66 -0
  30. data/src/examples/simple_router/arp-table.rb +6 -17
  31. data/src/examples/simple_router/interface.rb +20 -29
  32. data/src/examples/simple_router/routing-table.rb +15 -22
  33. data/src/examples/simple_router/simple-router.rb +75 -64
  34. data/src/lib/chibach.c +3 -2
  35. data/src/lib/event_handler.c +55 -23
  36. data/src/lib/event_handler.h +0 -5
  37. data/src/lib/external_callback.c +126 -0
  38. data/src/lib/external_callback.h +46 -0
  39. data/src/lib/messenger.c +58 -35
  40. data/src/lib/openflow_message.c +32 -11
  41. data/src/lib/trema.c +13 -7
  42. data/src/lib/trema.h +1 -0
  43. data/src/lib/utility.c +13 -2
  44. data/src/switch_manager/secure_channel_receiver.c +6 -1
  45. data/src/switch_manager/switch.c +27 -26
  46. data/src/switch_manager/switch_manager.c +31 -10
  47. data/src/tremashark/packet_capture.c +3 -2
  48. data/src/tremashark/tremashark.c +2 -2
  49. data/trema.gemspec +1 -1
  50. data/unittests/lib/external_callback_test.c +282 -0
  51. data/unittests/lib/messenger_test.c +22 -0
  52. data/unittests/lib/openflow_message_test.c +1 -1
  53. data/unittests/lib/trema_test.c +1 -1
  54. data/unittests/switch_manager/switch_manager_test.c +3 -3
  55. metadata +12 -6
  56. data/src/examples/simple_router/router-utils.rb +0 -211
@@ -17,7 +17,7 @@
17
17
 
18
18
 
19
19
  module Trema
20
- VERSION = "0.4.5"
20
+ VERSION = "0.4.6"
21
21
  end
22
22
 
23
23
 
@@ -38,7 +38,7 @@ module Trema
38
38
 
39
39
  context = mock(
40
40
  "context",
41
- :port => 6633,
41
+ :port => 6653,
42
42
  :tremashark => nil,
43
43
  :switch_manager => nil,
44
44
  :packetin_filter => nil,
@@ -23,7 +23,7 @@ require "trema/packetin-filter"
23
23
 
24
24
  describe Trema::DSL::Syntax do
25
25
  before( :each ) do
26
- @context = mock( "context", :port => 6633, :dump_to => nil )
26
+ @context = mock( "context", :port => 6653, :dump_to => nil )
27
27
  @syntax = Trema::DSL::Syntax.new( @context )
28
28
  end
29
29
 
@@ -41,7 +41,7 @@ describe Trema::Shell, ".vswitch" do
41
41
 
42
42
  context "executed within a shell" do
43
43
  before {
44
- $config = mock( "config", :port => 6633 )
44
+ $config = mock( "config", :port => 6653 )
45
45
  $context = mock( "context", :dump => true )
46
46
  }
47
47
  after { Trema::OpenflowSwitch[ "0xabc" ].shutdown! if Trema::OpenflowSwitch[ "0xabc" ] }
@@ -142,7 +142,7 @@ describe StatsReply, ".new( VALID OPTIONS )" do
142
142
  its( :tx_packets ) { should == 10 }
143
143
  its( :rx_bytes ) { should == 1454 }
144
144
  its( :tx_bytes ) { should == 2314 }
145
- its ( :rx_dropped ) { should == 1 }
145
+ its( :rx_dropped ) { should == 1 }
146
146
  its( :tx_dropped ) { should == 1 }
147
147
  its( :rx_errors ) { should == 1 }
148
148
  its( :tx_errors ) { should == 1 }
@@ -178,6 +178,7 @@ describe StatsReply, ".new( VALID OPTIONS )" do
178
178
 
179
179
  it { should respond_to( :to_s ) }
180
180
  its( :vendor_id ) { should == 123 }
181
+ its( :data ) { should be_nil }
181
182
  end
182
183
 
183
184
 
@@ -137,6 +137,7 @@ describe StatsRequest do
137
137
  subject { VendorStatsRequest.new }
138
138
  it_should_behave_like "any stats-request"
139
139
  its( :vendor_id ) { should == 0x00004cff }
140
+ its( :data ) { should be_nil }
140
141
  end
141
142
 
142
143
 
@@ -144,6 +145,16 @@ describe StatsRequest do
144
145
  subject { VendorStatsRequest.new :vendor_id => 123 }
145
146
  it_should_behave_like "any stats-request"
146
147
  its( :vendor_id ) { should == 123 }
148
+ its( :data ) { should be_nil }
149
+ end
150
+
151
+
152
+ context "when .VendorStatsRequest.new(:data => value)" do
153
+ subject { VendorStatsRequest.new :data => data }
154
+ it_should_behave_like "any stats-request"
155
+ let( :data ) { "VENDOR DATA".unpack( "C*" ) }
156
+ its( :data ) { should == [86, 69, 78, 68, 79, 82, 32, 68, 65, 84, 65] }
157
+ its( :vendor_id ) { should == 0x00004cff }
147
158
  end
148
159
  end
149
160
 
@@ -22,6 +22,7 @@ class CbenchSwitch < Controller
22
22
  def packet_in datapath_id, message
23
23
  send_flow_mod_add(
24
24
  datapath_id,
25
+ :cookie => 0,
25
26
  :match => ExactMatch.from( message ),
26
27
  :buffer_id => message.buffer_id,
27
28
  :actions => ActionOutput.new( :port => message.in_port + 1 )
@@ -32,7 +32,7 @@ handle_packet_in( uint64_t datapath_id, packet_in message ) {
32
32
  buffer *flow_mod = create_flow_mod(
33
33
  get_transaction_id(),
34
34
  match,
35
- get_cookie(),
35
+ 0,
36
36
  OFPFC_ADD,
37
37
  0,
38
38
  0,
@@ -19,12 +19,12 @@
19
19
 
20
20
 
21
21
  class VendorActionSampleController < Controller
22
- NX_VENDOR_ID = 0x00002320
23
- NXAST_NOTE = 8
22
+ OVS_VENDOR_ID = 0x00002320
23
+ OVSAST_NOTE = 8
24
24
 
25
25
  def switch_ready datapath_id
26
- body = [ NXAST_NOTE, 0x54, 0x72, 0x65, 0x6d, 0x61, 0x00 ].pack( "nC6" )
27
- actions = VendorAction.new( NX_VENDOR_ID, body.unpack( "C*" ) )
26
+ body = [ OVSAST_NOTE, 0x54, 0x72, 0x65, 0x6d, 0x61, 0x00 ].pack( "nC6" )
27
+ actions = VendorAction.new( OVS_VENDOR_ID, body.unpack( "C*" ) )
28
28
  send_flow_mod_modify(
29
29
  datapath_id,
30
30
  :hard_timeout => 60,
@@ -0,0 +1,66 @@
1
+ #
2
+ # "Vendor Stats Request" sample application
3
+ #
4
+ # Copyright (C) 2013 NEC Corporation
5
+ #
6
+ # This program is free software; you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License, version 2, as
8
+ # published by the Free Software Foundation.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License along
16
+ # with this program; if not, write to the Free Software Foundation, Inc.,
17
+ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18
+ #
19
+
20
+
21
+ class VendorStatsRequestSample < Controller
22
+ OVS_VENDOR_ID = 0x00002320
23
+ OVSST_FLOW = 0
24
+
25
+ def switch_ready datapath_id
26
+ send_vendor_stats_request datapath_id
27
+ end
28
+
29
+
30
+ def stats_reply datapath_id, message
31
+ if message.type == StatsReply::OFPST_VENDOR
32
+ vendor_stats_reply datapath_id, message
33
+ end
34
+ end
35
+
36
+
37
+ private
38
+
39
+
40
+ def vendor_stats_reply datapath_id, message
41
+ info "[vendor_stats_reply]"
42
+ info "vendor_id: 0x%08x" % message.stats.first.vendor_id
43
+ info "data: [#{ message.stats.first.data.map { | n | "0x%02x" % n }.join ", " }]"
44
+ end
45
+
46
+
47
+ def send_vendor_stats_request datapath_id
48
+ data = [
49
+ OVSST_FLOW,
50
+ 0x0, 0x0, 0x0, 0x0,
51
+ OFPP_NONE,
52
+ 0x0,
53
+ 0xff,
54
+ 0x0, 0x0, 0x0
55
+ ].pack( "NC4 nnCC3" )
56
+ vendor_request = VendorStatsRequest.new( :vendor_id => OVS_VENDOR_ID, :data => data.unpack( "C*" ) )
57
+ send_message( datapath_id, vendor_request )
58
+ end
59
+ end
60
+
61
+
62
+ ### Local variables:
63
+ ### mode: Ruby
64
+ ### coding: utf-8-unix
65
+ ### indent-tabs-mode: nil
66
+ ### End:
@@ -17,16 +17,13 @@
17
17
  # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18
18
  #
19
19
 
20
-
21
20
  class ARPEntry
22
21
  include Trema::DefaultLogger
23
22
 
24
-
25
23
  attr_reader :port
26
24
  attr_reader :hwaddr
27
25
  attr_writer :age_max
28
26
 
29
-
30
27
  def initialize port, hwaddr, age_max
31
28
  @port = port
32
29
  @hwaddr = hwaddr
@@ -35,7 +32,6 @@ class ARPEntry
35
32
  info "New entry: MAC addr = #{ @hwaddr.to_s }, port = #{ @port }"
36
33
  end
37
34
 
38
-
39
35
  def update port, hwaddr
40
36
  @port = port
41
37
  @hwaddr = hwaddr
@@ -43,7 +39,6 @@ class ARPEntry
43
39
  info "Update entry: MAC addr = #{ @hwaddr.to_s }, port = #{ @port }"
44
40
  end
45
41
 
46
-
47
42
  def aged_out?
48
43
  aged_out = Time.now - @last_updated > @age_max
49
44
  info "Age out: An ARP entry (MAC address = #{ @hwaddr.to_s }, port number = #{ @port }) has been aged-out" if aged_out
@@ -51,40 +46,34 @@ class ARPEntry
51
46
  end
52
47
  end
53
48
 
54
-
55
49
  class ARPTable
56
50
  DEFAULT_AGE_MAX = 300
57
51
 
58
-
59
52
  def initialize
60
53
  @db = {}
61
54
  end
62
55
 
63
-
64
56
  def update port, ipaddr, hwaddr
65
- entry = @db[ ipaddr.to_i ]
57
+ entry = @db[ipaddr.to_i]
66
58
  if entry
67
- entry.update( port, hwaddr )
59
+ entry.update(port, hwaddr)
68
60
  else
69
- new_entry = ARPEntry.new( port, hwaddr, DEFAULT_AGE_MAX )
70
- @db[ ipaddr.to_i ] = new_entry
61
+ new_entry = ARPEntry.new(port, hwaddr, DEFAULT_AGE_MAX)
62
+ @db[ipaddr.to_i] = new_entry
71
63
  end
72
64
  end
73
65
 
74
-
75
66
  def lookup ipaddr
76
- @db[ ipaddr.to_i ]
67
+ @db[ipaddr.to_i]
77
68
  end
78
69
 
79
-
80
70
  def age
81
- @db.delete_if do | ipaddr, entry |
71
+ @db.delete_if do |ipaddr, entry|
82
72
  entry.aged_out?
83
73
  end
84
74
  end
85
75
  end
86
76
 
87
-
88
77
  ### Local variables:
89
78
  ### mode: Ruby
90
79
  ### coding: utf-8-unix
@@ -17,10 +17,10 @@
17
17
  # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18
18
  #
19
19
 
20
+ require 'arp-table'
21
+ require 'routing-table'
20
22
 
21
- require "arp-table"
22
- require "routing-table"
23
-
23
+ require 'pio'
24
24
 
25
25
  class Interface
26
26
  attr_reader :hwaddr
@@ -28,70 +28,61 @@ class Interface
28
28
  attr_reader :masklen
29
29
  attr_reader :port
30
30
 
31
-
32
31
  def initialize options
33
- @port = options[ :port ]
34
- @hwaddr = Mac.new( options[ :hwaddr ] )
35
- @ipaddr = IPAddr.new( options[ :ipaddr ] )
36
- @masklen = options[ :masklen ]
32
+ @port = options[:port]
33
+ @hwaddr = Pio::Mac.new(options[:hwaddr])
34
+ @ipaddr = Pio::IPv4Address.new(options[:ipaddr])
35
+ @masklen = options[:masklen]
37
36
  end
38
37
 
39
-
40
38
  def has? mac
41
39
  mac == hwaddr
42
40
  end
43
41
  end
44
42
 
45
-
46
43
  class Interfaces
47
44
  def initialize interfaces = []
48
45
  @list = []
49
- interfaces.each do | each |
50
- @list << Interface.new( each )
46
+ interfaces.each do |each|
47
+ @list << Interface.new(each)
51
48
  end
52
49
  end
53
50
 
54
-
55
51
  def find_by_port port
56
- @list.find do | each |
52
+ @list.find do |each|
57
53
  each.port == port
58
54
  end
59
55
  end
60
56
 
61
-
62
57
  def find_by_ipaddr ipaddr
63
- @list.find do | each |
64
- each.ipaddr == ipaddr
58
+ @list.find do |each|
59
+ each.ipaddr.to_i == ipaddr.to_i
65
60
  end
66
61
  end
67
62
 
68
-
69
63
  def find_by_prefix ipaddr
70
- @list.find do | each |
64
+ @list.find do |each|
71
65
  masklen = each.masklen
72
- each.ipaddr.mask( masklen ) == ipaddr.mask( masklen )
66
+ each.ipaddr.mask(masklen).to_s == ipaddr.mask(masklen).to_s
73
67
  end
74
68
  end
75
69
 
76
-
77
70
  def find_by_port_and_ipaddr port, ipaddr
78
- @list.find do | each |
79
- each.port == port and each.ipaddr == ipaddr
71
+ @list.find do |each|
72
+ each.port == port and each.ipaddr.to_i == ipaddr.to_i
80
73
  end
81
74
  end
82
75
 
83
-
84
76
  def ours? port, macda
85
- return true if macda.broadcast?
77
+ true if macda.broadcast?
86
78
 
87
- interface = find_by_port( port )
88
- if not interface.nil? and interface.has?( macda )
89
- return true
79
+ interface = find_by_port(port)
80
+ if not interface.nil? and interface.has?(macda)
81
+ true
90
82
  end
91
83
  end
92
84
  end
93
85
 
94
-
95
86
  ### Local variables:
96
87
  ### mode: Ruby
97
88
  ### coding: utf-8
@@ -17,49 +17,42 @@
17
17
  # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18
18
  #
19
19
 
20
-
21
- require "ipaddr"
22
-
20
+ require 'pio'
23
21
 
24
22
  class RoutingTable
25
23
  ADDR_LEN = 32
26
24
 
27
-
28
25
  def initialize route = []
29
- @db = Array.new( ADDR_LEN + 1 ) { Hash.new }
30
- route.each do | each |
31
- add( each )
26
+ @db = Array.new(ADDR_LEN + 1) { Hash.new }
27
+ route.each do |each|
28
+ add(each)
32
29
  end
33
30
  end
34
31
 
35
-
36
32
  def add options
37
- dest = IPAddr.new( options[ :destination ] )
38
- masklen = options[ :masklen ]
39
- prefix = dest.mask( masklen )
40
- @db[ masklen ][ prefix.to_i ] = IPAddr.new( options[ :nexthop ] )
33
+ dest = Pio::IPv4Address.new(options[:destination])
34
+ masklen = options[:masklen]
35
+ prefix = dest.mask(masklen)
36
+ @db[masklen][prefix.to_i] = Pio::IPv4Address.new(options[:nexthop])
41
37
  end
42
38
 
43
-
44
39
  def delete options
45
- dest = IPAddr.new( options[ :destination ] )
46
- masklen = options[ :masklen ]
47
- prefix = dest.mask( masklen )
48
- @db[ masklen ].delete( prefix.to_i )
40
+ dest = Pio::IPv4Address.new(options[:destination])
41
+ masklen = options[:masklen]
42
+ prefix = dest.mask(masklen)
43
+ @db[masklen].delete(prefix.to_i)
49
44
  end
50
45
 
51
-
52
46
  def lookup dest
53
- ( 0..ADDR_LEN ).reverse_each do | masklen |
54
- prefix = dest.mask( masklen )
55
- entry = @db[ masklen ][ prefix.to_i ]
47
+ (0..ADDR_LEN).reverse_each do |masklen|
48
+ prefix = dest.mask(masklen)
49
+ entry = @db[masklen][prefix.to_i]
56
50
  return entry if entry
57
51
  end
58
52
  nil
59
53
  end
60
54
  end
61
55
 
62
-
63
56
  ### Local variables:
64
57
  ### mode: Ruby
65
58
  ### coding: utf-8-unix
@@ -17,26 +17,21 @@
17
17
  # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18
18
  #
19
19
 
20
- require "arp-table"
21
- require "interface"
22
- require "router-utils"
23
- require "routing-table"
24
-
20
+ require 'arp-table'
21
+ require 'interface'
22
+ require 'routing-table'
25
23
 
26
24
  class SimpleRouter < Controller
27
- include RouterUtils
28
-
29
25
 
30
26
  def start
31
- load "simple_router.conf"
32
- @interfaces = Interfaces.new( $interface )
27
+ load 'simple_router.conf'
28
+ @interfaces = Interfaces.new($interface)
33
29
  @arp_table = ARPTable.new
34
- @routing_table = RoutingTable.new( $route )
30
+ @routing_table = RoutingTable.new($route)
35
31
  end
36
32
 
37
-
38
- def packet_in( dpid, message )
39
- return if not to_me?( message )
33
+ def packet_in(dpid, message)
34
+ return if not to_me?(message)
40
35
 
41
36
  if message.arp_request?
42
37
  handle_arp_request dpid, message
@@ -49,38 +44,33 @@ class SimpleRouter < Controller
49
44
  end
50
45
  end
51
46
 
52
-
53
47
  private
54
48
 
55
-
56
- def to_me?( message )
49
+ def to_me?(message)
57
50
  return true if message.macda.broadcast?
58
51
 
59
- interface = @interfaces.find_by_port( message.in_port )
60
- if interface and interface.has?( message.macda )
52
+ interface = @interfaces.find_by_port(message.in_port)
53
+ if interface and interface.has?(message.macda)
61
54
  return true
62
55
  end
63
56
  end
64
57
 
65
-
66
- def handle_arp_request( dpid, message )
58
+ def handle_arp_request(dpid, message)
67
59
  port = message.in_port
68
60
  daddr = message.arp_tpa
69
- interface = @interfaces.find_by_port_and_ipaddr( port, daddr )
61
+ interface = @interfaces.find_by_port_and_ipaddr(port, daddr)
70
62
  if interface
71
- arp_reply = create_arp_reply_from( message, interface.hwaddr )
72
- packet_out dpid, arp_reply, SendOutPort.new( interface.port )
63
+ arp_reply = create_arp_reply_from(message, interface.hwaddr)
64
+ packet_out dpid, arp_reply, SendOutPort.new(interface.port)
73
65
  end
74
66
  end
75
67
 
76
-
77
- def handle_arp_reply( message )
68
+ def handle_arp_reply(message)
78
69
  @arp_table.update message.in_port, message.arp_spa, message.arp_sha
79
70
  end
80
71
 
81
-
82
- def handle_ipv4( dpid, message )
83
- if should_forward?( message )
72
+ def handle_ipv4(dpid, message)
73
+ if should_forward?(message)
84
74
  forward dpid, message
85
75
  elsif message.icmpv4_echo_request?
86
76
  handle_icmpv4_echo_request dpid, message
@@ -89,38 +79,35 @@ class SimpleRouter < Controller
89
79
  end
90
80
  end
91
81
 
92
-
93
- def should_forward?( message )
94
- not @interfaces.find_by_ipaddr( message.ipv4_daddr )
82
+ def should_forward?(message)
83
+ not @interfaces.find_by_ipaddr(message.ipv4_daddr)
95
84
  end
96
85
 
97
-
98
- def handle_icmpv4_echo_request( dpid, message )
99
- interface = @interfaces.find_by_port( message.in_port )
100
- saddr = message.ipv4_saddr.value
101
- arp_entry = @arp_table.lookup( saddr )
86
+ def handle_icmpv4_echo_request(dpid, message)
87
+ interface = @interfaces.find_by_port(message.in_port)
88
+ saddr = message.ipv4_saddr
89
+ arp_entry = @arp_table.lookup(saddr)
102
90
  if arp_entry
103
- icmpv4_reply = create_icmpv4_reply( arp_entry, interface, message )
104
- packet_out dpid, icmpv4_reply, SendOutPort.new( interface.port )
91
+ icmpv4_reply = create_icmpv4_reply(arp_entry, interface, message)
92
+ packet_out dpid, icmpv4_reply, SendOutPort.new(interface.port)
105
93
  else
106
94
  handle_unresolved_packet dpid, message, interface, saddr
107
95
  end
108
96
  end
109
97
 
98
+ def forward(dpid, message)
99
+ next_hop = resolve_next_hop(message.ipv4_daddr)
110
100
 
111
- def forward( dpid, message )
112
- next_hop = resolve_next_hop( message.ipv4_daddr )
113
-
114
- interface = @interfaces.find_by_prefix( next_hop )
101
+ interface = @interfaces.find_by_prefix(next_hop)
115
102
  if not interface or interface.port == message.in_port
116
103
  return
117
104
  end
118
105
 
119
- arp_entry = @arp_table.lookup( next_hop )
106
+ arp_entry = @arp_table.lookup(next_hop)
120
107
  if arp_entry
121
108
  macsa = interface.hwaddr
122
109
  macda = arp_entry.hwaddr
123
- action = create_action_from( macsa, macda, interface.port )
110
+ action = create_action_from(macsa, macda, interface.port)
124
111
  flow_mod dpid, message, action
125
112
  packet_out dpid, message.data, action
126
113
  else
@@ -128,27 +115,24 @@ class SimpleRouter < Controller
128
115
  end
129
116
  end
130
117
 
131
-
132
- def resolve_next_hop( daddr )
133
- interface = @interfaces.find_by_prefix( daddr.value )
118
+ def resolve_next_hop(daddr)
119
+ interface = @interfaces.find_by_prefix(daddr.value)
134
120
  if interface
135
- daddr.value
121
+ daddr
136
122
  else
137
- @routing_table.lookup( daddr.value )
123
+ @routing_table.lookup(daddr.value)
138
124
  end
139
125
  end
140
126
 
141
-
142
- def flow_mod( dpid, message, action )
127
+ def flow_mod(dpid, message, action)
143
128
  send_flow_mod_add(
144
129
  dpid,
145
- :match => ExactMatch.from( message ),
130
+ :match => ExactMatch.from(message),
146
131
  :actions => action
147
132
  )
148
133
  end
149
134
 
150
-
151
- def packet_out( dpid, packet, action )
135
+ def packet_out(dpid, packet, action)
152
136
  send_packet_out(
153
137
  dpid,
154
138
  :data => packet,
@@ -156,22 +140,49 @@ class SimpleRouter < Controller
156
140
  )
157
141
  end
158
142
 
159
-
160
- def handle_unresolved_packet( dpid, message, interface, ipaddr )
161
- arp_request = create_arp_request_from( interface, ipaddr )
162
- packet_out dpid, arp_request, SendOutPort.new( interface.port )
143
+ def handle_unresolved_packet(dpid, message, interface, ipaddr)
144
+ arp_request = create_arp_request_from(interface, ipaddr)
145
+ packet_out dpid, arp_request, SendOutPort.new(interface.port)
163
146
  end
164
147
 
165
-
166
- def create_action_from( macsa, macda, port )
148
+ def create_action_from(macsa, macda, port)
167
149
  [
168
- SetEthSrcAddr.new( macsa ),
169
- SetEthDstAddr.new( macda ),
170
- SendOutPort.new( port )
150
+ SetEthSrcAddr.new(macsa),
151
+ SetEthDstAddr.new(macda),
152
+ SendOutPort.new(port)
171
153
  ]
172
154
  end
173
- end
174
155
 
156
+ def create_arp_request_from(interface, addr)
157
+ Pio::Arp::Request.new(
158
+ :source_mac => interface.hwaddr,
159
+ :sender_protocol_address => interface.ipaddr,
160
+ :target_protocol_address => addr
161
+ ).to_binary
162
+ end
163
+
164
+ def create_arp_reply_from(message, replyaddr)
165
+ Pio::Arp::Reply.new(
166
+ :source_mac => replyaddr,
167
+ :destination_mac => message.macsa,
168
+ :sender_protocol_address => message.arp_tpa,
169
+ :target_protocol_address => message.arp_spa
170
+ ).to_binary
171
+ end
172
+
173
+ def create_icmpv4_reply(entry, interface, message)
174
+ request = Pio::Icmp.read(message.data)
175
+ Pio::Icmp::Reply.new(
176
+ :destination_mac => entry.hwaddr,
177
+ :source_mac => interface.hwaddr,
178
+ :ip_source_address => message.ipv4_daddr,
179
+ :ip_destination_address => message.ipv4_saddr,
180
+ :icmp_identifier => request.icmp_identifier,
181
+ :icmp_sequence_number => request.icmp_sequence_number,
182
+ :echo_data => request.echo_data
183
+ ).to_binary
184
+ end
185
+ end
175
186
 
176
187
  ### Local variables:
177
188
  ### mode: Ruby