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.
- checksums.yaml +5 -5
- data/.gitignore +1 -0
- data/.rvmrc +52 -0
- data/.travis.yml +3 -0
- data/Gemfile +1 -1
- data/Rakefile +259 -1
- data/Rantfile +79 -216
- data/features/.nav +12 -0
- data/features/dsl/switch_port_specifier.feature +15 -0
- data/features/examples/switch-event/C-add_forward_entry.feature +130 -0
- data/features/examples/switch-event/C-delete_forward_entry.feature +97 -0
- data/features/examples/switch-event/C-dump_forward_entries.feature +80 -0
- data/features/examples/switch-event/C-set_forward_entries.feature +85 -0
- data/features/examples/switch-event/README.md +40 -0
- data/features/examples/switch-event/add_forward_entry.feature +142 -0
- data/features/examples/switch-event/delete_forward_entry.feature +142 -0
- data/features/examples/switch-event/dump_forward_entries.feature +91 -0
- data/features/examples/switch-event/set_forward_entries.feature +90 -0
- data/features/support/hooks.rb +1 -0
- data/ruby/rake/c/dependency.rb +42 -0
- data/ruby/rake/c/library-task.rb +142 -0
- data/ruby/rake/c/shared-library-task.rb +38 -0
- data/ruby/rake/c/static-library-task.rb +32 -0
- data/ruby/trema/path.rb +1 -0
- data/ruby/trema/switch-event.c +647 -0
- data/{src/switch_manager/management_interface.h → ruby/trema/switch-event.h} +7 -21
- data/ruby/trema/trema.c +2 -0
- data/ruby/trema/version.rb +1 -1
- data/spec/spec_helper.rb +26 -2
- data/src/examples/switch_event_config/.gitignore +7 -0
- data/src/examples/switch_event_config/add_forward_entry.c +227 -0
- data/src/examples/switch_event_config/delete_forward_entry.c +226 -0
- data/src/examples/switch_event_config/dump_forward_entries.c +190 -0
- data/src/examples/switch_event_config/set_forward_entries.c +210 -0
- data/src/lib/event_forward_interface.c +783 -0
- data/src/lib/event_forward_interface.h +138 -0
- data/src/lib/trema.h +1 -0
- data/src/lib/utility.c +13 -1
- data/src/lib/utility.h +3 -0
- data/src/switch_manager/event_forward_entry_manipulation.c +120 -0
- data/src/switch_manager/event_forward_entry_manipulation.h +31 -0
- data/src/switch_manager/secure_channel_listener.c +23 -3
- data/src/switch_manager/switch.c +99 -29
- data/src/switch_manager/switch_manager.c +176 -3
- data/src/switch_manager/switch_manager.h +4 -0
- data/src/switch_manager/switch_option.c +30 -0
- data/src/switch_manager/switch_option.h +41 -0
- data/trema.gemspec +2 -1
- data/unittests/lib/event_forward_interface_test.c +1646 -0
- data/unittests/lib/utility_test.c +23 -1
- metadata +48 -10
data/features/support/hooks.rb
CHANGED
@@ -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
@@ -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
|
+
}
|