trema 0.4.3 → 0.4.4
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +2 -0
- data/CONTRIBUTING.md +12 -0
- data/Gemfile +5 -3
- data/README.md +3 -3
- data/Rakefile +30 -14
- data/bin/trema +3 -0
- data/cruise.rb +1 -1
- data/features/examples/switch_monitor.feature +2 -2
- data/features/switch_event/add_forward_entry.feature +0 -1
- data/features/switch_event/delete_forward_entry.feature +0 -1
- data/features/switch_event/dump_forward_entries.feature +0 -1
- data/features/switch_event/set_forward_entries.feature +0 -1
- data/ruby/trema/command/run.rb +3 -0
- data/ruby/trema/dsl/runner.rb +1 -0
- data/ruby/trema/mac.rb +4 -145
- data/ruby/trema/match.c +8 -8
- data/ruby/trema/packet-in.c +12 -12
- data/ruby/trema/port-mod.c +7 -4
- data/ruby/trema/port.c +4 -1
- data/ruby/trema/set-eth-dst-addr.rb +3 -5
- data/ruby/trema/set-eth-src-addr.rb +5 -6
- data/ruby/trema/stats-reply.c +1 -1
- data/ruby/trema/switch-event.c +10 -10
- data/ruby/trema/trema.c +3 -0
- data/ruby/trema/version.rb +1 -1
- data/spec/spec_helper.rb +1 -1
- data/spec/trema/packet-in_spec.rb +2 -2
- data/spec/trema/set-eth-addr_spec.rb +5 -43
- data/src/examples/learning_switch/learning-switch.rb +2 -0
- data/src/lib/daemon.c +37 -22
- data/src/lib/log.c +31 -0
- data/src/lib/messenger.c +13 -5
- data/src/lib/trema.c +6 -5
- data/src/switch_manager/switch.c +178 -41
- data/src/switch_manager/switchinfo.h +6 -2
- data/trema.gemspec +3 -3
- data/unittests/lib/daemon_test.c +36 -36
- data/unittests/lib/trema_test.c +25 -8
- metadata +124 -96
- checksums.yaml +0 -7
- data/spec/trema/mac_spec.rb +0 -100
data/.travis.yml
CHANGED
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
# Contributing to Trema
|
2
|
+
|
3
|
+
* Check out the latest develop to make sure the feature hasn't been
|
4
|
+
implemented or the bug hasn't been fixed yet.
|
5
|
+
* Check out the issue tracker to make sure someone already hasn't
|
6
|
+
requested it and/or contributed it.
|
7
|
+
* Fork the project.
|
8
|
+
* Commit and push until you are happy with your contribution.
|
9
|
+
* Make sure to add tests for it. This is important so I don't break it
|
10
|
+
in a future version unintentionally.
|
11
|
+
* Squash your commits.
|
12
|
+
* Create a pull-request.
|
data/Gemfile
CHANGED
@@ -16,14 +16,16 @@ group :development do
|
|
16
16
|
gem "aruba", "~> 0.5.3"
|
17
17
|
gem "cucumber", "~> 1.3.8"
|
18
18
|
gem "flay", "~> 2.4.0"
|
19
|
-
gem "flog", "~> 4.
|
19
|
+
gem "flog", "~> 4.2.0"
|
20
20
|
gem "rcov", "~> 1.0.0" if RUBY_VERSION < "1.9.0"
|
21
21
|
gem "redcarpet", "~> 2.3.0" if RUBY_VERSION < "1.9.0"
|
22
22
|
gem "redcarpet", "~> 3.0.0" if RUBY_VERSION >= "1.9.0"
|
23
|
-
gem "reek", "~> 1.3.
|
23
|
+
gem "reek", "~> 1.3.4"
|
24
24
|
gem "relish", "~> 0.7"
|
25
25
|
gem "rspec", "~> 2.14.1"
|
26
|
-
gem "yard", "~> 0.8.7.
|
26
|
+
gem "yard", "~> 0.8.7.2"
|
27
|
+
gem 'mime-types', '~> 1.25' if RUBY_VERSION < '1.9.0'
|
28
|
+
gem 'mime-types', '~> 2.0' if RUBY_VERSION >= '1.9.0'
|
27
29
|
end
|
28
30
|
|
29
31
|
|
data/README.md
CHANGED
@@ -49,15 +49,15 @@ Getting Started
|
|
49
49
|
1.Install the prerequisites at the command prompt:
|
50
50
|
|
51
51
|
(In Ubuntu or Debian GNU/Linux)
|
52
|
-
$ sudo apt-get install gcc make ruby rubygems ruby-dev libpcap-dev libsqlite3-dev libglib2.0-dev
|
52
|
+
$ sudo apt-get install gcc make git ruby rubygems ruby-dev libpcap-dev libsqlite3-dev libglib2.0-dev
|
53
53
|
|
54
54
|
(In Ubuntu 10.04)
|
55
|
-
$ sudo apt-get install gcc make ruby rubygems ruby-dev libopenssl-ruby libpcap-dev libsqlite3-dev libglib2.0-dev
|
55
|
+
$ sudo apt-get install gcc make git ruby rubygems ruby-dev libopenssl-ruby libpcap-dev libsqlite3-dev libglib2.0-dev
|
56
56
|
$ sudo gem install rubygems-update
|
57
57
|
$ sudo /var/lib/gems/1.8/bin/update_rubygems
|
58
58
|
|
59
59
|
(In Fedora 16-19)
|
60
|
-
$ sudo yum install gcc make ruby rubygems ruby-devel libpcap-devel libsqlite3x-devel glib2-devel
|
60
|
+
$ sudo yum install gcc make git ruby rubygems ruby-devel libpcap-devel libsqlite3x-devel glib2-devel
|
61
61
|
|
62
62
|
2.Install Trema at the command prompt:
|
63
63
|
|
data/Rakefile
CHANGED
@@ -105,7 +105,7 @@ end
|
|
105
105
|
|
106
106
|
desc "Build Trema Ruby library."
|
107
107
|
task "rubylib" => "libtrema:static"
|
108
|
-
PaperHouse::
|
108
|
+
PaperHouse::RubyExtensionTask.new "rubylib" do | task |
|
109
109
|
task.library_name = "trema"
|
110
110
|
task.target_directory = Trema.ruby
|
111
111
|
task.sources = "#{ Trema.ruby }/trema/*.c"
|
@@ -191,8 +191,8 @@ file Trema.openflow_h => Trema.objects do
|
|
191
191
|
end
|
192
192
|
directory Trema.objects
|
193
193
|
|
194
|
-
CLOBBER.include
|
195
|
-
CLOBBER.include File.join( Trema.
|
194
|
+
CLOBBER.include( Trema.vendor_openflow ) if FileTest.exists?( Trema.vendor_openflow )
|
195
|
+
CLOBBER.include( File.join( Trema.objects, "openflow" ) ) if FileTest.exists?( File.join( Trema.objects, "openflow" ) )
|
196
196
|
|
197
197
|
|
198
198
|
################################################################################
|
@@ -205,6 +205,24 @@ def phost_src
|
|
205
205
|
File.join Trema.vendor_phost, "src"
|
206
206
|
end
|
207
207
|
|
208
|
+
def phost_objects
|
209
|
+
FileList[ File.join( phost_src, "*.o" ) ]
|
210
|
+
end
|
211
|
+
|
212
|
+
def phost_vendor_binary
|
213
|
+
File.join phost_src, "phost"
|
214
|
+
end
|
215
|
+
|
216
|
+
def phost_cli_vendor_binary
|
217
|
+
File.join phost_src, "cli"
|
218
|
+
end
|
219
|
+
|
220
|
+
def phost_clean_targets
|
221
|
+
( phost_objects + [ phost_vendor_binary, phost_cli_vendor_binary ] ).select do | each |
|
222
|
+
FileTest.exists? each
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
208
226
|
file Trema::Executables.phost do
|
209
227
|
cd phost_src do
|
210
228
|
sh "make"
|
@@ -221,10 +239,8 @@ file Trema::Executables.cli do
|
|
221
239
|
install File.join( phost_src, "cli" ), Trema::Executables.cli, :mode => 0755
|
222
240
|
end
|
223
241
|
|
224
|
-
CLEAN.include
|
225
|
-
|
226
|
-
CLEAN.include File.join( phost_src, "cli" )
|
227
|
-
CLOBBER.include Trema.phost
|
242
|
+
CLEAN.include phost_clean_targets
|
243
|
+
CLOBBER.include( Trema.phost ) if FileTest.exists?( Trema.phost )
|
228
244
|
|
229
245
|
|
230
246
|
################################################################################
|
@@ -253,8 +269,8 @@ file Trema::Executables.ovs_openflowd do
|
|
253
269
|
end
|
254
270
|
end
|
255
271
|
|
256
|
-
CLEAN.include Trema.vendor_openvswitch
|
257
|
-
CLOBBER.include Trema.openvswitch
|
272
|
+
CLEAN.include( Trema.vendor_openvswitch ) if FileTest.exists?( Trema.vendor_openvswitch )
|
273
|
+
CLOBBER.include( Trema.openvswitch ) if FileTest.exists?( Trema.openvswitch )
|
258
274
|
|
259
275
|
|
260
276
|
################################################################################
|
@@ -298,8 +314,8 @@ file cbench_command => Trema.openflow_h do
|
|
298
314
|
end
|
299
315
|
end
|
300
316
|
|
301
|
-
CLEAN.include Trema.oflops
|
302
|
-
CLOBBER.include Trema.vendor_oflops
|
317
|
+
CLEAN.include( Trema.oflops ) if FileTest.exists?( Trema.oflops )
|
318
|
+
CLOBBER.include( Trema.vendor_oflops ) if FileTest.exists?( Trema.vendor_oflops )
|
303
319
|
|
304
320
|
|
305
321
|
################################################################################
|
@@ -315,8 +331,8 @@ file Trema.libcmockery_a do
|
|
315
331
|
end
|
316
332
|
end
|
317
333
|
|
318
|
-
CLEAN.include Trema.vendor_cmockery
|
319
|
-
CLOBBER.include Trema.cmockery
|
334
|
+
CLEAN.include( Trema.vendor_cmockery ) if FileTest.exists?( Trema.vendor_cmockery )
|
335
|
+
CLOBBER.include( Trema.cmockery ) if FileTest.exists?( Trema.cmockery )
|
320
336
|
|
321
337
|
|
322
338
|
################################################################################
|
@@ -736,7 +752,7 @@ directory $wireshark_plugins_dir
|
|
736
752
|
|
737
753
|
task :openflow_wireshark_plugin => $wireshark_plugin
|
738
754
|
|
739
|
-
CLEAN.include Trema.vendor_openflow_git
|
755
|
+
CLEAN.include( Trema.vendor_openflow_git ) if FileTest.exists?( Trema.vendor_openflow_git )
|
740
756
|
|
741
757
|
|
742
758
|
################################################################################
|
data/bin/trema
CHANGED
@@ -60,6 +60,9 @@ class BinTrema
|
|
60
60
|
c.desc "Specifies emulated network configuration"
|
61
61
|
c.flag [ :c, :conf ]
|
62
62
|
|
63
|
+
c.desc "Disables initial flow cleanup for a connected switch"
|
64
|
+
c.switch [ :r, :no_flow_cleanup ], :negatable => false
|
65
|
+
|
63
66
|
c.action do | global_options, options, args |
|
64
67
|
trema_run options
|
65
68
|
end
|
data/cruise.rb
CHANGED
@@ -17,7 +17,7 @@ Feature: "Switch Monitor" sample application
|
|
17
17
|
Given I run `trema run ../../objects/examples/switch_monitor/switch_monitor -c switch_monitor.conf -d`
|
18
18
|
And wait until "switch_monitor" is up
|
19
19
|
When I run `trema kill 0x3`
|
20
|
-
And *** sleep
|
20
|
+
And *** sleep 2 ***
|
21
21
|
Then the file "../../tmp/log/switch_monitor.log" should contain "Switch 0x3 is DOWN"
|
22
22
|
When I run `trema up 0x3`
|
23
23
|
And *** sleep 10 ***
|
@@ -28,7 +28,7 @@ Feature: "Switch Monitor" sample application
|
|
28
28
|
Given I run `trema run ../../src/examples/switch_monitor/switch-monitor.rb -c switch_monitor.conf -d`
|
29
29
|
And wait until "SwitchMonitor" is up
|
30
30
|
When I run `trema kill 0x3`
|
31
|
-
And *** sleep
|
31
|
+
And *** sleep 2 ***
|
32
32
|
Then the file "../../tmp/log/SwitchMonitor.log" should contain "Switch 0x3 is DOWN"
|
33
33
|
When I run `trema up 0x3`
|
34
34
|
And *** sleep 10 ***
|
data/ruby/trema/command/run.rb
CHANGED
data/ruby/trema/dsl/runner.rb
CHANGED
data/ruby/trema/mac.rb
CHANGED
@@ -16,154 +16,12 @@
|
|
16
16
|
#
|
17
17
|
|
18
18
|
|
19
|
-
require "
|
19
|
+
require "rubygems"
|
20
|
+
require "pio"
|
20
21
|
|
21
22
|
|
22
23
|
module Trema
|
23
|
-
|
24
|
-
# Ethernet address class
|
25
|
-
#
|
26
|
-
class Mac
|
27
|
-
extend Forwardable
|
28
|
-
def_delegator :@value, :hash
|
29
|
-
|
30
|
-
|
31
|
-
#
|
32
|
-
# Returns an Ethernet address in its numeric presentation.
|
33
|
-
#
|
34
|
-
# @example
|
35
|
-
# Mac.new("11:22:33:44:55:66") #=> 18838586676582
|
36
|
-
#
|
37
|
-
# @return [Number] the Ethernet address in numeric format
|
38
|
-
#
|
39
|
-
attr_reader :value
|
40
|
-
|
41
|
-
|
42
|
-
#
|
43
|
-
# Creates a {Mac} instance that encapsulates Ethernet addresses.
|
44
|
-
#
|
45
|
-
# @overload initialize(value)
|
46
|
-
#
|
47
|
-
# @param [String,Integer] value
|
48
|
-
# the Ethernet address to set to.
|
49
|
-
#
|
50
|
-
# @example address as a hexadecimal string
|
51
|
-
# Mac.new("11:22:33:44:55:66")
|
52
|
-
#
|
53
|
-
# @example address as a hexadecimal number
|
54
|
-
# Mac.new(0xffffffffffff)
|
55
|
-
#
|
56
|
-
# @raise [ArgumentError] if invalid format is detected.
|
57
|
-
# @raise [TypeError] if supplied argument is not a String or Integer.
|
58
|
-
#
|
59
|
-
def initialize value
|
60
|
-
case value
|
61
|
-
when String
|
62
|
-
@value = create_from( value )
|
63
|
-
when Integer
|
64
|
-
@value = value
|
65
|
-
validate_value_range
|
66
|
-
when Mac
|
67
|
-
@value = create_from( value.to_s )
|
68
|
-
else
|
69
|
-
raise TypeError, "Invalid MAC address: #{ value.inspect }"
|
70
|
-
end
|
71
|
-
@string = string_format
|
72
|
-
end
|
73
|
-
|
74
|
-
|
75
|
-
#
|
76
|
-
# Returns the Ethernet address as 6 pairs of hexadecimal digits
|
77
|
-
# delimited by colons.
|
78
|
-
#
|
79
|
-
# @example
|
80
|
-
# Mac.new(18838586676582).to_s #=> "11:22:33:44:55:66"
|
81
|
-
#
|
82
|
-
# @return [String] the Ethernet address in String format
|
83
|
-
#
|
84
|
-
def to_s
|
85
|
-
@string
|
86
|
-
end
|
87
|
-
|
88
|
-
|
89
|
-
#
|
90
|
-
# Returns an array of decimal numbers converted from Ethernet's
|
91
|
-
# address string format.
|
92
|
-
#
|
93
|
-
# @example
|
94
|
-
# Mac.new("11:22:33:44:55:66").to_a #=> [ 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 ]
|
95
|
-
#
|
96
|
-
# @return [Array] the Ethernet address in Array format
|
97
|
-
#
|
98
|
-
def to_a
|
99
|
-
@string.split( ":" ).collect do | each |
|
100
|
-
each.hex
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
|
105
|
-
#
|
106
|
-
# @private
|
107
|
-
#
|
108
|
-
def == other
|
109
|
-
@value == other.value
|
110
|
-
end
|
111
|
-
alias :eql? :==
|
112
|
-
|
113
|
-
|
114
|
-
#
|
115
|
-
# Returns true if Ethernet address is a multicast address.
|
116
|
-
#
|
117
|
-
# @example
|
118
|
-
# Mac.new("01:00:00:00:00:00").multicast? #=> true
|
119
|
-
# Mac.new("00:00:00:00:00:00").multicast? #=> false
|
120
|
-
#
|
121
|
-
# @return [Boolean] whether the Ethernet address is multicast
|
122
|
-
#
|
123
|
-
def multicast?
|
124
|
-
to_a[ 0 ] & 1 == 1
|
125
|
-
end
|
126
|
-
|
127
|
-
|
128
|
-
#
|
129
|
-
# Returns true if Ethernet address is a broadcast address.
|
130
|
-
#
|
131
|
-
# @example
|
132
|
-
# Mac.new("ff:ff:ff:ff:ff:ff").broadcast? #=> true
|
133
|
-
#
|
134
|
-
# @return [Boolean] whether the Ethernet address is broadcast
|
135
|
-
#
|
136
|
-
def broadcast?
|
137
|
-
to_a.all? { | each | each == 0xff }
|
138
|
-
end
|
139
|
-
|
140
|
-
|
141
|
-
################################################################################
|
142
|
-
private
|
143
|
-
################################################################################
|
144
|
-
|
145
|
-
|
146
|
-
def create_from string
|
147
|
-
octet_regex = "[0-9a-fA-F][0-9a-fA-F]"
|
148
|
-
if /^(#{ octet_regex }:){5}(#{ octet_regex })$/=~ string
|
149
|
-
string.gsub( ":", "" ).hex
|
150
|
-
else
|
151
|
-
raise ArgumentError, %{Invalid MAC address: "#{ string }"}
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
|
156
|
-
def validate_value_range
|
157
|
-
unless ( @value >= 0 and @value <= 0xffffffffffff )
|
158
|
-
raise ArgumentError, "Invalid MAC address: #{ @value }"
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
|
163
|
-
def string_format
|
164
|
-
sprintf( "%012x", @value ).unpack( "a2" * 6 ).join( ":" )
|
165
|
-
end
|
166
|
-
end
|
24
|
+
Mac = Pio::Mac
|
167
25
|
end
|
168
26
|
|
169
27
|
|
@@ -172,3 +30,4 @@ end
|
|
172
30
|
### coding: utf-8-unix
|
173
31
|
### indent-tabs-mode: nil
|
174
32
|
### End:
|
33
|
+
|
data/ruby/trema/match.c
CHANGED
@@ -238,7 +238,7 @@ match_dl( VALUE self, uint8_t which ) {
|
|
238
238
|
else {
|
239
239
|
dl_addr = match->dl_dst;
|
240
240
|
}
|
241
|
-
return rb_funcall( rb_eval_string( "
|
241
|
+
return rb_funcall( rb_eval_string( "Pio::Mac" ), rb_intern( "new" ), 1, ULL2NUM( mac_to_uint64( dl_addr ) ) );
|
242
242
|
}
|
243
243
|
|
244
244
|
|
@@ -395,16 +395,16 @@ match_tp_dst( VALUE self ) {
|
|
395
395
|
* @option options [Number] :in_port
|
396
396
|
* the physical port number to match.
|
397
397
|
*
|
398
|
-
* @option options [String,Number,
|
398
|
+
* @option options [String,Number,Mac] :dl_src
|
399
399
|
* the source ethernet address to match specified either as 6
|
400
400
|
* pairs of hexadecimal digits delimited by colon or as a
|
401
|
-
* hexadecimal number or as a
|
401
|
+
* hexadecimal number or as a Mac object.
|
402
402
|
* (eg. "00:11:22:33:44:55" or 0x001122334455 or Mac.new("00:11:22:33:44:55")).
|
403
403
|
*
|
404
404
|
* @option options [String,Number] :dl_dst
|
405
405
|
* the destination ethernet address to match specified either as a
|
406
406
|
* 6 pairs of hexadecimal digits delimited by colon or as a
|
407
|
-
* hexadecimal number or as a
|
407
|
+
* hexadecimal number or as a Mac object.
|
408
408
|
* (eg. "00:11:22:33:44:55" or 0x001122334455 or Mac.new("00:11:22:33:44:55")).
|
409
409
|
*
|
410
410
|
* @option options [Number] :dl_type
|
@@ -472,11 +472,11 @@ match_init( int argc, VALUE *argv, VALUE self ) {
|
|
472
472
|
VALUE dl_src = rb_hash_aref( options, ID2SYM( rb_intern( "dl_src" ) ) );
|
473
473
|
if ( dl_src != Qnil ) {
|
474
474
|
VALUE dl_addr;
|
475
|
-
if ( rb_obj_is_kind_of( dl_src, rb_eval_string( "
|
475
|
+
if ( rb_obj_is_kind_of( dl_src, rb_eval_string( "Pio::Mac" ) ) ) {
|
476
476
|
dl_addr = dl_src;
|
477
477
|
}
|
478
478
|
else {
|
479
|
-
dl_addr = rb_funcall( rb_eval_string( "
|
479
|
+
dl_addr = rb_funcall( rb_eval_string( "Pio::Mac" ), rb_intern( "new" ), 1, dl_src );
|
480
480
|
}
|
481
481
|
dl_addr_to_a( dl_addr, match->dl_src );
|
482
482
|
match->wildcards &= ( uint32_t ) ~OFPFW_DL_SRC;
|
@@ -485,11 +485,11 @@ match_init( int argc, VALUE *argv, VALUE self ) {
|
|
485
485
|
VALUE dl_dst = rb_hash_aref( options, ID2SYM( rb_intern( "dl_dst" ) ) );
|
486
486
|
if ( dl_dst != Qnil ) {
|
487
487
|
VALUE dl_addr;
|
488
|
-
if ( rb_obj_is_kind_of( dl_dst, rb_eval_string( "
|
488
|
+
if ( rb_obj_is_kind_of( dl_dst, rb_eval_string( "Pio::Mac" ) ) ) {
|
489
489
|
dl_addr = dl_dst;
|
490
490
|
}
|
491
491
|
else {
|
492
|
-
dl_addr = rb_funcall( rb_eval_string( "
|
492
|
+
dl_addr = rb_funcall( rb_eval_string( "Pio::Mac" ), rb_intern( "new" ), 1, dl_dst );
|
493
493
|
}
|
494
494
|
dl_addr_to_a( dl_addr, match->dl_dst );
|
495
495
|
match->wildcards &= ( uint32_t ) ~OFPFW_DL_DST;
|