pio 0.25.0 → 0.26.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (134) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/README.md +4 -0
  4. data/Rakefile +1 -1
  5. data/bin/terminal-notifier +16 -0
  6. data/features/open_flow10/bad_request.feature +35 -0
  7. data/features/open_flow10/bad_request.raw +0 -0
  8. data/features/open_flow10/barrier_reply.feature +4 -4
  9. data/features/open_flow10/barrier_request.feature +4 -4
  10. data/features/open_flow10/echo_reply.feature +13 -13
  11. data/features/open_flow10/echo_request.feature +6 -6
  12. data/features/open_flow10/enqueue.feature +17 -0
  13. data/features/open_flow10/features_reply.feature +2 -2
  14. data/features/open_flow10/features_request.feature +28 -28
  15. data/features/open_flow10/flow_mod.feature +5 -5
  16. data/features/open_flow10/flow_stats_reply.feature +12 -12
  17. data/features/open_flow10/flow_stats_request.feature +3 -3
  18. data/features/open_flow10/hello.feature +8 -15
  19. data/features/open_flow10/hello_failed.feature +69 -0
  20. data/features/open_flow10/hello_failed.raw +0 -0
  21. data/features/open_flow10/nxast_learn.raw +0 -0
  22. data/features/open_flow10/packet_in.feature +2 -2
  23. data/features/open_flow10/packet_out.feature +13 -13
  24. data/features/open_flow10/port_status.feature +1 -1
  25. data/features/open_flow10/send_out_port.feature +106 -0
  26. data/features/open_flow10/set_ether_destination_address.feature +16 -0
  27. data/features/open_flow10/set_ether_source_address.feature +16 -0
  28. data/features/open_flow10/set_ip_destination_address.feature +16 -0
  29. data/features/open_flow10/set_ip_source_address.feature +16 -0
  30. data/features/open_flow10/set_ip_tos.feature +16 -0
  31. data/features/open_flow10/set_transport_destination_port.feature +16 -0
  32. data/features/open_flow10/set_transport_source_port.feature +16 -0
  33. data/features/open_flow10/set_vlan_priority.feature +16 -0
  34. data/features/open_flow10/set_vlan_vid.feature +16 -0
  35. data/features/open_flow10/strip_vlan_header.feature +15 -0
  36. data/features/open_flow10/vendor_action.feature +14 -0
  37. data/features/open_flow13/bad_request.feature +35 -0
  38. data/features/open_flow13/bad_request.raw +0 -0
  39. data/features/open_flow13/echo_reply.feature +7 -7
  40. data/features/open_flow13/echo_request.feature +7 -7
  41. data/features/open_flow13/features_reply.feature +2 -2
  42. data/features/open_flow13/features_request.feature +28 -28
  43. data/features/open_flow13/flow_mod.feature +24 -24
  44. data/features/open_flow13/hello.feature +5 -5
  45. data/features/open_flow13/hello_failed.feature +69 -0
  46. data/features/open_flow13/hello_failed.raw +0 -0
  47. data/features/open_flow13/packet_in.feature +3 -3
  48. data/features/open_flow13/packet_out.feature +3 -3
  49. data/features/open_flow13/send_out_port.feature +101 -10
  50. data/features/open_flow13/table_stats_reply.raw +0 -0
  51. data/features/open_flow13/table_stats_request.raw +0 -0
  52. data/features/open_flow_read.feature +6 -0
  53. data/features/step_definitions/Gemfile +9 -0
  54. data/features/step_definitions/Gemfile.lock +76 -0
  55. data/features/step_definitions/Guardfile +4 -0
  56. data/features/step_definitions/LICENSE +675 -0
  57. data/features/step_definitions/README.md +7 -0
  58. data/features/step_definitions/Rakefile +10 -0
  59. data/features/step_definitions/dump_flows_steps.rb +13 -0
  60. data/features/step_definitions/packet_data_steps.rb +4 -0
  61. data/features/step_definitions/rest_api_steps.rb +40 -0
  62. data/features/step_definitions/show_stats_steps.rb +83 -0
  63. data/features/step_definitions/trema_steps.rb +33 -0
  64. data/features/step_definitions/virtual_link_steps.rb +8 -0
  65. data/lib/pio/open_flow.rb +5 -5
  66. data/lib/pio/open_flow/echo.rb +1 -1
  67. data/lib/pio/open_flow/error.rb +19 -0
  68. data/lib/pio/open_flow/format.rb +2 -1
  69. data/lib/pio/open_flow/hello_failed_code.rb +21 -0
  70. data/lib/pio/open_flow/open_flow_header.rb +11 -2
  71. data/lib/pio/open_flow/port.rb +69 -0
  72. data/lib/pio/open_flow10.rb +5 -0
  73. data/lib/pio/open_flow10/actions.rb +8 -6
  74. data/lib/pio/open_flow10/enqueue.rb +13 -13
  75. data/lib/pio/open_flow10/error.rb +28 -0
  76. data/lib/pio/open_flow10/error/bad_request.rb +66 -0
  77. data/lib/pio/open_flow10/error/error_type10.rb +26 -0
  78. data/lib/pio/open_flow10/error/hello_failed.rb +41 -0
  79. data/lib/pio/open_flow10/features.rb +6 -10
  80. data/lib/pio/open_flow10/flow_mod.rb +1 -1
  81. data/lib/pio/open_flow10/flow_stats_request.rb +1 -1
  82. data/lib/pio/open_flow10/hello.rb +2 -2
  83. data/lib/pio/open_flow10/match.rb +2 -2
  84. data/lib/pio/{open_flow/phy_port.rb → open_flow10/phy_port16.rb} +4 -4
  85. data/lib/pio/open_flow10/port16.rb +21 -0
  86. data/lib/pio/open_flow10/port_status.rb +1 -1
  87. data/lib/pio/open_flow10/send_out_port.rb +16 -40
  88. data/lib/pio/open_flow10/set_ether_address.rb +9 -8
  89. data/lib/pio/open_flow10/set_ip_address.rb +4 -4
  90. data/lib/pio/open_flow10/set_ip_tos.rb +4 -4
  91. data/lib/pio/open_flow10/set_transport_port.rb +12 -12
  92. data/lib/pio/open_flow10/set_vlan.rb +4 -4
  93. data/lib/pio/open_flow10/set_vlan_vid.rb +0 -12
  94. data/lib/pio/open_flow10/strip_vlan_header.rb +7 -7
  95. data/lib/pio/open_flow10/vendor_action.rb +33 -0
  96. data/lib/pio/open_flow13.rb +3 -0
  97. data/lib/pio/open_flow13/actions.rb +3 -3
  98. data/lib/pio/open_flow13/error.rb +28 -0
  99. data/lib/pio/open_flow13/error/bad_request.rb +66 -0
  100. data/lib/pio/open_flow13/error/error_type13.rb +37 -0
  101. data/lib/pio/open_flow13/error/hello_failed.rb +42 -0
  102. data/lib/pio/open_flow13/features_reply.rb +33 -33
  103. data/lib/pio/open_flow13/features_request.rb +3 -3
  104. data/lib/pio/open_flow13/flow_mod.rb +2 -2
  105. data/lib/pio/open_flow13/goto_table.rb +2 -0
  106. data/lib/pio/open_flow13/packet_out.rb +1 -1
  107. data/lib/pio/open_flow13/port32.rb +21 -0
  108. data/lib/pio/open_flow13/send_out_port.rb +3 -2
  109. data/lib/pio/version.rb +1 -1
  110. data/pio.gemspec +5 -5
  111. data/spec/pio/open_flow10/enqueue_spec.rb +22 -22
  112. data/spec/pio/open_flow10/error/hello_failed_spec.rb +26 -0
  113. data/spec/pio/open_flow10/flow_mod_spec.rb +6 -6
  114. data/spec/pio/open_flow10/flow_stats_request_spec.rb +1 -1
  115. data/spec/pio/open_flow10/hello_spec.rb +3 -3
  116. data/spec/pio/open_flow10/packet_out_spec.rb +33 -33
  117. data/spec/pio/{open_flow/phy_port_spec.rb → open_flow10/phy_port16_spec.rb} +7 -7
  118. data/spec/pio/open_flow10/send_out_port_spec.rb +28 -28
  119. data/spec/pio/open_flow10/set_ether_destination_address_spec.rb +2 -2
  120. data/spec/pio/open_flow10/set_ether_source_address_spec.rb +2 -2
  121. data/spec/pio/open_flow10/set_ip_destination_address_spec.rb +4 -4
  122. data/spec/pio/open_flow10/set_ip_source_address_spec.rb +4 -4
  123. data/spec/pio/open_flow10/set_ip_tos_spec.rb +4 -4
  124. data/spec/pio/open_flow10/set_transport_destination_port_spec.rb +11 -11
  125. data/spec/pio/open_flow10/set_transport_source_port_spec.rb +11 -11
  126. data/spec/pio/open_flow10/set_vlan_priority_spec.rb +4 -4
  127. data/spec/pio/open_flow10/set_vlan_vid_spec.rb +4 -4
  128. data/spec/pio/open_flow10/strip_vlan_header_spec.rb +6 -6
  129. data/spec/pio/open_flow13/error/bad_request_spec.rb +6 -0
  130. data/spec/pio/open_flow13/error/hello_failed_spec.rb +26 -0
  131. data/spec/pio/open_flow13/hello_spec.rb +3 -3
  132. data/spec/support/shared_examples_for_openflow_messages.rb +40 -27
  133. metadata +106 -16
  134. data/lib/pio/open_flow/port_number.rb +0 -39
