trema 0.3.19 → 0.3.20

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 +7 -7
  3. data/README.md +3 -3
  4. data/Rakefile +13 -4
  5. data/cruise.rb +1 -1
  6. data/features/examples/switch_monitor.feature +2 -0
  7. data/features/switch_event/C-add_forward_entry.feature +4 -24
  8. data/features/switch_event/C-delete_forward_entry.feature +3 -18
  9. data/features/switch_event/C-dump_forward_entries.feature +2 -12
  10. data/features/switch_event/C-set_forward_entries.feature +2 -12
  11. data/features/switch_event/add_forward_entry.feature +44 -29
  12. data/features/switch_event/delete_forward_entry.feature +31 -16
  13. data/features/switch_event/dump_forward_entries.feature +23 -13
  14. data/features/switch_event/set_forward_entries.feature +17 -7
  15. data/features/trema_commands/dump_flows.feature +1 -0
  16. data/features/trema_commands/reset_stats.feature +1 -0
  17. data/features/trema_commands/show_stats.feature +1 -0
  18. data/ruby/trema/features-reply.c +9 -6
  19. data/ruby/trema/monkey-patch/integer/validators.rb +36 -0
  20. data/ruby/trema/monkey-patch/integer.rb +2 -0
  21. data/ruby/trema/packet-in.c +140 -0
  22. data/ruby/trema/packet-queue.rb +130 -126
  23. data/ruby/trema/port.c +11 -0
  24. data/ruby/trema/queue-get-config-reply.c +8 -5
  25. data/ruby/trema/set-ip-tos.rb +3 -3
  26. data/ruby/trema/vendor-action.rb +5 -1
  27. data/ruby/trema/version.rb +1 -1
  28. data/spec/trema/echo-reply_spec.rb +8 -8
  29. data/spec/trema/echo-request_spec.rb +1 -1
  30. data/spec/trema/hello_spec.rb +6 -6
  31. data/spec/trema/packet-in_spec.rb +131 -0
  32. data/spec/trema/queue-get-config-reply_spec.rb +1 -1
  33. data/spec/trema/set-ip-tos_spec.rb +5 -0
  34. data/spec/trema/vendor-action_spec.rb +5 -0
  35. data/src/examples/switch_event_config/.gitignore +0 -1
  36. data/src/examples/switch_event_config/network.conf +2 -0
  37. data/src/lib/arp.h +3 -1
  38. data/src/lib/ether.h +1 -0
  39. data/src/lib/event_forward_interface.c +9 -4
  40. data/src/lib/openflow_message.c +6 -0
  41. data/src/lib/openflow_message.h +1 -0
  42. data/src/lib/packet_info.c +23 -0
  43. data/src/lib/packet_info.h +5 -0
  44. data/src/lib/packet_parser.c +8 -3
  45. data/src/lib/utility.c +13 -13
  46. data/src/lib/utility.h +15 -0
  47. data/src/switch_manager/event_forward_entry_manipulation.c +1 -1
  48. data/src/switch_manager/secure_channel_listener.c +3 -6
  49. data/src/switch_manager/switch.c +68 -9
  50. data/trema.gemspec +4 -4
  51. data/unittests/lib/event_forward_interface_test.c +30 -0
  52. data/unittests/lib/openflow_message_test.c +19 -0
  53. data/unittests/lib/packet_info_test.c +16 -0
  54. data/unittests/lib/packet_parser_test.c +37 -0
  55. data/unittests/lib/test_packets/rarp_req.cap +0 -0
  56. metadata +9 -6
