trema 0.3.16 → 0.3.17

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -0
  3. data/.rvmrc +52 -0
  4. data/.travis.yml +3 -0
  5. data/Gemfile +1 -1
  6. data/Rakefile +259 -1
  7. data/Rantfile +79 -216
  8. data/features/.nav +12 -0
  9. data/features/dsl/switch_port_specifier.feature +15 -0
  10. data/features/examples/switch-event/C-add_forward_entry.feature +130 -0
  11. data/features/examples/switch-event/C-delete_forward_entry.feature +97 -0
  12. data/features/examples/switch-event/C-dump_forward_entries.feature +80 -0
  13. data/features/examples/switch-event/C-set_forward_entries.feature +85 -0
  14. data/features/examples/switch-event/README.md +40 -0
  15. data/features/examples/switch-event/add_forward_entry.feature +142 -0
  16. data/features/examples/switch-event/delete_forward_entry.feature +142 -0
  17. data/features/examples/switch-event/dump_forward_entries.feature +91 -0
  18. data/features/examples/switch-event/set_forward_entries.feature +90 -0
  19. data/features/support/hooks.rb +1 -0
  20. data/ruby/rake/c/dependency.rb +42 -0
  21. data/ruby/rake/c/library-task.rb +142 -0
  22. data/ruby/rake/c/shared-library-task.rb +38 -0
  23. data/ruby/rake/c/static-library-task.rb +32 -0
  24. data/ruby/trema/path.rb +1 -0
  25. data/ruby/trema/switch-event.c +647 -0
  26. data/{src/switch_manager/management_interface.h → ruby/trema/switch-event.h} +7 -21
  27. data/ruby/trema/trema.c +2 -0
  28. data/ruby/trema/version.rb +1 -1
  29. data/spec/spec_helper.rb +26 -2
  30. data/src/examples/switch_event_config/.gitignore +7 -0
  31. data/src/examples/switch_event_config/add_forward_entry.c +227 -0
  32. data/src/examples/switch_event_config/delete_forward_entry.c +226 -0
  33. data/src/examples/switch_event_config/dump_forward_entries.c +190 -0
  34. data/src/examples/switch_event_config/set_forward_entries.c +210 -0
  35. data/src/lib/event_forward_interface.c +783 -0
  36. data/src/lib/event_forward_interface.h +138 -0
  37. data/src/lib/trema.h +1 -0
  38. data/src/lib/utility.c +13 -1
  39. data/src/lib/utility.h +3 -0
  40. data/src/switch_manager/event_forward_entry_manipulation.c +120 -0
  41. data/src/switch_manager/event_forward_entry_manipulation.h +31 -0
  42. data/src/switch_manager/secure_channel_listener.c +23 -3
  43. data/src/switch_manager/switch.c +99 -29
  44. data/src/switch_manager/switch_manager.c +176 -3
  45. data/src/switch_manager/switch_manager.h +4 -0
  46. data/src/switch_manager/switch_option.c +30 -0
  47. data/src/switch_manager/switch_option.h +41 -0
  48. data/trema.gemspec +2 -1
  49. data/unittests/lib/event_forward_interface_test.c +1646 -0
  50. data/unittests/lib/utility_test.c +23 -1
  51. metadata +48 -10
@@ -46,6 +46,7 @@ end
46
46
  After do
47
47
  run "trema killall"
48
48
  wait_until_all_pid_files_are_deleted
49
+ processes.clear
49
50
  end
50
51
 
51
52
 
