pio 0.15.0 → 0.15.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/lib/pio/echo.rb +6 -8
- data/lib/pio/features.rb +7 -6
- data/lib/pio/flow_mod.rb +7 -4
- data/lib/pio/hello.rb +4 -4
- data/lib/pio/open_flow.rb +16 -1
- data/lib/pio/open_flow/flags.rb +50 -44
- data/lib/pio/open_flow/message.rb +70 -93
- data/lib/pio/open_flow/open_flow_header.rb +38 -9
- data/lib/pio/open_flow/phy_port.rb +60 -62
- data/lib/pio/packet_in.rb +8 -3
- data/lib/pio/packet_out.rb +5 -2
- data/lib/pio/port_status.rb +6 -3
- data/lib/pio/version.rb +1 -1
- data/spec/pio/echo/reply_spec.rb +6 -6
- data/spec/pio/echo/request_spec.rb +6 -6
- data/spec/pio/features/reply_spec.rb +2 -2
- data/spec/pio/features/request_spec.rb +5 -5
- data/spec/pio/open_flow/phy_port_spec.rb +7 -7
- data/spec/pio/open_flow/type_spec.rb +2 -2
- metadata +2 -3
- data/lib/pio/open_flow/type.rb +0 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 72d822a526ecc76b756781275560ac85461cb743
|
4
|
+
data.tar.gz: 016ffba5c86e40a62e17baa73ad148796d3e1c9f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: badd7676a9c52f24e3941f47b2d6d7da1a26a14a6865119434307d08219be1c34c21336b32869b5836ef2ed89317f431c5d142d51d0d84f025297eea96cc3b77
|
7
|
+
data.tar.gz: 68591ec7d20cc8a5082c3742ae634e954871ec297bd7097fac3d6ebefa7af3ab439587b75b968862b973b7f396918b9d57dc0535cf1b01014627ba786a8e1071
|
data/CHANGELOG.md
CHANGED
@@ -3,6 +3,11 @@
|
|
3
3
|
## develop (unreleased)
|
4
4
|
|
5
5
|
|
6
|
+
## 0.15.1 (2/17/2015)
|
7
|
+
### Bugs fixed
|
8
|
+
* [#127](https://github.com/trema/pio/pull/127): Make OpenFlow classes thread safe.
|
9
|
+
|
10
|
+
|
6
11
|
## 0.15.0 (2/12/2015)
|
7
12
|
### New features
|
8
13
|
* [#126](https://github.com/trema/pio/pull/126): Add new class `Pio::PortStatus`.
|
data/lib/pio/echo.rb
CHANGED
@@ -3,14 +3,12 @@ require 'pio/open_flow'
|
|
3
3
|
module Pio
|
4
4
|
# OpenFlow 1.0 Echo Request and Reply message.
|
5
5
|
module Echo
|
6
|
-
#
|
7
|
-
|
8
|
-
|
9
|
-
class Request < OpenFlow::Message.factory(OpenFlow::Type::ECHO_REQUEST); end
|
6
|
+
# OpenFlow 1.0 Echo Request message.
|
7
|
+
class Request; end
|
8
|
+
OpenFlow::Message.factory(Request, OpenFlow::ECHO_REQUEST)
|
10
9
|
|
11
|
-
#
|
12
|
-
|
13
|
-
|
14
|
-
class Reply < OpenFlow::Message.factory(OpenFlow::Type::ECHO_REPLY); end
|
10
|
+
# OpenFlow 1.0 Echo Reply message.
|
11
|
+
class Reply; end
|
12
|
+
OpenFlow::Message.factory(Reply, OpenFlow::ECHO_REPLY)
|
15
13
|
end
|
16
14
|
end
|
data/lib/pio/features.rb
CHANGED
@@ -4,14 +4,13 @@ module Pio
|
|
4
4
|
# OpenFlow 1.0 Features Request and Reply message.
|
5
5
|
class Features
|
6
6
|
# OpenFlow 1.0 Features Request message.
|
7
|
-
class Request
|
8
|
-
|
7
|
+
class Request; end
|
8
|
+
OpenFlow::Message.factory(Request, OpenFlow::FEATURES_REQUEST)
|
9
9
|
|
10
|
-
|
11
|
-
class Reply < OpenFlow::Message.factory(OpenFlow::Type::FEATURES_REPLY)
|
10
|
+
class Reply
|
12
11
|
# Message body of features reply.
|
13
|
-
class
|
14
|
-
extend Flags
|
12
|
+
class Body < BinData::Record
|
13
|
+
extend OpenFlow::Flags
|
15
14
|
|
16
15
|
# enum ofp_capabilities
|
17
16
|
flags_32bit :capabilities,
|
@@ -58,7 +57,9 @@ module Pio
|
|
58
57
|
24 + ports.to_binary_s.length
|
59
58
|
end
|
60
59
|
end
|
60
|
+
end
|
61
61
|
|
62
|
+
OpenFlow::Message.factory(Reply, OpenFlow::FEATURES_REPLY) do
|
62
63
|
def_delegators :body, :datapath_id
|
63
64
|
def_delegator :body, :datapath_id, :dpid
|
64
65
|
def_delegators :body, :n_buffers
|
data/lib/pio/flow_mod.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
require 'pio/match'
|
2
2
|
require 'pio/open_flow'
|
3
3
|
|
4
|
+
# Base module.
|
4
5
|
module Pio
|
5
|
-
# OpenFlow 1.0
|
6
|
-
class FlowMod
|
6
|
+
# OpenFlow 1.0 Flow Mod message.
|
7
|
+
class FlowMod
|
7
8
|
# enum ofp_flow_mod_command
|
8
9
|
class Command < BinData::Primitive
|
9
10
|
COMMANDS = {
|
@@ -27,7 +28,7 @@ module Pio
|
|
27
28
|
end
|
28
29
|
|
29
30
|
# Message body of FlowMod.
|
30
|
-
class
|
31
|
+
class Body < BinData::Record
|
31
32
|
# Pio::MatchFormat wrapper.
|
32
33
|
class Match < BinData::Primitive
|
33
34
|
endian :big
|
@@ -43,7 +44,7 @@ module Pio
|
|
43
44
|
end
|
44
45
|
end
|
45
46
|
|
46
|
-
extend Flags
|
47
|
+
extend OpenFlow::Flags
|
47
48
|
|
48
49
|
flags_16bit :flags,
|
49
50
|
[:send_flow_rem,
|
@@ -71,7 +72,9 @@ module Pio
|
|
71
72
|
64 + actions.binary.length
|
72
73
|
end
|
73
74
|
end
|
75
|
+
end
|
74
76
|
|
77
|
+
OpenFlow::Message.factory(FlowMod, OpenFlow::FLOW_MOD) do
|
75
78
|
def_delegators :body, :match
|
76
79
|
def_delegators :body, :cookie
|
77
80
|
def_delegators :body, :command
|
data/lib/pio/hello.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
require 'pio/open_flow'
|
2
2
|
|
3
|
+
# Base module.
|
3
4
|
module Pio
|
4
|
-
#
|
5
|
-
|
6
|
-
|
7
|
-
class Hello < OpenFlow::Message.factory(Pio::OpenFlow::Type::HELLO); end
|
5
|
+
# OpenFlow 1.0 Hello message
|
6
|
+
class Hello; end
|
7
|
+
OpenFlow::Message.factory(Hello, OpenFlow::HELLO)
|
8
8
|
end
|
data/lib/pio/open_flow.rb
CHANGED
@@ -1,7 +1,22 @@
|
|
1
|
+
module Pio
|
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
17
|
require 'pio/open_flow/actions'
|
2
18
|
require 'pio/open_flow/flags'
|
3
19
|
require 'pio/open_flow/message'
|
4
20
|
require 'pio/open_flow/open_flow_header'
|
5
21
|
require 'pio/open_flow/phy_port'
|
6
22
|
require 'pio/open_flow/port_number'
|
7
|
-
require 'pio/open_flow/type'
|
data/lib/pio/open_flow/flags.rb
CHANGED
@@ -1,55 +1,61 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
1
|
+
module Pio
|
2
|
+
module OpenFlow
|
3
|
+
# bitmap functions.
|
4
|
+
# This class smells of :reek:DataClump
|
5
|
+
module Flags
|
6
|
+
def flags_32bit(name, flags)
|
7
|
+
_def_flags name, 32, flags
|
8
|
+
end
|
7
9
|
|
8
|
-
|
9
|
-
|
10
|
-
|
10
|
+
def flags_16bit(name, flags)
|
11
|
+
_def_flags name, 16, flags
|
12
|
+
end
|
11
13
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
14
|
+
# rubocop:disable MethodLength
|
15
|
+
# This method smells of :reek:TooManyStatements
|
16
|
+
def _def_flags(name, size, flags)
|
17
|
+
flag_value = case flags
|
18
|
+
when Array
|
19
|
+
shift = 0
|
20
|
+
flags.each_with_object({}) do |each, result|
|
21
|
+
result[each] = 1 << shift
|
22
|
+
shift += 1
|
23
|
+
result
|
24
|
+
end
|
25
|
+
when Hash
|
26
|
+
flags
|
27
|
+
end
|
26
28
|
|
27
|
-
|
28
|
-
|
29
|
+
klass_name = name.to_s.split('_').map(&:capitalize).join
|
30
|
+
flags_hash = flag_value.inspect
|
29
31
|
|
30
|
-
|
31
|
-
|
32
|
-
|
32
|
+
code = %{
|
33
|
+
class #{klass_name} < BinData::Primitive
|
34
|
+
endian :big
|
33
35
|
|
34
|
-
|
36
|
+
uint#{size} :#{name}
|
35
37
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
38
|
+
def get
|
39
|
+
list = #{flags_hash}
|
40
|
+
list.each_with_object([]) do |(key, value), result|
|
41
|
+
result << key if #{name} & value != 0
|
42
|
+
result
|
43
|
+
end
|
44
|
+
end
|
43
45
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
46
|
+
def set(v)
|
47
|
+
list = #{flags_hash}
|
48
|
+
v.each do |each|
|
49
|
+
fail "Invalid state flag: \#{v}" unless list.keys.include?(each)
|
50
|
+
end
|
51
|
+
self.#{name} = v.empty? ?
|
52
|
+
0 :
|
53
|
+
v.map { |each| list[each] }.inject(:|)
|
54
|
+
end
|
48
55
|
end
|
49
|
-
|
50
|
-
|
56
|
+
}
|
57
|
+
module_eval code
|
51
58
|
end
|
52
|
-
|
53
|
-
module_eval code
|
59
|
+
end
|
54
60
|
end
|
55
61
|
end
|
@@ -7,126 +7,103 @@ module Pio
|
|
7
7
|
module OpenFlow
|
8
8
|
# Defines shortcuts to OpenFlow header fields.
|
9
9
|
class Message
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
def_delegator :open_flow_header, :transaction_id, :xid
|
19
|
-
|
20
|
-
def_delegators :@format, :body
|
21
|
-
def_delegator :@format, :body, :user_data
|
22
|
-
|
23
|
-
def_delegator :@format, :to_binary_s, :to_binary
|
24
|
-
|
25
|
-
def self.factory(message_type)
|
26
|
-
@message_type = message_type
|
27
|
-
self
|
28
|
-
end
|
29
|
-
|
30
|
-
def self.klass(message_type)
|
31
|
-
@messages.fetch(message_type)
|
32
|
-
end
|
33
|
-
|
34
|
-
def self.inherited(child)
|
35
|
-
child.const_set(:MESSAGE_TYPE, @message_type)
|
36
|
-
@messages ||= {}
|
37
|
-
@messages[@message_type] = child
|
38
|
-
end
|
39
|
-
|
40
|
-
def self.read(raw_data)
|
41
|
-
message = allocate
|
42
|
-
message.instance_variable_set(:@format, format.read(raw_data))
|
43
|
-
message
|
44
|
-
rescue BinData::ValidityError
|
45
|
-
message_name = name.split('::')[1..-1].join(' ')
|
46
|
-
raise Pio::ParseError, "Invalid #{message_name} message."
|
47
|
-
end
|
48
|
-
|
49
|
-
def self.format
|
50
|
-
const_get(:Format)
|
51
|
-
rescue NameError
|
52
|
-
define_message_format const_get(:MESSAGE_TYPE)
|
53
|
-
retry
|
10
|
+
def self.factory(klass, message_type, &block)
|
11
|
+
klass.extend Forwardable
|
12
|
+
klass.module_eval(&block) if block
|
13
|
+
klass.module_eval _format_class(klass, message_type)
|
14
|
+
klass.module_eval(&_define_open_flow_accessors)
|
15
|
+
klass.module_eval(&_define_self_read)
|
16
|
+
klass.module_eval(&_define_initialize)
|
17
|
+
klass.module_eval(&_define_to_binary)
|
54
18
|
end
|
55
19
|
|
56
20
|
# rubocop:disable MethodLength
|
57
|
-
def self.
|
58
|
-
|
21
|
+
def self._format_class(klass, message_type)
|
22
|
+
%(
|
59
23
|
class Format < BinData::Record
|
60
24
|
endian :big
|
61
25
|
|
62
26
|
open_flow_header :open_flow_header,
|
63
|
-
|
27
|
+
message_type_value: #{message_type}
|
64
28
|
virtual assert: -> do
|
65
29
|
open_flow_header.message_type == #{message_type}
|
66
30
|
end
|
67
31
|
|
68
|
-
#{
|
32
|
+
#{klass.const_defined?(:Body) ? 'body' : 'string'} :body
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.format
|
36
|
+
const_get :Format
|
69
37
|
end
|
70
38
|
)
|
71
|
-
module_eval code
|
72
39
|
end
|
73
40
|
# rubocop:enable MethodLength
|
74
41
|
|
75
|
-
def self.
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
42
|
+
def self._define_open_flow_accessors
|
43
|
+
proc do
|
44
|
+
def_delegators :@format, :open_flow_header
|
45
|
+
def_delegators :open_flow_header, :ofp_version
|
46
|
+
def_delegators :open_flow_header, :message_type
|
47
|
+
def_delegators :open_flow_header, :message_length
|
48
|
+
def_delegators :open_flow_header, :transaction_id
|
49
|
+
def_delegator :open_flow_header, :transaction_id, :xid
|
50
|
+
|
51
|
+
def_delegators :@format, :body
|
52
|
+
def_delegator :@format, :body, :user_data
|
53
|
+
end
|
85
54
|
end
|
86
55
|
|
87
|
-
def
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
56
|
+
def self._define_self_read
|
57
|
+
proc do
|
58
|
+
def self.read(raw_data)
|
59
|
+
allocate.tap do |message|
|
60
|
+
message.instance_variable_set(:@format, format.read(raw_data))
|
61
|
+
end
|
62
|
+
rescue BinData::ValidityError
|
63
|
+
message_name = name.split('::')[1..-1].join(' ')
|
64
|
+
raise Pio::ParseError, "Invalid #{message_name} message."
|
65
|
+
end
|
66
|
+
end
|
92
67
|
end
|
93
68
|
|
94
|
-
|
69
|
+
# rubocop:disable MethodLength
|
70
|
+
# rubocop:disable AbcSize
|
71
|
+
def self._define_initialize
|
72
|
+
proc do
|
73
|
+
def initialize(user_options = {})
|
74
|
+
header_options = OpenFlowHeader::Options.parse(user_options)
|
75
|
+
body_options = parse_body_options(user_options)
|
76
|
+
@format = self.class.format.new(open_flow_header: header_options,
|
77
|
+
body: body_options)
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
95
81
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
82
|
+
def parse_body_options(options)
|
83
|
+
if options.respond_to?(:fetch)
|
84
|
+
options.delete :transaction_id
|
85
|
+
options.delete :xid
|
86
|
+
dpid = options[:dpid]
|
87
|
+
options[:datapath_id] = dpid if dpid
|
88
|
+
if options.keys.size > 1
|
89
|
+
options
|
102
90
|
else
|
103
|
-
|
91
|
+
options[:user_data] || ''
|
104
92
|
end
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
end
|
109
|
-
|
110
|
-
# rubocop:disable MethodLength
|
111
|
-
# This method smells of :reek:TooManyStatements
|
112
|
-
# This method smells of :reek:FeatureEnvy
|
113
|
-
# This method smells of :reek:UtilityFunction
|
114
|
-
def parse_body_options(options)
|
115
|
-
if options.respond_to?(:fetch)
|
116
|
-
options.delete :transaction_id
|
117
|
-
options.delete :xid
|
118
|
-
dpid = options[:dpid]
|
119
|
-
options[:datapath_id] = dpid if dpid
|
120
|
-
if options.keys.size > 1
|
121
|
-
options
|
122
|
-
else
|
123
|
-
options[:user_data] || ''
|
93
|
+
else
|
94
|
+
''
|
95
|
+
end
|
124
96
|
end
|
125
|
-
else
|
126
|
-
''
|
127
97
|
end
|
128
98
|
end
|
129
99
|
# rubocop:enable MethodLength
|
100
|
+
# rubocop:enable AbcSize
|
101
|
+
|
102
|
+
def self._define_to_binary
|
103
|
+
proc do
|
104
|
+
def_delegator :@format, :to_binary_s, :to_binary
|
105
|
+
end
|
106
|
+
end
|
130
107
|
end
|
131
108
|
end
|
132
109
|
end
|
@@ -1,17 +1,46 @@
|
|
1
1
|
require 'bindata'
|
2
2
|
|
3
3
|
module Pio
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
4
|
+
# OpenFlow 1.0 format.
|
5
|
+
module OpenFlow
|
6
|
+
# OpenFlow 1.0 message header format.
|
7
|
+
class OpenFlowHeader < BinData::Record
|
8
|
+
# Transaction ID (uint32)
|
9
|
+
class TransactionId < BinData::Primitive
|
9
10
|
endian :big
|
11
|
+
uint32 :xid
|
10
12
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
13
|
+
def set(value)
|
14
|
+
unless value.unsigned_32bit?
|
15
|
+
fail(ArgumentError,
|
16
|
+
'Transaction ID should be an unsigned 32-bit integer.')
|
17
|
+
end
|
18
|
+
self.xid = value
|
19
|
+
end
|
20
|
+
|
21
|
+
def get
|
22
|
+
xid
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
endian :big
|
27
|
+
uint8 :ofp_version, value: 1
|
28
|
+
uint8 :message_type, initial_value: :message_type_value
|
29
|
+
uint16 :message_length, initial_value: -> { 8 + body.length }
|
30
|
+
transaction_id :transaction_id, initial_value: 0
|
31
|
+
|
32
|
+
# parse header options
|
33
|
+
class Options
|
34
|
+
def self.parse(options)
|
35
|
+
xid = if options.respond_to?(:to_i)
|
36
|
+
options.to_i
|
37
|
+
elsif options.respond_to?(:fetch)
|
38
|
+
options[:transaction_id] || options[:xid] || 0
|
39
|
+
else
|
40
|
+
fail TypeError
|
41
|
+
end
|
42
|
+
{ transaction_id: xid }
|
43
|
+
end
|
15
44
|
end
|
16
45
|
end
|
17
46
|
end
|
@@ -2,79 +2,77 @@ require 'bindata'
|
|
2
2
|
require 'pio/type/mac_address'
|
3
3
|
|
4
4
|
module Pio
|
5
|
-
module
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
extend Flags
|
5
|
+
module OpenFlow
|
6
|
+
# Description of a physical port
|
7
|
+
class PhyPort < BinData::Record
|
8
|
+
extend Flags
|
10
9
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
10
|
+
# enum ofp_port_config
|
11
|
+
flags_32bit :port_config,
|
12
|
+
[:port_down,
|
13
|
+
:no_stp,
|
14
|
+
:no_recv,
|
15
|
+
:no_recv_stp,
|
16
|
+
:no_flood,
|
17
|
+
:no_fwd,
|
18
|
+
:no_packet_in]
|
20
19
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
20
|
+
# enum ofp_port_state
|
21
|
+
flags_32bit :port_state,
|
22
|
+
link_down: 1 << 0,
|
23
|
+
stp_listen: 0 << 8,
|
24
|
+
stp_learn: 1 << 8,
|
25
|
+
stp_forward: 2 << 8,
|
26
|
+
stp_block: 3 << 8
|
28
27
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
28
|
+
# enum ofp_port_features
|
29
|
+
flags_32bit :port_feature,
|
30
|
+
[:port_10mb_hd,
|
31
|
+
:port_10mb_fd,
|
32
|
+
:port_100mb_hd,
|
33
|
+
:port_100mb_fd,
|
34
|
+
:port_1gb_hd,
|
35
|
+
:port_1gb_fd,
|
36
|
+
:port_10gb_fd,
|
37
|
+
:port_copper,
|
38
|
+
:port_fiber,
|
39
|
+
:port_autoneg,
|
40
|
+
:port_pause,
|
41
|
+
:port_pause_asym]
|
43
42
|
|
44
|
-
|
43
|
+
endian :big
|
45
44
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
45
|
+
uint16 :port_no
|
46
|
+
mac_address :hardware_address
|
47
|
+
string :name, length: 16, trim_padding: true
|
48
|
+
port_config :config
|
49
|
+
port_state :state
|
50
|
+
port_feature :curr
|
51
|
+
port_feature :advertised
|
52
|
+
port_feature :supported
|
53
|
+
port_feature :peer
|
55
54
|
|
56
|
-
|
57
|
-
|
55
|
+
attr_accessor :datapath_id
|
56
|
+
alias_method :dpid, :datapath_id
|
58
57
|
|
59
|
-
|
60
|
-
|
61
|
-
|
58
|
+
def number
|
59
|
+
port_no
|
60
|
+
end
|
62
61
|
|
63
|
-
|
64
|
-
|
65
|
-
|
62
|
+
def mac_address
|
63
|
+
hardware_address
|
64
|
+
end
|
66
65
|
|
67
|
-
|
68
|
-
|
69
|
-
|
66
|
+
def up?
|
67
|
+
!down?
|
68
|
+
end
|
70
69
|
|
71
|
-
|
72
|
-
|
73
|
-
|
70
|
+
def down?
|
71
|
+
config.include?(:port_down) || state.include?(:link_down)
|
72
|
+
end
|
74
73
|
|
75
|
-
|
76
|
-
|
77
|
-
end
|
74
|
+
def local?
|
75
|
+
port_no == PortNumber::NUMBERS[:local]
|
78
76
|
end
|
79
77
|
end
|
80
78
|
end
|
data/lib/pio/packet_in.rb
CHANGED
@@ -1,10 +1,13 @@
|
|
1
1
|
require 'bindata'
|
2
2
|
require 'pio/open_flow'
|
3
3
|
require 'pio/parse_error'
|
4
|
+
require 'pio/type/ethernet_header'
|
5
|
+
require 'pio/type/ipv4_header'
|
4
6
|
|
7
|
+
# Base module.
|
5
8
|
module Pio
|
6
9
|
# OpenFlow 1.0 Packet-In message
|
7
|
-
class PacketIn
|
10
|
+
class PacketIn
|
8
11
|
# Why is this packet being sent to the controller?
|
9
12
|
# (enum ofp_packet_in_reason)
|
10
13
|
class Reason < BinData::Primitive
|
@@ -22,7 +25,7 @@ module Pio
|
|
22
25
|
end
|
23
26
|
|
24
27
|
# Message body of Packet-In.
|
25
|
-
class
|
28
|
+
class Body < BinData::Record
|
26
29
|
endian :big
|
27
30
|
|
28
31
|
uint32 :buffer_id
|
@@ -85,7 +88,9 @@ module Pio
|
|
85
88
|
end
|
86
89
|
# rubocop:enable MethodLength
|
87
90
|
end
|
91
|
+
end
|
88
92
|
|
93
|
+
OpenFlow::Message.factory(PacketIn, OpenFlow::PACKET_IN) do
|
89
94
|
attr_accessor :datapath_id
|
90
95
|
alias_method :dpid, :datapath_id
|
91
96
|
alias_method :dpid=, :datapath_id=
|
@@ -97,7 +102,7 @@ module Pio
|
|
97
102
|
def_delegators :body, :data
|
98
103
|
|
99
104
|
def parsed_data
|
100
|
-
@parsed_data ||= DataParser.read(data)
|
105
|
+
@parsed_data ||= PacketIn::DataParser.read(data)
|
101
106
|
end
|
102
107
|
|
103
108
|
def lldp?
|
data/lib/pio/packet_out.rb
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
require 'bindata'
|
2
2
|
require 'pio/open_flow'
|
3
3
|
|
4
|
+
# Base module.
|
4
5
|
module Pio
|
5
6
|
# OpenFlow 1.0 Packet-Out message
|
6
|
-
class PacketOut
|
7
|
+
class PacketOut
|
7
8
|
# Message body of Packet-Out
|
8
|
-
class
|
9
|
+
class Body < BinData::Record
|
9
10
|
endian :big
|
10
11
|
|
11
12
|
uint32 :buffer_id
|
@@ -22,7 +23,9 @@ module Pio
|
|
22
23
|
8 + actions_len + data.length
|
23
24
|
end
|
24
25
|
end
|
26
|
+
end
|
25
27
|
|
28
|
+
OpenFlow::Message.factory(PacketOut, OpenFlow::PACKET_OUT) do
|
26
29
|
def_delegators :body, :buffer_id
|
27
30
|
def_delegators :body, :in_port
|
28
31
|
def_delegators :body, :actions_len
|
data/lib/pio/port_status.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
require 'pio/open_flow'
|
2
2
|
|
3
|
+
# Base module.
|
3
4
|
module Pio
|
4
5
|
# OpenFlow 1.0 Port Status message
|
5
|
-
class PortStatus
|
6
|
+
class PortStatus
|
6
7
|
# What changed about the physical port
|
7
8
|
class Reason < BinData::Primitive
|
8
9
|
REASONS = { add: 0, delete: 1, modify: 2 }
|
@@ -18,8 +19,8 @@ module Pio
|
|
18
19
|
end
|
19
20
|
end
|
20
21
|
|
21
|
-
# Message body of
|
22
|
-
class
|
22
|
+
# Message body of Port Status
|
23
|
+
class Body < BinData::Record
|
23
24
|
endian :big
|
24
25
|
|
25
26
|
reason :reason
|
@@ -27,7 +28,9 @@ module Pio
|
|
27
28
|
hide :padding
|
28
29
|
phy_port :desc
|
29
30
|
end
|
31
|
+
end
|
30
32
|
|
33
|
+
OpenFlow::Message.factory(PortStatus, OpenFlow::PORT_STATUS) do
|
31
34
|
def_delegators :body, :desc
|
32
35
|
|
33
36
|
def reason
|
data/lib/pio/version.rb
CHANGED
data/spec/pio/echo/reply_spec.rb
CHANGED
@@ -8,7 +8,7 @@ describe Pio::Echo::Reply do
|
|
8
8
|
Given(:binary) { [1, 3, 0, 8, 0, 0, 0, 0].pack('C*') }
|
9
9
|
|
10
10
|
Then { echo_reply.ofp_version == 1 }
|
11
|
-
Then { echo_reply.message_type == Pio::OpenFlow::
|
11
|
+
Then { echo_reply.message_type == Pio::OpenFlow::ECHO_REPLY }
|
12
12
|
Then { echo_reply.message_length == 8 }
|
13
13
|
Then { echo_reply.transaction_id == 0 }
|
14
14
|
Then { echo_reply.xid == 0 }
|
@@ -34,7 +34,7 @@ describe Pio::Echo::Reply do
|
|
34
34
|
When(:echo_reply) { Pio::Echo::Reply.new }
|
35
35
|
|
36
36
|
Then { echo_reply.ofp_version == 1 }
|
37
|
-
Then { echo_reply.message_type == Pio::OpenFlow::
|
37
|
+
Then { echo_reply.message_type == Pio::OpenFlow::ECHO_REPLY }
|
38
38
|
Then { echo_reply.message_length == 8 }
|
39
39
|
Then { echo_reply.transaction_id == 0 }
|
40
40
|
Then { echo_reply.xid == 0 }
|
@@ -49,7 +49,7 @@ describe Pio::Echo::Reply do
|
|
49
49
|
When(:echo_reply) { Pio::Echo::Reply.new(123) }
|
50
50
|
|
51
51
|
Then { echo_reply.ofp_version == 1 }
|
52
|
-
Then { echo_reply.message_type == Pio::OpenFlow::
|
52
|
+
Then { echo_reply.message_type == Pio::OpenFlow::ECHO_REPLY }
|
53
53
|
Then { echo_reply.message_length == 8 }
|
54
54
|
Then { echo_reply.transaction_id == 123 }
|
55
55
|
Then { echo_reply.xid == 123 }
|
@@ -64,7 +64,7 @@ describe Pio::Echo::Reply do
|
|
64
64
|
When(:echo_reply) { Pio::Echo::Reply.new(transaction_id: 123) }
|
65
65
|
|
66
66
|
Then { echo_reply.ofp_version == 1 }
|
67
|
-
Then { echo_reply.message_type == Pio::OpenFlow::
|
67
|
+
Then { echo_reply.message_type == Pio::OpenFlow::ECHO_REPLY }
|
68
68
|
Then { echo_reply.message_length == 8 }
|
69
69
|
Then { echo_reply.transaction_id == 123 }
|
70
70
|
Then { echo_reply.xid == 123 }
|
@@ -79,7 +79,7 @@ describe Pio::Echo::Reply do
|
|
79
79
|
When(:echo_reply) { Pio::Echo::Reply.new(xid: 123) }
|
80
80
|
|
81
81
|
Then { echo_reply.ofp_version == 1 }
|
82
|
-
Then { echo_reply.message_type == Pio::OpenFlow::
|
82
|
+
Then { echo_reply.message_type == Pio::OpenFlow::ECHO_REPLY }
|
83
83
|
Then { echo_reply.message_length == 8 }
|
84
84
|
Then { echo_reply.transaction_id == 123 }
|
85
85
|
Then { echo_reply.xid == 123 }
|
@@ -94,7 +94,7 @@ describe Pio::Echo::Reply do
|
|
94
94
|
When(:echo_reply) { Pio::Echo::Reply.new(xid: 123, user_data: 'foobar') }
|
95
95
|
|
96
96
|
Then { echo_reply.ofp_version == 1 }
|
97
|
-
Then { echo_reply.message_type == Pio::OpenFlow::
|
97
|
+
Then { echo_reply.message_type == Pio::OpenFlow::ECHO_REPLY }
|
98
98
|
Then { echo_reply.message_length == 14 }
|
99
99
|
Then { echo_reply.transaction_id == 123 }
|
100
100
|
Then { echo_reply.xid == 123 }
|
@@ -8,7 +8,7 @@ describe Pio::Echo::Request do
|
|
8
8
|
Given(:binary) { [1, 2, 0, 8, 0, 0, 0, 0].pack('C*') }
|
9
9
|
|
10
10
|
Then { echo_request.ofp_version == 1 }
|
11
|
-
Then { echo_request.message_type == Pio::OpenFlow::
|
11
|
+
Then { echo_request.message_type == Pio::OpenFlow::ECHO_REQUEST }
|
12
12
|
Then { echo_request.message_length == 8 }
|
13
13
|
Then { echo_request.transaction_id == 0 }
|
14
14
|
Then { echo_request.xid == 0 }
|
@@ -34,7 +34,7 @@ describe Pio::Echo::Request do
|
|
34
34
|
When(:echo_request) { Pio::Echo::Request.new }
|
35
35
|
|
36
36
|
Then { echo_request.ofp_version == 1 }
|
37
|
-
Then { echo_request.message_type == Pio::OpenFlow::
|
37
|
+
Then { echo_request.message_type == Pio::OpenFlow::ECHO_REQUEST }
|
38
38
|
Then { echo_request.message_length == 8 }
|
39
39
|
Then { echo_request.transaction_id == 0 }
|
40
40
|
Then { echo_request.xid == 0 }
|
@@ -49,7 +49,7 @@ describe Pio::Echo::Request do
|
|
49
49
|
When(:echo_request) { Pio::Echo::Request.new(123) }
|
50
50
|
|
51
51
|
Then { echo_request.ofp_version == 1 }
|
52
|
-
Then { echo_request.message_type == Pio::OpenFlow::
|
52
|
+
Then { echo_request.message_type == Pio::OpenFlow::ECHO_REQUEST }
|
53
53
|
Then { echo_request.message_length == 8 }
|
54
54
|
Then { echo_request.transaction_id == 123 }
|
55
55
|
Then { echo_request.xid == 123 }
|
@@ -64,7 +64,7 @@ describe Pio::Echo::Request do
|
|
64
64
|
When(:echo_request) { Pio::Echo::Request.new(transaction_id: 123) }
|
65
65
|
|
66
66
|
Then { echo_request.ofp_version == 1 }
|
67
|
-
Then { echo_request.message_type == Pio::OpenFlow::
|
67
|
+
Then { echo_request.message_type == Pio::OpenFlow::ECHO_REQUEST }
|
68
68
|
Then { echo_request.message_length == 8 }
|
69
69
|
Then { echo_request.transaction_id == 123 }
|
70
70
|
Then { echo_request.xid == 123 }
|
@@ -79,7 +79,7 @@ describe Pio::Echo::Request do
|
|
79
79
|
When(:echo_request) { Pio::Echo::Request.new(xid: 123) }
|
80
80
|
|
81
81
|
Then { echo_request.ofp_version == 1 }
|
82
|
-
Then { echo_request.message_type == Pio::OpenFlow::
|
82
|
+
Then { echo_request.message_type == Pio::OpenFlow::ECHO_REQUEST }
|
83
83
|
Then { echo_request.message_length == 8 }
|
84
84
|
Then { echo_request.transaction_id == 123 }
|
85
85
|
Then { echo_request.xid == 123 }
|
@@ -96,7 +96,7 @@ describe Pio::Echo::Request do
|
|
96
96
|
end
|
97
97
|
|
98
98
|
Then { echo_request.ofp_version == 1 }
|
99
|
-
Then { echo_request.message_type == Pio::OpenFlow::
|
99
|
+
Then { echo_request.message_type == Pio::OpenFlow::ECHO_REQUEST }
|
100
100
|
Then { echo_request.message_length == 14 }
|
101
101
|
Then { echo_request.transaction_id == 123 }
|
102
102
|
Then { echo_request.xid == 123 }
|
@@ -30,7 +30,7 @@ describe Pio::Features::Reply do
|
|
30
30
|
Then { result.ofp_version == 1 }
|
31
31
|
Then do
|
32
32
|
result.message_type ==
|
33
|
-
Pio::OpenFlow::
|
33
|
+
Pio::OpenFlow::FEATURES_REPLY
|
34
34
|
end
|
35
35
|
Then { result.message_length == 176 }
|
36
36
|
Then { result.transaction_id == 2 }
|
@@ -101,7 +101,7 @@ describe Pio::Features::Reply do
|
|
101
101
|
When(:features_reply) { Pio::Features::Reply.new(options) }
|
102
102
|
|
103
103
|
Then { features_reply.ofp_version == 1 }
|
104
|
-
Then { features_reply.message_type == Pio::OpenFlow::
|
104
|
+
Then { features_reply.message_type == Pio::OpenFlow::FEATURES_REPLY }
|
105
105
|
Then { features_reply.transaction_id == 0 }
|
106
106
|
Then { features_reply.xid == 0 }
|
107
107
|
Then { features_reply.dpid == 0x123 }
|
@@ -11,7 +11,7 @@ describe Pio::Features::Request do
|
|
11
11
|
Then { result.ofp_version == 1 }
|
12
12
|
Then do
|
13
13
|
result.message_type ==
|
14
|
-
Pio::OpenFlow::
|
14
|
+
Pio::OpenFlow::FEATURES_REQUEST
|
15
15
|
end
|
16
16
|
Then { result.message_length == 8 }
|
17
17
|
Then { result.transaction_id == 0 }
|
@@ -35,7 +35,7 @@ describe Pio::Features::Request do
|
|
35
35
|
When(:result) { Pio::Features::Request.new }
|
36
36
|
|
37
37
|
Then { result.ofp_version == 1 }
|
38
|
-
Then { result.message_type == Pio::OpenFlow::
|
38
|
+
Then { result.message_type == Pio::OpenFlow::FEATURES_REQUEST }
|
39
39
|
Then { result.message_length == 8 }
|
40
40
|
Then { result.transaction_id == 0 }
|
41
41
|
Then { result.xid == 0 }
|
@@ -48,7 +48,7 @@ describe Pio::Features::Request do
|
|
48
48
|
When(:result) { Pio::Features::Request.new(123) }
|
49
49
|
|
50
50
|
Then { result.ofp_version == 1 }
|
51
|
-
Then { result.message_type == Pio::OpenFlow::
|
51
|
+
Then { result.message_type == Pio::OpenFlow::FEATURES_REQUEST }
|
52
52
|
Then { result.message_length == 8 }
|
53
53
|
Then { result.transaction_id == 123 }
|
54
54
|
Then { result.xid == 123 }
|
@@ -61,7 +61,7 @@ describe Pio::Features::Request do
|
|
61
61
|
When(:result) { Pio::Features::Request.new(transaction_id: 123) }
|
62
62
|
|
63
63
|
Then { result.ofp_version == 1 }
|
64
|
-
Then { result.message_type == Pio::OpenFlow::
|
64
|
+
Then { result.message_type == Pio::OpenFlow::FEATURES_REQUEST }
|
65
65
|
Then { result.message_length == 8 }
|
66
66
|
Then { result.transaction_id == 123 }
|
67
67
|
Then { result.xid == 123 }
|
@@ -74,7 +74,7 @@ describe Pio::Features::Request do
|
|
74
74
|
When(:result) { Pio::Features::Request.new(xid: 123) }
|
75
75
|
|
76
76
|
Then { result.ofp_version == 1 }
|
77
|
-
Then { result.message_type == Pio::OpenFlow::
|
77
|
+
Then { result.message_type == Pio::OpenFlow::FEATURES_REQUEST }
|
78
78
|
Then { result.message_length == 8 }
|
79
79
|
Then { result.transaction_id == 123 }
|
80
80
|
Then { result.xid == 123 }
|
@@ -1,14 +1,14 @@
|
|
1
1
|
require 'pio'
|
2
2
|
|
3
|
-
describe Pio::
|
3
|
+
describe Pio::OpenFlow::PhyPort do
|
4
4
|
describe '.new' do
|
5
5
|
When(:phy_port) do
|
6
|
-
Pio::
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
6
|
+
Pio::OpenFlow::PhyPort.new(port_no: 1,
|
7
|
+
hardware_address: '11:22:33:44:55:66',
|
8
|
+
name: 'port123',
|
9
|
+
config: [:port_down],
|
10
|
+
state: [:link_down],
|
11
|
+
curr: [:port_10gb_fd, :port_copper])
|
12
12
|
end
|
13
13
|
|
14
14
|
Then { phy_port.port_no == 1 }
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pio
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.15.
|
4
|
+
version: 0.15.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yasuhito Takamiya
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-02-
|
11
|
+
date: 2015-02-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bindata
|
@@ -503,7 +503,6 @@ files:
|
|
503
503
|
- lib/pio/open_flow/open_flow_header.rb
|
504
504
|
- lib/pio/open_flow/phy_port.rb
|
505
505
|
- lib/pio/open_flow/port_number.rb
|
506
|
-
- lib/pio/open_flow/type.rb
|
507
506
|
- lib/pio/options.rb
|
508
507
|
- lib/pio/packet_in.rb
|
509
508
|
- lib/pio/packet_out.rb
|
data/lib/pio/open_flow/type.rb
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
module Pio
|
2
|
-
module OpenFlow
|
3
|
-
# OFPT_* constants.
|
4
|
-
module Type
|
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
|
-
end
|