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
@@ -0,0 +1,190 @@
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
+
19
+ #include <getopt.h>
20
+ #include "trema.h"
21
+
22
+
23
+ static bool sw_manager = true;
24
+ static uint64_t dpid;
25
+ static enum efi_event_type type;
26
+
27
+ static struct option long_options[] = {
28
+ { "manager", 0, NULL, 'm' },
29
+ { "switch", 1, NULL, 's' },
30
+ { "type", 1, NULL, 't' },
31
+ { NULL, 0, NULL, 0 },
32
+ };
33
+
34
+ static char short_options[] = "ms:t:";
35
+
36
+
37
+ void
38
+ usage() {
39
+ printf(
40
+ "Dump OpenFlow Switch Manager/Daemon event forward entries.\n"
41
+ " Switch Manager: %s -m -t EVENT_TYPE\n"
42
+ " Switch Daemon : %s -s SWITCH_DPID -t EVENT_TYPE\n"
43
+ "\n"
44
+ " EVENT_TYPE:\n"
45
+ " -t, --type={vendor,packet_in,port_status,state_notify} Specify event type.\n"
46
+ " TREMA COMMON:\n"
47
+ " -n, --name=SERVICE_NAME service name\n"
48
+ " -d, --daemonize run in the background\n"
49
+ " -l, --logging_level=LEVEL set logging level\n"
50
+ " -g, --syslog output log messages to syslog\n"
51
+ " -f, --logging_facility=FACILITY set syslog facility\n"
52
+ " -h, --help display this help and exit\n"
53
+ , get_executable_name()
54
+ , get_executable_name()
55
+ );
56
+ }
57
+
58
+
59
+ static bool
60
+ parse_argument( int argc, char *argv[] ) {
61
+
62
+ bool type_specified = false;
63
+
64
+ int c;
65
+ while ( ( c = getopt_long( argc, argv, short_options, long_options, NULL ) ) != -1 ) {
66
+ switch ( c ) {
67
+ case 'm':
68
+ sw_manager = true;
69
+ break;
70
+
71
+ case 's':
72
+ sw_manager = false;
73
+ if ( !string_to_datapath_id( optarg, &dpid ) ) {
74
+ error( "Invalid dpid '%s' specified. ", optarg );
75
+ usage();
76
+ exit( EXIT_FAILURE );
77
+ return false;
78
+ }
79
+ break;
80
+
81
+ case 't': // add
82
+ type_specified = true;
83
+ if ( false ) {
84
+ }
85
+ else if ( strcasecmp( "vendor", optarg ) == 0 ) {
86
+ type = EVENT_FORWARD_TYPE_VENDOR;
87
+ }
88
+ else if ( strcasecmp( "packet_in", optarg ) == 0 ) {
89
+ type = EVENT_FORWARD_TYPE_PACKET_IN;
90
+ }
91
+ else if ( strcasecmp( "port_status", optarg ) == 0 ) {
92
+ type = EVENT_FORWARD_TYPE_PORT_STATUS;
93
+ }
94
+ else if ( strcasecmp( "state_notify", optarg ) == 0 ) {
95
+ type = EVENT_FORWARD_TYPE_STATE_NOTIFY;
96
+ }
97
+ else {
98
+ error( "Invalid type '%s' specified. Must e one of vendor, packet_in, port_status, or state_notify\n", optarg );
99
+ usage();
100
+ exit( EXIT_FAILURE );
101
+ return false;
102
+ }
103
+ break;
104
+
105
+ default:
106
+ error( "Encountered unknown option." );
107
+ usage();
108
+ exit( EXIT_FAILURE );
109
+ return false;
110
+ break;
111
+ }
112
+ }
113
+
114
+ if ( !type_specified ) {
115
+ error( "Event Type was not specified with -t option.\n" );
116
+ usage();
117
+ exit( EXIT_FAILURE );
118
+ return false;
119
+ }
120
+
121
+ return true;
122
+ }
123
+
124
+
125
+ static void
126
+ timeout( void *user_data ) {
127
+ UNUSED( user_data );
128
+
129
+ error( "Request timed out." );
130
+ stop_trema();
131
+ exit( EXIT_FAILURE );
132
+ }
133
+
134
+
135
+ static void
136
+ current_result_callback( event_forward_operation_result result, void *user_data) {
137
+ UNUSED( user_data );
138
+
139
+ if ( result.result != EFI_OPERATION_SUCCEEDED ) {
140
+ error( "Operation Failed." );
141
+ stop_trema();
142
+ exit( EXIT_FAILURE );
143
+ }
144
+ else {
145
+ if ( result.n_services == 0 ) {
146
+ info( "Current service name list is empty.");
147
+ }
148
+ else {
149
+ info( "Current service name list:" );
150
+ unsigned i;
151
+ for ( i = 0; i < result.n_services; ++i ) {
152
+ info( " %s", result.services[ i ] );
153
+ }
154
+ }
155
+ stop_trema();
156
+ }
157
+ }
158
+
159
+
160
+ static void
161
+ send_efi_request( void ) {
162
+ info( "Dumping current service name list... " );
163
+ if ( sw_manager ) {
164
+ dump_switch_manager_event_forward_entries( type,
165
+ current_result_callback, NULL );
166
+ }
167
+ else {
168
+ dump_switch_event_forward_entries( dpid, type,
169
+ current_result_callback, NULL );
170
+ }
171
+ }
172
+
173
+
174
+ int
175
+ main( int argc, char *argv[] ) {
176
+ init_trema( &argc, &argv );
177
+ parse_argument( argc, argv );
178
+
179
+ init_event_forward_interface();
180
+
181
+ send_efi_request();
182
+
183
+ add_periodic_event_callback( 30, timeout, NULL );
184
+
185
+ start_trema();
186
+
187
+ finalize_event_forward_interface();
188
+
189
+ return 0;
190
+ }
@@ -0,0 +1,210 @@
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
+
19
+ #include <getopt.h>
20
+ #include "trema.h"
21
+
22
+
23
+ static bool sw_manager = true;
24
+ static uint64_t dpid;
25
+ static enum efi_event_type type;
26
+ static list_element *service_names = NULL;
27
+
28
+ static struct option long_options[] = {
29
+ { "manager", 0, NULL, 'm' },
30
+ { "switch", 1, NULL, 's' },
31
+ { "type", 1, NULL, 't' },
32
+ { NULL, 0, NULL, 0 },
33
+ };
34
+
35
+ static char short_options[] = "ms:t:";
36
+
37
+
38
+ void
39
+ usage() {
40
+ printf(
41
+ "Set OpenFlow Switch Manager/Daemon event forward entries.\n"
42
+ " Switch Manager: %s -m -t EVENT_TYPE service_name1,service_name2,...\n"
43
+ " Switch Daemon : %s -s SWITCH_DPID -t EVENT_TYPE service_name1,service_name2,...\n"
44
+ "\n"
45
+ " EVENT_TYPE:\n"
46
+ " -t, --type={vendor,packet_in,port_status,state_notify} Specify event type.\n"
47
+ " TREMA COMMON:\n"
48
+ " -n, --name=SERVICE_NAME service name\n"
49
+ " -d, --daemonize run in the background\n"
50
+ " -l, --logging_level=LEVEL set logging level\n"
51
+ " -g, --syslog output log messages to syslog\n"
52
+ " -f, --logging_facility=FACILITY set syslog facility\n"
53
+ " -h, --help display this help and exit\n"
54
+ , get_executable_name()
55
+ , get_executable_name()
56
+ );
57
+ }
58
+
59
+
60
+ static bool
61
+ parse_argument( int argc, char *argv[] ) {
62
+
63
+ bool type_specified = false;
64
+
65
+ create_list( &service_names );
66
+
67
+ int c;
68
+ while ( ( c = getopt_long( argc, argv, short_options, long_options, NULL ) ) != -1 ) {
69
+ switch ( c ) {
70
+ case 'm':
71
+ sw_manager = true;
72
+ break;
73
+
74
+ case 's':
75
+ sw_manager = false;
76
+ if ( !string_to_datapath_id( optarg, &dpid ) ) {
77
+ error( "Invalid dpid '%s' specified. ", optarg );
78
+ usage();
79
+ exit( EXIT_FAILURE );
80
+ return false;
81
+ }
82
+ break;
83
+
84
+ case 't': // add
85
+ type_specified = true;
86
+ if ( false ) {
87
+ }
88
+ else if ( strcasecmp( "vendor", optarg ) == 0 ) {
89
+ type = EVENT_FORWARD_TYPE_VENDOR;
90
+ }
91
+ else if ( strcasecmp( "packet_in", optarg ) == 0 ) {
92
+ type = EVENT_FORWARD_TYPE_PACKET_IN;
93
+ }
94
+ else if ( strcasecmp( "port_status", optarg ) == 0 ) {
95
+ type = EVENT_FORWARD_TYPE_PORT_STATUS;
96
+ }
97
+ else if ( strcasecmp( "state_notify", optarg ) == 0 ) {
98
+ type = EVENT_FORWARD_TYPE_STATE_NOTIFY;
99
+ }
100
+ else {
101
+ error( "Invalid type '%s' specified. Must e one of vendor, packet_in, port_status, or state_notify\n", optarg );
102
+ usage();
103
+ exit( EXIT_FAILURE );
104
+ return false;
105
+ }
106
+ break;
107
+
108
+ default:
109
+ error( "Encountered unknown option." );
110
+ usage();
111
+ exit( EXIT_FAILURE );
112
+ return false;
113
+ break;
114
+ }
115
+ }
116
+
117
+ if ( !type_specified ) {
118
+ error( "Event Type was not specified with -t option.\n" );
119
+ usage();
120
+ exit( EXIT_FAILURE );
121
+ return false;
122
+ }
123
+
124
+ if ( optind >= argc ) {
125
+ error( "Service names were not specified.\n" );
126
+ usage();
127
+ exit( EXIT_FAILURE );
128
+ return false;
129
+ }
130
+
131
+ int i;
132
+ for ( i = optind; i < argc; ++i ) {
133
+ char *service_name = strtok( argv[ i ], "," );
134
+ if ( service_name != NULL ) {
135
+ append_to_tail( &service_names, service_name );
136
+ while ( ( service_name = strtok( NULL, "," ) ) != NULL ) {
137
+ append_to_tail( &service_names, service_name );
138
+ }
139
+ }
140
+ }
141
+
142
+ return true;
143
+ }
144
+
145
+
146
+ static void
147
+ timeout( void *user_data ) {
148
+ UNUSED( user_data );
149
+
150
+ error( "Request timed out." );
151
+ stop_trema();
152
+ exit( EXIT_FAILURE );
153
+ }
154
+
155
+
156
+ static void
157
+ update_result_callback( event_forward_operation_result result, void *user_data) {
158
+ UNUSED( user_data );
159
+
160
+ if ( result.result != EFI_OPERATION_SUCCEEDED ) {
161
+ error( "Operation Failed." );
162
+ stop_trema();
163
+ exit( EXIT_FAILURE );
164
+ }
165
+ else {
166
+ if ( result.n_services == 0 ) {
167
+ info( "Updated service name list is empty.");
168
+ }
169
+ else {
170
+ info( "Updated service name list:" );
171
+ unsigned i;
172
+ for ( i = 0; i < result.n_services; ++i ) {
173
+ info( " %s", result.services[ i ] );
174
+ }
175
+ }
176
+ stop_trema();
177
+ }
178
+ }
179
+
180
+
181
+ static void
182
+ send_efi_request( void ) {
183
+ info( "Setting service names... " );
184
+ if ( sw_manager ) {
185
+ set_switch_manager_event_forward_entries( type, service_names,
186
+ update_result_callback, NULL );
187
+ } else {
188
+ set_switch_event_forward_entries( dpid, type, service_names,
189
+ update_result_callback, NULL );
190
+ }
191
+ }
192
+
193
+
194
+ int
195
+ main( int argc, char *argv[] ) {
196
+ init_trema( &argc, &argv );
197
+ parse_argument( argc, argv );
198
+
199
+ init_event_forward_interface();
200
+
201
+ send_efi_request();
202
+
203
+ add_periodic_event_callback( 30, timeout, NULL );
204
+
205
+ start_trema();
206
+
207
+ finalize_event_forward_interface();
208
+
209
+ return 0;
210
+ }
@@ -0,0 +1,783 @@
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 <sys/types.h>
20
+ #include <unistd.h>
21
+ #include "trema.h"
22
+ #include "trema_wrapper.h"
23
+ #include "event_forward_interface.h"
24
+
25
+
26
+ static char *efi_queue_name = NULL;
27
+
28
+
29
+ // txid -> all_sw_tx;
30
+ static hash_table *efi_tx_table = NULL;
31
+
32
+
33
+ struct event_forward_operation_request_param {
34
+ event_forward_entry_operation_callback callback;
35
+ void *user_data;
36
+ };
37
+
38
+
39
+ struct event_forward_operation_to_all_request_param {
40
+ bool add;
41
+ enum efi_event_type type;
42
+ char *service_name;
43
+ event_forward_entry_to_all_callback callback;
44
+ void *user_data;
45
+ };
46
+
47
+
48
+ struct sw_list_request_param {
49
+ switch_list_request_callback callback;
50
+ void *user_data;
51
+ };
52
+
53
+
54
+ typedef struct all_sw_tx {
55
+ uint32_t txid;
56
+ hash_table *waiting_dpid;
57
+ enum efi_result tx_result;
58
+
59
+ struct event_forward_operation_to_all_request_param *request_param;
60
+ } all_sw_tx;
61
+
62
+
63
+ struct txinfo {
64
+ uint64_t dpid;
65
+ uint32_t txid;
66
+ };
67
+
68
+
69
+ static void
70
+ xfree_event_forward_operation_to_all_request_param( struct event_forward_operation_to_all_request_param *param ) {
71
+ xfree( param->service_name );
72
+ param->service_name = NULL;
73
+ xfree( param );
74
+ }
75
+
76
+
77
+ // foreach_hash helper function
78
+ static void
79
+ xfree_dpid( void *key, void *value, void *user_data ) {
80
+ UNUSED( value );
81
+ UNUSED( user_data );
82
+ xfree( key );
83
+ }
84
+
85
+
86
+ static void
87
+ xfree_all_sw_tx( all_sw_tx *tx ) {
88
+ struct event_forward_operation_to_all_request_param *param = tx->request_param;
89
+ xfree_event_forward_operation_to_all_request_param( param );
90
+ tx->request_param = NULL;
91
+
92
+ foreach_hash( tx->waiting_dpid, xfree_dpid, NULL );
93
+ delete_hash( tx->waiting_dpid );
94
+ tx->waiting_dpid = NULL;
95
+ xfree( tx );
96
+ }
97
+
98
+
99
+ const char*
100
+ _get_efi_queue_name( void ) {
101
+ return efi_queue_name;
102
+ }
103
+
104
+
105
+ buffer*
106
+ create_event_forward_operation_request( buffer *buf, enum efi_event_type type, list_element *service_list ) {
107
+ if ( buf == NULL ) {
108
+ buf = alloc_buffer_with_length( sizeof( event_forward_operation_request ) + MESSENGER_SERVICE_NAME_LENGTH );
109
+ }
110
+ event_forward_operation_request *req = append_back_buffer( buf, sizeof( event_forward_operation_request ) );
111
+ memset( req, 0, sizeof( event_forward_operation_request ) );
112
+
113
+ req->type = ( uint8_t ) type;
114
+
115
+ size_t request_head_offset = sizeof( event_forward_operation_request );
116
+ uint32_t n_services = 0;
117
+ if ( service_list != NULL ) {
118
+ for ( list_element *e = service_list; e != NULL; e = e->next ) {
119
+ const size_t len = strlen( e->data );
120
+ char *dst = append_back_buffer( buf, len + 1 );
121
+ req = ( event_forward_operation_request * )( dst - request_head_offset );
122
+ request_head_offset += len + 1;
123
+ strcpy( dst, e->data );
124
+ dst[ len ] = '\0';
125
+ ++n_services;
126
+ }
127
+ }
128
+
129
+ req->n_services = htonl( n_services );
130
+ return buf;
131
+ }
132
+
133
+
134
+ buffer*
135
+ create_event_forward_operation_reply( enum efi_event_type type, enum efi_result result, list_element *service_list ) {
136
+ buffer *buf = alloc_buffer_with_length( sizeof( event_forward_operation_reply ) + MESSENGER_SERVICE_NAME_LENGTH );
137
+ event_forward_operation_reply *rep = append_back_buffer( buf, sizeof( event_forward_operation_reply ) );
138
+ memset( rep, 0, sizeof( event_forward_operation_reply ) );
139
+
140
+ rep->type = ( uint8_t ) type;
141
+ rep->result = ( uint8_t ) result;
142
+
143
+ size_t reply_head_offset = sizeof( event_forward_operation_reply );
144
+ uint32_t n_services = 0;
145
+ if ( service_list != NULL ) {
146
+ for ( list_element *e = service_list; e != NULL; e = e->next ) {
147
+ const size_t len = strlen( e->data );
148
+ char *dst = append_back_buffer( buf, len + 1 );
149
+ rep = ( event_forward_operation_reply * )( dst - reply_head_offset );
150
+ reply_head_offset += len + 1;
151
+ strcpy( dst, e->data );
152
+ dst[ len ] = '\0';
153
+ ++n_services;
154
+ }
155
+ }
156
+
157
+ rep->n_services = htonl( n_services );
158
+ return buf;
159
+ }
160
+
161
+
162
+ static void
163
+ handle_event_forward_operation_reply( management_application_reply *reply, size_t length, struct event_forward_operation_request_param *param ) {
164
+ event_forward_operation_result result;
165
+ result.result = EFI_OPERATION_FAILED;
166
+ result.n_services = 0;
167
+ result.services = NULL;
168
+
169
+ event_forward_operation_reply *efi_reply = ( event_forward_operation_reply * ) reply->data;
170
+ efi_reply->n_services = ntohl( efi_reply->n_services );
171
+
172
+ if ( reply->header.status == MANAGEMENT_REQUEST_FAILED ) {
173
+ warn( "Management request failed." );
174
+ result.result = EFI_OPERATION_FAILED;
175
+ if ( param->callback != NULL ) {
176
+ param->callback( result, param->user_data );
177
+ }
178
+ return;
179
+ }
180
+
181
+ switch ( efi_reply->result ) {
182
+ case EFI_OPERATION_SUCCEEDED:
183
+ result.result = EFI_OPERATION_SUCCEEDED;
184
+ break;
185
+ case EFI_OPERATION_FAILED:
186
+ result.result = EFI_OPERATION_FAILED;
187
+ break;
188
+ default:
189
+ warn( "Unknown result type %#x. Translating as FAILED.", efi_reply->result );
190
+ result.result = EFI_OPERATION_FAILED;
191
+ break;
192
+ }
193
+
194
+ if ( result.result == EFI_OPERATION_FAILED ) {
195
+ if ( param->callback != NULL ) {
196
+ param->callback( result, param->user_data );
197
+ }
198
+ return;
199
+ }
200
+
201
+ const size_t service_list_len = length
202
+ - offsetof( management_application_reply, data )
203
+ - offsetof( event_forward_operation_reply, service_list );
204
+
205
+ // null terminate input to avoid overrun.
206
+ efi_reply->service_list[ service_list_len ] = '\0';
207
+
208
+ const uint32_t n_services_expected = efi_reply->n_services;
209
+ result.services = xcalloc( n_services_expected, sizeof( char * ) );
210
+
211
+ result.n_services = 0;
212
+ const char *next_name = efi_reply->service_list;
213
+ while ( next_name < &efi_reply->service_list[ service_list_len ] ) {
214
+ const size_t name_len = strlen( next_name );
215
+ if ( name_len > 0 ) {
216
+ if ( result.n_services < n_services_expected ) {
217
+ result.services[ result.n_services++ ] = next_name;
218
+ }
219
+ else {
220
+ warn( "Expected %d name(s), but found more service name. Ignoring '%s'.", n_services_expected, next_name );
221
+ }
222
+ }
223
+ else {
224
+ warn( "Encountered empty service name." );
225
+ }
226
+ next_name += name_len + 1;
227
+ }
228
+
229
+ if ( param->callback != NULL ) {
230
+ param->callback( result, param->user_data );
231
+ }
232
+ xfree( result.services );
233
+ }
234
+
235
+
236
+ static void
237
+ handle_get_switch_list_reply( management_application_reply *reply, size_t length, struct sw_list_request_param *param ) {
238
+
239
+ if ( reply->header.status == MANAGEMENT_REQUEST_FAILED ) {
240
+ warn( "Management request failed." );
241
+ if ( param->callback != NULL ) {
242
+ param->callback( NULL, 0, param->user_data );
243
+ }
244
+ return;
245
+ }
246
+
247
+ uint64_t *dpids = ( uint64_t * ) reply->data;
248
+ const size_t data_bytes = length - sizeof( management_application_reply );
249
+ if ( data_bytes % sizeof( uint64_t ) != 0 ) {
250
+ warn( "data length was not multiple of uint64_t size %zu", data_bytes );
251
+ }
252
+ const size_t n_dpids = data_bytes / sizeof( uint64_t );
253
+
254
+ for ( size_t i = 0 ; i < n_dpids ; ++i ) {
255
+ dpids[ i ] = ntohll( dpids[ i ] );
256
+ }
257
+
258
+ if ( param->callback != NULL ) {
259
+ param->callback( dpids, n_dpids, param->user_data );
260
+ }
261
+ }
262
+
263
+
264
+ static void
265
+ handle_efi_reply( uint16_t tag, void *data, size_t length, void *user_data ) {
266
+
267
+ debug( "handle_efi_reply: tag=%#x, data=%p, length=%zu, user_data=%p", tag, data, length, user_data );
268
+
269
+ if ( tag != MESSENGER_MANAGEMENT_REPLY ) {
270
+ error( "Unexpected message received tag=%#x", tag );
271
+ return;
272
+ }
273
+ if ( data == NULL ) {
274
+ error( "Received reply had no data" );
275
+ return;
276
+ }
277
+ if ( length < sizeof( management_application_reply ) ) {
278
+ error( "Data length too short %zu. expecting >= %zu", length, sizeof( management_application_reply ) );
279
+ return;
280
+ }
281
+
282
+ management_application_reply *reply = data;
283
+ if ( ntohs( reply->header.type ) != MANAGEMENT_APPLICATION_REPLY ) {
284
+ error( "Invalid reply type %#x, expecting MANAGEMENT_APPLICATION_REPLY:%#x", ntohs( reply->header.type ), MANAGEMENT_APPLICATION_REPLY );
285
+ return;
286
+ }
287
+ const uint32_t command = ntohl( reply->application_id );
288
+
289
+ // check command validity
290
+ switch ( command ) {
291
+ case EVENT_FORWARD_ENTRY_ADD:
292
+ case EVENT_FORWARD_ENTRY_DELETE:
293
+ case EVENT_FORWARD_ENTRY_DUMP:
294
+ case EVENT_FORWARD_ENTRY_SET:
295
+ {
296
+ struct event_forward_operation_request_param *param = user_data;
297
+ handle_event_forward_operation_reply( reply, length, param );
298
+ xfree( param );
299
+ return;
300
+ }
301
+ break;
302
+
303
+ case EFI_GET_SWLIST:
304
+ {
305
+ struct sw_list_request_param *param = user_data;
306
+ handle_get_switch_list_reply( reply, length, param );
307
+ xfree( param );
308
+ return;
309
+ }
310
+ break;
311
+
312
+ default:
313
+ warn( "Invalid command/application_id: %#x", command );
314
+ return;
315
+ break;
316
+ }
317
+ }
318
+
319
+
320
+ bool
321
+ init_event_forward_interface( void ) {
322
+ if ( efi_queue_name != NULL ) {
323
+ warn( "already initialized." );
324
+ return false;
325
+ }
326
+
327
+ efi_queue_name = xcalloc( 1, MESSENGER_SERVICE_NAME_LENGTH );
328
+
329
+ int chWrite = snprintf( efi_queue_name, MESSENGER_SERVICE_NAME_LENGTH,
330
+ "%s-efic-%d", get_trema_name(), trema_getpid() );
331
+ if ( chWrite >= MESSENGER_SERVICE_NAME_LENGTH ) {
332
+ snprintf( efi_queue_name, MESSENGER_SERVICE_NAME_LENGTH,
333
+ "efic-%d", trema_getpid() );
334
+ }
335
+
336
+ // management reply handler
337
+ add_message_replied_callback( efi_queue_name, handle_efi_reply );
338
+
339
+ efi_tx_table = create_hash( compare_uint32, hash_uint32 );
340
+ return true;
341
+ }
342
+
343
+
344
+ static void
345
+ maybe_init_event_forward_interface( void ) {
346
+ if ( efi_queue_name == NULL ) {
347
+ info( "Initializing at maybe_init_event_forward_interface()" );
348
+ init_event_forward_interface();
349
+ }
350
+ }
351
+
352
+
353
+ void
354
+ _cleanup_tx_table() {
355
+ hash_iterator it;
356
+ init_hash_iterator( efi_tx_table, &it );
357
+ hash_entry *e = NULL;
358
+ while ( ( e = iterate_hash_next( &it ) ) != NULL ) {
359
+ all_sw_tx *tx = e->value;
360
+ warn( "txid:%#x was left behind.", tx->txid );
361
+
362
+ delete_hash_entry( efi_tx_table, &tx->txid );
363
+ xfree_all_sw_tx( tx );
364
+ }
365
+ }
366
+
367
+
368
+ bool
369
+ finalize_event_forward_interface( void ) {
370
+ if ( efi_queue_name == NULL ) {
371
+ warn( "already finalized." );
372
+ return false;
373
+ }
374
+ delete_message_replied_callback( efi_queue_name, handle_efi_reply );
375
+
376
+ xfree( efi_queue_name );
377
+ efi_queue_name = NULL;
378
+
379
+ _cleanup_tx_table();
380
+ delete_hash( efi_tx_table );
381
+ efi_tx_table = NULL;
382
+
383
+ return true;
384
+ }
385
+
386
+
387
+ static bool
388
+ send_efi_event_config_request( const char *service_name, enum switch_management_command command, enum efi_event_type type, list_element *service_list, event_forward_entry_operation_callback callback, void *user_data ) {
389
+ maybe_init_event_forward_interface();
390
+ if ( service_name == NULL ) {
391
+ return false;
392
+ }
393
+ switch( command ) {
394
+ case EVENT_FORWARD_ENTRY_ADD:
395
+ case EVENT_FORWARD_ENTRY_DELETE:
396
+ case EVENT_FORWARD_ENTRY_DUMP:
397
+ case EVENT_FORWARD_ENTRY_SET:
398
+ // do nothing;
399
+ break;
400
+ default:
401
+ return false;
402
+ }
403
+
404
+ buffer *all_req = alloc_buffer_with_length( sizeof( management_application_request ) + sizeof( event_forward_operation_request ) + MESSENGER_SERVICE_NAME_LENGTH );
405
+
406
+ management_application_request *apreq = append_back_buffer( all_req, sizeof( management_application_request ) );
407
+ apreq->header.type = htons( MANAGEMENT_APPLICATION_REQUEST );
408
+ apreq->application_id = htonl( command );
409
+ create_event_forward_operation_request( all_req, type, service_list );
410
+ apreq = all_req->data;
411
+ apreq->header.length = htonl( ( uint32_t ) all_req->length );
412
+
413
+ struct event_forward_operation_request_param *param = xcalloc( 1, sizeof( struct event_forward_operation_request_param ) );
414
+ param->callback = callback;
415
+ param->user_data = user_data;
416
+
417
+ bool sent = send_request_message( service_name, efi_queue_name, MESSENGER_MANAGEMENT_REQUEST,
418
+ all_req->data, all_req->length, param );
419
+ if ( !sent ) {
420
+ xfree( param );
421
+ }
422
+ free_buffer( all_req );
423
+
424
+ return sent;
425
+ }
426
+
427
+
428
+ // Low level API for switch manager
429
+ bool
430
+ set_switch_manager_event_forward_entries( enum efi_event_type type, list_element *service_list, event_forward_entry_operation_callback callback, void *user_data ) {
431
+ const char switch_manager[] = "switch_manager.m";
432
+ return send_efi_event_config_request( switch_manager, EVENT_FORWARD_ENTRY_SET, type, service_list, callback, user_data );
433
+ }
434
+
435
+
436
+ bool
437
+ add_switch_manager_event_forward_entry( enum efi_event_type type, const char *service_name, event_forward_entry_operation_callback callback, void *user_data ) {
438
+ const char switch_manager[] = "switch_manager.m";
439
+ list_element service_list;
440
+ service_list.next = NULL;
441
+ #pragma GCC diagnostic push
442
+ #pragma GCC diagnostic ignored "-Wcast-qual"
443
+ service_list.data = ( void * ) service_name;
444
+ #pragma GCC diagnostic pop
445
+ return send_efi_event_config_request( switch_manager, EVENT_FORWARD_ENTRY_ADD, type, &service_list, callback, user_data );
446
+ }
447
+
448
+
449
+ bool
450
+ delete_switch_manager_event_forward_entry( enum efi_event_type type, const char *service_name, event_forward_entry_operation_callback callback, void *user_data ) {
451
+ const char switch_manager[] = "switch_manager.m";
452
+ list_element service_list;
453
+ service_list.next = NULL;
454
+ #pragma GCC diagnostic push
455
+ #pragma GCC diagnostic ignored "-Wcast-qual"
456
+ service_list.data = ( void * ) service_name;
457
+ #pragma GCC diagnostic pop
458
+ return send_efi_event_config_request( switch_manager, EVENT_FORWARD_ENTRY_DELETE, type, &service_list, callback, user_data );
459
+ }
460
+
461
+
462
+ bool
463
+ dump_switch_manager_event_forward_entries( enum efi_event_type type, event_forward_entry_operation_callback callback, void *user_data ) {
464
+ const char switch_manager[] = "switch_manager.m";
465
+ return send_efi_event_config_request( switch_manager, EVENT_FORWARD_ENTRY_DUMP, type, NULL, callback, user_data );
466
+ }
467
+
468
+
469
+ bool
470
+ set_switch_event_forward_entries( uint64_t dpid, enum efi_event_type type, list_element *service_list, event_forward_entry_operation_callback callback, void *user_data ) {
471
+ char switch_name[ MESSENGER_SERVICE_NAME_LENGTH ];
472
+ snprintf( switch_name, MESSENGER_SERVICE_NAME_LENGTH, "switch.%#" PRIx64 ".m", dpid );
473
+ return send_efi_event_config_request( switch_name, EVENT_FORWARD_ENTRY_SET, type, service_list, callback, user_data );
474
+ }
475
+
476
+
477
+ bool
478
+ add_switch_event_forward_entry( uint64_t dpid, enum efi_event_type type, const char *service_name, event_forward_entry_operation_callback callback, void *user_data ) {
479
+ char switch_name[ MESSENGER_SERVICE_NAME_LENGTH ];
480
+ snprintf( switch_name, MESSENGER_SERVICE_NAME_LENGTH, "switch.%#" PRIx64 ".m", dpid );
481
+ list_element service_list;
482
+ service_list.next = NULL;
483
+ #pragma GCC diagnostic push
484
+ #pragma GCC diagnostic ignored "-Wcast-qual"
485
+ service_list.data = ( void * ) service_name;
486
+ #pragma GCC diagnostic pop
487
+ return send_efi_event_config_request( switch_name, EVENT_FORWARD_ENTRY_ADD, type, &service_list, callback, user_data );
488
+ }
489
+
490
+
491
+ bool
492
+ delete_switch_event_forward_entry( uint64_t dpid, enum efi_event_type type, const char *service_name, event_forward_entry_operation_callback callback, void *user_data ) {
493
+ char switch_name[ MESSENGER_SERVICE_NAME_LENGTH ];
494
+ snprintf( switch_name, MESSENGER_SERVICE_NAME_LENGTH, "switch.%#" PRIx64 ".m", dpid );
495
+ list_element service_list;
496
+ service_list.next = NULL;
497
+ #pragma GCC diagnostic push
498
+ #pragma GCC diagnostic ignored "-Wcast-qual"
499
+ service_list.data = ( void * ) service_name;
500
+ #pragma GCC diagnostic pop
501
+ return send_efi_event_config_request( switch_name, EVENT_FORWARD_ENTRY_DELETE, type, &service_list, callback, user_data );
502
+ }
503
+
504
+
505
+ bool
506
+ dump_switch_event_forward_entries( uint64_t dpid, enum efi_event_type type, event_forward_entry_operation_callback callback, void *user_data ) {
507
+ char switch_name[ MESSENGER_SERVICE_NAME_LENGTH ];
508
+ snprintf( switch_name, MESSENGER_SERVICE_NAME_LENGTH, "switch.%#" PRIx64 ".m", dpid );
509
+ return send_efi_event_config_request( switch_name, EVENT_FORWARD_ENTRY_DUMP, type, NULL, callback, user_data );
510
+ }
511
+
512
+
513
+ bool
514
+ send_efi_switch_list_request( switch_list_request_callback callback, void *user_data ) {
515
+ maybe_init_event_forward_interface();
516
+ if ( callback == NULL ) {
517
+ return false;
518
+ }
519
+
520
+ management_application_request req;
521
+ req.header.type = htons( MANAGEMENT_APPLICATION_REQUEST );
522
+ req.header.length = htonl( ( uint32_t ) sizeof( management_application_request ) );
523
+ req.application_id = htonl( EFI_GET_SWLIST );
524
+
525
+ struct sw_list_request_param *param = xcalloc( 1, sizeof( struct sw_list_request_param ) );
526
+ param->callback = callback;
527
+ param->user_data = user_data;
528
+
529
+ bool sent_ok = send_request_message( "switch_manager.m", efi_queue_name, MESSENGER_MANAGEMENT_REQUEST,
530
+ &req, sizeof( management_application_request ), param );
531
+ if ( !sent_ok ) {
532
+ xfree( param );
533
+ }
534
+
535
+ return sent_ok;
536
+ }
537
+
538
+
539
+ static uint32_t
540
+ get_txid() {
541
+ static uint32_t txid = 0;
542
+ return ++txid;
543
+ }
544
+
545
+
546
+ static bool
547
+ hash_table_is_empty( hash_table *tbl ) {
548
+ hash_iterator it;
549
+ init_hash_iterator( tbl, &it );
550
+ return ( iterate_hash_next( &it ) == NULL );
551
+ }
552
+
553
+
554
+ static bool
555
+ check_tx_result_and_respond( all_sw_tx *tx ) {
556
+ if ( tx->tx_result == EFI_OPERATION_FAILED ) {
557
+ struct event_forward_operation_to_all_request_param *all_param = tx->request_param;
558
+ if ( all_param->callback != NULL ) {
559
+ all_param->callback( tx->tx_result, all_param->user_data );
560
+ }
561
+
562
+ info( "txid %#x completed with failure.", tx->txid );
563
+ // remove and cleanup tx
564
+ delete_hash_entry( efi_tx_table, &tx->txid );
565
+ xfree_all_sw_tx( tx );
566
+ return true;
567
+ }
568
+ return false;
569
+ }
570
+
571
+
572
+ void
573
+ _switch_response_timeout( void *user_data ) {
574
+ struct txinfo *txinfo = user_data;
575
+ const uint64_t dpid = txinfo->dpid;
576
+ const uint32_t txid = txinfo->txid;
577
+ // xfree( txinfo ); // cannot free since _switch_response_handler may be called later.
578
+ txinfo = NULL;
579
+ debug( "txid %#x switch %#" PRIx64 " time out. called", txid, dpid );
580
+
581
+ all_sw_tx *tx = lookup_hash_entry( efi_tx_table, &txid );
582
+ if ( tx == NULL ) {
583
+ // transaction already failed. Do nothing.
584
+ return;
585
+ }
586
+
587
+ uint64_t *dpid_in_list = lookup_hash_entry( tx->waiting_dpid, &dpid );
588
+ if ( dpid_in_list != NULL ) {
589
+ info( "txid %#x switch %#" PRIx64 " timed out.", txid, dpid );
590
+ delete_hash_entry( tx->waiting_dpid, &dpid );
591
+ xfree( dpid_in_list );
592
+ tx->tx_result = EFI_OPERATION_FAILED;
593
+ }
594
+
595
+ check_tx_result_and_respond( tx );
596
+ }
597
+
598
+
599
+ void
600
+ _switch_response_handler( event_forward_operation_result result, void *user_data ) {
601
+ struct txinfo *txinfo = user_data;
602
+ const uint64_t dpid = txinfo->dpid;
603
+ const uint32_t txid = txinfo->txid;
604
+ delete_timer_event( _switch_response_timeout, txinfo );
605
+ xfree( txinfo );
606
+ txinfo = NULL;
607
+ debug( "txid %#x switch %#" PRIx64 " response.", txid, dpid );
608
+
609
+ all_sw_tx *tx = lookup_hash_entry( efi_tx_table, &txid );
610
+ if ( tx == NULL ) {
611
+ // transaction already failed. Do nothing.
612
+ return;
613
+ }
614
+
615
+ uint64_t *dpid_in_list = lookup_hash_entry( tx->waiting_dpid, &dpid );
616
+ if ( dpid_in_list == NULL ) {
617
+ // probably timed out. Do nothing.
618
+ return;
619
+ }
620
+ delete_hash_entry( tx->waiting_dpid, &dpid );
621
+ xfree( dpid_in_list );
622
+ dpid_in_list = NULL;
623
+
624
+ if ( result.result == EFI_OPERATION_FAILED ) {
625
+ warn( "txid %#x Setting event forwarding entry to switch %#" PRIx64 " failed.", txid, dpid );
626
+ tx->tx_result = EFI_OPERATION_FAILED;
627
+ }
628
+
629
+ bool tx_ended = check_tx_result_and_respond( tx );
630
+ if ( tx_ended ) return;
631
+
632
+ struct event_forward_operation_to_all_request_param *all_param = tx->request_param;
633
+ if ( hash_table_is_empty( tx->waiting_dpid ) ) {
634
+ // was last element in tx. callback result.
635
+ if ( all_param->callback != NULL ) {
636
+ all_param->callback( tx->tx_result, all_param->user_data );
637
+ }
638
+
639
+ info( "txid %#x complete.", tx->txid );
640
+ // remove and cleanup tx
641
+ delete_hash_entry( efi_tx_table, &tx->txid );
642
+ xfree_all_sw_tx( tx );
643
+ return;
644
+ }
645
+ }
646
+
647
+
648
+ all_sw_tx*
649
+ _insert_tx( size_t n_dpids, struct event_forward_operation_to_all_request_param *param ) {
650
+ all_sw_tx *tx = xcalloc( 1, sizeof(all_sw_tx) );
651
+ tx->txid = get_txid();
652
+ info( "txid %#x Start dispatching to switches", tx->txid );
653
+ tx->request_param = param;
654
+ tx->tx_result = EFI_OPERATION_SUCCEEDED;
655
+ tx->waiting_dpid = create_hash_with_size( compare_datapath_id,
656
+ hash_datapath_id,
657
+ ( unsigned ) n_dpids );
658
+ void *dupe_tx = insert_hash_entry( efi_tx_table, &tx->txid, tx );
659
+ assert( dupe_tx == NULL );
660
+ return tx;
661
+ }
662
+
663
+
664
+ void
665
+ _dispatch_to_all_switch( uint64_t *dpids, size_t n_dpids, void *user_data ) {
666
+ struct event_forward_operation_to_all_request_param *param = user_data;
667
+
668
+ all_sw_tx *tx = _insert_tx( n_dpids, param );
669
+
670
+ // copy dpid hash to transaction.
671
+ for ( size_t i = 0 ; i < n_dpids ; ++i ) {
672
+ uint64_t *dpid = xmalloc( sizeof( uint64_t ) );
673
+ *dpid = dpids[i];
674
+ uint64_t *dupe_dpid = insert_hash_entry( tx->waiting_dpid, dpid, dpid );
675
+ if ( dupe_dpid == NULL ) {
676
+ struct txinfo *txinfo = xcalloc( 1, sizeof( struct txinfo ) );
677
+ txinfo->dpid = *dpid;
678
+ txinfo->txid = tx->txid;
679
+ bool send_ok;
680
+
681
+ if ( param->add ) {
682
+ send_ok = add_switch_event_forward_entry( *dpid, param->type, param->service_name, _switch_response_handler, txinfo );
683
+ }
684
+ else {
685
+ send_ok = delete_switch_event_forward_entry( *dpid, param->type, param->service_name, _switch_response_handler, txinfo );
686
+ }
687
+
688
+ if ( !send_ok ) {
689
+ tx->tx_result = EFI_OPERATION_FAILED;
690
+ warn( "txid %#x Failed to send request to switch %#" PRIx64 ".", tx->txid, *dpid );
691
+ xfree( delete_hash_entry( tx->waiting_dpid, dpid ) );
692
+ dpid = NULL;
693
+ xfree( txinfo );
694
+ continue;
695
+ }
696
+
697
+ struct itimerspec interval;
698
+ interval.it_interval.tv_sec = 0;
699
+ interval.it_interval.tv_nsec = 0;
700
+ interval.it_value.tv_sec = 5; // FIXME make this configurable?
701
+ interval.it_value.tv_nsec = 0;
702
+ bool set_ok = add_timer_event_callback( &interval, _switch_response_timeout, txinfo );
703
+ if ( !set_ok ) {
704
+ tx->tx_result = EFI_OPERATION_FAILED;
705
+ warn( "txid %#x Failed to set timeout timer for switch %#" PRIx64 ".", tx->txid, *dpid );
706
+ xfree( delete_hash_entry( tx->waiting_dpid, dpid ) );
707
+ dpid = NULL;
708
+ // txinfo will be freed by _switch_response_handler
709
+ continue;
710
+ }
711
+ }
712
+ else {
713
+ warn( "Duplicate dpid returned %#." PRIx64, *dupe_dpid );
714
+ xfree( dupe_dpid );
715
+ }
716
+ }
717
+
718
+ if ( tx->tx_result == EFI_OPERATION_FAILED ) {
719
+ if ( param->callback != NULL ) {
720
+ param->callback( tx->tx_result, param->user_data );
721
+ }
722
+ info( "txid %#x completed with failure.", tx->txid );
723
+ // remove and cleanup tx
724
+ delete_hash_entry( efi_tx_table, &tx->txid );
725
+ xfree_all_sw_tx( tx );
726
+ }
727
+ }
728
+
729
+
730
+ void
731
+ _get_switch_list_after_swm_succ( event_forward_operation_result result, void *user_data ) {
732
+ struct event_forward_operation_to_all_request_param *param = user_data;
733
+ bool success = true;
734
+ if ( result.result == EFI_OPERATION_SUCCEEDED ) {
735
+ // get switch list
736
+ success = send_efi_switch_list_request( _dispatch_to_all_switch, param );
737
+ }
738
+ else {
739
+ success = false;
740
+ }
741
+
742
+ if ( !success ) {
743
+ warn( "Failed to set event forwarding entry to switch manager." );
744
+ if ( param->callback != NULL ) {
745
+ param->callback( EFI_OPERATION_FAILED, param->user_data );
746
+ }
747
+ xfree_event_forward_operation_to_all_request_param( param );
748
+ }
749
+ }
750
+
751
+
752
+ bool
753
+ add_event_forward_entry_to_all_switches( enum efi_event_type type, const char *service_name, event_forward_entry_to_all_callback callback, void *user_data ) {
754
+ struct event_forward_operation_to_all_request_param *param = xcalloc( 1, sizeof( struct event_forward_operation_to_all_request_param ) );
755
+ param->add = true;
756
+ param->type = type;
757
+ param->service_name = xstrdup( service_name );
758
+ param->callback = callback;
759
+ param->user_data = user_data;
760
+ bool sent_ok = add_switch_manager_event_forward_entry( type, service_name, _get_switch_list_after_swm_succ, param );
761
+ if ( !sent_ok ) {
762
+ xfree_event_forward_operation_to_all_request_param( param );
763
+ }
764
+ return sent_ok;
765
+ }
766
+
767
+
768
+ bool
769
+ delete_event_forward_entry_to_all_switches( enum efi_event_type type, const char *service_name, event_forward_entry_to_all_callback callback, void *user_data ) {
770
+ struct event_forward_operation_to_all_request_param *param = xcalloc( 1, sizeof( struct event_forward_operation_to_all_request_param ) );
771
+ param->add = false;
772
+ param->type = type;
773
+ param->service_name = xstrdup( service_name );
774
+ param->callback = callback;
775
+ param->user_data = user_data;
776
+ bool sent_ok = delete_switch_manager_event_forward_entry( type, service_name, _get_switch_list_after_swm_succ, param );
777
+ if ( !sent_ok ) {
778
+ xfree_event_forward_operation_to_all_request_param( param );
779
+ }
780
+ return sent_ok;
781
+ }
782
+
783
+