@@ -0,0 +1,42 @@
1
+ require "pstore"
2
+ require "trema/path"
3
+
4
+
5
+ module Rake
6
+ module C
7
+ module Dependency
8
+ @@store = {}
9
+
10
+
11
+ def self.read name, file
12
+ dump_of( name ).transaction( true ) do | store |
13
+ store[ file ]
14
+ end || []
15
+ end
16
+
17
+
18
+ def self.write name, file, dependency
19
+ dump_of( name ).transaction( false ) do | store |
20
+ store[ file ] = dependency
21
+ end
22
+ end
23
+
24
+
25
+ def self.dump_of name
26
+ @@store[ name ] ||= PStore.new( path( name ) )
27
+ end
28
+
29
+
30
+ def self.path name
31
+ File.join Trema.home, ".#{ name }.depends"
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+
38
+ ### Local variables:
39
+ ### mode: Ruby
40
+ ### coding: utf-8-unix
41
+ ### indent-tabs-mode: nil
42
+ ### End:
@@ -0,0 +1,142 @@
1
+ require "popen4"
2
+ require "rake/c/dependency"
3
+ require "rake/clean"
4
+ require "rake/tasklib"
5
+
6
+
7
+ module Rake
8
+ module C
9
+ class LibraryTask < TaskLib
10
+ attr_accessor :cflags
11
+ attr_accessor :includes
12
+ attr_accessor :library_name
13
+ attr_accessor :name
14
+ attr_accessor :target_directory
15
+ attr_writer :sources
16
+
17
+
18
+ def initialize name, &block
19
+ init name
20
+ block.call self
21
+ define
22
+ end
23
+
24
+
25
+ def sources
26
+ FileList.new @sources
27
+ end
28
+
29
+
30
+ ##########################################################################
31
+ private
32
+ ##########################################################################
33
+
34
+
35
+ def init name
36
+ @name = name
37
+ @includes = []
38
+ end
39
+
40
+
41
+ def define
42
+ CLEAN.include objects
43
+ CLOBBER.include target_directory
44
+ CLOBBER.include Dependency.path( @library_name )
45
+
46
+ task name => [ target_directory, target_path ]
47
+ directory target_directory
48
+
49
+ sources.zip( objects ) do | source, object |
50
+ task object => source do | task |
51
+ compile task.name, task.prerequisites[ 0 ]
52
+ end
53
+ end
54
+
55
+ file target_path => objects do | task |
56
+ generate_library
57
+ end
58
+ end
59
+
60
+
61
+ def generate_library
62
+ raise NotImplementedError, "Override this!"
63
+ end
64
+
65
+
66
+ def target_file_name
67
+ raise NotImplementedError, "Override this!"
68
+ end
69
+
70
+
71
+ def target_path
72
+ File.join @target_directory, target_file_name
73
+ end
74
+
75
+
76
+ def objects
77
+ sources.collect do | each |
78
+ File.join @target_directory, File.basename( each ).ext( ".o" )
79
+ end
80
+ end
81
+
82
+
83
+ def compile o_file, c_file
84
+ return if uptodate?( o_file, [ c_file ] + Dependency.read( library_name, o_file ) )
85
+ autodepends = run_gcc_H( "gcc -H #{ gcc_cflags } -fPIC #{ gcc_I_options } -c #{ c_file } -o #{ o_file }" )
86
+ Dependency.write( library_name, o_file, autodepends )
87
+ end
88
+
89
+
90
+ def run_gcc_H command
91
+ autodepends = []
92
+
93
+ puts command
94
+ status = POpen4.popen4( command ) do | stdout, stderr, stdin, pid |
95
+ stdin.close
96
+ stderr.each do | line |
97
+ case line
98
+ when /^\./
99
+ autodepends << line.sub( /^\.+\s+/, "" ).strip
100
+ when /Multiple include guards/
101
+ # Filter out include guards warnings.
102
+ stderr.each do | line |
103
+ if line =~ /:$/
104
+ puts line
105
+ break
106
+ end
107
+ end
108
+ else
109
+ puts line
110
+ end
111
+ end
112
+ end
113
+ fail "gcc failed" if status.exitstatus != 0
114
+
115
+ autodepends
116
+ end
117
+
118
+
119
+ def gcc_cflags
120
+ @cflags.join " "
121
+ end
122
+
123
+
124
+ def gcc_I_options
125
+ @includes.collect do | each |
126
+ "-I#{ each }"
127
+ end.join( " " )
128
+ end
129
+ end
130
+ end
131
+ end
132
+
133
+
134
+ require "rake/c/shared-library-task"
135
+ require "rake/c/static-library-task"
136
+
137
+
138
+ ### Local variables:
139
+ ### mode: Ruby
140
+ ### coding: utf-8-unix
141
+ ### indent-tabs-mode: nil
142
+ ### End:
@@ -0,0 +1,38 @@
1
+ require "rake/c/library-task"
2
+
3
+
4
+ module Rake
5
+ module C
6
+ class SharedLibraryTask < LibraryTask
7
+ attr_accessor :version
8
+
9
+
10
+ ##########################################################################
11
+ private
12
+ ##########################################################################
13
+
14
+
15
+ def generate_library
16
+ return if uptodate?( target_path, objects )
17
+ sh "gcc -shared -Wl,-soname=#{ soname } -o #{ target_path } #{ objects.to_s }"
18
+ end
19
+
20
+
21
+ def soname
22
+ File.basename( target_file_name ).sub( /\.\d+\.\d+\Z/, "" )
23
+ end
24
+
25
+
26
+ def target_file_name
27
+ @library_name + ".so." + @version
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+
34
+ ### Local variables:
35
+ ### mode: Ruby
36
+ ### coding: utf-8-unix
37
+ ### indent-tabs-mode: nil
38
+ ### End:
@@ -0,0 +1,32 @@
1
+ require "rake/c/library-task"
2
+
3
+
4
+ module Rake
5
+ module C
6
+ class StaticLibraryTask < LibraryTask
7
+ ##########################################################################
8
+ private
9
+ ##########################################################################
10
+
11
+
12
+ def generate_library
13
+ if not uptodate?( target_path, objects )
14
+ sh "ar -cq #{ target_path } #{ objects.join ' ' }"
15
+ sh "ranlib #{ target_path }"
16
+ end
17
+ end
18
+
19
+
20
+ def target_file_name
21
+ @library_name + ".a"
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+
28
+ ### Local variables:
29
+ ### mode: Ruby
30
+ ### coding: utf-8-unix
31
+ ### indent-tabs-mode: nil
32
+ ### End:
data/ruby/trema/path.rb CHANGED
@@ -60,6 +60,7 @@ module Trema
60
60
  dir :objects, "oflops"
