pio 0.23.1 → 0.24.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 +16 -0
- data/README.md +2 -0
- data/Rakefile +1 -1
- data/features/open_flow10/barrier_reply.feature +58 -0
- data/features/open_flow10/barrier_request.feature +58 -0
- data/features/open_flow10/echo_reply.feature +50 -40
- data/features/open_flow10/echo_request.feature +54 -51
- data/features/open_flow10/features_reply.feature +62 -63
- data/features/open_flow10/features_request.feature +2 -19
- data/features/open_flow10/flow_mod.feature +1 -0
- data/features/open_flow10/hello.feature +38 -44
- data/features/open_flow10/packet_in.feature +1 -2
- data/features/open_flow10/packet_in.raw +0 -0
- data/features/open_flow10/packet_out.feature +14 -14
- data/features/open_flow10/port_status.feature +17 -17
- data/features/open_flow13/apply_actions.feature +15 -17
- data/features/open_flow13/echo_reply.feature +58 -58
- data/features/open_flow13/echo_request.feature +58 -58
- data/features/open_flow13/features_reply.feature +2 -6
- data/features/open_flow13/features_request.feature +3 -23
- data/features/open_flow13/flow_mod.feature +86 -93
- data/features/open_flow13/goto_table.feature +4 -4
- data/features/open_flow13/hello.feature +8 -15
- data/features/open_flow13/match.feature +14 -3
- data/features/open_flow13/meter.feature +3 -3
- data/features/open_flow13/oxm_experimenter_stratos_basic_dot11.raw +0 -0
- data/features/open_flow13/oxm_invalid_field.raw +0 -0
- data/features/open_flow13/packet_in.feature +15 -20
- data/features/open_flow13/packet_out.feature +39 -42
- data/features/open_flow13/send_out_port.feature +1 -5
- data/features/open_flow13/write_metadata.feature +3 -3
- data/features/open_flow_read.feature +43 -0
- data/features/open_flow_version.feature +10 -0
- data/features/step_definitions/open_flow_steps.rb +10 -2
- data/features/step_definitions/packet_data_steps.rb +4 -0
- data/features/support/hooks.rb +7 -0
- data/lib/pio.rb +1 -1
- data/lib/pio/monkey_patch/integer/ranges.rb +4 -0
- data/lib/pio/open_flow.rb +54 -16
- data/lib/pio/open_flow/datapath_id.rb +26 -0
- data/lib/pio/open_flow/echo.rb +44 -0
- data/lib/pio/open_flow/format.rb +45 -0
- data/lib/pio/open_flow/message.rb +88 -0
- data/lib/pio/open_flow/open_flow_header.rb +0 -14
- data/lib/pio/open_flow10.rb +3 -8
- data/lib/pio/open_flow10/actions.rb +1 -1
- data/lib/pio/open_flow10/barrier_reply.rb +21 -0
- data/lib/pio/open_flow10/barrier_request.rb +22 -0
- data/lib/pio/open_flow10/echo.rb +15 -11
- data/lib/pio/open_flow10/features.rb +99 -71
- data/lib/pio/open_flow10/flow_mod.rb +73 -66
- data/lib/pio/open_flow10/hello.rb +19 -4
- data/lib/pio/open_flow10/match.rb +133 -131
- data/lib/pio/open_flow10/packet_in.rb +55 -49
- data/lib/pio/open_flow10/packet_out.rb +31 -24
- data/lib/pio/open_flow10/port_status.rb +54 -27
- data/lib/pio/open_flow10/send_out_port.rb +66 -64
- data/lib/pio/open_flow13.rb +0 -15
- data/lib/pio/open_flow13/echo.rb +11 -68
- data/lib/pio/open_flow13/features_reply.rb +48 -77
- data/lib/pio/open_flow13/features_request.rb +16 -45
- data/lib/pio/open_flow13/flow_mod.rb +125 -148
- data/lib/pio/open_flow13/goto_table.rb +1 -0
- data/lib/pio/open_flow13/hello.rb +54 -84
- data/lib/pio/open_flow13/match.rb +69 -11
- data/lib/pio/open_flow13/meter.rb +1 -0
- data/lib/pio/open_flow13/packet_in.rb +38 -50
- data/lib/pio/open_flow13/packet_out.rb +50 -75
- data/lib/pio/open_flow13/send_out_port.rb +34 -34
- data/lib/pio/open_flow13/write_metadata.rb +1 -0
- data/lib/pio/parser.rb +3 -0
- data/lib/pio/version.rb +1 -1
- data/pio.gemspec +6 -6
- data/spec/pio/open_flow10/echo_reply_spec.rb +7 -0
- data/spec/pio/open_flow10/echo_request_spec.rb +7 -0
- data/spec/pio/open_flow10/features_reply_spec.rb +8 -0
- data/spec/pio/open_flow10/features_request_spec.rb +13 -0
- data/spec/pio/open_flow10/flow_mod_spec.rb +17 -16
- data/spec/pio/open_flow10/hello_spec.rb +7 -0
- data/spec/pio/open_flow10/match_spec.rb +8 -6
- data/spec/pio/open_flow10/packet_in_spec.rb +14 -0
- data/spec/pio/open_flow10/packet_out_spec.rb +21 -14
- data/spec/pio/open_flow10/send_out_port_spec.rb +4 -4
- data/spec/pio/open_flow10/wildcards_spec.rb +2 -2
- data/spec/pio/open_flow13/echo_reply_spec.rb +7 -0
- data/spec/pio/open_flow13/echo_request_spec.rb +7 -0
- data/spec/pio/open_flow13/features_reply_spec.rb +8 -0
- data/spec/pio/open_flow13/features_request_spec.rb +13 -0
- data/spec/pio/open_flow13/hello_spec.rb +14 -59
- data/spec/pio/open_flow13/packet_in_spec.rb +14 -0
- data/spec/pio/open_flow13/packet_out_spec.rb +7 -0
- data/spec/pio/open_flow_spec.rb +34 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/support/shared_examples_for_openflow_messages.rb +75 -0
- metadata +215 -170
- data/bin/byebug +0 -16
- data/bin/terminal-notifier +0 -16
- data/lib/pio/open_flow10/message.rb +0 -78
- data/spec/pio/open_flow/type_spec.rb +0 -5
data/lib/pio.rb
CHANGED
data/lib/pio/open_flow.rb
CHANGED
@@ -1,20 +1,58 @@
|
|
1
|
-
|
2
|
-
# OpenFlow specific types.
|
3
|
-
module OpenFlow
|
4
|
-
# OFPT_* constants.
|
5
|
-
HELLO = 0
|
6
|
-
ECHO_REQUEST = 2
|
7
|
-
ECHO_REPLY = 3
|
8
|
-
FEATURES_REQUEST = 5
|
9
|
-
FEATURES_REPLY = 6
|
10
|
-
PACKET_IN = 10
|
11
|
-
PORT_STATUS = 12
|
12
|
-
PACKET_OUT = 13
|
13
|
-
FLOW_MOD = 14
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
1
|
+
require 'pio/open_flow/datapath_id'
|
17
2
|
require 'pio/open_flow/flags'
|
3
|
+
require 'pio/open_flow/format'
|
4
|
+
require 'pio/open_flow/message'
|
18
5
|
require 'pio/open_flow/open_flow_header'
|
19
6
|
require 'pio/open_flow/phy_port'
|
20
7
|
require 'pio/open_flow/port_number'
|
8
|
+
require 'pio/open_flow10'
|
9
|
+
require 'pio/open_flow13'
|
10
|
+
|
11
|
+
module Pio
|
12
|
+
# Common OpenFlow modules/classes.
|
13
|
+
module OpenFlow
|
14
|
+
def self.version
|
15
|
+
fail unless @version
|
16
|
+
@version
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.switch_version(version)
|
20
|
+
[:Barrier, :Echo, :Features, :FlowMod, :Hello, :Match,
|
21
|
+
:PacketIn, :PacketOut, :SendOutPort, :PortStatus].each do |each|
|
22
|
+
set_message_class_name each, version
|
23
|
+
@version = version.to_s
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# rubocop:disable MethodLength
|
28
|
+
def self.read(binary)
|
29
|
+
parser = {
|
30
|
+
0 => Pio::Hello,
|
31
|
+
2 => Pio::Echo::Request,
|
32
|
+
3 => Pio::Echo::Reply,
|
33
|
+
5 => Pio::Features::Request,
|
34
|
+
6 => Pio::Features::Reply,
|
35
|
+
10 => Pio::PacketIn,
|
36
|
+
12 => Pio::PortStatus
|
37
|
+
}
|
38
|
+
header = OpenFlowHeaderParser.read(binary)
|
39
|
+
parser.fetch(header.message_type).read(binary)
|
40
|
+
rescue
|
41
|
+
raise "Unknown message type #{header.message_type}"
|
42
|
+
end
|
43
|
+
# rubocop:enable MethodLength
|
44
|
+
|
45
|
+
def self.set_message_class_name(klass_name, version)
|
46
|
+
open_flow_module = Pio.const_get(version)
|
47
|
+
return unless open_flow_module.const_defined?(klass_name)
|
48
|
+
Pio.__send__ :remove_const, klass_name if Pio.const_defined?(klass_name)
|
49
|
+
Pio.const_set(klass_name, open_flow_module.const_get(klass_name))
|
50
|
+
rescue NameError
|
51
|
+
raise "#{version} is not supported yet."
|
52
|
+
end
|
53
|
+
private_class_method :set_message_class_name
|
54
|
+
|
55
|
+
# The default OpenFlow version is 1.0
|
56
|
+
switch_version 'OpenFlow10'
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'bindata'
|
2
|
+
require 'pio/monkey_patch/integer'
|
3
|
+
|
4
|
+
module Pio
|
5
|
+
module OpenFlow
|
6
|
+
# Datapath unique ID. The lower 48-bits are for a MAC address,
|
7
|
+
# while the upper 16-bits are implementer-defined.
|
8
|
+
class DatapathId < BinData::Primitive
|
9
|
+
endian :big
|
10
|
+
|
11
|
+
uint64 :datapath_id
|
12
|
+
|
13
|
+
def set(value)
|
14
|
+
unless value.unsigned_64bit?
|
15
|
+
fail(ArgumentError,
|
16
|
+
'Datapath ID should be an unsigned 64-bit integer.')
|
17
|
+
end
|
18
|
+
self.datapath_id = value
|
19
|
+
end
|
20
|
+
|
21
|
+
def get
|
22
|
+
datapath_id
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'pio/open_flow/format'
|
2
|
+
require 'pio/open_flow/message'
|
3
|
+
|
4
|
+
module Pio
|
5
|
+
module OpenFlow
|
6
|
+
# Base class of Echo Request and Reply.
|
7
|
+
class Echo < OpenFlow::Message
|
8
|
+
# rubocop:disable MethodLength
|
9
|
+
def self.inherited(child)
|
10
|
+
child.module_eval <<-EOS
|
11
|
+
class Format < BinData::Record
|
12
|
+
extend OpenFlow::Format
|
13
|
+
|
14
|
+
header version: :of_version,
|
15
|
+
message_type: :of_message_type
|
16
|
+
string :body, read_length: -> { message_length - header_length }
|
17
|
+
|
18
|
+
def user_data
|
19
|
+
body
|
20
|
+
end
|
21
|
+
end
|
22
|
+
EOS
|
23
|
+
end
|
24
|
+
# rubocop:enable MethodLength
|
25
|
+
|
26
|
+
def self.version(version)
|
27
|
+
const_get(:Format).tap do |klass|
|
28
|
+
klass.__send__(:define_method, :of_version) { version }
|
29
|
+
klass.class_eval { private :of_version }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.message_type(message_type)
|
34
|
+
const_get(:Format).tap do |klass|
|
35
|
+
klass.__send__(:define_method, :of_message_type) { message_type }
|
36
|
+
klass.class_eval { private :of_message_type }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
body_option :body
|
41
|
+
body_option :user_data
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'pio/open_flow/open_flow_header'
|
2
|
+
|
3
|
+
module Pio
|
4
|
+
module OpenFlow
|
5
|
+
# OpenFlow message definition macros.
|
6
|
+
module Format
|
7
|
+
include Forwardable
|
8
|
+
|
9
|
+
# rubocop:disable NestedMethodDefinition
|
10
|
+
def self.extended(base)
|
11
|
+
base.module_eval do
|
12
|
+
def header_length
|
13
|
+
8
|
14
|
+
end
|
15
|
+
|
16
|
+
def method_missing(method, *args, &block)
|
17
|
+
body.__send__ method, *args, &block
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
# rubocop:enable NestedMethodDefinition
|
22
|
+
|
23
|
+
# rubocop:disable MethodLength
|
24
|
+
def header(options)
|
25
|
+
module_eval do
|
26
|
+
endian :big
|
27
|
+
|
28
|
+
open_flow_header :header,
|
29
|
+
ofp_version_value: options.fetch(:version),
|
30
|
+
message_type_value: options.fetch(:message_type)
|
31
|
+
|
32
|
+
def_delegators :header, :snapshot
|
33
|
+
def_delegators :snapshot, :ofp_version
|
34
|
+
def_delegators :snapshot, :message_type
|
35
|
+
def_delegators :snapshot, :message_length
|
36
|
+
def_delegators :snapshot, :transaction_id
|
37
|
+
def_delegator :snapshot, :transaction_id, :xid
|
38
|
+
|
39
|
+
alias_method :to_binary, :to_binary_s
|
40
|
+
end
|
41
|
+
end
|
42
|
+
# rubocop:enable MethodLength
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module Pio
|
2
|
+
module OpenFlow
|
3
|
+
# OpenFlow messages.
|
4
|
+
class Message
|
5
|
+
# rubocop:disable MethodLength
|
6
|
+
def self.inherited(child)
|
7
|
+
child.class_eval <<-EOS
|
8
|
+
def self.read(raw_data)
|
9
|
+
allocate.tap do |message|
|
10
|
+
format_klass = self.const_get(:Format)
|
11
|
+
message.instance_variable_set(:@format,
|
12
|
+
format_klass.read(raw_data))
|
13
|
+
end
|
14
|
+
rescue BinData::ValidityError
|
15
|
+
message_name = name.split('::')[1..-1].join(' ')
|
16
|
+
raise Pio::ParseError, "Invalid \#{message_name} message."
|
17
|
+
end
|
18
|
+
EOS
|
19
|
+
end
|
20
|
+
# rubocop:enable MethodLength
|
21
|
+
|
22
|
+
def self.body_option(name)
|
23
|
+
unless class_variable_defined?(:@@valid_body_options)
|
24
|
+
class_variable_set(:@@valid_body_options, [])
|
25
|
+
end
|
26
|
+
class_variable_set(:@@valid_body_options,
|
27
|
+
class_variable_get(:@@valid_body_options) + [name])
|
28
|
+
end
|
29
|
+
|
30
|
+
def initialize(user_options = {})
|
31
|
+
validate_user_options user_options
|
32
|
+
@format = self.class.const_get(:Format).new(parse_options(user_options))
|
33
|
+
end
|
34
|
+
|
35
|
+
def method_missing(method, *args, &block)
|
36
|
+
@format.__send__ method, *args, &block
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def validate_user_options(user_options)
|
42
|
+
unknown_options =
|
43
|
+
user_options.keys - valid_header_options - valid_body_options
|
44
|
+
return if unknown_options.empty?
|
45
|
+
fail "Unknown option: #{unknown_options.first}"
|
46
|
+
end
|
47
|
+
|
48
|
+
def parse_options(user_options)
|
49
|
+
if valid_body_options.empty?
|
50
|
+
{ header: parse_header_options(user_options) }
|
51
|
+
else
|
52
|
+
{ header: parse_header_options(user_options),
|
53
|
+
body: parse_body_options(user_options) }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def parse_header_options(user_options)
|
58
|
+
transaction_id =
|
59
|
+
user_options[:transaction_id] || user_options[:xid] || 0
|
60
|
+
{ transaction_id: transaction_id }
|
61
|
+
end
|
62
|
+
|
63
|
+
def parse_body_options(user_options)
|
64
|
+
if valid_body_options.include?(:body)
|
65
|
+
return user_options[:body] || user_options[:user_data] || ''
|
66
|
+
end
|
67
|
+
options = user_options.dup
|
68
|
+
options.delete :transaction_id
|
69
|
+
options.delete :xid
|
70
|
+
dpid = options[:dpid]
|
71
|
+
options[:datapath_id] = dpid if dpid
|
72
|
+
options.empty? ? {} : options
|
73
|
+
end
|
74
|
+
|
75
|
+
def valid_header_options
|
76
|
+
[:transaction_id, :xid]
|
77
|
+
end
|
78
|
+
|
79
|
+
def valid_body_options
|
80
|
+
if self.class.class_variable_defined?(:@@valid_body_options)
|
81
|
+
self.class.class_variable_get(:@@valid_body_options)
|
82
|
+
else
|
83
|
+
[]
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -22,19 +22,5 @@ module Pio
|
|
22
22
|
virtual assert: -> { message_type == message_type_value }
|
23
23
|
uint16 :message_length, initial_value: -> { 8 + body.length }
|
24
24
|
transaction_id :transaction_id, initial_value: 0
|
25
|
-
|
26
|
-
# parse header options
|
27
|
-
class Options
|
28
|
-
def self.parse(options)
|
29
|
-
xid = if options.respond_to?(:to_i)
|
30
|
-
options.to_i
|
31
|
-
elsif options.respond_to?(:fetch)
|
32
|
-
options[:transaction_id] || options[:xid] || 0
|
33
|
-
else
|
34
|
-
fail TypeError
|
35
|
-
end
|
36
|
-
{ transaction_id: xid }
|
37
|
-
end
|
38
|
-
end
|
39
25
|
end
|
40
26
|
end
|
data/lib/pio/open_flow10.rb
CHANGED
@@ -1,11 +1,5 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
module OpenFlow
|
4
|
-
VERSION = 1
|
5
|
-
end
|
6
|
-
end
|
7
|
-
|
8
|
-
require 'pio/open_flow10/actions'
|
1
|
+
require 'pio/open_flow10/barrier_reply'
|
2
|
+
require 'pio/open_flow10/barrier_request'
|
9
3
|
require 'pio/open_flow10/echo'
|
10
4
|
require 'pio/open_flow10/exact_match'
|
11
5
|
require 'pio/open_flow10/features'
|
@@ -14,3 +8,4 @@ require 'pio/open_flow10/hello'
|
|
14
8
|
require 'pio/open_flow10/packet_in'
|
15
9
|
require 'pio/open_flow10/packet_out'
|
16
10
|
require 'pio/open_flow10/port_status'
|
11
|
+
require 'pio/open_flow10/send_out_port'
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'pio/open_flow/format'
|
2
|
+
require 'pio/open_flow/message'
|
3
|
+
|
4
|
+
module Pio
|
5
|
+
# OpenFlow 1.0 messages
|
6
|
+
module OpenFlow10
|
7
|
+
# OpenFlow 1.0 Barrier messages
|
8
|
+
module Barrier
|
9
|
+
# OpenFlow 1.0 Barrier Request message
|
10
|
+
class Reply < OpenFlow::Message
|
11
|
+
# OpenFlow 1.0 Barrier Request message format
|
12
|
+
class Format < BinData::Record
|
13
|
+
extend OpenFlow::Format
|
14
|
+
|
15
|
+
header version: 1, message_type: 19
|
16
|
+
string :body, value: ''
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'pio/open_flow/format'
|
2
|
+
require 'pio/open_flow/message'
|
3
|
+
|
4
|
+
# Base module.
|
5
|
+
module Pio
|
6
|
+
# OpenFlow 1.0 messages
|
7
|
+
module OpenFlow10
|
8
|
+
# OpenFlow 1.0 Barrier messages
|
9
|
+
module Barrier
|
10
|
+
# OpenFlow 1.0 Barrier Request message
|
11
|
+
class Request < OpenFlow::Message
|
12
|
+
# OpenFlow 1.0 Barrier Request message format
|
13
|
+
class Format < BinData::Record
|
14
|
+
extend OpenFlow::Format
|
15
|
+
|
16
|
+
header version: 1, message_type: 18
|
17
|
+
string :body, value: ''
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/pio/open_flow10/echo.rb
CHANGED
@@ -1,16 +1,20 @@
|
|
1
|
-
require '
|
2
|
-
require 'pio/open_flow'
|
3
|
-
require 'pio/open_flow10/message'
|
1
|
+
require 'pio/open_flow/echo'
|
4
2
|
|
5
3
|
module Pio
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
4
|
+
module OpenFlow10
|
5
|
+
# OpenFlow 1.0 Echo Request and Reply message.
|
6
|
+
module Echo
|
7
|
+
# OpenFlow 1.0 Echo Request message.
|
8
|
+
class Request < OpenFlow::Echo
|
9
|
+
version 1
|
10
|
+
message_type 2
|
11
|
+
end
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
|
13
|
+
# OpenFlow 1.0 Echo Reply message.
|
14
|
+
class Reply < OpenFlow::Echo
|
15
|
+
version 1
|
16
|
+
message_type 3
|
17
|
+
end
|
18
|
+
end
|
15
19
|
end
|
16
20
|
end
|
@@ -1,85 +1,113 @@
|
|
1
|
-
require 'forwardable'
|
2
1
|
require 'pio/open_flow'
|
3
2
|
|
4
3
|
module Pio
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
:table_stats,
|
21
|
-
:port_stats,
|
22
|
-
:stp,
|
23
|
-
:reserved,
|
24
|
-
:ip_reasm,
|
25
|
-
:queue_stats,
|
26
|
-
:arp_match_ip]
|
27
|
-
|
28
|
-
# enum ofp_action_type
|
29
|
-
flags_32bit :actions_flag,
|
30
|
-
[:output,
|
31
|
-
:set_vlan_vid,
|
32
|
-
:set_vlan_pcp,
|
33
|
-
:strip_vlan,
|
34
|
-
:set_ether_source_address,
|
35
|
-
:set_ether_destination_address,
|
36
|
-
:set_ip_source_address,
|
37
|
-
:set_ip_destination_address,
|
38
|
-
:set_ip_tos,
|
39
|
-
:set_transport_source_port,
|
40
|
-
:set_transport_destination_port,
|
41
|
-
:enqueue]
|
42
|
-
|
43
|
-
endian :big
|
44
|
-
|
45
|
-
uint64 :datapath_id
|
46
|
-
uint32 :n_buffers
|
47
|
-
uint8 :n_tables
|
48
|
-
uint24 :padding
|
49
|
-
hide :padding
|
50
|
-
capabilities :capabilities
|
51
|
-
actions_flag :actions
|
52
|
-
array :ports, type: :phy_port, read_until: :eof
|
53
|
-
|
54
|
-
def empty?
|
55
|
-
false
|
4
|
+
module OpenFlow10
|
5
|
+
# OpenFlow 1.0 Features Request and Reply message.
|
6
|
+
class Features
|
7
|
+
# OpenFlow 1.0 Features Request message.
|
8
|
+
class Request < OpenFlow::Message
|
9
|
+
# OpenFlow 1.0 Features Request message
|
10
|
+
class Format < BinData::Record
|
11
|
+
extend OpenFlow::Format
|
12
|
+
|
13
|
+
header version: 1, message_type: 5
|
14
|
+
string :body, value: ''
|
15
|
+
|
16
|
+
def user_data
|
17
|
+
body
|
18
|
+
end
|
56
19
|
end
|
57
20
|
|
58
|
-
def
|
59
|
-
|
21
|
+
def initialize(user_options = {})
|
22
|
+
validate_user_options user_options
|
23
|
+
@format = Format.new(header: parse_header_options(user_options))
|
60
24
|
end
|
61
25
|
end
|
62
|
-
end
|
63
26
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
27
|
+
# OpenFlow 1.0 Features Reply message.
|
28
|
+
class Reply < OpenFlow::Message
|
29
|
+
# Message body of features reply.
|
30
|
+
class Body < BinData::Record
|
31
|
+
extend OpenFlow::Flags
|
32
|
+
|
33
|
+
# enum ofp_capabilities
|
34
|
+
flags_32bit :capabilities,
|
35
|
+
[:flow_stats,
|
36
|
+
:table_stats,
|
37
|
+
:port_stats,
|
38
|
+
:stp,
|
39
|
+
:reserved,
|
40
|
+
:ip_reasm,
|
41
|
+
:queue_stats,
|
42
|
+
:arp_match_ip]
|
43
|
+
|
44
|
+
# enum ofp_action_type
|
45
|
+
flags_32bit :actions_flag,
|
46
|
+
[:output,
|
47
|
+
:set_vlan_vid,
|
48
|
+
:set_vlan_pcp,
|
49
|
+
:strip_vlan,
|
50
|
+
:set_ether_source_address,
|
51
|
+
:set_ether_destination_address,
|
52
|
+
:set_ip_source_address,
|
53
|
+
:set_ip_destination_address,
|
54
|
+
:set_ip_tos,
|
55
|
+
:set_transport_source_port,
|
56
|
+
:set_transport_destination_port,
|
57
|
+
:enqueue]
|
58
|
+
|
59
|
+
endian :big
|
60
|
+
|
61
|
+
datapath_id :datapath_id
|
62
|
+
uint32 :n_buffers
|
63
|
+
uint8 :n_tables
|
64
|
+
uint24 :padding
|
65
|
+
hide :padding
|
66
|
+
capabilities :capabilities
|
67
|
+
actions_flag :actions
|
68
|
+
array :ports, type: :phy_port, read_until: :eof
|
69
|
+
|
70
|
+
def dpid
|
71
|
+
datapath_id
|
72
|
+
end
|
73
|
+
|
74
|
+
def empty?
|
75
|
+
false
|
76
|
+
end
|
77
|
+
|
78
|
+
def length
|
79
|
+
24 + ports.to_binary_s.length
|
80
|
+
end
|
76
81
|
end
|
77
|
-
end
|
78
82
|
|
79
|
-
|
80
|
-
|
81
|
-
|
83
|
+
# OpenFlow 1.0 Features Reply message
|
84
|
+
class Format < BinData::Record
|
85
|
+
extend OpenFlow::Format
|
86
|
+
|
87
|
+
header version: 1, message_type: 6
|
88
|
+
body :body
|
89
|
+
|
90
|
+
def ports
|
91
|
+
body.snapshot.ports.map do |each|
|
92
|
+
each.instance_variable_set :@datapath_id, datapath_id
|
93
|
+
each
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def physical_ports
|
98
|
+
ports.select do |each|
|
99
|
+
each.port_no <= PortNumber::MAX
|
100
|
+
end
|
101
|
+
end
|
82
102
|
end
|
103
|
+
|
104
|
+
body_option :dpid
|
105
|
+
body_option :datapath_id
|
106
|
+
body_option :n_buffers
|
107
|
+
body_option :n_tables
|
108
|
+
body_option :capabilities
|
109
|
+
body_option :actions
|
110
|
+
body_option :ports
|
83
111
|
end
|
84
112
|
end
|
85
113
|
end
|