trema 0.4.5 → 0.4.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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