@@ -0,0 +1,7 @@
1
+ Cucumber Step Definitions
2
+ =========================
3
+
4
+ A collection of step definitions for use with [Trema][trema] and Trema apps.
5
+ These steps are highly specific to Trema.
6
+
7
+ [trema]: https://github.com/trema/trema_ruby
@@ -0,0 +1,10 @@
1
+ task default: :rubocop
2
+
3
+ begin
4
+ require 'rubocop/rake_task'
5
+ RuboCop::RakeTask.new
6
+ rescue LoadError
7
+ task :rubocop do
8
+ $stderr.puts 'RuboCop is disabled'
9
+ end
10
+ end
@@ -0,0 +1,13 @@
1
+ # rubocop:disable LineLength
2
+
3
+ Then(/^the switch "(.*?)" has (\d+) flow entr(?:y|ies)$/) do |switch, num_entries|
4
+ command = "trema dump_flows #{switch} -S."
5
+ step "I run `#{command}`"
6
+ expect(output_from(command).split("\n").size - 1).to eq(num_entries.to_i)
7
+ end
8
+
9
+ Then(/^the switch "(.*?)" has no flow entry$/) do |switch|
10
+ step %(the switch "#{switch}" has 0 flow entry)
11
+ end
12
+
13
+ # rubocop:enable LineLength
@@ -59,6 +59,10 @@ Then(/^the message has the following fields and values:$/) do |table|
59
59
  step 'the packet has the following fields and values:', table
