pio 0.25.0 → 0.26.0

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 (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."