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
@@ -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
+