60
60
  end
61
61
 
62
+ Then(/^the action has the following fields and values:$/) do |table|
63
+ step 'the packet has the following fields and values:', table
64
+ end
65
+
62
66
  # rubocop:disable LineLength
63
67
  Then(/^the message \#(\d+) have the following fields and values:$/) do |index, table|
64
68
  table.hashes.each do |each|
@@ -0,0 +1,40 @@
1
+ begin
2
+ require 'rack/test'
3
+
4
+ World(Rack::Test::Methods)
5
+
6
+ Given(/^I send and accept JSON$/) do
7
+ header 'Accept', 'application/json'
8
+ header 'Cotent-Type', 'application/json'
9
+ end
10
+
11
+ Given(/^I send a GET request for "([^\"]*)"$/) do |path|
12
+ in_current_dir { get path }
13
+ end
14
+
15
+ # rubocop:disable LineLength
16
+ Given(/^I send a POST request for "([^\"]*)" with body "([^\"]*)"$/) do |path, body|
17
+ in_current_dir { post path, Object.instance_eval(body) }
18
+ end
19
+ # rubocop:enable LineLength
20
+
21
+ # rubocop:disable LineLength
22
+ Given(/^I send a DELETE request for "([^\"]*)" with body "([^\"]*)"$/) do |path, body|
23
+ in_current_dir { delete path, Object.instance_eval(body) }
24
+ end
25
+ # rubocop:enable LineLength
26
+
27
+ Then(/^the response should be "([^\"]*)"$/) do |status|
28
+ expect(last_response.status).to eq(status.to_i)
29
+ end
30
+
31
+ Then(/^the JSON response should be "([^\"]*)"$/) do |json|
32
+ expect(JSON.parse(last_response.body)).to eq(JSON.parse(json))
33
+ end
34
+
35
+ Then(/^the JSON response should be:$/) do |json|
36
+ expect(JSON.parse(last_response.body)).to eq(JSON.parse(json))
37
+ end
38
+ rescue LoadError
39
+ $stderr.puts 'Rack is disabled'
40
+ end
@@ -0,0 +1,83 @@
1
+ # rubocop:disable LineLength
2
+
3
+ Then(/^the number of packets sent from "(.*?)" should be:$/) do |host_name, table|
4
+ command = "trema show_stats #{host_name}"
5
+ step "I run `#{command}`"
6
+
7
+ result = {}
8
+ cd('.') do
9
+ output_from(command).split("\n").each do |each|
10
+ case each
11
+ when /Packets sent/
12
+ next
13
+ when /Packets recevied/
14
+ break
15
+ when /-> (\S+) = (\d+) packet/
16
+ result[Regexp.last_match(1)] = Regexp.last_match(2).to_i
17
+ else
18
+ fail "Failed to parse line '#{each}'"
19
+ end
20
+ end
21
+ end
22
+ table.hashes.each do |each|
23
+ ip_address = each.fetch('destination')
24
+ expect(result.fetch(ip_address)).to eq(each.fetch('#packets').to_i)
25
+ end
26
+ end
27
+
28
+ Then(/^the number of packets received by "(.*?)" should be:$/) do |host_name, table|
29
+ command = "trema show_stats #{host_name}"
30
+ step "I run `#{command}`"
31
+
32
+ result = Hash.new(0)
33
+ cd('.') do
34
+ received = false
35
+ output_from(command).split("\n").each do |each|
36
+ case each
37
+ when /Packets sent/
38
+ next
39
+ when /Packets received/
40
+ received = true
41
+ next
42
+ when /(\S+) -> (\S+) = (\d+) packet/
43
+ next unless received
44
+ result[Regexp.last_match(1)] = Regexp.last_match(3).to_i
45
+ else
46
+ fail "Failed to parse line '#{each}'"
47
+ end
48
+ end
49
+ end
50
+ table.hashes.each do |each|
51
+ ip_address = each.fetch('source')
52
+ expect(result[ip_address]).to eq(each.fetch('#packets').to_i)
53
+ end
54
+ end
55
+
56
+ Then(/^the total number of received packets should be:$/) do |table|
57
+ table.hashes[0].each_pair do |host_name, npackets|
58
+ command = "trema show_stats #{host_name}"
59
+ step "I run `#{command}`"
60
+
61
+ result = 0
62
+ cd('.') do
63
+ received = false
64
+ output_from(command).split("\n").each do |each|
65
+ case each
66
+ when /Packets sent/
67
+ next
68
+ when /Packets received/
69
+ received = true
70
+ next
71
+ when /(\S+) -> (\S+) = (\d+) packet/
72
+ next unless received
73
+ result += Regexp.last_match(3).to_i
74
+ else
75
+ fail "Failed to parse line '#{each}'"
76
+ end
77
+ end
78
+ end
79
+ expect(result).to eq(npackets.to_i)
80
+ end
81
+ end
82
+
83
+ # rubocop:enable LineLength
@@ -0,0 +1,33 @@
1
+ Given(/^I use OpenFlow 1\.0$/) do
2
+ @open_flow_version = :open_flow10
3
+ end
4
+
5
+ Given(/^I use OpenFlow 1\.3$/) do
6
+ @open_flow_version = :open_flow13
7
+ end
8
+
9
+ # rubocop:disable LineLength
10
+ When(/^I trema run "([^"]*)"( interactively)? with the configuration "([^"]*)"$/) do |controller_file, interactive, configuration_file|
11
+ open_flow_option = @open_flow_version == :open_flow13 ? ' --openflow13' : ''
12
+ run_arguments = "#{File.join '..', '..', controller_file}#{open_flow_option} -c #{configuration_file}"
13
+ if interactive
14
+ step %(I run `trema run #{run_arguments}` interactively)
15
+ else
16
+ step %(I successfully run `trema run #{run_arguments} -d`)
17
+ end
18
+ step %(I successfully run `sleep 3`)
19
+ end
20
+ # rubocop:enable LineLength
21
+
22
+ When(/^I trema killall "([^"]*)"$/) do |controller_name|
23
+ step %(I successfully run `trema killall #{controller_name}`)
24
+ end
25
+
26
+ # rubocop:disable LineLength
27
+ Then(/^the log file "([^"]*)" should contain following messages:$/) do |log_file, messages|
28
+ step %(a file named "#{log_file}" should exist)
29
+ messages.rows.flatten.each do |each|
30
+ step %(the file "#{log_file}" should contain "#{each}")
31
+ end
32
+ end
33
+ # rubocop:enable LineLength
@@ -0,0 +1,8 @@
1
+ # rubocop:disable LineLength
2
+
3
+ Then(/^virtual links should not exist$/) do
4
+ step %(I run `bash -c 'ifconfig | grep "^link[0-9]\+-[0-9]\+" > virtual_links.txt'`)
5
+ step 'the file "virtual_links.txt" should not contain "link"'
6
+ end
7
+
8
+ # rubocop:enable LineLength
@@ -1,10 +1,9 @@
1
1
  require 'pio/open_flow/datapath_id'