61
61
  dir :objects, "openflow"
62
62
  dir :objects, "openvswitch"
63
+ dir :objects, "phost"
63
64
  dir :tmp, "log"
64
65
  dir :tmp, "pid"
65
66
  dir :tmp, "sock"
@@ -0,0 +1,647 @@
1
+ /*
2
+ * Copyright (C) 2013 NEC Corporation
3
+ *
4
+ * This program is free software; you can redistribute it and/or modify
5
+ * it under the terms of the GNU General Public License, version 2, as
6
+ * published by the Free Software Foundation.
7
+ *
8
+ * This program is distributed in the hope that it will be useful,
9
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ * GNU General Public License for more details.
12
+ *
13
+ * You should have received a copy of the GNU General Public License along
14
+ * with this program; if not, write to the Free Software Foundation, Inc.,
15
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16
+ */
17
+
18
+ #include <assert.h>
19
+ #include "ruby.h"
20
+ #include "switch-event.h"
21
+
22
+ #include "trema.h"
23
+
24
+ extern VALUE mTrema;
25
+ VALUE mSwitchEvent;
26
+
27
+ static ID idVendor;
28
+ static ID idPacketIn;
29
+ static ID idPortStatus;
30
+ static ID idStateNotify;
31
+
32
+
33
+ typedef struct callback_info {
34
+ VALUE self;
35
+ VALUE block;
36
+ } callback_info;
37
+
38
+
39
+ static bool
40
+ event_type_symbol_to_enum( VALUE rType, enum efi_event_type *cType ) {
41
+ assert( cType != NULL );
42
+ const ID idType = rb_to_id( rType );
43
+ if ( false ) {
44
+ }
45
+ else if ( idType == idVendor ) {
46
+ *cType = EVENT_FORWARD_TYPE_VENDOR;
47
+ }
48
+ else if ( idType == idPacketIn ) {
49
+ *cType = EVENT_FORWARD_TYPE_PACKET_IN;
50
+ }
51
+ else if ( idType == idPortStatus ) {
52
+ *cType = EVENT_FORWARD_TYPE_PORT_STATUS;
53
+ }
54
+ else if ( idType == idStateNotify ) {
55
+ *cType = EVENT_FORWARD_TYPE_STATE_NOTIFY;
56
+ }
57
+ else {
58
+ return false;
59
+ }
60
+ return true;
61
+ }
62
+
63
+
64
+ static void
65
+ handle_event_forward_entry_to_all_callback( enum efi_result result,
66
+ void *user_data ) {
67
+ debug( "%s", __func__ );
68
+ callback_info *cb = user_data;
69
+ if ( cb->block != Qnil ) {
70
+ if ( result == EFI_OPERATION_SUCCEEDED ) {
71
+ rb_funcall( cb->block, rb_intern( "call" ), 1, Qtrue );
72
+ }
73
+ else {
74
+ rb_funcall( cb->block, rb_intern( "call" ), 1, Qfalse );
75
+ }
76
+ }
77
+ xfree( cb );
78
+
79
+ }
80
+
81
+ /*
82
+ * @!group Operation for all existing switches and switch manager
83
+ *
84
+ * @overload add_forward_entry_to_all_switches type, service_name, {|result| ... }
85
+ * Add forwarding entry to all existing switches and switch manager.
86
+ *
87
+ * @param [Symbol] type Switch event type. it must be one of :vendor, :packet_in, :port_status, :state_notify
88
+ * @param [String] service_name Name of controller to forward event.
89
+ * @return [Boolean] true if request was sent successfully.
90
+ *
91
+ * @yield Callback to notify the result of operation.
92
+ * @yieldparam result [Boolean] true if result successful on all switches and switch manager
93
+ */
94
+ static VALUE
95
+ add_forward_entry_to_all_switches( VALUE self, VALUE type, VALUE service_name ) {
96
+ debug( "%s", __func__ );
97
+ enum efi_event_type c_type;
98
+ if ( !event_type_symbol_to_enum( type, &c_type ) ) {
99
+ warn( "Invalid event type was specified" );
100
+ return Qfalse;
101
+ }
102
+
103
+ const char *c_service_name = StringValuePtr( service_name );
104
+ if ( strlen( c_service_name ) == 0 ) {
105
+ warn( "service_name cannot be empty" );
106
+ return Qfalse;
107
+ }
108
+
109
+ callback_info *cb = xcalloc( 1, sizeof( callback_info ) );
110
+ cb->self = self;
111
+ cb->block = Qnil;
112
+ if ( rb_block_given_p() == Qtrue ) {
113
+ cb->block = rb_block_proc();
114
+ }
115
+ bool succ = add_event_forward_entry_to_all_switches(
116
+ c_type, c_service_name,
117
+ handle_event_forward_entry_to_all_callback,
118
+ cb );
119
+ if ( succ ) {
120
+ return Qtrue;
121
+ }
122
+ else {
123
+ xfree( cb );
124
+ return Qfalse;
125
+ }
126
+ }
127
+
128
+
129
+ /*
130
+ * @!group Operation for all existing switches and switch manager
131
+ *
132
+ * @overload delete_forward_entry_from_all_switches type, service_name, {|result| ... }
133
+ * Delete forwarding entry to all existing switches and switch manager.
134
+ *
135
+ * @param [Symbol] type Switch event type. it must be one of :vendor, :packet_in, :port_status, :state_notify
136
+ * @param [String] service_name Name of controller to forward event.
137
+ * @return [Boolean] true if request was sent successfully.
138
+ *
139
+ * @yield Callback to notify the result of operation.
140
+ * @yieldparam result [Boolean] true if result successful on all switches and switch manager
141
+ */
142
+ static VALUE
143
+ delete_forward_entry_from_all_switches( VALUE self, VALUE type,
144
+ VALUE service_name ) {
145
+ debug( "%s", __func__ );
146
+ enum efi_event_type c_type;
147
+ if ( !event_type_symbol_to_enum( type, &c_type ) ) {
148
+ warn( "Invalid event type was specified" );
149
+ return Qfalse;
150
+ }
151
+
152
+ const char *c_service_name = StringValuePtr( service_name );
153
+ if ( strlen( c_service_name ) == 0 ) {
154
+ warn( "service_name cannot be empty" );
155
+ return Qfalse;
156
+ }
157
+
158
+ callback_info *cb = xcalloc( 1, sizeof( callback_info ) );
159
+ cb->self = self;
160
+ cb->block = Qnil;
161
+ if ( rb_block_given_p() == Qtrue ) {
162
+ cb->block = rb_block_proc();
163
+ }
164
+ bool succ = delete_event_forward_entry_to_all_switches(
165
+ c_type, c_service_name,
166
+ handle_event_forward_entry_to_all_callback,
167
+ cb );
168
+ if ( succ ) {
169
+ return Qtrue;
170
+ }
171
+ else {
172
+ xfree( cb );
173
+ return Qfalse;
174
+ }
175
+ }
176
+
177
+
178
+ static void
179
+ handle_event_forward_entry_operation_callback(
180
+ event_forward_operation_result result, void *user_data ) {
181
+ debug( "%s", __func__ );
182
+ callback_info *cb = user_data;
183
+
184
+ if ( cb->block != Qnil ) {
185
+ if ( result.result == EFI_OPERATION_SUCCEEDED ) {
186
+ VALUE aryDpid = rb_ary_new2( ( long ) result.n_services );
187
+ for ( uint32_t i = 0 ; i < result.n_services ; ++i ) {
188
+ VALUE service_name = rb_str_new2( result.services[i] );
189
+ rb_ary_push( aryDpid, service_name );
190
+ }
191
+ rb_funcall( cb->block, rb_intern( "call" ), 2, Qtrue, aryDpid );
192
+ }
193
+ else {
194
+ VALUE aryDpid = rb_ary_new();
195
+ rb_funcall( cb->block, rb_intern( "call" ), 2, Qfalse, aryDpid );
196
+ }
197
+ }
198
+ xfree( cb );
199
+ }
200
+
201
+
202
+ /*
203
+ * @!group Operation for existing switch
204
+ *
205
+ * @overload add_forward_entry_to_switch datapath_id, type, service_name, {|result, services| ... }
206
+ * Add forwarding entry of a switch specified.
207
+ *
208
+ * @param [Integer] dpid Switch datapath_id
209
+ * @param [Symbol] type Switch event type. it must be one of :vendor, :packet_in, :port_status, :state_notify
210
+ * @param [String] service_name Name of controller to forward event.
211
+ * @return [Boolean] true if request was sent successfully.
212
+ *
213
+ * @yield Callback to notify the result of operation.
214
+ * @yieldparam result [Boolean] true if result successful.
215
+ * @yieldparam services [Array<String>] Service Name list on forwarding entry after operation.
216
+ */
217
+ static VALUE
218
+ add_forward_entry_to_switch( VALUE self, VALUE dpid, VALUE type,
219
+ VALUE service_name ) {
220
+ debug( "%s", __func__ );
221
+ enum efi_event_type c_type;
222
+ if ( !event_type_symbol_to_enum( type, &c_type ) ) {
223
+ warn( "Invalid event type was specified" );
224
+ return Qfalse;
225
+ }
226
+
227
+ const uint64_t c_dpid = NUM2ULL( dpid );
228
+ const char *c_service_name = StringValuePtr( service_name );
229
+ if ( strlen( c_service_name ) == 0 ) {
230
+ warn( "service_name cannot be empty" );
231
+ return Qfalse;
232
+ }
233
+
234
+ callback_info *cb = xcalloc( 1, sizeof( callback_info ) );
235
+ cb->self = self;
236
+ cb->block = Qnil;
237
+ if ( rb_block_given_p() == Qtrue ) {
238
+ cb->block = rb_block_proc();
239
+ }
240
+ bool succ = add_switch_event_forward_entry(
241
+ c_dpid, c_type, c_service_name,
242
+ handle_event_forward_entry_operation_callback,
243
+ cb );
244
+ if ( succ ) {
245
+ return Qtrue;
246
+ }
247
+ else {
248
+ xfree( cb );
249
+ return Qfalse;
250
+ }
251
+ }
252
+
253
+
254
+ /*
255
+ * @!group Operation for existing switch
256
+ *
257
+ * @overload delete_forward_entry_from_switch datapath_id, type, service_name, {|result, services| ... }
258
+ * Delete forwarding entry of a switch specified.
259
+ *
260
+ * @param [Integer] dpid Switch datapath_id
261
+ * @param [Symbol] type Switch event type. it must be one of :vendor, :packet_in, :port_status, :state_notify
262
+ * @param [String] service_name Name of controller to forward event.
263
+ * @return [Boolean] true if request was sent successfully.
264
+ *
265
+ * @yield Callback to notify the result of operation.
266
+ * @yieldparam result [Boolean] true if result successful.
267
+ * @yieldparam services [Array<String>] Service Name list on forwarding entry after operation.
268
+ */
269
+ static VALUE
270
+ delete_forward_entry_from_switch( VALUE self, VALUE dpid, VALUE type,
271
+ VALUE service_name ) {
272
+ debug( "%s", __func__ );
273
+ enum efi_event_type c_type;
274
+ if ( !event_type_symbol_to_enum( type, &c_type ) ) {
275
+ warn( "Invalid event type was specified" );
276
+ return Qfalse;
277
+ }
278
+
279
+ const uint64_t c_dpid = NUM2ULL( dpid );
280
+ const char *c_service_name = StringValuePtr( service_name );
281
+ if ( strlen( c_service_name ) == 0 ) {
282
+ warn( "service_name cannot be empty" );
283
+ return Qfalse;
284
+ }
285
+
286
+ callback_info *cb = xcalloc( 1, sizeof( callback_info ) );
287
+ cb->self = self;
288
+ cb->block = Qnil;
289
+ if ( rb_block_given_p() == Qtrue ) {
290
+ cb->block = rb_block_proc();
291
+ }
292
+ bool succ = delete_switch_event_forward_entry(
293
+ c_dpid, c_type, c_service_name,
294
+ handle_event_forward_entry_operation_callback,
295
+ cb );
296
+ if ( succ ) {
297
+ return Qtrue;
298
+ }
299
+ else {
300
+ xfree( cb );
301
+ return Qfalse;
302
+ }
303
+ }
304
+
305
+
306
+ /*
307
+ * @!group Operation for existing switch
308
+ *
309
+ * @overload set_forward_entries_to_switch datapath_id, type, service_name, {|result, services| ... }
310
+ * Set forwarding entries of a switch specified.
311
+ *
312
+ * @param [Integer] dpid Switch datapath_id
313
+ * @param [Symbol] type Switch event type. it must be one of :vendor, :packet_in, :port_status, :state_notify
314
+ * @param [Array<String>] service_names Name of controller to forward event.
315
+ * @return [Boolean] true if request was sent successfully.
316
+ *
317
+ * @yield Callback to notify the result of operation.
318
+ * @yieldparam result [Boolean] true if result successful.
319
+ * @yieldparam services [Array<String>] Service Name list on forwarding entry after operation.
320
+ */
321
+ static VALUE
322
+ set_forward_entries_to_switch( VALUE self, VALUE dpid, VALUE type,
323
+ VALUE service_names ) {
324
+ debug( "%s", __func__ );
325
+ enum efi_event_type c_type;
326
+ if ( !event_type_symbol_to_enum( type, &c_type ) ) {
327
+ warn( "Invalid event type was specified" );
328
+ return Qfalse;
329
+ }
330
+
331
+ const uint64_t c_dpid = NUM2ULL( dpid );
332
+ list_element *service_list = NULL;
333
+ create_list( &service_list );
334
+ for ( long i = 0 ; i < RARRAY( service_names )->len ; ++i ) {
335
+ VALUE ruby_service_name = rb_ary_entry( service_names, i );
336
+ char *c_service_name = StringValuePtr( ruby_service_name );
337
+ if ( strlen( c_service_name ) == 0 ) {
338
+ warn( "Ignoring empty service_name" );
339
+ continue;
340
+ }
341
+ append_to_tail( &service_list, c_service_name );
342
+ }
343
+
344
+ callback_info *cb = xcalloc( 1, sizeof( callback_info ) );
345
+ cb->self = self;
346
+ cb->block = Qnil;
347
+ if ( rb_block_given_p() == Qtrue ) {
348
+ cb->block = rb_block_proc();
349
+ }
350
+ bool succ = set_switch_event_forward_entries(
351
+ c_dpid, c_type, service_list,
352
+ handle_event_forward_entry_operation_callback,
353
+ cb );
354
+
355
+ delete_list( service_list );
356
+
357
+ if ( succ ) {
358
+ return Qtrue;
359
+ }
360
+ else {
361
+ xfree( cb );
362
+ return Qfalse;
363
+ }
364
+ }
365
+
366
+
367
+ /*
368
+ * @!group Operation for existing switch
369
+ *
370
+ * @overload dump_forward_entries_from_switch datapath_id, type, {|result, services| ... }
371
+ * Dump forwarding entry of a switch specified.
372
+ *
373
+ * @param [Integer] dpid Switch datapath_id
374
+ * @param [Symbol] type Switch event type. it must be one of :vendor, :packet_in, :port_status, :state_notify
375
+ * @return [Boolean] true if request was sent successfully.
376
+ *
377
+ * @yield Callback to notify the result of operation.
378
+ * @yieldparam result [Boolean] true if result successful on all switches and switch manager
379
+ * @yieldparam services [Array<String>] Service Name list on forwarding entry after operation.
380
+ */
381
+ static VALUE
382
+ dump_forward_entries_from_switch( VALUE self, VALUE dpid, VALUE type ) {
383
+ debug( "%s", __func__ );
384
+ enum efi_event_type c_type;
385
+ if ( !event_type_symbol_to_enum( type, &c_type ) ) {
386
+ warn( "Invalid event type was specified" );
387
+ return Qfalse;
388
+ }
389
+
390
+ const uint64_t c_dpid = NUM2ULL( dpid );
391
+
392
+ callback_info *cb = xcalloc( 1, sizeof( callback_info ) );
393
+ cb->self = self;
394
+ cb->block = Qnil;
395
+ if ( rb_block_given_p() == Qtrue ) {
396
+ cb->block = rb_block_proc();
397
+ }
398
+ bool succ = dump_switch_event_forward_entries(
399
+ c_dpid, c_type,
400
+ handle_event_forward_entry_operation_callback,
401
+ cb );
402
+ if ( succ ) {
403
+ return Qtrue;
404
+ }
405
+ else {
406
+ xfree( cb );
407
+ return Qfalse;
408
+ }
409
+ }
410
+
411
+
412
+ /*
413
+ * @!group Operation for switch manager
414
+ *
415
+ * @overload add_forward_entry_to_switch_manager type, service_name, {|result, services| ... }
416
+ * Add forwarding entry to a switch manager.
417
+ *
418
+ * @param [Symbol] type Switch event type. it must be one of :vendor, :packet_in, :port_status, :state_notify
419
+ * @param [String] service_name Name of controller to forward event.
420
+ * @return [Boolean] true if request was sent successfully.
421
+ *
422
+ * @yield Callback to notify the result of operation.
423
+ * @yieldparam result [Boolean] true if result successful.
424
+ * @yieldparam services [Array<String>] Service Name list on forwarding entry after operation.
425
+ */
426
+ static VALUE
427
+ add_forward_entry_to_switch_manager( VALUE self, VALUE type,
428
+ VALUE service_name ) {
429
+ debug( "%s", __func__ );
430
+ enum efi_event_type c_type;
431
+ if ( !event_type_symbol_to_enum( type, &c_type ) ) {
432
+ warn( "Invalid event type was specified" );
433
+ return Qfalse;
434
+ }
435
+
436
+ const char *c_service_name = StringValuePtr( service_name );
437
+ if ( strlen( c_service_name ) == 0 ) {
438
+ warn( "service_name cannot be empty" );
439
+ return Qfalse;
440
+ }
441
+
442
+ callback_info *cb = xcalloc( 1, sizeof( callback_info ) );
443
+ cb->self = self;
444
+ cb->block = Qnil;
445
+ if ( rb_block_given_p() == Qtrue ) {
446
+ cb->block = rb_block_proc();
447
+ }
448
+ bool succ = add_switch_manager_event_forward_entry(
449
+ c_type, c_service_name,
450
+ handle_event_forward_entry_operation_callback,
451
+ cb );
452
+ if ( succ ) {
453
+ return Qtrue;
454
+ }
455
+ else {
456
+ xfree( cb );
457
+ return Qfalse;
458
+ }
459
+ }
460
+
461
+
462
+ /*
463
+ * @!group Operation for switch manager
464
+ *
465
+ * @overload delete_forward_entry_from_switch_manager type, service_name, {|result, services| ... }
466
+ * Delete forwarding entry of a switch manager.
467
+ *
468
+ * @param [Symbol] type Switch event type. it must be one of :vendor, :packet_in, :port_status, :state_notify
469
+ * @param [String] service_name Name of controller to forward event.
470
+ * @return [Boolean] true if request was sent successfully.
471
+ *
472
+ * @yield Callback to notify the result of operation.
473
+ * @yieldparam result [Boolean] true if result successful.
474
+ * @yieldparam services [Array<String>] Service Name list on forwarding entry after operation.
475
+ */
476
+ static VALUE
477
+ delete_forward_entry_from_switch_manager( VALUE self, VALUE type,
478
+ VALUE service_name ) {
479
+ debug( "%s", __func__ );
480
+ enum efi_event_type c_type;
481
+ if ( !event_type_symbol_to_enum( type, &c_type ) ) {
482
+ warn( "Invalid event type was specified" );
483
+ return Qfalse;
484
+ }
485
+
486
+ const char *c_service_name = StringValuePtr( service_name );
487
+ if ( strlen( c_service_name ) == 0 ) {
488
+ warn( "service_name cannot be empty" );
489
+ return Qfalse;
490
+ }
491
+
492
+ callback_info *cb = xcalloc( 1, sizeof( callback_info ) );
493
+ cb->self = self;
494
+ cb->block = Qnil;
495
+ if ( rb_block_given_p() == Qtrue ) {
496
+ cb->block = rb_block_proc();
497
+ }
498
+ bool succ = delete_switch_manager_event_forward_entry(
499
+ c_type, c_service_name,
500
+ handle_event_forward_entry_operation_callback,
501
+ cb );
502
+ if ( succ ) {
503
+ return Qtrue;
504
+ }
505
+ else {
506
+ xfree( cb );
507
+ return Qfalse;
508
+ }
509
+ }
510
+
511
+
512
+ /*
513
+ * @!group Operation for switch manager
514
+ *
515
+ * @overload set_forward_entries_to_switch_manager type, service_names, {|result, services| ... }
516
+ * Set forwarding entries of a switch manager.
517
+ *
518
+ * @param [Symbol] type Switch event type. it must be one of :vendor, :packet_in, :port_status, :state_notify
519
+ * @param [Array<String>] service_names Name of controller to forward event.
520
+ * @return [Boolean] true if request was sent successfully.
521
+ *
522
+ * @yield Callback to notify the result of operation.
523
+ * @yieldparam result [Boolean] true if result successful.
524
+ * @yieldparam services [Array<String>] Service Name list on forwarding entry after operation.
525
+ */
526
+ static VALUE
527
+ set_forward_entries_to_switch_manager( VALUE self, VALUE type,
528
+ VALUE service_names ) {
529
+ debug( "%s", __func__ );
530
+ enum efi_event_type c_type;
531
+ if ( !event_type_symbol_to_enum( type, &c_type ) ) {
532
+ warn( "Invalid event type was specified" );
533
+ return Qfalse;
534
+ }
535
+
536
+ list_element *service_list = NULL;
537
+ create_list( &service_list );
538
+ for ( long i = 0 ; i < RARRAY( service_names )->len ; ++i ) {
539
+ VALUE ruby_service_name = rb_ary_entry( service_names, i );
540
+ char *c_service_name = StringValuePtr( ruby_service_name );
541
+ if ( strlen( c_service_name ) == 0 ) {
542
+ warn( "Ignoring empty service_name" );
543
+ continue;
544
+ }
545
+ append_to_tail( &service_list, c_service_name );
546
+ }
547
+
548
+ callback_info *cb = xcalloc( 1, sizeof( callback_info ) );
549
+ cb->self = self;
550
+ cb->block = Qnil;
551
+ if ( rb_block_given_p() == Qtrue ) {
552
+ cb->block = rb_block_proc();
553
+ }
554
+ bool succ = set_switch_manager_event_forward_entries(
555
+ c_type, service_list,
556
+ handle_event_forward_entry_operation_callback,
557
+ cb );
558
+
559
+ delete_list( service_list );
560
+
561
+ if ( succ ) {
562
+ return Qtrue;
563
+ }
564
+ else {
565
+ xfree( cb );
566
+ return Qfalse;
567
+ }
568
+ }
569
+
570
+
571
+ /*
572
+ * @!group Operation for switch manager
573
+ *
574
+ * @overload dump_forward_entries_from_switch type, {|result, services| ... }
575
+ * Dump forwarding entry of a switch manager.
576
+ *
577
+ * @param [Symbol] type Switch event type. it must be one of :vendor, :packet_in, :port_status, :state_notify
578
+ * @return [Boolean] true if request was sent successfully.
579
+ *
580
+ * @yield Callback to notify the result of operation.
581
+ * @yieldparam result [Boolean] true if result successful on all switches and switch manager
582
+ * @yieldparam services [Array<String>] Service Name list on forwarding entry after operation.
583
+ */
584
+ static VALUE
585
+ dump_forward_entries_from_switch_manager( VALUE self, VALUE type ) {
586
+ debug( "%s", __func__ );
587
+ enum efi_event_type c_type;
588
+ if ( !event_type_symbol_to_enum( type, &c_type ) ) {
589
+ warn( "Invalid event type was specified" );
590
+ return Qfalse;
591
+ }
592
+
593
+ callback_info *cb = xcalloc( 1, sizeof( callback_info ) );
594
+ cb->self = self;
595
+ cb->block = Qnil;
596
+ if ( rb_block_given_p() == Qtrue ) {
597
+ cb->block = rb_block_proc();
598
+ }
599
+ bool succ = dump_switch_manager_event_forward_entries(
600
+ c_type,
601
+ handle_event_forward_entry_operation_callback,
602
+ cb );
603
+ if ( succ ) {
604
+ return Qtrue;
605
+ }
606
+ else {
607
+ xfree( cb );
608
+ return Qfalse;
609
+ }
610
+ }
611
+
612
+
613
+ /*
614
+ * Document-module: Trema::SwitchEvent
615
+ */
616
+ void
617
+ Init_switch_event( void ) {
618
+ mSwitchEvent = rb_define_module_under( mTrema, "SwitchEvent" );
619
+
620
+ idVendor = rb_intern( "vendor" );
621
+ idPacketIn = rb_intern( "packet_in" );
622
+ idPortStatus = rb_intern( "port_status" );
623
+ idStateNotify = rb_intern( "state_notify" );
624
+
625
+ rb_define_method( mSwitchEvent, "add_forward_entry_to_all_switches",
626
+ add_forward_entry_to_all_switches, 2 );
627
+ rb_define_method( mSwitchEvent, "delete_forward_entry_from_all_switches",
628
+ delete_forward_entry_from_all_switches, 2 );
629
+
630
+ rb_define_method( mSwitchEvent, "add_forward_entry_to_switch",
631
+ add_forward_entry_to_switch, 3 );
632
+ rb_define_method( mSwitchEvent, "delete_forward_entry_from_switch",
633
+ delete_forward_entry_from_switch, 3 );
634
+ rb_define_method( mSwitchEvent, "set_forward_entries_to_switch",
635
+ set_forward_entries_to_switch, 3 );
636
+ rb_define_method( mSwitchEvent, "dump_forward_entries_from_switch",
637
+ dump_forward_entries_from_switch, 2 );
638
+
639
+ rb_define_method( mSwitchEvent, "add_forward_entry_to_switch_manager",
640
+ add_forward_entry_to_switch_manager, 2 );
641
+ rb_define_method( mSwitchEvent, "delete_forward_entry_from_switch_manager",
642
+ delete_forward_entry_from_switch_manager, 2 );
643
+ rb_define_method( mSwitchEvent, "set_forward_entries_to_switch_manager",
644
+ set_forward_entries_to_switch_manager, 2 );
645
+ rb_define_method( mSwitchEvent, "dump_forward_entries_from_switch_manager",
646
+ dump_forward_entries_from_switch_manager, 1 );
647
+ }