trema 0.4.8 → 0.5.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/bin/trema +2 -1
- data/features/echo_reply_handler.feature +29 -0
- data/features/open_flow13.feature +29 -0
- data/features/trema_run.feature +11 -0
- data/lib/trema/controller.rb +43 -1
- data/lib/trema/switch.rb +30 -18
- data/lib/trema/version.rb +1 -1
- data/trema.gemspec +7 -7
- metadata +17 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cd254b79f9c14fa501bbd579c616b4a387f2d832
|
4
|
+
data.tar.gz: fbf648fbf79f72498a28fa45d93095042c93a074
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 960bf892ff737db25a541bd8b20929d76b4e6103a541fc16fc6c0fb0c7e92f85ffc4ede76bb5ce9558bff7d567b20e6a65cff7eadc8e944bafc407e03ded2af6
|
7
|
+
data.tar.gz: 7d2229720caa81f7f3a9a36b1a4b326e024c724bdea82745d0896fb93205abee59d382f7370c202c133c20b98b42b5e65c4dac7a0876e5a3b4e8c052ebbe23cd
|
data/CHANGELOG.md
CHANGED
@@ -3,6 +3,11 @@
|
|
3
3
|
## develop (unreleased)
|
4
4
|
|
5
5
|
|
6
|
+
## 0.5.0 (8/2/2015)
|
7
|
+
### Changes
|
8
|
+
* [#392](https://github.com/trema/trema/pull/392): Allow packet_in, etc during startup.
|
9
|
+
|
10
|
+
|
6
11
|
## 0.4.8 (6/29/2015)
|
7
12
|
### Changes
|
8
13
|
* [#384](https://github.com/trema/trema/pull/384): Add trema run --port (-p) option to override the default OpenFlow channel listen port.
|
data/bin/trema
CHANGED
@@ -4,6 +4,7 @@ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
|
4
4
|
require 'drb/drb'
|
5
5
|
require 'gli'
|
6
6
|
require 'phut'
|
7
|
+
require 'pio'
|
7
8
|
require 'rake'
|
8
9
|
require 'trema'
|
9
10
|
|
@@ -47,7 +48,7 @@ module Trema
|
|
47
48
|
Phut.pid_dir = options[:pid_dir]
|
48
49
|
Phut.log_dir = options[:log_dir]
|
49
50
|
Phut.socket_dir = options[:socket_dir]
|
50
|
-
|
51
|
+
Pio::OpenFlow.switch_version 'OpenFlow13' if options[:openflow13]
|
51
52
|
require 'trema/switch'
|
52
53
|
Trema::Command.new.run(args, global_options.merge(options))
|
53
54
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
Feature: Trema::Controller#echo_reply handler
|
2
|
+
Background:
|
3
|
+
Given I set the environment variables to:
|
4
|
+
| variable | value |
|
5
|
+
| TREMA_LOG_DIR | . |
|
6
|
+
| TREMA_PID_DIR | . |
|
7
|
+
| TREMA_SOCKET_DIR | . |
|
8
|
+
|
9
|
+
@sudo
|
10
|
+
Scenario: the default port
|
11
|
+
Given a file named "echo_reply.rb" with:
|
12
|
+
"""
|
13
|
+
class EchoReply < Trema::Controller
|
14
|
+
def switch_ready(dpid)
|
15
|
+
send_message dpid, Echo::Request.new
|
16
|
+
end
|
17
|
+
|
18
|
+
def echo_reply(dpid, message)
|
19
|
+
logger.info 'echo_reply handler is invoked'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
"""
|
23
|
+
And a file named "trema.conf" with:
|
24
|
+
"""
|
25
|
+
vswitch { datapath_id 0xabc }
|
26
|
+
"""
|
27
|
+
When I successfully run `trema -v run echo_reply.rb -c trema.conf -d`
|
28
|
+
And I run `sleep 5`
|
29
|
+
Then the file "EchoReply.log" should contain "echo_reply handler is invoked"
|
@@ -19,3 +19,32 @@ Feature: OpenFlow1.3
|
|
19
19
|
When I successfully run `trema -v run null_controller.rb --openflow13 -c trema.conf -d`
|
20
20
|
And I run `sleep 5`
|
21
21
|
Then the output should contain "protocols=OpenFlow13"
|
22
|
+
|
23
|
+
@sudo
|
24
|
+
Scenario: send_flow_mod_add
|
25
|
+
Given a file named "flow_mod_controller.rb" with:
|
26
|
+
"""
|
27
|
+
class FlowModController < Trema::Controller
|
28
|
+
def switch_ready(datapath_id)
|
29
|
+
logger.info 'Sending a FlowMod with OpenFlow 1.3 options'
|
30
|
+
send_flow_mod_add(
|
31
|
+
datapath_id,
|
32
|
+
table_id: 0,
|
33
|
+
idle_timeout: 180,
|
34
|
+
flags: [],
|
35
|
+
priority: 1,
|
36
|
+
match: Match.new({}),
|
37
|
+
instructions: []
|
38
|
+
)
|
39
|
+
logger.info 'Sent a FlowMod successfully'
|
40
|
+
end
|
41
|
+
end
|
42
|
+
"""
|
43
|
+
And a file named "trema.conf" with:
|
44
|
+
"""
|
45
|
+
vswitch { datapath_id 0xabc }
|
46
|
+
"""
|
47
|
+
When I successfully run `trema run flow_mod_controller.rb --openflow13 -c trema.conf -d`
|
48
|
+
And I run `sleep 5`
|
49
|
+
Then the file "FlowModController.log" should contain "Sent a FlowMod successfully"
|
50
|
+
|
data/features/trema_run.feature
CHANGED
@@ -45,3 +45,14 @@ Feature: trema run command
|
|
45
45
|
And I run `sleep 5`
|
46
46
|
Then the file "SwitchReady.log" should contain "Hello 0xabc!"
|
47
47
|
|
48
|
+
@sudo
|
49
|
+
Scenario: trema run empty file and error
|
50
|
+
Given a file named "empty.rb" with:
|
51
|
+
"""
|
52
|
+
"""
|
53
|
+
When I run `trema -v run empty.rb`
|
54
|
+
Then the exit status should not be 0
|
55
|
+
And the stderr should contain:
|
56
|
+
"""
|
57
|
+
No controller class is defined.
|
58
|
+
"""
|
data/lib/trema/controller.rb
CHANGED
@@ -21,7 +21,9 @@ module Trema
|
|
21
21
|
def to_hash
|
22
22
|
{
|
23
23
|
command: :add,
|
24
|
+
priority: @user_options[:priority] || 0,
|
24
25
|
transaction_id: rand(0xffffffff),
|
26
|
+
idle_timeout: @user_options[:idle_timeout] || 0,
|
25
27
|
hard_timeout: @user_options[:hard_timeout] || 0,
|
26
28
|
buffer_id: @user_options[:buffer_id] || 0xffffffff,
|
27
29
|
match: @user_options.fetch(:match),
|
@@ -30,6 +32,35 @@ module Trema
|
|
30
32
|
end
|
31
33
|
end
|
32
34
|
|
35
|
+
# Pio::FlowMod.new argument (OpenFlow 1.3)
|
36
|
+
class FlowModAdd13Option
|
37
|
+
def initialize(user_options)
|
38
|
+
@user_options = user_options
|
39
|
+
end
|
40
|
+
|
41
|
+
# rubocop:disable MethodLength
|
42
|
+
# rubocop:disable CyclomaticComplexity
|
43
|
+
# rubocop:disable PerceivedComplexity
|
44
|
+
def to_hash
|
45
|
+
{
|
46
|
+
command: :add,
|
47
|
+
priority: @user_options[:priority] || 0,
|
48
|
+
transaction_id: rand(0xffffffff),
|
49
|
+
idle_timeout: @user_options[:idle_timeout] || 0,
|
50
|
+
hard_timeout: @user_options[:hard_timeout] || 0,
|
51
|
+
buffer_id: @user_options[:buffer_id] || 0xffffffff,
|
52
|
+
match: @user_options.fetch(:match),
|
53
|
+
table_id: @user_options[:table_id] || 0,
|
54
|
+
flags: @user_options[:flags] || [],
|
55
|
+
instructions: @user_options[:instructions] || [],
|
56
|
+
actions: @user_options[:actions] || []
|
57
|
+
}
|
58
|
+
end
|
59
|
+
# rubocop:enable MethodLength
|
60
|
+
# rubocop:enable CyclomaticComplexity
|
61
|
+
# rubocop:enable PerceivedComplexity
|
62
|
+
end
|
63
|
+
|
33
64
|
# Pio::FlowMod.new argument
|
34
65
|
class FlowModDeleteOption
|
35
66
|
def initialize(user_options)
|
@@ -103,6 +134,7 @@ module Trema
|
|
103
134
|
|
104
135
|
# @private
|
105
136
|
def self.create(port_number = DEFAULT_TCP_PORT)
|
137
|
+
fail 'No controller class is defined.' unless @controller_klass
|
106
138
|
@controller_klass.new(port_number)
|
107
139
|
end
|
108
140
|
|
@@ -140,7 +172,15 @@ module Trema
|
|
140
172
|
# @!group OpenFlow Message
|
141
173
|
|
142
174
|
def send_flow_mod_add(datapath_id, options)
|
143
|
-
flow_mod =
|
175
|
+
flow_mod =
|
176
|
+
case Pio::OpenFlow.version
|
177
|
+
when 'OpenFlow10'
|
178
|
+
FlowMod.new(FlowModAddOption.new(options).to_hash)
|
179
|
+
when 'OpenFlow13'
|
180
|
+
FlowMod.new(FlowModAdd13Option.new(options).to_hash)
|
181
|
+
else
|
182
|
+
fail "Unsupported OpenFlow version: #{Pio::OpenFlow.version}"
|
183
|
+
end
|
144
184
|
send_message datapath_id, flow_mod
|
145
185
|
end
|
146
186
|
|
@@ -250,6 +290,8 @@ module Trema
|
|
250
290
|
case message
|
251
291
|
when Echo::Request
|
252
292
|
maybe_send_handler :echo_request, datapath_id, message
|
293
|
+
when Echo::Reply
|
294
|
+
maybe_send_handler :echo_reply, datapath_id, message
|
253
295
|
when Features::Reply
|
254
296
|
maybe_send_handler :features_reply, datapath_id, message
|
255
297
|
when PacketIn
|
data/lib/trema/switch.rb
CHANGED
@@ -7,15 +7,6 @@ module Trema
|
|
7
7
|
|
8
8
|
OPENFLOW_HEADER_LENGTH = 8
|
9
9
|
|
10
|
-
OPENFLOW_MESSAGE_PARSER = {
|
11
|
-
OpenFlow::HELLO => Hello,
|
12
|
-
OpenFlow::ECHO_REQUEST => Echo::Request,
|
13
|
-
OpenFlow::ECHO_REPLY => Echo::Reply,
|
14
|
-
OpenFlow::FEATURES_REPLY => Features::Reply,
|
15
|
-
OpenFlow::PACKET_IN => PacketIn,
|
16
|
-
OpenFlow::PORT_STATUS => PortStatus
|
17
|
-
}
|
18
|
-
|
19
10
|
def initialize(socket)
|
20
11
|
@socket = socket
|
21
12
|
end
|
@@ -38,10 +29,7 @@ module Trema
|
|
38
29
|
end
|
39
30
|
|
40
31
|
def read
|
41
|
-
|
42
|
-
OPENFLOW_MESSAGE_PARSER.fetch(message_type).read(binary)
|
43
|
-
rescue KeyError
|
44
|
-
raise "Unknown OpenFlow message (message_type = #{message_type})."
|
32
|
+
OpenFlow.read read_openflow_binary
|
45
33
|
end
|
46
34
|
|
47
35
|
private
|
@@ -53,14 +41,38 @@ module Trema
|
|
53
41
|
|
54
42
|
def exchange_echo_messages
|
55
43
|
write Echo::Request.new
|
56
|
-
|
44
|
+
loop do
|
45
|
+
message = read
|
46
|
+
if message.is_a?(Echo::Reply)
|
47
|
+
break
|
48
|
+
else
|
49
|
+
handle_early message 'Failed to exchange Echo messages'
|
50
|
+
end
|
51
|
+
end
|
57
52
|
end
|
58
53
|
|
59
54
|
def exchange_features_messages
|
60
55
|
write Features::Request.new
|
61
|
-
|
62
|
-
|
63
|
-
|
56
|
+
loop do
|
57
|
+
message = read
|
58
|
+
if message.is_a?(Features::Reply)
|
59
|
+
@features_reply = message
|
60
|
+
break
|
61
|
+
else
|
62
|
+
handle_early message 'Failed to exchange Features messages'
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def handle_early(message, fail_message)
|
68
|
+
case message
|
69
|
+
when Echo::Request
|
70
|
+
write Echo::Reply.new xid: message.xid
|
71
|
+
when PacketIn, FlowRemoved, PortStatus
|
72
|
+
return
|
73
|
+
else
|
74
|
+
fail fail_message
|
75
|
+
end
|
64
76
|
end
|
65
77
|
|
66
78
|
def read_openflow_binary
|
@@ -68,7 +80,7 @@ module Trema
|
|
68
80
|
header = OpenFlowHeaderParser.read(header_binary)
|
69
81
|
body_binary = drain(header.message_length - OPENFLOW_HEADER_LENGTH)
|
70
82
|
fail if (header_binary + body_binary).length != header.message_length
|
71
|
-
|
83
|
+
header_binary + body_binary
|
72
84
|
end
|
73
85
|
|
74
86
|
def drain(length)
|
data/lib/trema/version.rb
CHANGED
data/trema.gemspec
CHANGED
@@ -21,22 +21,22 @@ Gem::Specification.new do |gem|
|
|
21
21
|
|
22
22
|
gem.test_files = `git ls-files -- {spec,features}/*`.split("\n")
|
23
23
|
|
24
|
-
gem.add_dependency 'bundler', '~> 1.10.
|
24
|
+
gem.add_dependency 'bundler', '~> 1.10.6'
|
25
25
|
gem.add_dependency 'gli', '~> 2.13.1'
|
26
|
-
gem.add_dependency 'phut', '~> 0.6.
|
27
|
-
gem.add_dependency 'pio', '~> 0.
|
26
|
+
gem.add_dependency 'phut', '~> 0.6.6'
|
27
|
+
gem.add_dependency 'pio', '~> 0.24.0'
|
28
28
|
gem.add_dependency 'rake'
|
29
29
|
|
30
30
|
# Docs
|
31
31
|
gem.add_development_dependency 'yard', '~> 0.8.7.6'
|
32
32
|
|
33
33
|
# Test
|
34
|
-
gem.add_development_dependency 'aruba', '~> 0.
|
34
|
+
gem.add_development_dependency 'aruba', '~> 0.8.1'
|
35
35
|
gem.add_development_dependency 'codeclimate-test-reporter', '~> 0.4.7'
|
36
36
|
gem.add_development_dependency 'coveralls', '~> 0.8.2'
|
37
|
-
gem.add_development_dependency 'cucumber', '~> 2.0.
|
38
|
-
gem.add_development_dependency 'reek', '~>
|
37
|
+
gem.add_development_dependency 'cucumber', '~> 2.0.2'
|
38
|
+
gem.add_development_dependency 'reek', '~> 3.1'
|
39
39
|
gem.add_development_dependency 'rspec', '~> 3.3.0'
|
40
|
-
gem.add_development_dependency 'rspec-given', '~> 3.7.
|
40
|
+
gem.add_development_dependency 'rspec-given', '~> 3.7.1'
|
41
41
|
gem.add_development_dependency 'rubocop', '~> 0.32.1'
|
42
42
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: trema
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
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-
|
11
|
+
date: 2015-08-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ~>
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 1.10.
|
19
|
+
version: 1.10.6
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ~>
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 1.10.
|
26
|
+
version: 1.10.6
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: gli
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -44,28 +44,28 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - ~>
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: 0.6.
|
47
|
+
version: 0.6.6
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - ~>
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: 0.6.
|
54
|
+
version: 0.6.6
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: pio
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - ~>
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: 0.
|
61
|
+
version: 0.24.0
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - ~>
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: 0.
|
68
|
+
version: 0.24.0
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rake
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -100,14 +100,14 @@ dependencies:
|
|
100
100
|
requirements:
|
101
101
|
- - ~>
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: 0.
|
103
|
+
version: 0.8.1
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
108
|
- - ~>
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: 0.
|
110
|
+
version: 0.8.1
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: codeclimate-test-reporter
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -142,28 +142,28 @@ dependencies:
|
|
142
142
|
requirements:
|
143
143
|
- - ~>
|
144
144
|
- !ruby/object:Gem::Version
|
145
|
-
version: 2.0.
|
145
|
+
version: 2.0.2
|
146
146
|
type: :development
|
147
147
|
prerelease: false
|
148
148
|
version_requirements: !ruby/object:Gem::Requirement
|
149
149
|
requirements:
|
150
150
|
- - ~>
|
151
151
|
- !ruby/object:Gem::Version
|
152
|
-
version: 2.0.
|
152
|
+
version: 2.0.2
|
153
153
|
- !ruby/object:Gem::Dependency
|
154
154
|
name: reek
|
155
155
|
requirement: !ruby/object:Gem::Requirement
|
156
156
|
requirements:
|
157
157
|
- - ~>
|
158
158
|
- !ruby/object:Gem::Version
|
159
|
-
version:
|
159
|
+
version: '3.1'
|
160
160
|
type: :development
|
161
161
|
prerelease: false
|
162
162
|
version_requirements: !ruby/object:Gem::Requirement
|
163
163
|
requirements:
|
164
164
|
- - ~>
|
165
165
|
- !ruby/object:Gem::Version
|
166
|
-
version:
|
166
|
+
version: '3.1'
|
167
167
|
- !ruby/object:Gem::Dependency
|
168
168
|
name: rspec
|
169
169
|
requirement: !ruby/object:Gem::Requirement
|
@@ -184,14 +184,14 @@ dependencies:
|
|
184
184
|
requirements:
|
185
185
|
- - ~>
|
186
186
|
- !ruby/object:Gem::Version
|
187
|
-
version: 3.7.
|
187
|
+
version: 3.7.1
|
188
188
|
type: :development
|
189
189
|
prerelease: false
|
190
190
|
version_requirements: !ruby/object:Gem::Requirement
|
191
191
|
requirements:
|
192
192
|
- - ~>
|
193
193
|
- !ruby/object:Gem::Version
|
194
|
-
version: 3.7.
|
194
|
+
version: 3.7.1
|
195
195
|
- !ruby/object:Gem::Dependency
|
196
196
|
name: rubocop
|
197
197
|
requirement: !ruby/object:Gem::Requirement
|
@@ -229,6 +229,7 @@ files:
|
|
229
229
|
- bin/.gitignore
|
230
230
|
- bin/trema
|
231
231
|
- features/cleanup_on_failure.feature
|
232
|
+
- features/echo_reply_handler.feature
|
232
233
|
- features/logging.feature
|
233
234
|
- features/open_flow13.feature
|
234
235
|
- features/step_definitions/.gitignore
|