2
+ require 'pio/open_flow/error'
2
3
  require 'pio/open_flow/flags'
3
4
  require 'pio/open_flow/format'
4
5
  require 'pio/open_flow/message'
5
6
  require 'pio/open_flow/open_flow_header'
6
- require 'pio/open_flow/phy_port'
7
- require 'pio/open_flow/port_number'
8
7
  require 'pio/open_flow10'
9
8
  require 'pio/open_flow13'
10
9
 
@@ -19,7 +18,7 @@ module Pio
19
18
  def self.switch_version(version)
20
19
  [:Barrier, :Echo, :Features, :FlowMod, :Hello, :Match,
21
20
  :PacketIn, :PacketOut, :SendOutPort, :PortStatus,
22
- :FlowStats].each do |each|
21
+ :FlowStats, :Error].each do |each|
23
22
  set_message_class_name each, version
24
23
  @version = version.to_s
25
24
  end
@@ -29,12 +28,15 @@ module Pio
29
28
  def self.read(binary)
30
29
  parser = {
31
30
  0 => Pio::Hello,
31
+ 1 => Pio::OpenFlow::Error,
32
32
  2 => Pio::Echo::Request,
33
33
  3 => Pio::Echo::Reply,
34
34
  5 => Pio::Features::Request,
35
35
  6 => Pio::Features::Reply,
36
36
  10 => Pio::PacketIn,
37
37
  12 => Pio::PortStatus,
38
+ 13 => Pio::PacketOut,
39
+ 14 => Pio::FlowMod,
38
40
  16 => Pio::FlowStats::Request,
39
41
  17 => Pio::FlowStats::Reply,
40
42
  18 => Pio::Barrier::Request,
@@ -42,8 +44,6 @@ module Pio
42
44
  }
43
45
  header = OpenFlowHeaderParser.read(binary)
44
46
  parser.fetch(header.message_type).read(binary)
45
- rescue
46
- raise "Unknown message type #{header.message_type}"
47
47
  end
48
48
  # rubocop:enable MethodLength
49
49
 
@@ -13,7 +13,7 @@ module Pio
13
13
 
14
14
  header version: :of_version,
15
15
  message_type: :of_message_type
16
- string :body, read_length: -> { message_length - header_length }
16
+ string :body, read_length: -> { length - header_length }
17
17
 
18
18
  def user_data
19
19
  body
@@ -0,0 +1,19 @@
1
+ module Pio
2
+ module OpenFlow
3
+ # Error message parser
4
+ class Error
5
+ def self.read(binary)
6
+ version = OpenFlowHeaderParser.read(binary).ofp_version
7
+ error_parser = case version
8
+ when 1
9
+ Pio::OpenFlow10::Error
10
+ when 4
11
+ Pio::OpenFlow13::Error
12
+ else
13
+ fail "Unsupported OpenFlow version: #{version}"
14
+ end
15
+ error_parser.read binary
16
+ end
17
+ end
18
+ end
19
+ end
@@ -32,10 +32,11 @@ module Pio
32
32
  def_delegators :header, :snapshot
33
33
  def_delegators :snapshot, :ofp_version
34
34
  def_delegators :snapshot, :message_type
35
- def_delegators :snapshot, :message_length
35
+ def_delegators :snapshot, :_length
36
36
  def_delegators :snapshot, :transaction_id
37
37
  def_delegator :snapshot, :transaction_id, :xid
38
38
 
39
+ alias_method :length, :_length
39
40
  alias_method :to_binary, :to_binary_s
40
41
  end
41
42
  end
@@ -0,0 +1,21 @@
1
+ require 'bindata'
2
+
3
+ module Pio
4
+ module OpenFlow
5
+ # enum ofp_hello_failed_code
6
+ class HelloFailedCode < BinData::Primitive
7
+ ERROR_CODES = { incompatible: 0, permissions_error: 1 }
8
+
9
+ endian :big
10
+ uint16 :error_code
11
+
12
+ def get
13
+ ERROR_CODES.invert.fetch(error_code)
14
+ end
15
+
16
+ def set(value)
17
+ self.error_code = ERROR_CODES.fetch(value)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -8,8 +8,13 @@ module Pio
8
8
 
9
9
  uint8 :ofp_version
10
10
  uint8 :message_type
11
- uint16 :message_length
11
+ uint16 :_length
12
12
  transaction_id :transaction_id
13
+ rest :body
14
+
15
+ def length
16
+ _length
17
+ end
13
18
  end
14
19
 
15
20
  # OpenFlow message header.
@@ -20,7 +25,11 @@ module Pio
20
25
  virtual assert: -> { ofp_version == ofp_version_value }
21
26
  uint8 :message_type, value: :message_type_value
22
27
  virtual assert: -> { message_type == message_type_value }
23
- uint16 :message_length, initial_value: -> { 8 + body.length }
28
+ uint16 :_length, initial_value: -> { 8 + body.length }
24
29
  transaction_id :transaction_id, initial_value: 0
30
+
31
+ def length
32
+ _length
33
+ end
25
34
  end
26
35
  end
@@ -0,0 +1,69 @@
1
+ module Pio
2
+ module OpenFlow
3
+ # Port numbering.
4
+ class Port < BinData::Primitive
5
+ endian :big
6
+
7
+ def self.port_size_in_bytes(nbytes)
8
+ class_eval "uint#{nbytes} :port"
9
+ end
10
+
11
+ def self.max_port_number(port_number)
12
+ const_set :MAX, port_number
13
+ end
14
+
15
+ def self.reserved_ports(port_name_and_number)
16
+ @reserved = port_name_and_number
17
+ end
18
+
19
+ def self.reserved_port_number(port_name)
20
+ @reserved.fetch port_name
21
+ end
22
+
23
+ def self.reserved_port_name?(port_name)
24
+ @reserved.key? port_name
25
+ end
26
+
27
+ def max
28
+ self.class.const_get :MAX
29
+ end
30
+
31
+ def reserved_port_number(port_name)
32
+ self.class.reserved_port_number port_name
33
+ end
34
+
35
+ def reserved_port_name?(port_name)
36
+ self.class.reserved_port_name? port_name
37
+ end
38
+
39
+ def reserved_port_number?(port_number)
40
+ self.class.instance_variable_get(:@reserved).invert.key?(port_number)
41
+ end
42
+
43
+ def reserved_port_name(port_number)
44
+ self.class.instance_variable_get(:@reserved).invert.fetch(port_number)
45
+ end
46
+
47
+ def get
48
+ if reserved_port_number?(port)
49
+ reserved_port_name(port)
50
+ else
51
+ port
52
+ end
53
+ end
54
+
55
+ def set(port)
56
+ if reserved_port_name?(port)
57
+ self.port = reserved_port_number(port)
58
+ else
59
+ port_num = port.to_i
60
+ fail ArgumentError, 'The port should be > 0' if port_num < 1
61
+ if port_num >= max
62
+ fail ArgumentError, "The port should be < #{max.to_hex}"
63
+ end
64
+ self.port = port_num
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -1,6 +1,9 @@
1
1
  require 'pio/open_flow10/barrier_reply'
