pio 0.25.0 → 0.26.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/README.md +4 -0
- data/Rakefile +1 -1
- data/bin/terminal-notifier +16 -0
- data/features/open_flow10/bad_request.feature +35 -0
- data/features/open_flow10/bad_request.raw +0 -0
- data/features/open_flow10/barrier_reply.feature +4 -4
- data/features/open_flow10/barrier_request.feature +4 -4
- data/features/open_flow10/echo_reply.feature +13 -13
- data/features/open_flow10/echo_request.feature +6 -6
- data/features/open_flow10/enqueue.feature +17 -0
- data/features/open_flow10/features_reply.feature +2 -2
- data/features/open_flow10/features_request.feature +28 -28
- data/features/open_flow10/flow_mod.feature +5 -5
- data/features/open_flow10/flow_stats_reply.feature +12 -12
- data/features/open_flow10/flow_stats_request.feature +3 -3
- data/features/open_flow10/hello.feature +8 -15
- data/features/open_flow10/hello_failed.feature +69 -0
- data/features/open_flow10/hello_failed.raw +0 -0
- data/features/open_flow10/nxast_learn.raw +0 -0
- data/features/open_flow10/packet_in.feature +2 -2
- data/features/open_flow10/packet_out.feature +13 -13
- data/features/open_flow10/port_status.feature +1 -1
- data/features/open_flow10/send_out_port.feature +106 -0
- data/features/open_flow10/set_ether_destination_address.feature +16 -0
- data/features/open_flow10/set_ether_source_address.feature +16 -0
- data/features/open_flow10/set_ip_destination_address.feature +16 -0
- data/features/open_flow10/set_ip_source_address.feature +16 -0
- data/features/open_flow10/set_ip_tos.feature +16 -0
- data/features/open_flow10/set_transport_destination_port.feature +16 -0
- data/features/open_flow10/set_transport_source_port.feature +16 -0
- data/features/open_flow10/set_vlan_priority.feature +16 -0
- data/features/open_flow10/set_vlan_vid.feature +16 -0
- data/features/open_flow10/strip_vlan_header.feature +15 -0
- data/features/open_flow10/vendor_action.feature +14 -0
- data/features/open_flow13/bad_request.feature +35 -0
- data/features/open_flow13/bad_request.raw +0 -0
- data/features/open_flow13/echo_reply.feature +7 -7
- data/features/open_flow13/echo_request.feature +7 -7
- data/features/open_flow13/features_reply.feature +2 -2
- data/features/open_flow13/features_request.feature +28 -28
- data/features/open_flow13/flow_mod.feature +24 -24
- data/features/open_flow13/hello.feature +5 -5
- data/features/open_flow13/hello_failed.feature +69 -0
- data/features/open_flow13/hello_failed.raw +0 -0
- data/features/open_flow13/packet_in.feature +3 -3
- data/features/open_flow13/packet_out.feature +3 -3
- data/features/open_flow13/send_out_port.feature +101 -10
- data/features/open_flow13/table_stats_reply.raw +0 -0
- data/features/open_flow13/table_stats_request.raw +0 -0
- data/features/open_flow_read.feature +6 -0
- data/features/step_definitions/Gemfile +9 -0
- data/features/step_definitions/Gemfile.lock +76 -0
- data/features/step_definitions/Guardfile +4 -0
- data/features/step_definitions/LICENSE +675 -0
- data/features/step_definitions/README.md +7 -0
- data/features/step_definitions/Rakefile +10 -0
- data/features/step_definitions/dump_flows_steps.rb +13 -0
- data/features/step_definitions/packet_data_steps.rb +4 -0
- data/features/step_definitions/rest_api_steps.rb +40 -0
- data/features/step_definitions/show_stats_steps.rb +83 -0
- data/features/step_definitions/trema_steps.rb +33 -0
- data/features/step_definitions/virtual_link_steps.rb +8 -0
- data/lib/pio/open_flow.rb +5 -5
- data/lib/pio/open_flow/echo.rb +1 -1
- data/lib/pio/open_flow/error.rb +19 -0
- data/lib/pio/open_flow/format.rb +2 -1
- data/lib/pio/open_flow/hello_failed_code.rb +21 -0
- data/lib/pio/open_flow/open_flow_header.rb +11 -2
- data/lib/pio/open_flow/port.rb +69 -0
- data/lib/pio/open_flow10.rb +5 -0
- data/lib/pio/open_flow10/actions.rb +8 -6
- data/lib/pio/open_flow10/enqueue.rb +13 -13
- data/lib/pio/open_flow10/error.rb +28 -0
- data/lib/pio/open_flow10/error/bad_request.rb +66 -0
- data/lib/pio/open_flow10/error/error_type10.rb +26 -0
- data/lib/pio/open_flow10/error/hello_failed.rb +41 -0
- data/lib/pio/open_flow10/features.rb +6 -10
- data/lib/pio/open_flow10/flow_mod.rb +1 -1
- data/lib/pio/open_flow10/flow_stats_request.rb +1 -1
- data/lib/pio/open_flow10/hello.rb +2 -2
- data/lib/pio/open_flow10/match.rb +2 -2
- data/lib/pio/{open_flow/phy_port.rb → open_flow10/phy_port16.rb} +4 -4
- data/lib/pio/open_flow10/port16.rb +21 -0
- data/lib/pio/open_flow10/port_status.rb +1 -1
- data/lib/pio/open_flow10/send_out_port.rb +16 -40
- data/lib/pio/open_flow10/set_ether_address.rb +9 -8
- data/lib/pio/open_flow10/set_ip_address.rb +4 -4
- data/lib/pio/open_flow10/set_ip_tos.rb +4 -4
- data/lib/pio/open_flow10/set_transport_port.rb +12 -12
- data/lib/pio/open_flow10/set_vlan.rb +4 -4
- data/lib/pio/open_flow10/set_vlan_vid.rb +0 -12
- data/lib/pio/open_flow10/strip_vlan_header.rb +7 -7
- data/lib/pio/open_flow10/vendor_action.rb +33 -0
- data/lib/pio/open_flow13.rb +3 -0
- data/lib/pio/open_flow13/actions.rb +3 -3
- data/lib/pio/open_flow13/error.rb +28 -0
- data/lib/pio/open_flow13/error/bad_request.rb +66 -0
- data/lib/pio/open_flow13/error/error_type13.rb +37 -0
- data/lib/pio/open_flow13/error/hello_failed.rb +42 -0
- data/lib/pio/open_flow13/features_reply.rb +33 -33
- data/lib/pio/open_flow13/features_request.rb +3 -3
- data/lib/pio/open_flow13/flow_mod.rb +2 -2
- data/lib/pio/open_flow13/goto_table.rb +2 -0
- data/lib/pio/open_flow13/packet_out.rb +1 -1
- data/lib/pio/open_flow13/port32.rb +21 -0
- data/lib/pio/open_flow13/send_out_port.rb +3 -2
- data/lib/pio/version.rb +1 -1
- data/pio.gemspec +5 -5
- data/spec/pio/open_flow10/enqueue_spec.rb +22 -22
- data/spec/pio/open_flow10/error/hello_failed_spec.rb +26 -0
- data/spec/pio/open_flow10/flow_mod_spec.rb +6 -6
- data/spec/pio/open_flow10/flow_stats_request_spec.rb +1 -1
- data/spec/pio/open_flow10/hello_spec.rb +3 -3
- data/spec/pio/open_flow10/packet_out_spec.rb +33 -33
- data/spec/pio/{open_flow/phy_port_spec.rb → open_flow10/phy_port16_spec.rb} +7 -7
- data/spec/pio/open_flow10/send_out_port_spec.rb +28 -28
- data/spec/pio/open_flow10/set_ether_destination_address_spec.rb +2 -2
- data/spec/pio/open_flow10/set_ether_source_address_spec.rb +2 -2
- data/spec/pio/open_flow10/set_ip_destination_address_spec.rb +4 -4
- data/spec/pio/open_flow10/set_ip_source_address_spec.rb +4 -4
- data/spec/pio/open_flow10/set_ip_tos_spec.rb +4 -4
- data/spec/pio/open_flow10/set_transport_destination_port_spec.rb +11 -11
- data/spec/pio/open_flow10/set_transport_source_port_spec.rb +11 -11
- data/spec/pio/open_flow10/set_vlan_priority_spec.rb +4 -4
- data/spec/pio/open_flow10/set_vlan_vid_spec.rb +4 -4
- data/spec/pio/open_flow10/strip_vlan_header_spec.rb +6 -6
- data/spec/pio/open_flow13/error/bad_request_spec.rb +6 -0
- data/spec/pio/open_flow13/error/hello_failed_spec.rb +26 -0
- data/spec/pio/open_flow13/hello_spec.rb +3 -3
- data/spec/support/shared_examples_for_openflow_messages.rb +40 -27
- metadata +106 -16
- data/lib/pio/open_flow/port_number.rb +0 -39
@@ -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
|
data/lib/pio/open_flow.rb
CHANGED
@@ -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
|
|
data/lib/pio/open_flow/echo.rb
CHANGED
@@ -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
|
data/lib/pio/open_flow/format.rb
CHANGED
@@ -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, :
|
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 :
|
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 :
|
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
|
data/lib/pio/open_flow10.rb
CHANGED
@@ -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::
|
22
|
-
5 => Pio::
|
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(
|
38
|
-
self.binary =
|
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.
|
52
|
+
tmp = tmp[action.length..-1]
|
51
53
|
actions << action
|
52
54
|
rescue KeyError
|
53
55
|
raise "action type #{type} is not supported."
|