trema 0.3.16 → 0.3.17

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.
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
+ }