2
2
  require 'pio/open_flow10/barrier_request'
3
3
  require 'pio/open_flow10/echo'
4
+ require 'pio/open_flow10/error'
5
+ require 'pio/open_flow10/error/bad_request'
6
+ require 'pio/open_flow10/error/hello_failed'
4
7
  require 'pio/open_flow10/exact_match'
5
8
  require 'pio/open_flow10/features'
6
9
  require 'pio/open_flow10/flow_mod'
@@ -9,5 +12,7 @@ require 'pio/open_flow10/flow_stats_request'
9
12
  require 'pio/open_flow10/hello'
10
13
  require 'pio/open_flow10/packet_in'
11
14
  require 'pio/open_flow10/packet_out'
15
+ require 'pio/open_flow10/phy_port16'
16
+ require 'pio/open_flow10/port16'
12
17
  require 'pio/open_flow10/port_status'
13
18
  require 'pio/open_flow10/send_out_port'
@@ -8,6 +8,7 @@ require 'pio/open_flow10/set_transport_port'
8
8
  require 'pio/open_flow10/set_vlan_priority'
9
9
  require 'pio/open_flow10/set_vlan_vid'
10
10
  require 'pio/open_flow10/strip_vlan_header'
11
+ require 'pio/open_flow10/vendor_action'
11
12
 
12
13
  module Pio
13
14
  module OpenFlow
@@ -18,14 +19,15 @@ module Pio
18
19
  1 => Pio::SetVlanVid,
19
20
  2 => Pio::SetVlanPriority,
20
21
  3 => Pio::StripVlanHeader,
21
- 4 => Pio::SetEtherSourceAddr,
22
- 5 => Pio::SetEtherDestinationAddr,
22
+ 4 => Pio::SetEtherSourceAddress,
23
+ 5 => Pio::SetEtherDestinationAddress,
23
24
  6 => Pio::SetIpSourceAddress,
24
25
  7 => Pio::SetIpDestinationAddress,
25
26
  8 => Pio::SetIpTos,
26
27
  9 => Pio::SetTransportSourcePort,
27
28
  10 => Pio::SetTransportDestinationPort,
28
- 11 => Pio::Enqueue
29
+ 11 => Pio::Enqueue,
30
+ 0xffff => Pio::VendorAction
29
31
  }
30
32
 
31
33
  mandatory_parameter :length
@@ -34,8 +36,8 @@ module Pio
34
36
 
35
37
  string :binary, read_length: :length
36
38
 
37
- def set(value)
38
- self.binary = [value].flatten.map(&:to_binary).join
39
+ def set(actions)
40
+ self.binary = Array(actions).map(&:to_binary).join
39
41
  end
40
42
 
41
43
  # rubocop:disable MethodLength
@@ -47,7 +49,7 @@ module Pio
47
49
  type = BinData::Uint16be.read(tmp)
48
50
  begin
49
51
  action = ACTION_CLASS.fetch(type).read(tmp)
50
- tmp = tmp[action.message_length..-1]
52
+ tmp = tmp[action.length..-1]
51
53
  actions << action
52
54
  rescue KeyError
53
55
  raise "action type #{type} is not supported."