@@ -131,16 +131,20 @@ get_property( struct ofp_packet_queue *pq, VALUE packet_queue ) {
131
131
  struct ofp_queue_prop_header *qph;
132
132
  qph = ( struct ofp_queue_prop_header * ) ( ( char * ) pq + offset );
133
133
 
134
- uint16_t properties_length = ( uint16_t ) ( pq->len - offset );
134
+ uint16_t properties_length = ( uint16_t ) ( qph->len - offset );
135
135
  struct ofp_queue_prop_min_rate *qpmr;
136
136
  while ( properties_length > 0 ) {
137
137
  if ( qph->property == OFPQT_MIN_RATE ) {
138
138
  qpmr = ( struct ofp_queue_prop_min_rate * ) qph;
139
- rb_funcall( rb_eval_string( "Trema::MinRateQueue" ), rb_intern( "new" ), 4,
139
+ rb_funcall(
140
+ rb_eval_string( "Trema::MinRateQueue" ),
141
+ rb_intern( "new" ),
142
+ 4,
140
143
  UINT2NUM( qph->property ),
141
144
  UINT2NUM( qph->len ),
142
145
  UINT2NUM( qpmr->rate ),
143
- packet_queue );
146
+ packet_queue
147
+ );
144
148
  }
145
149
  properties_length = ( uint16_t ) ( properties_length - pq->len );
146
150
  if ( properties_length > 0 ) {
@@ -170,7 +174,6 @@ handle_queue_get_config_reply(
170
174
  VALUE pq_attributes = rb_hash_new();
171
175
  VALUE packet_queue;
172
176
 
173
-
174
177
  rb_hash_aset( attributes, ID2SYM( rb_intern( "datapath_id" ) ), ULL2NUM( datapath_id ) );
175
178
  rb_hash_aset( attributes, ID2SYM( rb_intern( "transaction_id" ) ), UINT2NUM( transaction_id ) );
176
179
  rb_hash_aset( attributes, ID2SYM( rb_intern( "port" ) ), UINT2NUM( port ) );
@@ -187,7 +190,7 @@ handle_queue_get_config_reply(
187
190
  get_property( pq, packet_queue );
188
191
  queue = queue->next;
189
192
  }
190
- rb_hash_aset( attributes, ID2SYM( rb_intern( "queues" ) ), rb_eval_string( "PacketQueue.queues" ) );
193
+ rb_hash_aset( attributes, ID2SYM( rb_intern( "queues" ) ), rb_eval_string( "Trema::Queue.queues" ) );
191
194
  }
192
195
  VALUE queue_get_config_reply = rb_funcall( cQueueGetConfigReply, rb_intern( "new" ), 1, attributes );
193
196
  rb_funcall( controller, rb_intern( "queue_get_config_reply" ), 2, ULL2NUM( datapath_id ), queue_get_config_reply );
@@ -38,15 +38,15 @@ module Trema
38
38
  # @param [Integer] type_of_service
39
39
  # the ToS/DSCP field to set to.
40
40
  #
41
- # @raise [ArgumentError] if type_of_service argument is not an unsigned 8-bit Integer.
41
+ # @raise [ArgumentError] if type_of_service value is invalid.
42
42
  # @raise [TypeError] if type_of_service argument is not an Integer.
43
43
  #
44
44
  def initialize type_of_service
45
45
  unless type_of_service.is_a?( Integer )
46
46
  raise TypeError, "ToS must be an unsigned 8-bit integer"
47
47
  end
48
- unless type_of_service.unsigned_8bit?
49
- raise ArgumentError, "ToS must be an unsigned 8-bit integer"
48
+ unless type_of_service.valid_nw_tos?
49
+ raise ArgumentError, "Invalid type_of_service (ToS) value."
50
50
  end
51
51
  @type_of_service = type_of_service
52
52
  end
@@ -49,6 +49,7 @@ module Trema
49
49
  # @raise [TypeError] if vendor ID is not an Integer.
50
50
  # @raise [ArgumentError] if vendor ID is not an unsigned 32-bit Integer.
51
51
  # @raise [TypeError] if body is not an Array.
52
+ # @raise [ArgumentError] if body length is not a multiple of 8.
52
53
  #
53
54
  def initialize vendor_id, body = nil
54
55
  unless vendor_id.is_a?( Integer )
@@ -57,9 +58,12 @@ module Trema
57
58
  unless vendor_id.unsigned_32bit?
58
59
  raise ArgumentError, "Vendor ID must be an unsigned 32-bit integer"
59
60
  end
60
- if ( not body.nil? ) and ( not body.is_a?( Array ) )
61
+ if ( not body.nil? ) and ( not body.is_a?( Array ) )
61
62
  raise TypeError, "Body must be an Array"
62
63
  end
64
+ if ( not body.nil? ) and ( body.size % 8 != 0 )
65
+ raise ArgumentError, "Body length must be a multiple of 8"
66
+ end
63
67
 
64
68
  @vendor_id = vendor_id
65
69
  @body = body
@@ -17,7 +17,7 @@
17
17
 
18
18
 
19
19
  module Trema
20
- VERSION = "0.3.19"
20
+ VERSION = "0.3.20"
21
21
  end
22
22
 
23
23
 
@@ -21,44 +21,44 @@ require "trema"
21
21
 
22
22
 
23
23
  module Trema
24
- describe EchoReply, ".new", :nosudo => true do
24
+ describe EchoReply, ".new" do
25
25
  it_should_behave_like "any Openflow message with default transaction ID"
26
26
  its( :user_data ) { should be_nil }
27
27
  end
28
28
 
29
29
 
30
- describe EchoReply, ".new(nil)", :nosudo => true do
30
+ describe EchoReply, ".new(nil)" do
31
31
  subject { EchoReply.new( nil ) }
32
32
  it_should_behave_like "any Openflow message with default transaction ID"
33
33
  its( :user_data ) { should be_nil }
34
34
  end
35
35
 
36
36
 
37
- describe EchoReply, ".new(transaction_id)", :nosudo => true do
37
+ describe EchoReply, ".new(transaction_id)" do
38
38
  subject { EchoReply.new( transaction_id ) }
39
39
  it_should_behave_like "any Openflow message with transaction ID"
40
40
  end
41
41
 
42
42
 
43
- describe EchoReply, ".new(:transaction_id => value)", :nosudo => true do
43
+ describe EchoReply, ".new(:transaction_id => value)" do
44
44
  subject { EchoReply.new( :transaction_id => transaction_id ) }
45
45
  it_should_behave_like "any Openflow message with transaction ID"
46
46
  end
47
47
 
48
48
 
49
- describe EchoReply, ".new(:xid => value)", :nosudo => true do
49
+ describe EchoReply, ".new(:xid => value)" do
50
50
  subject { EchoReply.new( :xid => xid ) }
51
51
  it_should_behave_like "any Openflow message with xid"
52
52
  end
53
53
 
54
54
 
55
- describe EchoReply, ".new(:user_data => value)", :nosudo => true do
55
+ describe EchoReply, ".new(:user_data => value)" do
56
56
  subject { EchoReply.new( :user_data => user_data ) }
57
57
  it_should_behave_like "any Openflow message with user_data"
58
58
  end
59
59
 
60
60
 
61
- describe EchoReply, ".new(:transaction_id => value, :user_data => value)", :nosudo => true do
61
+ describe EchoReply, ".new(:transaction_id => value, :user_data => value)" do
62
62
  subject { EchoReply.new( :transaction_id => transaction_id, :user_data => user_data ) }
63
63
 
64
64
  context 'transaction_id: 123, user_data: "USER DATA"' do
@@ -71,7 +71,7 @@ module Trema
71
71
  end
72
72
 
73
73
 
74
- describe EchoReply, '.new("INVALID OPTION")', :nosudo => true do
74
+ describe EchoReply, '.new("INVALID OPTION")' do
75
75
  it { expect { EchoReply.new "INVALID OPTION" }.to raise_error( TypeError ) }
76
76
  end
77
77
  end
@@ -115,7 +115,7 @@ module Trema
115
115
  end
116
116
 
117
117
 
118
- describe EchoRequest, '.new("INVALID OPTION")', :nosudo => true do
118
+ describe EchoRequest, '.new("INVALID OPTION")' do
119
119
  it { expect { EchoRequest.new "INVALID OPTION" }.to raise_error( TypeError ) }
120
120
  end
121
121
  end
@@ -21,36 +21,36 @@ require "trema"
21
21
 
22
22
 
23
23
  module Trema
24
- describe Hello, ".new", :nosudo => true do
24
+ describe Hello, ".new" do
25
25
  it_should_behave_like "any Openflow message with default transaction ID"
26
26
  end
27
27
 
28
28
 
29
- describe Hello, ".new(nil)", :nosudo => true do
29
+ describe Hello, ".new(nil)" do
30
30
  subject { Hello.new( nil ) }
31
31
  it_should_behave_like "any Openflow message with default transaction ID"
32
32
  end
33
33
 
34
34
 
35
- describe Hello, ".new(transaction_id)", :nosudo => true do
35
+ describe Hello, ".new(transaction_id)" do
36
36
  subject { Hello.new( transaction_id ) }
37
37
  it_should_behave_like "any Openflow message with transaction ID"
38
38
  end
39
39
 
40
40
 
41
- describe Hello, ".new(:transaction_id => value)", :nosudo => true do
41
+ describe Hello, ".new(:transaction_id => value)" do
42
42
  subject { Hello.new( :transaction_id => transaction_id ) }
43
43
  it_should_behave_like "any Openflow message with transaction ID"
44
44
  end
45
45
 
46
46
 
47
- describe Hello, ".new(:xid => value)", :nosudo => true do
47
+ describe Hello, ".new(:xid => value)" do
48
48
  subject { Hello.new( :xid => xid ) }
49
49
  it_should_behave_like "any Openflow message with xid"
50
50
  end
51
51
 
52
52
 
53
- describe Hello, '.new("INVALID OPTION")', :nosudo => true do
53
+ describe Hello, '.new("INVALID OPTION")' do
54
54
  it { expect { Hello.new "INVALID OPTION" }.to raise_error( TypeError ) }
55
55
  end
56
56
  end
@@ -130,6 +130,7 @@ describe Trema::PacketIn do
130
130
  expect( message.in_port ).to be > 0
131
131
  expect( message.vtag? ).to be_false
132
132
  expect( message.arp? ).to be_true
133
+ expect( message.rarp? ).to be_false
133
134
  expect( message.ipv4? ).to be_false
134
135
  expect( message.lldp? ).to be_false
135
136
  expect( message.tcp? ).to be_false
@@ -145,6 +146,125 @@ describe Trema::PacketIn do
145
146
  expect( message.arp_request? ).to be_false
146
147
  expect( message.arp_reply? ).to be_true
147
148
 
149
+ expect( message.rarp_oper ).to be_nil
150
+ expect( message.rarp_sha ).to be_nil
151
+ expect( message.rarp_spa ).to be_nil
152
+ expect( message.rarp_tha ).to be_nil
153
+ expect( message.rarp_tpa ).to be_nil
154
+ expect( message.rarp_request? ).to be_false
155
+ expect( message.rarp_reply? ).to be_false
156
+
157
+ expect( message.vlan_tpid ).to be_nil
158
+ expect( message.vlan_tci ).to be_nil
159
+ expect( message.vlan_prio ).to be_nil
160
+ expect( message.vlan_cfi ).to be_nil
161
+ expect( message.vlan_vid ).to be_nil
162
+
163
+ expect( message.ipv4_version ).to be_nil
164
+ expect( message.ipv4_ihl ).to be_nil
165
+ expect( message.ipv4_tos ).to be_nil
166
+ expect( message.ipv4_tot_len ).to be_nil
167
+ expect( message.ipv4_id ).to be_nil
168
+ expect( message.ipv4_frag_off ).to be_nil
169
+ expect( message.ipv4_ttl ).to be_nil
170
+ expect( message.ipv4_protocol ).to be_nil
171
+ expect( message.ipv4_checksum ).to be_nil
172
+ expect( message.ipv4_saddr ).to be_nil
173
+ expect( message.ipv4_daddr ).to be_nil
174
+
175
+ expect( message.icmpv4_type ).to be_nil
176
+ expect( message.icmpv4_code ).to be_nil
177
+ expect( message.icmpv4_checksum ).to be_nil
178
+ expect( message.icmpv4_id ).to be_nil
179
+ expect( message.icmpv4_seq ).to be_nil
180
+ expect( message.icmpv4_gateway ).to be_nil
181
+
182
+ expect( message.igmp_type ).to be_nil
183
+ expect( message.igmp_checksum ).to be_nil
184
+ expect( message.igmp_group ).to be_nil
185
+
186
+ expect( message.tcp_src_port ).to be_nil
187
+ expect( message.tcp_dst_port ).to be_nil
188
+ expect( message.tcp_seq_no ).to be_nil
189
+ expect( message.tcp_ack_no ).to be_nil
190
+ expect( message.tcp_offset ).to be_nil
191
+ expect( message.tcp_flags ).to be_nil
192
+ expect( message.tcp_window ).to be_nil
193
+ expect( message.tcp_checksum ).to be_nil
194
+ expect( message.tcp_urgent ).to be_nil
195
+
196
+ expect( message.udp_src_port ).to be_nil
197
+ expect( message.udp_dst_port ).to be_nil
198
+ expect( message.udp_checksum ).to be_nil
199
+ expect( message.udp_len ).to be_nil
200
+ end
201
+
202
+ controller( "PacketInSendController" ).send_packet_out(
203
+ 0xabc,
204
+ :data => data,
205
+ :actions => Trema::ActionOutput.new( :port => Controller::OFPP_CONTROLLER )
206
+ )
207
+ sleep 2
208
+ }
209
+ end
210
+
211
+ it "should have correct RARP packet fields" do
212
+ network {
213
+ vswitch( "packet-in" ) { datapath_id 0xabc }
214
+ vhost "host1"
215
+ vhost ( "host2" ) { mac "00:00:00:00:00:02" }
216
+ link "host1", "packet-in"
217
+ link "host2", "packet-in"
218
+ }.run( PacketInSendController ) {
219
+ data = [
220
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, # dst
221
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, # src
222
+ 0x80, 0x35, # ether type
223
+ # rarp
224
+ 0x00, 0x01, # hardware type
225
+ 0x08, 0x00, # protocol type
226
+ 0x06, # hardware address length
227
+ 0x04, # protocol address length
228
+ 0x00, 0x03, # operation
229
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, # sender hardware address
230
+ 0xc0, 0xa8, 0x00, 0x01, # sender protocol address
231
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, # target hardware address
232
+ 0x00, 0x00, 0x00, 0x00, # target protocol address
233
+ # padding to 64 bytes
234
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
235
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
236
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
237
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
238
+ 0x00, 0x00
239
+ ].pack( "C*" )
240
+ controller( "PacketInSendController" ).should_receive( :packet_in ) do | datapath_id, message |
241
+ expect( message.in_port ).to be > 0
242
+ expect( message.vtag? ).to be_false
243
+ expect( message.arp? ).to be_false
244
+ expect( message.rarp? ).to be_true
245
+ expect( message.ipv4? ).to be_false
246
+ expect( message.lldp? ).to be_false
247
+ expect( message.tcp? ).to be_false
248
+ expect( message.udp? ).to be_false
249
+ expect( message.icmpv4? ).to be_false
250
+ expect( message.igmp? ).to be_false
251
+
252
+ expect( message.arp_oper ).to be_nil
253
+ expect( message.arp_sha ).to be_nil
254
+ expect( message.arp_spa ).to be_nil
255
+ expect( message.arp_tha ).to be_nil
256
+ expect( message.arp_tpa ).to be_nil
257
+ expect( message.arp_request? ).to be_false
258
+ expect( message.arp_reply? ).to be_false
259
+
260
+ expect( message.rarp_oper ).to eq( 3 )
261
+ expect( message.rarp_sha.to_s ).to eq( "00:00:00:00:00:01" )
262
+ expect( message.rarp_spa.to_s ).to eq( "192.168.0.1" )
263
+ expect( message.rarp_tha.to_s ).to eq( "00:00:00:00:00:02" )
264
+ expect( message.rarp_tpa.to_s ).to eq( "0.0.0.0" )
265
+ expect( message.rarp_request? ).to be_true
266
+ expect( message.rarp_reply? ).to be_false
267
+
148
268
  expect( message.vlan_tpid ).to be_nil
149
269
  expect( message.vlan_tci ).to be_nil
150
270
  expect( message.vlan_prio ).to be_nil
@@ -241,6 +361,7 @@ describe Trema::PacketIn do
241
361
  expect( message.in_port ).to be > 0
242
362
  expect( message.vtag? ).to be_false
243
363
  expect( message.arp? ).to be_false
364
+ expect( message.rarp? ).to be_false
244
365
  expect( message.ipv4? ).to be_true
245
366
  expect( message.lldp? ).to be_false
246
367
  expect( message.udp? ).to be_false
@@ -275,6 +396,12 @@ describe Trema::PacketIn do
275
396
  expect( message.arp_spa ).to be_nil
276
397
  expect( message.arp_tha ).to be_nil
277
398
  expect( message.arp_tpa ).to be_nil
399
+
400
+ expect( message.rarp_oper ).to be_nil
401
+ expect( message.rarp_sha ).to be_nil
402
+ expect( message.rarp_spa ).to be_nil
403
+ expect( message.rarp_tha ).to be_nil
404
+ expect( message.rarp_tpa ).to be_nil
278
405
  end
279
406
 
280
407
  controller( "PacketInSendController" ).send_packet_out(
@@ -325,6 +452,7 @@ describe Trema::PacketIn do
325
452
  expect( message.in_port ).to be > 0
326
453
  expect( message.vtag? ).to be_false
327
454
  expect( message.arp? ).to be_false
455
+ expect( message.rarp? ).to be_false
328
456
  expect( message.ipv4? ).to be_true
329
457
  expect( message.lldp? ).to be_false
330
458
  expect( message.tcp? ).to be_false
@@ -406,6 +534,7 @@ describe Trema::PacketIn do
406
534
  expect( message.in_port ).to be > 0
407
535
  expect( message.vtag? ).to be_true
408
536
  expect( message.arp? ).to be_false
537
+ expect( message.rarp? ).to be_false
409
538
  expect( message.ipv4? ).to be_true
410
539
  expect( message.lldp? ).to be_false
411
540
  expect( message.udp? ).to be_false
@@ -490,6 +619,7 @@ describe Trema::PacketIn do
490
619
  expect( message.in_port ).to be > 0
491
620
  expect( message.vtag? ).to be_false
492
621
  expect( message.arp? ).to be_false
622
+ expect( message.rarp? ).to be_false
493
623
  expect( message.ipv4? ).to be_true
494
624
  expect( message.lldp? ).to be_false
495
625
  expect( message.udp? ).to be_false
@@ -555,6 +685,7 @@ describe Trema::PacketIn do
555
685
  expect( message.in_port ).to be > 0
556
686
  expect( message.vtag? ).to be_false
557
687
  expect( message.arp? ).to be_false
688
+ expect( message.rarp? ).to be_false
558
689
  expect( message.ipv4? ).to be_false
559
690
  expect( message.lldp? ).to be_true
560
691
  expect( message.udp? ).to be_false
@@ -29,7 +29,7 @@ describe QueueGetConfigReply, ".new( VALID OPTIONS )" do
29
29
  QueueGetConfigReply.new( :datapath_id => 0xabc,
30
30
  :transaction_id => 123,
31
31
  :port => 1,
32
- :queues => Queue.queues
32
+ :queues => Trema::Queue.queues
33
33
  )
34
34
  end
35
35
  its( "queues.length" ) { should == 2 }
@@ -40,6 +40,11 @@ describe SetIpTos, ".new( type_of_service )", :type => "actions" do
40
40
  it { expect { subject }.to raise_error( TypeError ) }
41
41
  end
42
42
 
43
+ context "with type_of_service (1)" do
44
+ let( :type_of_service ) { 1 }
45
+ it { expect { subject }.to raise_error( ArgumentError ) }
46
+ end
47
+
43
48
  context "when sending a Flow Mod with SetIpTos" do
44
49
  let( :type_of_service ) { 4 }
45
50
 
@@ -45,6 +45,11 @@ describe VendorAction, ".new(0x00002320, body)", :type => "actions" do
45
45
  it { expect { subject }.to raise_error( TypeError ) }
46
46
  end
47
47
 
48
+ context "with body 9 octets long" do
49
+ let( :body ) { [ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 ] }
50
+ it { expect { subject }.to raise_error( ArgumentError ) }
51
+ end
52
+
48
53
  context "when sending a Flow Mod with VendorAction" do
49
54
  let( :body ) { [ 0x00, 0x08, 0x54, 0x72, 0x65, 0x6d, 0x61, 0x00 ] }
50
55
 
@@ -2,6 +2,5 @@ add_forward_entry
2
2
  delete_forward_entry
3
3
  dump_forward_entries
4
4
  set_forward_entries
5
- nw_dsl.conf
6
5
  switch_event_config_add.conf
7
6
 
@@ -0,0 +1,2 @@
1
+ vswitch { datapath_id 0x1 }
2
+ vswitch { datapath_id 0x2 }
data/src/lib/arp.h CHANGED
@@ -48,7 +48,9 @@ typedef struct arp_header {
48
48
 
49
49
 
50
50
  #define ARP_OP_REQUEST 1
51
- #define ARP_OP_REPLY 2
51
+ #define ARP_OP_REPLY 2
52
+ #define ARP_OP_RREQUEST 3
53
+ #define ARP_OP_RREPLY 4
52
54
 
53
55
 
54
56
  #endif // ARP_H
data/src/lib/ether.h CHANGED
@@ -39,6 +39,7 @@
39
39
  #define ETH_ETHTYPE_8023 0x05dc
40
40
  #define ETH_ETHTYPE_IPV4 0x0800
41
41
  #define ETH_ETHTYPE_ARP 0x0806
42
+ #define ETH_ETHTYPE_RARP 0x8035
42
43
  #define ETH_ETHTYPE_TPID 0x8100
43
44
  #define ETH_ETHTYPE_IPV6 0x86DD
44
45
  #define ETH_ETHTYPE_EAPOL 0x88c7
@@ -649,7 +649,6 @@ all_sw_tx*
649
649
  _insert_tx( size_t n_dpids, struct event_forward_operation_to_all_request_param *param ) {
650
650
  all_sw_tx *tx = xcalloc( 1, sizeof(all_sw_tx) );
651
651
  tx->txid = get_txid();
652
- info( "txid %#x Start dispatching to switches", tx->txid );
653
652
  tx->request_param = param;
654
653
  tx->tx_result = EFI_OPERATION_SUCCEEDED;
655
654
  tx->waiting_dpid = create_hash_with_size( compare_datapath_id,
@@ -666,7 +665,8 @@ _dispatch_to_all_switch( uint64_t *dpids, size_t n_dpids, void *user_data ) {
666
665
  struct event_forward_operation_to_all_request_param *param = user_data;
667
666
 
668
667
  all_sw_tx *tx = _insert_tx( n_dpids, param );
669
-
668
+ info( "txid %#x Start dispatching to switches", tx->txid );
669
+ debug( "dispatching to %zd switches", n_dpids );
670
670
  // copy dpid hash to transaction.
671
671
  for ( size_t i = 0 ; i < n_dpids ; ++i ) {
672
672
  uint64_t *dpid = xmalloc( sizeof( uint64_t ) );
@@ -715,11 +715,16 @@ _dispatch_to_all_switch( uint64_t *dpids, size_t n_dpids, void *user_data ) {
715
715
  }
716
716
  }
717
717
 
718
- if ( tx->tx_result == EFI_OPERATION_FAILED ) {
718
+ if ( n_dpids == 0 || tx->tx_result == EFI_OPERATION_FAILED ) {
719
+ if ( n_dpids == 0 ) {
720
+ info( "txid %#x completed. No switches found.", tx->txid );
721
+ }
722
+ else if ( tx->tx_result == EFI_OPERATION_FAILED ) {
723
+ info( "txid %#x completed with failure.", tx->txid );
724
+ }
719
725
  if ( param->callback != NULL ) {
720
726
  param->callback( tx->tx_result, param->user_data );
721
727
  }
722
- info( "txid %#x completed with failure.", tx->txid );
723
728
  // remove and cleanup tx
724
729
  delete_hash_entry( efi_tx_table, &tx->txid );
725
730
  xfree_all_sw_tx( tx );
@@ -1638,6 +1638,7 @@ append_action_vendor( openflow_actions *actions, const uint32_t vendor, const bu
1638
1638
  debug( "Appending a vendor action ( vendor = %#" PRIx32 ", body length = %u ).", vendor, body_length );
1639
1639
 
1640
1640
  assert( actions != NULL );
1641
+ assert( ( body_length % 8 ) == 0 );
1641
1642
 
1642
1643
  action_vendor = ( struct ofp_action_vendor_header * )
1643
1644
  xcalloc( 1, sizeof( struct ofp_action_vendor_header ) + body_length );
@@ -3457,6 +3458,9 @@ validate_action_vendor( const struct ofp_action_vendor_header *action ) {
3457
3458
  if ( ntohs( action->len ) < sizeof( struct ofp_action_vendor_header ) ) {
3458
3459
  return ERROR_TOO_SHORT_ACTION_VENDOR;
3459
3460
  }
3461
+ else if ( ntohs( action->len ) % 8 != 0 ) {
3462
+ return ERROR_INVALID_LENGTH_ACTION_VENDOR;
3463
+ }
3460
3464
 
3461
3465
  // action->vendor
3462
3466
 
@@ -3758,6 +3762,7 @@ static struct error_map {
3758
3762
  { ERROR_TOO_LONG_ACTION_ENQUEUE, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3759
3763
  { ERROR_INVALID_PORT_NO, OFPET_BAD_ACTION, OFPBAC_BAD_OUT_PORT },
3760
3764
  { ERROR_TOO_SHORT_ACTION_VENDOR, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3765
+ { ERROR_INVALID_LENGTH_ACTION_VENDOR, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3761
3766
  { ERROR_UNDEFINED_ACTION_TYPE, OFPET_BAD_ACTION, OFPBAC_BAD_TYPE },
3762
3767
  { 0, 0, 0 },
3763
3768
  }
@@ -3800,6 +3805,7 @@ static struct error_map {
3800
3805
  { ERROR_TOO_LONG_ACTION_ENQUEUE, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3801
3806
  { ERROR_INVALID_PORT_NO, OFPET_BAD_ACTION, OFPBAC_BAD_OUT_PORT },
3802
3807
  { ERROR_TOO_SHORT_ACTION_VENDOR, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3808
+ { ERROR_INVALID_LENGTH_ACTION_VENDOR, OFPET_BAD_ACTION, OFPBAC_BAD_LEN },
3803
3809
  { ERROR_UNDEFINED_ACTION_TYPE, OFPET_BAD_ACTION, OFPBAC_BAD_TYPE },
3804
3810
  { ERROR_INVALID_WILDCARDS, OFPET_FLOW_MOD_FAILED, OFPFMFC_EPERM }, // FIXME
3805
3811
  { ERROR_UNDEFINED_FLOW_MOD_COMMAND, OFPET_FLOW_MOD_FAILED, OFPFMFC_BAD_COMMAND },
@@ -202,6 +202,7 @@ enum {
202
202
  ERROR_TOO_SHORT_ACTION_ENQUEUE,
203
203
  ERROR_TOO_LONG_ACTION_ENQUEUE,
204
204
  ERROR_TOO_SHORT_ACTION_VENDOR,
205
+ ERROR_INVALID_LENGTH_ACTION_VENDOR,
205
206
  ERROR_UNSUPPORTED_STATS_TYPE,
206
207
  ERROR_INVALID_STATS_REPLY_FLAGS,
207
208
  ERROR_INVALID_FLOW_PRIORITY,
@@ -124,6 +124,13 @@ packet_type_arp( const buffer *frame ) {
124
124
  }
125
125
 
126
126
 
127
+ bool
128
+ packet_type_rarp( const buffer *frame ) {
129
+ die_if_NULL( frame );
130
+ return if_packet_type( frame, NW_RARP );
131
+ }
132
+
133
+
127
134
  bool
128
135
  packet_type_ipv4( const buffer *frame ) {
129
136
  die_if_NULL( frame );
@@ -218,6 +225,22 @@ packet_type_arp_reply( const buffer *frame ) {
218
225
  }
219
226
 
220
227
 
228
+ bool
229
+ packet_type_rarp_request( const buffer *frame ) {
230
+ die_if_NULL( frame );
231
+ return ( if_packet_type( frame, NW_RARP ) &
232
+ if_arp_opcode( frame, ARP_OP_RREQUEST ) );
233
+ }
234
+
235
+
236
+ bool
237
+ packet_type_rarp_reply( const buffer *frame ) {
238
+ die_if_NULL( frame );
239
+ return ( if_packet_type( frame, NW_RARP ) &
240
+ if_arp_opcode( frame, ARP_OP_RREPLY ) );
241
+ }
242
+
243
+
221
244
  static bool
222
245
  if_icmpv4_type( const buffer *frame, const uint32_t type ) {
223
246
  die_if_NULL( frame );
@@ -48,6 +48,7 @@ enum {
48
48
  NW_ARP = 0x00001000,
49
49
  NW_IGMP = 0x00002000,
50
50
  NW_LLDP = 0x00004000,
51
+ NW_RARP = 0x00008000,
51
52
  TP_TCP = 0x00010000,
52
53
  TP_UDP = 0x00020000,
53
54
  TP_ETHERIP = 0x00040000,
@@ -58,6 +59,7 @@ enum {
58
59
  ETH_VTAG_SNAP = ETH_8021Q | ETH_8023_SNAP,
59
60
  ETH_ARP = ETH_DIX | NW_ARP,
60
61
  ETH_LLDP = ETH_DIX | NW_LLDP,
62
+ ETH_RARP = ETH_DIX | NW_RARP,
61
63
  ETH_IPV4 = ETH_DIX | NW_IPV4,
62
64
  ETH_IPV4_ICMPV4 = ETH_IPV4 | NW_ICMPV4,
63
65
  ETH_IPV4_IGMP = ETH_IPV4 | NW_IGMP,
@@ -191,6 +193,7 @@ bool packet_type_eth_llc( const buffer *frame );
191
193
  bool packet_type_eth_snap( const buffer *frame );
192
194
  bool packet_type_ether( const buffer *frame );
193
195
  bool packet_type_arp( const buffer *frame );
196
+ bool packet_type_rarp( const buffer *frame );
194
197
  bool packet_type_ipv4( const buffer *frame );
195
198
  bool packet_type_ipv6( const buffer *frame );
196
199
  bool packet_type_lldp( const buffer *frame );
@@ -204,6 +207,8 @@ bool packet_type_ipv4_etherip( const buffer *frame );
204
207
 
205
208
  bool packet_type_arp_request( const buffer *frame );
206
209
  bool packet_type_arp_reply( const buffer *frame );
210
+ bool packet_type_rarp_request( const buffer *frame );
211
+ bool packet_type_rarp_reply( const buffer *frame );
207
212
 
208
213
  bool packet_type_icmpv4_echo_reply( const buffer *frame );
209
214
  bool packet_type_icmpv4_dst_unreach( const buffer *frame );
@@ -119,7 +119,7 @@ parse_ether( buffer *buf ) {
119
119
 
120
120
 
121
121
  static void
122
- parse_arp( buffer *buf ) {
122
+ parse_arp( buffer *buf, uint32_t format ) {
123
123
  assert( buf != NULL );
124
124
 
125
125
  packet_info *packet_info = buf->user_data;
@@ -144,7 +144,7 @@ parse_arp( buffer *buf ) {
144
144
  memcpy( packet_info->arp_tha, arp_header->tha, ETH_ADDRLEN );
145
145
  packet_info->arp_tpa = ntohl( arp_header->tip );
146
146
 
147
- packet_info->format |= NW_ARP;
147
+ packet_info->format |= format;
148
148
  }
149
149
 
150
150
 
@@ -441,7 +441,12 @@ parse_packet( buffer *buf ) {
441
441
  switch ( packet_info->eth_type ) {
442
442
  case ETH_ETHTYPE_ARP:
443
443
  packet_info->l3_header = packet_info->l2_payload;
444
- parse_arp( buf );
444
+ parse_arp( buf, NW_ARP );
445
+ break;
446
+
447
+ case ETH_ETHTYPE_RARP:
448
+ packet_info->l3_header = packet_info->l2_payload;
449
+ parse_arp( buf, NW_RARP );
445
450
  break;
446
451
 
447
452
  case ETH_ETHTYPE_IPV4: