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
@@ -27,10 +27,13 @@
27
27
  #include <string.h>
28
28
  #include <sys/wait.h>
29
29
  #include <unistd.h>
30
+ #include <assert.h>
30
31
  #include "trema.h"
31
32
  #include "secure_channel_listener.h"
32
33
  #include "switch_manager.h"
33
34
  #include "dpid_table.h"
35
+ #include "switch_option.h"
36
+ #include "event_forward_entry_manipulation.h"
34
37
 
35
38
 
36
39
  #ifdef UNIT_TESTING
@@ -155,7 +158,7 @@ void
155
158
  usage() {
156
159
  printf(
157
160
  "OpenFlow Switch Manager.\n"
158
- "Usage: %s [OPTION]... [-- SWITCH_MANAGER_OPTION]...\n"
161
+ "Usage: %s [OPTION]... [-- SWITCH_DAEMON_OPTION]...\n"
159
162
  "\n"
160
163
  " -s, --switch=PATH the command path of switch\n"
161
164
  " -n, --name=SERVICE_NAME service name\n"
@@ -253,6 +256,10 @@ init_listener_info( struct listener_info *listener_info ) {
253
256
  listener_info->switch_daemon = xconcatenate_path( get_trema_home(), SWITCH_MANAGER_PATH );
254
257
  listener_info->listen_port = OFP_TCP_PORT;
255
258
  listener_info->listen_fd = -1;
259
+ create_list( &listener_info->vendor_service_name_list );
260
+ create_list( &listener_info->packetin_service_name_list );
261
+ create_list( &listener_info->portstatus_service_name_list );
262
+ create_list( &listener_info->state_service_name_list );
256
263
  }
257
264
 
258
265
 
@@ -269,6 +276,25 @@ finalize_listener_info( struct listener_info *listener_info ) {
269
276
  close( listener_info->listen_fd );
270
277
  listener_info->listen_fd = -1;
271
278
  }
279
+ for ( int i = 0; i < listener_info->switch_daemon_argc; ++i ) {
280
+ xfree( listener_info->switch_daemon_argv[ i ] );
281
+ listener_info->switch_daemon_argv[ i ] = NULL;
282
+ }
283
+ xfree( listener_info->switch_daemon_argv );
284
+ listener_info->switch_daemon_argv = NULL;
285
+
286
+ iterate_list( listener_info->vendor_service_name_list, xfree_data, NULL );
287
+ delete_list( listener_info->vendor_service_name_list );
288
+ listener_info->vendor_service_name_list = NULL;
289
+ iterate_list( listener_info->packetin_service_name_list, xfree_data, NULL );
290
+ delete_list( listener_info->packetin_service_name_list );
291
+ listener_info->packetin_service_name_list = NULL;
292
+ iterate_list( listener_info->portstatus_service_name_list, xfree_data, NULL );
293
+ delete_list( listener_info->portstatus_service_name_list );
294
+ listener_info->portstatus_service_name_list = NULL;
295
+ iterate_list( listener_info->state_service_name_list, xfree_data, NULL );
296
+ delete_list( listener_info->state_service_name_list );
297
+ listener_info->state_service_name_list = NULL;
272
298
  }
273
299
 
274
300
 
@@ -310,8 +336,48 @@ parse_argument( struct listener_info *listener_info, int argc, char *argv[] ) {
310
336
  }
311
337
  }
312
338
 
313
- listener_info->switch_daemon_argc = argc - optind;
314
- listener_info->switch_daemon_argv = &argv[ optind ];
339
+ debug( "Start parsing switch daemon arguments." );
340
+ // index of first switch daemon arguments in argv
341
+ const int switch_arg_begin = optind;
342
+
343
+ // reorder switch daemon arguments
344
+ while ( getopt_long( argc, argv, switch_short_options, switch_long_options, NULL ) != -1 );
345
+
346
+ // index of first packet_in::..., etc. in argv
347
+ const int switch_arg_option_begin = optind;
348
+
349
+ // deep copy switch daemon arguments excluding packet_in::..., etc.
350
+ listener_info->switch_daemon_argc = switch_arg_option_begin - switch_arg_begin;
351
+ listener_info->switch_daemon_argv = xcalloc( ( size_t ) listener_info->switch_daemon_argc + 1,
352
+ sizeof( char * ) );
353
+ for ( int i = 0; i < listener_info->switch_daemon_argc; ++i ) {
354
+ debug( "switch daemon option: %s\n", argv[switch_arg_begin + i] );
355
+ listener_info->switch_daemon_argv[ i ] = xstrdup( argv[ switch_arg_begin + i ] );
356
+ }
357
+
358
+ // set service lists for each event type
359
+ for ( int i = switch_arg_option_begin; i < argc; i++ ) {
360
+ if ( strncmp( argv[ i ], VENDOR_PREFIX, strlen( VENDOR_PREFIX ) ) == 0 ) {
361
+ char *service_name = xstrdup( argv[ i ] + strlen( VENDOR_PREFIX ) );
362
+ debug( "event: " VENDOR_PREFIX "%s", service_name );
363
+ insert_in_front( &listener_info->vendor_service_name_list, service_name );
364
+ }
365
+ else if ( strncmp( argv[ i ], PACKET_IN_PREFIX, strlen( PACKET_IN_PREFIX ) ) == 0 ) {
366
+ char *service_name = xstrdup( argv[ i ] + strlen( PACKET_IN_PREFIX ) );
367
+ debug( "event: " PACKET_IN_PREFIX "%s", service_name );
368
+ insert_in_front( &listener_info->packetin_service_name_list, service_name );
369
+ }
370
+ else if ( strncmp( argv[ i ], PORTSTATUS_PREFIX, strlen( PORTSTATUS_PREFIX ) ) == 0 ) {
371
+ char *service_name = xstrdup( argv[ i ] + strlen( PORTSTATUS_PREFIX ) );
372
+ debug( "event: " PORTSTATUS_PREFIX "%s", service_name );
373
+ insert_in_front( &listener_info->portstatus_service_name_list, service_name );
374
+ }
375
+ else if ( strncmp( argv[ i ], STATE_PREFIX, strlen( STATE_PREFIX ) ) == 0 ) {
376
+ char *service_name = xstrdup( argv[ i ] + strlen( STATE_PREFIX ) );
377
+ debug( "event: " STATE_PREFIX "%s", service_name );
378
+ insert_in_front( &listener_info->state_service_name_list, service_name );
379
+ }
380
+ }
315
381
 
316
382
  return true;
317
383
  }
@@ -359,6 +425,112 @@ recv_request( const messenger_context_handle *handle,
359
425
  }
360
426
 
361
427
 
428
+ static void
429
+ management_event_forward_entry_operation( const messenger_context_handle *handle, uint32_t command, event_forward_operation_request *req, size_t data_len ) {
430
+
431
+ debug( "management efi command:%#x, type:%#x, n_services:%d", command, req->type, req->n_services );
432
+
433
+ list_element **subject = NULL;
434
+ switch ( req->type ) {
435
+ case EVENT_FORWARD_TYPE_VENDOR:
436
+ info( "Managing vendor event." );
437
+ subject = &listener_info.vendor_service_name_list;
438
+ break;
439
+
440
+ case EVENT_FORWARD_TYPE_PACKET_IN:
441
+ info( "Managing packet_in event." );
442
+ subject = &listener_info.packetin_service_name_list;
443
+ break;
444
+
445
+ case EVENT_FORWARD_TYPE_PORT_STATUS:
446
+ info( "Managing port_status event." );
447
+ subject = &listener_info.portstatus_service_name_list;
448
+ break;
449
+
450
+ case EVENT_FORWARD_TYPE_STATE_NOTIFY:
451
+ info( "Managing state_notify event." );
452
+ subject = &listener_info.state_service_name_list;
453
+ break;
454
+
455
+ default:
456
+ error( "Invalid EVENT_FWD_TYPE ( %#x )", req->type );
457
+ event_forward_operation_reply res;
458
+ memset( &res, 0, sizeof( event_forward_operation_reply ) );
459
+ res.type = req->type;
460
+ res.result = EFI_OPERATION_FAILED;
461
+ management_application_reply *reply = create_management_application_reply( MANAGEMENT_REQUEST_FAILED, command, &res, sizeof( event_forward_operation_reply ) );
462
+ send_management_application_reply( handle, reply );
463
+ xfree( reply );
464
+ return;
465
+ }
466
+ assert( subject != NULL );
467
+
468
+ switch ( command ) {
469
+ case EVENT_FORWARD_ENTRY_ADD:
470
+ management_event_forward_entry_add( subject, req, data_len );
471
+ break;
472
+
473
+ case EVENT_FORWARD_ENTRY_DELETE:
474
+ management_event_forward_entry_delete( subject, req, data_len );
475
+ break;
476
+
477
+ case EVENT_FORWARD_ENTRY_DUMP:
478
+ info( "Dumping current event filter." );
479
+ // do nothing
480
+ break;
481
+
482
+ case EVENT_FORWARD_ENTRY_SET:
483
+ management_event_forward_entries_set( subject, req, data_len );
484
+ break;
485
+ }
486
+
487
+ buffer *buf = create_event_forward_operation_reply( req->type, EFI_OPERATION_SUCCEEDED, *subject );
488
+ management_application_reply *reply = create_management_application_reply( MANAGEMENT_REQUEST_SUCCEEDED, command, buf->data, buf->length );
489
+ free_buffer( buf );
490
+ send_management_application_reply( handle, reply );
491
+ xfree( reply );
492
+ }
493
+
494
+
495
+ static void
496
+ management_recv( const messenger_context_handle *handle, uint32_t command, void *data, size_t data_len, void *user_data ) {
497
+ UNUSED( user_data );
498
+
499
+ switch ( command ) {
500
+ case EVENT_FORWARD_ENTRY_ADD:
501
+ case EVENT_FORWARD_ENTRY_DELETE:
502
+ case EVENT_FORWARD_ENTRY_DUMP:
503
+ case EVENT_FORWARD_ENTRY_SET:
504
+ {
505
+ event_forward_operation_request *req = data;
506
+ req->n_services = ntohl( req->n_services );
507
+ management_event_forward_entry_operation( handle, command, req, data_len );
508
+ return;
509
+ }
510
+ break;
511
+
512
+ case EFI_GET_SWLIST:
513
+ {
514
+ buffer *buf = get_switches();
515
+ management_application_reply *reply = create_management_application_reply( MANAGEMENT_REQUEST_SUCCEEDED, command, buf->data, buf->length );
516
+ free_buffer( buf );
517
+ send_management_application_reply( handle, reply );
518
+ xfree( reply );
519
+ }
520
+ break;
521
+
522
+ default:
523
+ {
524
+ error( "Undefined management command ( %#x )", command );
525
+ management_application_reply *reply = create_management_application_reply( MANAGEMENT_REQUEST_FAILED, command, NULL, 0 );
526
+ send_management_application_reply( handle, reply );
527
+ xfree( reply );
528
+ return;
529
+ }
530
+ }
531
+ }
532
+
533
+
362
534
  static bool
363
535
  start_service_management( void ) {
364
536
  return add_message_requested_callback( get_trema_name(), recv_request );
@@ -406,6 +578,7 @@ main( int argc, char *argv[] ) {
406
578
  finalize_listener_info( &listener_info );
407
579
  exit( EXIT_FAILURE );
408
580
  }
581
+ set_management_application_request_handler( management_recv, NULL );
409
582
 
410
583
  init_dpid_table();
411
584
  start_service_management();
@@ -47,6 +47,10 @@ struct listener_info {
47
47
  char **switch_daemon_argv;
48
48
  uint16_t listen_port;
49
49
  int listen_fd;
50
+ list_element *vendor_service_name_list; // vendor manager service
51
+ list_element *packetin_service_name_list; // packetin manager service
52
+ list_element *portstatus_service_name_list; // portstatus manager service
53
+ list_element *state_service_name_list; // switch state manager service
50
54
  };
51
55
 
52
56
 
@@ -0,0 +1,30 @@
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 "trema.h"
19
+ #include "switch_option.h"
20
+
21
+ struct option switch_long_options[] = {
22
+ { "socket", 1, NULL, 's' },
23
+ { "no-flow-cleanup", 0, NULL, NO_FLOW_CLEANUP_LONG_OPTION_VALUE },
24
+ { "no-cookie-translation", 0, NULL, NO_COOKIE_TRANSLATION_LONG_OPTION_VALUE },
25
+ { "no-packet_in", 0, NULL, NO_PACKET_IN_LONG_OPTION_VALUE },
26
+ { NULL, 0, NULL, 0 },
27
+ };
28
+
29
+ char switch_short_options[] = "s:";
30
+
@@ -0,0 +1,41 @@
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
+ #ifndef SWITCH_OPTION_H_
19
+ #define SWITCH_OPTION_H_
20
+
21
+ #include <getopt.h>
22
+
23
+ enum switch_long_options_val {
24
+ NO_FLOW_CLEANUP_LONG_OPTION_VALUE = 1,
25
+ NO_COOKIE_TRANSLATION_LONG_OPTION_VALUE = 2,
26
+ NO_PACKET_IN_LONG_OPTION_VALUE = 3,
27
+ };
28
+
29
+
30
+ extern struct option switch_long_options[];
31
+
32
+
33
+ extern char switch_short_options[];
34
+
35
+
36
+ #define VENDOR_PREFIX "vendor::"
37
+ #define PACKET_IN_PREFIX "packet_in::"
38
+ #define PORTSTATUS_PREFIX "port_status::"
39
+ #define STATE_PREFIX "state_notify::"
40
+
41
+ #endif /* SWITCH_OPTION_H_ */
data/trema.gemspec CHANGED
@@ -27,7 +27,8 @@ Gem::Specification.new do | gem |
27
27
  gem.test_files = `git ls-files -- {spec,features}/*`.split( "\n" )
28
28
 
29
29
  gem.add_dependency "bundler"
30
- gem.add_dependency "gli", "~> 2.5.4"
30
+ gem.add_dependency "gli", "~> 2.5.5"
31
+ gem.add_dependency "popen4", "~> 0.1.2"
31
32
  gem.add_dependency "rake", "~> 10.0.3"
32
33
  gem.add_dependency "rdoc", "~> 4.0.0"
33
34
  end
@@ -0,0 +1,1646 @@
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 <setjmp.h>
20
+ #include <stdarg.h>
21
+ #include <stdint.h>
22
+ #include <stdio.h>
23
+ #include <stdlib.h>
24
+ #include <string.h>
25
+ #include <unistd.h>
26
+ #include "event_forward_interface.h"
27
+ #include "trema.h"
28
+ #include "trema_private.h"
29
+ #include "trema_wrapper.h"
30
+ #include "cmockery_trema.h"
31
+
32
+
33
+ /********************************************************************************
34
+ * Fwd decl for internal functions.
35
+ ********************************************************************************/
36
+
37
+ struct event_forward_operation_to_all_request_param {
38
+ bool add;
39
+ enum efi_event_type type;
40
+ char *service_name;
41
+ event_forward_entry_to_all_callback callback;
42
+ void *user_data;
43
+ };
44
+
45
+ typedef struct all_sw_tx {
46
+ uint32_t txid;
47
+ hash_table *waiting_dpid;
48
+ enum efi_result tx_result;
49
+
50
+ void *user_data;
51
+ } all_sw_tx;
52
+
53
+ struct txinfo {
54
+ uint64_t dpid;
55
+ uint32_t txid;
56
+ };
57
+
58
+ extern const char *_get_efi_queue_name( void );
59
+ extern void _get_switch_list_after_swm_succ( event_forward_operation_result result, void *user_data );
60
+ extern void _dispatch_to_all_switch( uint64_t *dpids, size_t n_dpids, void *user_data );
61
+ extern void _switch_response_handler( event_forward_operation_result result, void *user_data );
62
+ extern void _cleanup_tx_table();
63
+ extern all_sw_tx *_insert_tx( size_t n_dpids, struct event_forward_operation_to_all_request_param *param );
64
+ extern void _switch_response_timeout( void *user_data );
65
+
66
+ /********************************************************************************
67
+ * Mock functions.
68
+ ********************************************************************************/
69
+
70
+ struct callback_info {
71
+ void *callback;
72
+ void *user_data;
73
+ };
74
+
75
+
76
+ static void ( *original_error )( const char *format, ... );
77
+ static void ( *original_warn )( const char *format, ... );
78
+ static void ( *original_debug )( const char *format, ... );
79
+ static bool ( *original_add_message_requested_callback )( const char *service_name, void ( *callback )( const messenger_context_handle *handle, uint16_t tag, void *data, size_t len ) );
80
+ static bool ( *original_add_message_replied_callback )( const char *service_name, void ( *callback )( uint16_t tag, void *data, size_t len, void *user_data ) );
81
+ static bool ( *original_delete_message_replied_callback )( const char *service_name, void ( *callback )( uint16_t tag, void *data, size_t len, void *user_data ) );
82
+ static bool ( *original_delete_message_requested_callback )( const char *service_name, void ( *callback )( const messenger_context_handle *handle, uint16_t tag, void *data, size_t len ) );
83
+ static const char *( *original_get_management_service_name )( const char *service_name );
84
+ static pid_t ( *original_getpid )( void );
85
+ static void ( *handle_efi_reply )( uint16_t tag, void *data, size_t length, void *user_data ) = NULL;
86
+ static bool ( *original_send_request_message )( const char *to_service_name, const char *from_service_name, const uint16_t tag, const void *data, size_t len, void *user_data );
87
+
88
+ static void
89
+ mock_error( const char *format, ... ) {
90
+ va_list args;
91
+ va_start( args, format );
92
+ char message[ 1000 ];
93
+ vsprintf( message, format, args );
94
+ va_end( args );
95
+
96
+ check_expected( message );
97
+ }
98
+
99
+
100
+ static void
101
+ mock_warn( const char *format, ... ) {
102
+ va_list args;
103
+ va_start( args, format );
104
+ char message[ 1000 ];
105
+ vsprintf( message, format, args );
106
+ va_end( args );
107
+
108
+ check_expected( message );
109
+ }
110
+
111
+
112
+ static void
113
+ mock_debug( const char *format, ... ) {
114
+ UNUSED( format );
115
+ }
116
+
117
+
118
+ static bool
119
+ mock_add_message_requested_callback( const char *service_name,
120
+ void ( *callback )( const messenger_context_handle *handle, uint16_t tag, void *data, size_t len ) ) {
121
+ UNUSED( callback );
122
+
123
+ check_expected( service_name );
124
+
125
+ return ( bool ) mock();
126
+ }
127
+
128
+
129
+ static bool
130
+ mock_add_message_replied_callback( const char *service_name,
131
+ void ( *callback )( uint16_t tag, void *data, size_t len, void *user_data ) ) {
132
+ check_expected( service_name );
133
+ assert_true( callback != NULL );
134
+ handle_efi_reply = callback;
135
+
136
+ return ( bool ) mock();
137
+ }
138
+
139
+
140
+ static bool
141
+ mock_delete_message_replied_callback( const char *service_name,
142
+ void ( *callback )( uint16_t tag, void *data, size_t len, void *user_data ) ) {
143
+ check_expected( service_name );
144
+ assert_true( callback != NULL );
145
+ handle_efi_reply = NULL;
146
+
147
+ return ( bool ) mock();
148
+ }
149
+
150
+
151
+ static bool
152
+ mock_delete_message_requested_callback( const char *service_name,
153
+ void ( *callback )( const messenger_context_handle *handle, uint16_t tag, void *data, size_t len ) ) {
154
+ UNUSED( callback );
155
+
156
+ check_expected( service_name );
157
+
158
+ return ( bool ) mock();
159
+ }
160
+
161
+
162
+ static const char *
163
+ mock_get_management_service_name( const char *service_name ) {
164
+ check_expected( service_name );
165
+
166
+ return ( const char * ) ( intptr_t ) mock();
167
+ }
168
+
169
+
170
+ static pid_t
171
+ mock_getpid( void ) {
172
+ return 1234;
173
+ }
174
+
175
+
176
+ static bool free_user_data_member = false;
177
+
178
+
179
+ static bool
180
+ mock_send_request_message( const char *to_service_name, const char *from_service_name,
181
+ const uint16_t tag, const void *data, size_t len, void *user_data ) {
182
+ uint32_t tag32 = tag;
183
+ struct callback_info *hd = user_data;
184
+
185
+ check_expected( to_service_name );
186
+ check_expected( from_service_name );
187
+ check_expected( tag32 );
188
+ check_expected( data );
189
+ check_expected( len );
190
+ check_expected( hd->callback );
191
+ check_expected( hd->user_data );
192
+
193
+ bool sent_ok = ( bool ) mock();
194
+ if ( sent_ok ) {
195
+ if ( free_user_data_member ) {
196
+ xfree( hd->user_data );
197
+ }
198
+ xfree( hd );
199
+ }
200
+ return sent_ok;
201
+ }
202
+
203
+
204
+ void mock_event_forward_entry_operation_callback( event_forward_operation_result result, void *user_data ) {
205
+ check_expected( result.result );
206
+ check_expected( result.n_services );
207
+ for ( unsigned i = 0; i < result.n_services; ++i ) {
208
+ const char *service = result.services[i];
209
+ check_expected( service );
210
+ }
211
+ check_expected( user_data );
212
+ }
213
+
214
+
215
+ void mock_switch_list_request_callback( uint64_t *dpids, size_t n_dpids, void *user_data ) {
216
+ check_expected( n_dpids );
217
+ check_expected( dpids );
218
+ check_expected( user_data );
219
+ }
220
+
221
+
222
+ void mock_event_forward_entry_to_all_callback( enum efi_result result, void *user_data ) {
223
+ check_expected( result );
224
+ check_expected( user_data );
225
+ }
226
+
227
+
228
+ /********************************************************************************
229
+ * Setup and teardown functions.
230
+ ********************************************************************************/
231
+
232
+ static void
233
+ setup() {
234
+ free_user_data_member = false;
235
+
236
+ original_error = error;
237
+ error = mock_error;
238
+ original_warn = warn;
239
+ warn = mock_warn;
240
+ original_debug = debug;
241
+ debug = mock_debug;
242
+ original_add_message_requested_callback= add_message_requested_callback;
243
+ add_message_requested_callback = mock_add_message_requested_callback;
244
+ original_delete_message_requested_callback= delete_message_requested_callback;
245
+ delete_message_requested_callback = mock_delete_message_requested_callback;
246
+ original_get_management_service_name = get_management_service_name;
247
+ get_management_service_name = mock_get_management_service_name;
248
+ original_getpid = trema_getpid;
249
+ trema_getpid = mock_getpid;
250
+ original_add_message_replied_callback = add_message_replied_callback;
251
+ add_message_replied_callback = mock_add_message_replied_callback;
252
+ original_delete_message_replied_callback = delete_message_replied_callback;
253
+ delete_message_replied_callback = mock_delete_message_replied_callback;
254
+ original_send_request_message = send_request_message;
255
+ send_request_message = mock_send_request_message;
256
+ }
257
+
258
+
259
+ static void
260
+ setup_init_efi() {
261
+ setup();
262
+
263
+ const char service_name[] = "tetris";
264
+ const char efi_queue_name[] = "tetris-efic-1234";
265
+ set_trema_name( service_name );
266
+
267
+ expect_string( mock_add_message_replied_callback, service_name, efi_queue_name );
268
+ will_return( mock_add_message_replied_callback, true );
269
+
270
+ assert_true( _get_efi_queue_name() == NULL );
271
+ assert_true( init_event_forward_interface() );
272
+ assert_false( _get_efi_queue_name() == NULL );
273
+ }
274
+
275
+ static void
276
+ teardown() {
277
+ bool *initialized = _get_management_interface_initialized();
278
+ *initialized = false;
279
+
280
+ error = original_error;
281
+ warn = original_warn;
282
+ debug = original_debug;
283
+ add_message_requested_callback= original_add_message_requested_callback;
284
+ delete_message_requested_callback= original_delete_message_requested_callback;
285
+ get_management_service_name = original_get_management_service_name;
286
+ trema_getpid = original_getpid;
287
+ add_message_replied_callback = original_add_message_replied_callback;
288
+ delete_message_replied_callback = original_delete_message_replied_callback;
289
+ send_request_message = original_send_request_message;
290
+ }
291
+
292
+
293
+ static void
294
+ teardown_finl_efi() {
295
+ const char efi_queue_name[] = "tetris-efic-1234";
296
+ expect_string( mock_delete_message_replied_callback, service_name, efi_queue_name );
297
+ will_return( mock_delete_message_replied_callback, true );
298
+
299
+ assert_true( finalize_event_forward_interface() );
300
+ assert_true( _get_efi_queue_name() == NULL );
301
+
302
+ _free_trema_name();
303
+ teardown();
304
+ }
305
+ /********************************************************************************
306
+ * init_event_forward_interface() tests.
307
+ ********************************************************************************/
308
+
309
+ static void
310
+ test_init_event_forward_interface_succeeds() {
311
+ const char service_name[] = "tetris";
312
+ const char efi_queue_name[] = "tetris-efic-1234";
313
+
314
+ set_trema_name( service_name );
315
+
316
+ expect_string( mock_add_message_replied_callback, service_name, efi_queue_name );
317
+ will_return( mock_add_message_replied_callback, true );
318
+
319
+ assert_true( _get_efi_queue_name() == NULL );
320
+ assert_true( init_event_forward_interface() );
321
+ assert_false( _get_efi_queue_name() == NULL );
322
+ assert_string_equal( _get_efi_queue_name(), efi_queue_name );
323
+
324
+ expect_string( mock_delete_message_replied_callback, service_name, efi_queue_name );
325
+ will_return( mock_delete_message_replied_callback, true );
326
+ assert_true( finalize_event_forward_interface() );
327
+
328
+ _free_trema_name();
329
+ }
330
+
331
+
332
+ static void
333
+ test_init_event_forward_interface_succeeds_even_with_long_name() {
334
+ const char service_name[] = "tetris1234567890123456";
335
+ const char efi_queue_name[] = "efic-1234";
336
+
337
+ set_trema_name( service_name );
338
+
339
+ expect_string( mock_add_message_replied_callback, service_name, efi_queue_name );
340
+ will_return( mock_add_message_replied_callback, true );
341
+
342
+ assert_true( _get_efi_queue_name() == NULL );
343
+ assert_true( init_event_forward_interface() );
344
+ assert_false( _get_efi_queue_name() == NULL );
345
+ assert_string_equal( _get_efi_queue_name(), efi_queue_name );
346
+
347
+ expect_string( mock_delete_message_replied_callback, service_name, efi_queue_name );
348
+ will_return( mock_delete_message_replied_callback, true );
349
+ assert_true( finalize_event_forward_interface() );
350
+
351
+ _free_trema_name();
352
+ }
353
+
354
+ static void
355
+ test_init_event_forward_interface_fails_if_already_initialized() {
356
+ const char service_name[] = "tetris";
357
+ const char efi_queue_name[] = "tetris-efic-1234";
358
+
359
+ set_trema_name( service_name );
360
+
361
+ expect_string( mock_add_message_replied_callback, service_name, efi_queue_name );
362
+ will_return( mock_add_message_replied_callback, true );
363
+
364
+ init_event_forward_interface();
365
+ assert_false( _get_efi_queue_name() == NULL );
366
+ assert_string_equal( _get_efi_queue_name(), efi_queue_name );
367
+
368
+ expect_string( mock_warn, message, "already initialized." );
369
+
370
+ assert_false( init_event_forward_interface() );
371
+
372
+ assert_false( _get_efi_queue_name() == NULL );
373
+ assert_string_equal( _get_efi_queue_name(), efi_queue_name );
374
+
375
+ expect_string( mock_delete_message_replied_callback, service_name, efi_queue_name );
376
+ will_return( mock_delete_message_replied_callback, true );
377
+
378
+ assert_true( finalize_event_forward_interface() );
379
+ _free_trema_name();
380
+ }
381
+
382
+
383
+ /********************************************************************************
384
+ * finalize_event_forward_interface() tests.
385
+ ********************************************************************************/
386
+
387
+ static void
388
+ test_finalize_event_forward_interface_succeeds() {
389
+ const char service_name[] = "tetris";
390
+ const char efi_queue_name[] = "tetris-efic-1234";
391
+
392
+ set_trema_name( service_name );
393
+
394
+ expect_string( mock_add_message_replied_callback, service_name, efi_queue_name );
395
+ will_return( mock_add_message_replied_callback, true );
396
+ assert_true( init_event_forward_interface() );
397
+
398
+
399
+ expect_string( mock_delete_message_replied_callback, service_name, efi_queue_name );
400
+ will_return( mock_delete_message_replied_callback, true );
401
+
402
+ assert_true( finalize_event_forward_interface() );
403
+ assert_true( _get_efi_queue_name() == NULL );
404
+
405
+ _free_trema_name();
406
+ }
407
+
408
+
409
+ static void
410
+ test_finalize_event_forward_interface_fails_if_not_initialized() {
411
+ expect_string( mock_warn, message, "already finalized." );
412
+
413
+ assert_false( finalize_event_forward_interface() );
414
+ assert_true( _get_efi_queue_name() == NULL );
415
+ }
416
+
417
+
418
+ /********************************************************************************
419
+ * set_switch_manager_event_forward_entries() tests.
420
+ ********************************************************************************/
421
+
422
+ static void
423
+ test_set_switch_manager_event_forward_entries_succeeds() {
424
+ list_element *head;
425
+ char alpha[] = "alpha-12345678901234567890";
426
+ char bravo[] = "bravo-12345678901234567890";
427
+ create_list( &head );
428
+ append_to_tail( &head, alpha );
429
+ append_to_tail( &head, bravo );
430
+
431
+ event_forward_entry_operation_callback callback = ( event_forward_entry_operation_callback ) 0x12345678;
432
+ void *user_data = ( void * ) 0xABCDEF;
433
+
434
+ struct expected_data {
435
+ management_application_request mgmt;
436
+ event_forward_operation_request efi;
437
+ char alpha[ 6 + 21 ];
438
+ char bravo[ 6 + 21 ];
439
+ } __attribute__( ( packed ) ) expected_data = {
440
+ .mgmt = {
441
+ .header = {
442
+ .type = htons( MANAGEMENT_APPLICATION_REQUEST ),
443
+ .length = htonl( sizeof( struct expected_data ) ),
444
+ },
445
+ .application_id = htonl( EVENT_FORWARD_ENTRY_SET ),
446
+ },
447
+ .efi = {
448
+ .type = EVENT_FORWARD_TYPE_VENDOR,
449
+ .n_services = htonl( 2 ),
450
+ },
451
+ .alpha = "alpha-12345678901234567890",
452
+ .bravo = "bravo-12345678901234567890",
453
+ };
454
+
455
+ expect_string( mock_send_request_message, to_service_name, "switch_manager.m" );
456
+ expect_string( mock_send_request_message, from_service_name, "tetris-efic-1234" );
457
+ expect_value( mock_send_request_message, tag32, MESSENGER_MANAGEMENT_REQUEST );
458
+ expect_memory( mock_send_request_message, data, &expected_data, sizeof( struct expected_data ) );
459
+ expect_value( mock_send_request_message, len, sizeof( struct expected_data ) );
460
+ expect_value( mock_send_request_message, hd->callback, callback );
461
+ expect_value( mock_send_request_message, hd->user_data, user_data );
462
+ will_return( mock_send_request_message, true );
463
+
464
+ assert_true( set_switch_manager_event_forward_entries( EVENT_FORWARD_TYPE_VENDOR, head, callback, user_data ) );
465
+
466
+ delete_list( head );
467
+ }
468
+
469
+
470
+ /********************************************************************************
471
+ * add_switch_manager_event_forward_entry() tests.
472
+ ********************************************************************************/
473
+
474
+ static void
475
+ test_add_switch_manager_event_forward_entry_succeeds() {
476
+
477
+ event_forward_entry_operation_callback callback = ( event_forward_entry_operation_callback ) 0x12345678;
478
+ void *user_data = ( void * ) 0xABCDEF;
479
+
480
+ struct expected_data {
481
+ management_application_request mgmt;
482
+ event_forward_operation_request efi;
483
+ char alpha[ 6 ];
484
+ } __attribute__( ( packed ) ) expected_data = {
485
+ .mgmt = {
486
+ .header = {
487
+ .type = htons( MANAGEMENT_APPLICATION_REQUEST ),
488
+ .length = htonl( sizeof( struct expected_data ) ),
489
+ },
490
+ .application_id = htonl( EVENT_FORWARD_ENTRY_ADD ),
491
+ },
492
+ .efi = {
493
+ .type = EVENT_FORWARD_TYPE_PACKET_IN,
494
+ .n_services = htonl( 1 ),
495
+ },
496
+ .alpha = "alpha",
497
+ };
498
+
499
+ expect_string( mock_send_request_message, to_service_name, "switch_manager.m" );
500
+ expect_string( mock_send_request_message, from_service_name, "tetris-efic-1234" );
501
+ expect_value( mock_send_request_message, tag32, MESSENGER_MANAGEMENT_REQUEST );
502
+ expect_memory( mock_send_request_message, data, &expected_data, sizeof( struct expected_data ) );
503
+ expect_value( mock_send_request_message, len, sizeof( struct expected_data ) );
504
+ expect_value( mock_send_request_message, hd->callback, callback );
505
+ expect_value( mock_send_request_message, hd->user_data, user_data );
506
+ will_return( mock_send_request_message, true );
507
+
508
+ assert_true( add_switch_manager_event_forward_entry( EVENT_FORWARD_TYPE_PACKET_IN, "alpha", callback, user_data ) );
509
+ }
510
+
511
+
512
+ /********************************************************************************
513
+ * delete_switch_manager_event_forward_entry() tests.
514
+ ********************************************************************************/
515
+
516
+ static void
517
+ test_delete_switch_manager_event_forward_entry_succeeds() {
518
+
519
+ event_forward_entry_operation_callback callback = ( event_forward_entry_operation_callback ) 0x12345678;
520
+ void *user_data = ( void * ) 0xABCDEF;
521
+
522
+ struct expected_data {
523
+ management_application_request mgmt;
524
+ event_forward_operation_request efi;
525
+ char alpha[ 6 ];
526
+ } __attribute__( ( packed ) ) expected_data = {
527
+ .mgmt = {
528
+ .header = {
529
+ .type = htons( MANAGEMENT_APPLICATION_REQUEST ),
530
+ .length = htonl( sizeof( struct expected_data ) ),
531
+ },
532
+ .application_id = htonl( EVENT_FORWARD_ENTRY_DELETE ),
533
+ },
534
+ .efi = {
535
+ .type = EVENT_FORWARD_TYPE_PORT_STATUS,
536
+ .n_services = htonl( 1 ),
537
+ },
538
+ .alpha = "alpha",
539
+ };
540
+
541
+ expect_string( mock_send_request_message, to_service_name, "switch_manager.m" );
542
+ expect_string( mock_send_request_message, from_service_name, "tetris-efic-1234" );
543
+ expect_value( mock_send_request_message, tag32, MESSENGER_MANAGEMENT_REQUEST );
544
+ expect_memory( mock_send_request_message, data, &expected_data, sizeof( struct expected_data ) );
545
+ expect_value( mock_send_request_message, len, sizeof( struct expected_data ) );
546
+ expect_value( mock_send_request_message, hd->callback, callback );
547
+ expect_value( mock_send_request_message, hd->user_data, user_data );
548
+ will_return( mock_send_request_message, true );
549
+
550
+ assert_true( delete_switch_manager_event_forward_entry( EVENT_FORWARD_TYPE_PORT_STATUS, "alpha", callback, user_data ) );
551
+ }
552
+
553
+
554
+ /********************************************************************************
555
+ * dump_switch_manager_event_forward_entries() tests.
556
+ ********************************************************************************/
557
+
558
+ static void
559
+ test_dump_switch_manager_event_forward_entries_succeeds() {
560
+
561
+ event_forward_entry_operation_callback callback = ( event_forward_entry_operation_callback ) 0x12345678;
562
+ void *user_data = ( void * ) 0xABCDEF;
563
+
564
+ struct expected_data {
565
+ management_application_request mgmt;
566
+ event_forward_operation_request efi;
567
+ } __attribute__( ( packed ) ) expected_data = {
568
+ .mgmt = {
569
+ .header = {
570
+ .type = htons( MANAGEMENT_APPLICATION_REQUEST ),
571
+ .length = htonl( sizeof( struct expected_data ) ),
572
+ },
573
+ .application_id = htonl( EVENT_FORWARD_ENTRY_DUMP ),
574
+ },
575
+ .efi = {
576
+ .type = EVENT_FORWARD_TYPE_STATE_NOTIFY,
577
+ .n_services = htonl( 0 ),
578
+ },
579
+ };
580
+
581
+ expect_string( mock_send_request_message, to_service_name, "switch_manager.m" );
582
+ expect_string( mock_send_request_message, from_service_name, "tetris-efic-1234" );
583
+ expect_value( mock_send_request_message, tag32, MESSENGER_MANAGEMENT_REQUEST );
584
+ expect_memory( mock_send_request_message, data, &expected_data, sizeof( struct expected_data ) );
585
+ expect_value( mock_send_request_message, len, sizeof( struct expected_data ) );
586
+ expect_value( mock_send_request_message, hd->callback, callback );
587
+ expect_value( mock_send_request_message, hd->user_data, user_data );
588
+ will_return( mock_send_request_message, true );
589
+
590
+ assert_true( dump_switch_manager_event_forward_entries( EVENT_FORWARD_TYPE_STATE_NOTIFY, callback, user_data ) );
591
+ }
592
+
593
+
594
+ /********************************************************************************
595
+ * set_switch_event_forward_entries() tests.
596
+ ********************************************************************************/
597
+
598
+ static void
599
+ test_set_switch_event_forward_entries_succeeds() {
600
+ list_element *head;
601
+ char alpha[] = "alpha";
602
+ char bravo[] = "bravo";
603
+ create_list( &head );
604
+ append_to_tail( &head, alpha );
605
+ append_to_tail( &head, bravo );
606
+
607
+ event_forward_entry_operation_callback callback = ( event_forward_entry_operation_callback ) 0x12345678;
608
+ void *user_data = ( void * ) 0xABCDEF;
609
+
610
+ struct expected_data {
611
+ management_application_request mgmt;
612
+ event_forward_operation_request efi;
613
+ char alpha[ 6 ];
614
+ char bravo[ 6 ];
615
+ } __attribute__( ( packed ) ) expected_data = {
616
+ .mgmt = {
617
+ .header = {
618
+ .type = htons( MANAGEMENT_APPLICATION_REQUEST ),
619
+ .length = htonl( sizeof( struct expected_data ) ),
620
+ },
621
+ .application_id = htonl( EVENT_FORWARD_ENTRY_SET ),
622
+ },
623
+ .efi = {
624
+ .type = EVENT_FORWARD_TYPE_VENDOR,
625
+ .n_services = htonl( 2 ),
626
+ },
627
+ .alpha = "alpha",
628
+ .bravo = "bravo",
629
+ };
630
+
631
+ expect_string( mock_send_request_message, to_service_name, "switch.0xabc.m" );
632
+ expect_string( mock_send_request_message, from_service_name, "tetris-efic-1234" );
633
+ expect_value( mock_send_request_message, tag32, MESSENGER_MANAGEMENT_REQUEST );
634
+ expect_memory( mock_send_request_message, data, &expected_data, sizeof( struct expected_data ) );
635
+ expect_value( mock_send_request_message, len, sizeof( struct expected_data ) );
636
+ expect_value( mock_send_request_message, hd->callback, callback );
637
+ expect_value( mock_send_request_message, hd->user_data, user_data );
638
+ will_return( mock_send_request_message, true );
639
+
640
+ assert_true( set_switch_event_forward_entries( 0xabc, EVENT_FORWARD_TYPE_VENDOR, head, callback, user_data ) );
641
+
642
+ delete_list( head );
643
+ }
644
+
645
+
646
+ /********************************************************************************
647
+ * add_switch_event_forward_entry() tests.
648
+ ********************************************************************************/
649
+
650
+ static void
651
+ test_add_switch_event_forward_entry_succeeds() {
652
+
653
+ event_forward_entry_operation_callback callback = ( event_forward_entry_operation_callback ) 0x12345678;
654
+ void *user_data = ( void * ) 0xABCDEF;
655
+
656
+ struct expected_data {
657
+ management_application_request mgmt;
658
+ event_forward_operation_request efi;
659
+ char alpha[ 6 ];
660
+ } __attribute__( ( packed ) ) expected_data = {
661
+ .mgmt = {
662
+ .header = {
663
+ .type = htons( MANAGEMENT_APPLICATION_REQUEST ),
664
+ .length = htonl( sizeof( struct expected_data ) ),
665
+ },
666
+ .application_id = htonl( EVENT_FORWARD_ENTRY_ADD ),
667
+ },
668
+ .efi = {
669
+ .type = EVENT_FORWARD_TYPE_PACKET_IN,
670
+ .n_services = htonl( 1 ),
671
+ },
672
+ .alpha = "alpha",
673
+ };
674
+
675
+ expect_string( mock_send_request_message, to_service_name, "switch.0xabc.m" );
676
+ expect_string( mock_send_request_message, from_service_name, "tetris-efic-1234" );
677
+ expect_value( mock_send_request_message, tag32, MESSENGER_MANAGEMENT_REQUEST );
678
+ expect_memory( mock_send_request_message, data, &expected_data, sizeof( struct expected_data ) );
679
+ expect_value( mock_send_request_message, len, sizeof( struct expected_data ) );
680
+ expect_value( mock_send_request_message, hd->callback, callback );
681
+ expect_value( mock_send_request_message, hd->user_data, user_data );
682
+ will_return( mock_send_request_message, true );
683
+
684
+ assert_true( add_switch_event_forward_entry( 0xabc, EVENT_FORWARD_TYPE_PACKET_IN, "alpha", callback, user_data ) );
685
+ }
686
+
687
+
688
+ /********************************************************************************
689
+ * delete_switch_event_forward_entry() tests.
690
+ ********************************************************************************/
691
+
692
+ static void
693
+ test_delete_switch_event_forward_entry_succeeds() {
694
+
695
+ event_forward_entry_operation_callback callback = ( event_forward_entry_operation_callback ) 0x12345678;
696
+ void *user_data = ( void * ) 0xABCDEF;
697
+
698
+ struct expected_data {
699
+ management_application_request mgmt;
700
+ event_forward_operation_request efi;
701
+ char alpha[ 6 ];
702
+ } __attribute__( ( packed ) ) expected_data = {
703
+ .mgmt = {
704
+ .header = {
705
+ .type = htons( MANAGEMENT_APPLICATION_REQUEST ),
706
+ .length = htonl( sizeof( struct expected_data ) ),
707
+ },
708
+ .application_id = htonl( EVENT_FORWARD_ENTRY_DELETE ),
709
+ },
710
+ .efi = {
711
+ .type = EVENT_FORWARD_TYPE_PORT_STATUS,
712
+ .n_services = htonl( 1 ),
713
+ },
714
+ .alpha = "alpha",
715
+ };
716
+
717
+ expect_string( mock_send_request_message, to_service_name, "switch.0xabc.m" );
718
+ expect_string( mock_send_request_message, from_service_name, "tetris-efic-1234" );
719
+ expect_value( mock_send_request_message, tag32, MESSENGER_MANAGEMENT_REQUEST );
720
+ expect_memory( mock_send_request_message, data, &expected_data, sizeof( struct expected_data ) );
721
+ expect_value( mock_send_request_message, len, sizeof( struct expected_data ) );
722
+ expect_value( mock_send_request_message, hd->callback, callback );
723
+ expect_value( mock_send_request_message, hd->user_data, user_data );
724
+ will_return( mock_send_request_message, true );
725
+
726
+ assert_true( delete_switch_event_forward_entry( 0xabc, EVENT_FORWARD_TYPE_PORT_STATUS, "alpha", callback, user_data ) );
727
+ }
728
+
729
+
730
+ /********************************************************************************
731
+ * dump_switch_event_forward_entries() tests.
732
+ ********************************************************************************/
733
+
734
+ static void
735
+ test_dump_switch_event_forward_entries_succeeds() {
736
+
737
+ event_forward_entry_operation_callback callback = ( event_forward_entry_operation_callback ) 0x12345678;
738
+ void *user_data = ( void * ) 0xABCDEF;
739
+
740
+ struct expected_data {
741
+ management_application_request mgmt;
742
+ event_forward_operation_request efi;
743
+ } __attribute__( ( packed ) ) expected_data = {
744
+ .mgmt = {
745
+ .header = {
746
+ .type = htons( MANAGEMENT_APPLICATION_REQUEST ),
747
+ .length = htonl( sizeof( struct expected_data ) ),
748
+ },
749
+ .application_id = htonl( EVENT_FORWARD_ENTRY_DUMP ),
750
+ },
751
+ .efi = {
752
+ .type = EVENT_FORWARD_TYPE_STATE_NOTIFY,
753
+ .n_services = htonl( 0 ),
754
+ },
755
+ };
756
+
757
+ expect_string( mock_send_request_message, to_service_name, "switch.0xabc.m" );
758
+ expect_string( mock_send_request_message, from_service_name, "tetris-efic-1234" );
759
+ expect_value( mock_send_request_message, tag32, MESSENGER_MANAGEMENT_REQUEST );
760
+ expect_memory( mock_send_request_message, data, &expected_data, sizeof( struct expected_data ) );
761
+ expect_value( mock_send_request_message, len, sizeof( struct expected_data ) );
762
+ expect_value( mock_send_request_message, hd->callback, callback );
763
+ expect_value( mock_send_request_message, hd->user_data, user_data );
764
+ will_return( mock_send_request_message, true );
765
+
766
+ assert_true( dump_switch_event_forward_entries( 0xabc, EVENT_FORWARD_TYPE_STATE_NOTIFY, callback, user_data ) );
767
+ }
768
+
769
+
770
+ /********************************************************************************
771
+ * handle_efi_reply() tests.
772
+ ********************************************************************************/
773
+
774
+ static void
775
+ test_handle_efi_reply_succeeds_with_success_reply() {
776
+
777
+ struct input_data {
778
+ management_application_reply mgmt;
779
+ event_forward_operation_reply efi;
780
+ char alpha[ 6 ];
781
+ char bravo[ 6 ];
782
+ } __attribute__( ( packed ) ) input_data = {
783
+ .mgmt = {
784
+ .header = {
785
+ .type = htons( MANAGEMENT_APPLICATION_REPLY ),
786
+ .status = MANAGEMENT_REQUEST_SUCCEEDED,
787
+ .length = htonl( sizeof( struct input_data ) ),
788
+ },
789
+ .application_id = htonl( EVENT_FORWARD_ENTRY_SET ),
790
+ },
791
+ .efi = {
792
+ .type = EVENT_FORWARD_TYPE_VENDOR,
793
+ .result = EFI_OPERATION_SUCCEEDED,
794
+ .n_services = htonl( 2 ),
795
+ },
796
+ .alpha = "alpha",
797
+ .bravo = "bravo"
798
+ };
799
+
800
+ struct callback_info *user_data = xcalloc( 1, sizeof( struct callback_info ) );
801
+ user_data->callback = mock_event_forward_entry_operation_callback;
802
+ user_data->user_data = ( void * ) 0x12345678;
803
+
804
+ expect_value( mock_event_forward_entry_operation_callback, result.result, EFI_OPERATION_SUCCEEDED );
805
+ expect_value( mock_event_forward_entry_operation_callback, result.n_services, 2 );
806
+ expect_string( mock_event_forward_entry_operation_callback, service, "alpha" );
807
+ expect_string( mock_event_forward_entry_operation_callback, service, "bravo" );
808
+ expect_value( mock_event_forward_entry_operation_callback, user_data, 0x12345678 );
809
+
810
+ handle_efi_reply( MESSENGER_MANAGEMENT_REPLY, &input_data, sizeof( struct input_data ), user_data );
811
+ }
812
+
813
+
814
+ static void
815
+ test_handle_efi_reply_succeeds_with_event_forward_entry_operation_failure_reply() {
816
+
817
+ struct input_data {
818
+ management_application_reply mgmt;
819
+ event_forward_operation_reply efi;
820
+ } __attribute__( ( packed ) ) input_data = {
821
+ .mgmt = {
822
+ .header = {
823
+ .type = htons( MANAGEMENT_APPLICATION_REPLY ),
824
+ .status = MANAGEMENT_REQUEST_SUCCEEDED,
825
+ .length = htonl( sizeof( struct input_data ) ),
826
+ },
827
+ .application_id = htonl( EVENT_FORWARD_ENTRY_SET ),
828
+ },
829
+ .efi = {
830
+ .type = EVENT_FORWARD_TYPE_VENDOR,
831
+ .result = EFI_OPERATION_FAILED,
832
+ .n_services = htonl( 0 ),
833
+ },
834
+ };
835
+
836
+ struct callback_info *user_data = xcalloc( 1, sizeof( struct callback_info ) );
837
+ user_data->callback = mock_event_forward_entry_operation_callback;
838
+ user_data->user_data = ( void * ) 0x12345678;
839
+
840
+ expect_value( mock_event_forward_entry_operation_callback, result.result, EFI_OPERATION_FAILED );
841
+ expect_value( mock_event_forward_entry_operation_callback, result.n_services, 0 );
842
+ expect_value( mock_event_forward_entry_operation_callback, user_data, 0x12345678 );
843
+
844
+ handle_efi_reply( MESSENGER_MANAGEMENT_REPLY, &input_data, sizeof( struct input_data ), user_data );
845
+ }
846
+
847
+
848
+ static void
849
+ test_handle_efi_reply_succeeds_with_management_failure_reply() {
850
+
851
+ struct input_data {
852
+ management_application_reply mgmt;
853
+ event_forward_operation_reply efi;
854
+ } __attribute__( ( packed ) ) input_data = {
855
+ .mgmt = {
856
+ .header = {
857
+ .type = htons( MANAGEMENT_APPLICATION_REPLY ),
858
+ .status = MANAGEMENT_REQUEST_FAILED,
859
+ .length = htonl( sizeof( struct input_data ) ),
860
+ },
861
+ .application_id = htonl( EVENT_FORWARD_ENTRY_SET ),
862
+ },
863
+ .efi = {
864
+ .type = EVENT_FORWARD_TYPE_VENDOR,
865
+ .result = EFI_OPERATION_FAILED,
866
+ .n_services = htonl( 0 ),
867
+ },
868
+ };
869
+
870
+ struct callback_info *user_data = xcalloc( 1, sizeof( struct callback_info ) );
871
+ user_data->callback = mock_event_forward_entry_operation_callback;
872
+ user_data->user_data = ( void * ) 0x12345678;
873
+
874
+ expect_string( mock_warn, message, "Management request failed." );
875
+
876
+ expect_value( mock_event_forward_entry_operation_callback, result.result, EFI_OPERATION_FAILED );
877
+ expect_value( mock_event_forward_entry_operation_callback, result.n_services, 0 );
878
+ expect_value( mock_event_forward_entry_operation_callback, user_data, 0x12345678 );
879
+
880
+ handle_efi_reply( MESSENGER_MANAGEMENT_REPLY, &input_data, sizeof( struct input_data ), user_data );
881
+ }
882
+
883
+
884
+ static void
885
+ test_handle_efi_reply_ignores_wrong_message_tag_reply() {
886
+
887
+ struct input_data {
888
+ management_application_reply mgmt;
889
+ } __attribute__( ( packed ) ) input_data = {
890
+ .mgmt = {
891
+ .header = {
892
+ .type = htons( MANAGEMENT_APPLICATION_REPLY ),
893
+ .status = MANAGEMENT_REQUEST_FAILED,
894
+ .length = htonl( sizeof( struct input_data ) ),
895
+ },
896
+ .application_id = htonl( EVENT_FORWARD_ENTRY_SET ),
897
+ },
898
+ };
899
+
900
+ struct callback_info *user_data = xcalloc( 1, sizeof( struct callback_info ) );
901
+ user_data->callback = mock_event_forward_entry_operation_callback;
902
+ user_data->user_data = ( void * ) 0x12345678;
903
+
904
+ expect_string( mock_error, message, "Unexpected message received tag=0x1234" );
905
+
906
+ handle_efi_reply( 0x1234, &input_data, sizeof( struct input_data ), user_data );
907
+ xfree( user_data );
908
+ }
909
+
910
+
911
+ static void
912
+ test_handle_efi_reply_ignores_wrong_message_length_reply() {
913
+
914
+ struct input_data {
915
+ management_application_reply mgmt;
916
+ } __attribute__( ( packed ) ) input_data = {
917
+ .mgmt = {
918
+ .header = {
919
+ .type = htons( MANAGEMENT_APPLICATION_REPLY ),
920
+ .status = MANAGEMENT_REQUEST_FAILED,
921
+ .length = htonl( sizeof( struct input_data ) ),
922
+ },
923
+ .application_id = htonl( EVENT_FORWARD_ENTRY_SET ),
924
+ },
925
+ };
926
+
927
+ struct callback_info *user_data = xcalloc( 1, sizeof( struct callback_info ) );
928
+ user_data->callback = mock_event_forward_entry_operation_callback;
929
+ user_data->user_data = ( void * ) 0x12345678;
930
+
931
+ expect_string( mock_error, message, "Data length too short 11. expecting >= 12" );
932
+
933
+ handle_efi_reply( MESSENGER_MANAGEMENT_REPLY, &input_data, sizeof( struct input_data )-1, user_data );
934
+ xfree( user_data );
935
+ }
936
+
937
+
938
+ static void
939
+ test_handle_efi_reply_ignores_empty_reply() {
940
+
941
+ struct callback_info *user_data = xcalloc( 1, sizeof( struct callback_info ) );
942
+ user_data->callback = mock_event_forward_entry_operation_callback;
943
+ user_data->user_data = ( void * ) 0x12345678;
944
+
945
+ expect_any( mock_error, message );
946
+
947
+ handle_efi_reply( MESSENGER_MANAGEMENT_REPLY, NULL, 0, user_data );
948
+ xfree( user_data );
949
+ }
950
+
951
+
952
+ static void
953
+ test_handle_efi_reply_ignores_wrong_event_forward_operation_command_reply() {
954
+
955
+ struct input_data {
956
+ management_application_reply mgmt;
957
+ event_forward_operation_reply efi;
958
+ } __attribute__( ( packed ) ) input_data = {
959
+ .mgmt = {
960
+ .header = {
961
+ .type = htons( MANAGEMENT_APPLICATION_REPLY ),
962
+ .status = MANAGEMENT_REQUEST_SUCCEEDED,
963
+ .length = htonl( sizeof( struct input_data ) ),
964
+ },
965
+ .application_id = htonl( 0x1234 ),
966
+ },
967
+ .efi = {
968
+ .type = EVENT_FORWARD_TYPE_VENDOR,
969
+ .result = EFI_OPERATION_FAILED,
970
+ .n_services = htonl( 0 ),
971
+ },
972
+ };
973
+
974
+ struct callback_info *user_data = xcalloc( 1, sizeof( struct callback_info ) );
975
+ user_data->callback = mock_event_forward_entry_operation_callback;
976
+ user_data->user_data = ( void * ) 0x12345678;
977
+
978
+ expect_string( mock_warn, message, "Invalid command/application_id: 0x1234" );
979
+
980
+ handle_efi_reply( MESSENGER_MANAGEMENT_REPLY, &input_data, sizeof( struct input_data ), user_data );
981
+ xfree( user_data );
982
+ }
983
+
984
+
985
+ static void
986
+ test_handle_efi_reply_succeeds_with_wrong_event_forward_operation_result_reply() {
987
+
988
+ struct input_data {
989
+ management_application_reply mgmt;
990
+ event_forward_operation_reply efi;
991
+ } __attribute__( ( packed ) ) input_data = {
992
+ .mgmt = {
993
+ .header = {
994
+ .type = htons( MANAGEMENT_APPLICATION_REPLY ),
995
+ .status = MANAGEMENT_REQUEST_SUCCEEDED,
996
+ .length = htonl( sizeof( struct input_data ) ),
997
+ },
998
+ .application_id = htonl( EVENT_FORWARD_ENTRY_ADD ),
999
+ },
1000
+ .efi = {
1001
+ .type = EVENT_FORWARD_TYPE_VENDOR,
1002
+ .result = 0xFF,
1003
+ .n_services = htonl( 0 ),
1004
+ },
1005
+ };
1006
+
1007
+ struct callback_info *user_data = xcalloc( 1, sizeof( struct callback_info ) );
1008
+ user_data->callback = mock_event_forward_entry_operation_callback;
1009
+ user_data->user_data = ( void * ) 0x12345678;
1010
+
1011
+ expect_string( mock_warn, message, "Unknown result type 0xff. Translating as FAILED." );
1012
+
1013
+ expect_value( mock_event_forward_entry_operation_callback, result.result, EFI_OPERATION_FAILED );
1014
+ expect_value( mock_event_forward_entry_operation_callback, result.n_services, 0 );
1015
+ expect_value( mock_event_forward_entry_operation_callback, user_data, 0x12345678 );
1016
+
1017
+ handle_efi_reply( MESSENGER_MANAGEMENT_REPLY, &input_data, sizeof( struct input_data ), user_data );
1018
+ }
1019
+
1020
+
1021
+ static void
1022
+ test_handle_efi_reply_succeeds_with_more_service_found_then_expected_reply() {
1023
+
1024
+ struct input_data {
1025
+ management_application_reply mgmt;
1026
+ event_forward_operation_reply efi;
1027
+ char alpha[ 6 ];
1028
+ char bravo[ 6 ];
1029
+ } __attribute__( ( packed ) ) input_data = {
1030
+ .mgmt = {
1031
+ .header = {
1032
+ .type = htons( MANAGEMENT_APPLICATION_REPLY ),
1033
+ .status = MANAGEMENT_REQUEST_SUCCEEDED,
1034
+ .length = htonl( sizeof( struct input_data ) ),
1035
+ },
1036
+ .application_id = htonl( EVENT_FORWARD_ENTRY_ADD ),
1037
+ },
1038
+ .efi = {
1039
+ .type = EVENT_FORWARD_TYPE_VENDOR,
1040
+ .result = EFI_OPERATION_SUCCEEDED,
1041
+ .n_services = htonl( 1 ),
1042
+ },
1043
+ .alpha = "alpha",
1044
+ .bravo = "bravo"
1045
+ };
1046
+
1047
+ struct callback_info *user_data = xcalloc( 1, sizeof( struct callback_info ) );
1048
+ user_data->callback = mock_event_forward_entry_operation_callback;
1049
+ user_data->user_data = ( void * ) 0x12345678;
1050
+
1051
+ expect_string( mock_warn, message, "Expected 1 name(s), but found more service name. Ignoring 'bravo'." );
1052
+
1053
+ expect_value( mock_event_forward_entry_operation_callback, result.result, EFI_OPERATION_SUCCEEDED );
1054
+ expect_value( mock_event_forward_entry_operation_callback, result.n_services, 1 );
1055
+ expect_string( mock_event_forward_entry_operation_callback, service, "alpha" );
1056
+ expect_value( mock_event_forward_entry_operation_callback, user_data, 0x12345678 );
1057
+
1058
+ handle_efi_reply( MESSENGER_MANAGEMENT_REPLY, &input_data, sizeof( struct input_data ), user_data );
1059
+ }
1060
+
1061
+
1062
+ static void
1063
+ test_handle_efi_reply_succeeds_with_empty_service_name_reply() {
1064
+
1065
+ struct input_data {
1066
+ management_application_reply mgmt;
1067
+ event_forward_operation_reply efi;
1068
+ char alpha[ 6 ];
1069
+ char bravo[ 1 ];
1070
+ } __attribute__( ( packed ) ) input_data = {
1071
+ .mgmt = {
1072
+ .header = {
1073
+ .type = htons( MANAGEMENT_APPLICATION_REPLY ),
1074
+ .status = MANAGEMENT_REQUEST_SUCCEEDED,
1075
+ .length = htonl( sizeof( struct input_data ) ),
1076
+ },
1077
+ .application_id = htonl( EVENT_FORWARD_ENTRY_ADD ),
1078
+ },
1079
+ .efi = {
1080
+ .type = EVENT_FORWARD_TYPE_VENDOR,
1081
+ .result = EFI_OPERATION_SUCCEEDED,
1082
+ .n_services = htonl( 2 ),
1083
+ },
1084
+ .alpha = "alpha",
1085
+ .bravo = ""
1086
+ };
1087
+
1088
+ struct callback_info *user_data = xcalloc( 1, sizeof( struct callback_info ) );
1089
+ user_data->callback = mock_event_forward_entry_operation_callback;
1090
+ user_data->user_data = ( void * ) 0x12345678;
1091
+
1092
+ expect_string( mock_warn, message, "Encountered empty service name." );
1093
+
1094
+ expect_value( mock_event_forward_entry_operation_callback, result.result, EFI_OPERATION_SUCCEEDED );
1095
+ expect_value( mock_event_forward_entry_operation_callback, result.n_services, 1 );
1096
+ expect_string( mock_event_forward_entry_operation_callback, service, "alpha" );
1097
+ expect_value( mock_event_forward_entry_operation_callback, user_data, 0x12345678 );
1098
+
1099
+ handle_efi_reply( MESSENGER_MANAGEMENT_REPLY, &input_data, sizeof( struct input_data ), user_data );
1100
+ }
1101
+
1102
+
1103
+ /********************************************************************************
1104
+ * create_event_forward_op_reply() tests.
1105
+ ********************************************************************************/
1106
+
1107
+ static void
1108
+ test_create_event_forward_operation_reply_with_null_service_list() {
1109
+ struct expected_data {
1110
+ event_forward_operation_reply efi;
1111
+ } __attribute__( ( packed ) ) expected_data = {
1112
+ .efi = {
1113
+ .type = EVENT_FORWARD_TYPE_PACKET_IN,
1114
+ .result = EFI_OPERATION_SUCCEEDED,
1115
+ .n_services = 0
1116
+ }
1117
+ };
1118
+ buffer *buf = create_event_forward_operation_reply( EVENT_FORWARD_TYPE_PACKET_IN, EFI_OPERATION_SUCCEEDED, NULL );
1119
+
1120
+ assert_memory_equal( buf->data, &expected_data, sizeof( struct expected_data ) );
1121
+ free_buffer( buf );
1122
+ }
1123
+
1124
+
1125
+ static void
1126
+ test_create_event_forward_operation_reply_with_empty_service_list() {
1127
+ struct expected_data {
1128
+ event_forward_operation_reply efi;
1129
+ } __attribute__( ( packed ) ) expected_data = {
1130
+ .efi = {
1131
+ .type = EVENT_FORWARD_TYPE_PACKET_IN,
1132
+ .result = EFI_OPERATION_SUCCEEDED,
1133
+ .n_services = 0
1134
+ }
1135
+ };
1136
+ list_element *head;
1137
+ create_list( &head );
1138
+ buffer *buf = create_event_forward_operation_reply( EVENT_FORWARD_TYPE_PACKET_IN, EFI_OPERATION_SUCCEEDED, head );
1139
+
1140
+ assert_memory_equal( buf->data, &expected_data, sizeof( struct expected_data ) );
1141
+ free_buffer( buf );
1142
+ delete_list( head );
1143
+ }
1144
+
1145
+
1146
+ static void
1147
+ test_create_event_forward_operation_reply_with_one_service_list() {
1148
+ char alpha[] = "alpha";
1149
+ struct expected_data {
1150
+ event_forward_operation_reply efi;
1151
+ const char service[ 6 ];
1152
+ } __attribute__( ( packed ) ) expected_data = {
1153
+ .efi = {
1154
+ .type = EVENT_FORWARD_TYPE_PACKET_IN,
1155
+ .result = EFI_OPERATION_SUCCEEDED,
1156
+ .n_services = htonl( 1 )
1157
+ },
1158
+ .service = "alpha"
1159
+ };
1160
+ list_element *head;
1161
+ create_list( &head );
1162
+ append_to_tail( &head, alpha );
1163
+ buffer *buf = create_event_forward_operation_reply( EVENT_FORWARD_TYPE_PACKET_IN, EFI_OPERATION_SUCCEEDED, head );
1164
+
1165
+ assert_memory_equal( buf->data, &expected_data, sizeof( struct expected_data ) );
1166
+ free_buffer( buf );
1167
+ delete_list( head );
1168
+ }
1169
+
1170
+
1171
+ static void
1172
+ test_create_event_forward_operation_reply_with_multi_service_list() {
1173
+ char alpha[] = "alpha-12345678901234567890";
1174
+ char bravo[] = "bravo-12345678901234567890";
1175
+ char charlie[] = "charlie-12345678901234567890";
1176
+ struct expected_data {
1177
+ event_forward_operation_reply efi;
1178
+ const char alpha[ 6 + 21 ];
1179
+ const char bravo[ 6 + 21 ];
1180
+ const char charlie[ 8 + 21 ];
1181
+ } __attribute__( ( packed ) ) expected_data = {
1182
+ .efi = {
1183
+ .type = EVENT_FORWARD_TYPE_PACKET_IN,
1184
+ .result = EFI_OPERATION_SUCCEEDED,
1185
+ .n_services = htonl( 3 )
1186
+ },
1187
+ .alpha = "alpha-12345678901234567890",
1188
+ .bravo = "bravo-12345678901234567890",
1189
+ .charlie = "charlie-12345678901234567890"
1190
+ };
1191
+ list_element *head;
1192
+ create_list( &head );
1193
+ append_to_tail( &head, alpha );
1194
+ append_to_tail( &head, bravo );
1195
+ append_to_tail( &head, charlie );
1196
+ buffer *buf = create_event_forward_operation_reply( EVENT_FORWARD_TYPE_PACKET_IN, EFI_OPERATION_SUCCEEDED, head );
1197
+
1198
+ assert_memory_equal( buf->data, &expected_data, sizeof( struct expected_data ) );
1199
+ free_buffer( buf );
1200
+ delete_list( head );
1201
+ }
1202
+
1203
+
1204
+ /********************************************************************************
1205
+ * send_efi_switch_list_request() tests.
1206
+ ********************************************************************************/
1207
+
1208
+ static void
1209
+ test_send_efi_switch_list_request_succeeds() {
1210
+
1211
+ switch_list_request_callback callback = ( switch_list_request_callback ) 0x12345678;
1212
+ void *user_data = ( void * ) 0xABCDEF;
1213
+
1214
+ struct expected_data {
1215
+ management_application_request mgmt;
1216
+ } __attribute__( ( packed ) ) expected_data = {
1217
+ .mgmt = {
1218
+ .header = {
1219
+ .type = htons( MANAGEMENT_APPLICATION_REQUEST ),
1220
+ .length = htonl( sizeof( struct expected_data ) ),
1221
+ },
1222
+ .application_id = htonl( EFI_GET_SWLIST ),
1223
+ },
1224
+ };
1225
+
1226
+ expect_string( mock_send_request_message, to_service_name, "switch_manager.m" );
1227
+ expect_string( mock_send_request_message, from_service_name, "tetris-efic-1234" );
1228
+ expect_value( mock_send_request_message, tag32, MESSENGER_MANAGEMENT_REQUEST );
1229
+ expect_memory( mock_send_request_message, data, &expected_data, sizeof( struct expected_data ) );
1230
+ expect_value( mock_send_request_message, len, sizeof( struct expected_data ) );
1231
+ expect_value( mock_send_request_message, hd->callback, callback );
1232
+ expect_value( mock_send_request_message, hd->user_data, user_data );
1233
+ will_return( mock_send_request_message, true );
1234
+
1235
+ assert_true( send_efi_switch_list_request( callback, user_data ) );
1236
+ }
1237
+
1238
+
1239
+ static void
1240
+ test_handle_efi_reply_succeeds_with_switch_list_reply() {
1241
+
1242
+ const uint64_t dpids_host[] = { 0x12345678, 0xabcdef00 };
1243
+ struct input_data {
1244
+ management_application_reply mgmt;
1245
+ uint64_t dpids[ 2 ];
1246
+ } __attribute__( ( packed ) ) input_data = {
1247
+ .mgmt = {
1248
+ .header = {
1249
+ .type = htons( MANAGEMENT_APPLICATION_REPLY ),
1250
+ .status = MANAGEMENT_REQUEST_SUCCEEDED,
1251
+ .length = htonl( sizeof( struct input_data ) ),
1252
+ },
1253
+ .application_id = htonl( EFI_GET_SWLIST ),
1254
+ },
1255
+ .dpids = {
1256
+ htonll( dpids_host[ 0 ] ),
1257
+ htonll( dpids_host[ 1 ] )
1258
+ }
1259
+ };
1260
+
1261
+ struct callback_info *user_data = xcalloc( 1, sizeof( struct callback_info ) );
1262
+ user_data->callback = mock_switch_list_request_callback;
1263
+ user_data->user_data = ( void * ) 0x12345678;
1264
+
1265
+ expect_value( mock_switch_list_request_callback, n_dpids, 2 );
1266
+ expect_memory( mock_switch_list_request_callback, dpids, dpids_host, 2 * sizeof( uint64_t ) );
1267
+ expect_value( mock_switch_list_request_callback, user_data, 0x12345678 );
1268
+
1269
+ handle_efi_reply( MESSENGER_MANAGEMENT_REPLY, &input_data, sizeof( struct input_data ), user_data );
1270
+ }
1271
+
1272
+
1273
+ static void
1274
+ test_handle_efi_reply_succeeds_with_management_failure_on_switch_list_reply() {
1275
+
1276
+ struct input_data {
1277
+ management_application_reply mgmt;
1278
+ } __attribute__( ( packed ) ) input_data = {
1279
+ .mgmt = {
1280
+ .header = {
1281
+ .type = htons( MANAGEMENT_APPLICATION_REPLY ),
1282
+ .status = MANAGEMENT_REQUEST_FAILED,
1283
+ .length = htonl( sizeof( struct input_data ) ),
1284
+ },
1285
+ .application_id = htonl( EFI_GET_SWLIST ),
1286
+ },
1287
+ };
1288
+
1289
+ struct callback_info *user_data = xcalloc( 1, sizeof( struct callback_info ) );
1290
+ user_data->callback = mock_switch_list_request_callback;
1291
+ user_data->user_data = ( void * ) 0x12345678;
1292
+
1293
+ expect_string( mock_warn, message, "Management request failed." );
1294
+
1295
+ expect_value( mock_switch_list_request_callback, n_dpids, 0 );
1296
+ expect_value( mock_switch_list_request_callback, dpids, NULL );
1297
+ expect_value( mock_switch_list_request_callback, user_data, 0x12345678 );
1298
+
1299
+ handle_efi_reply( MESSENGER_MANAGEMENT_REPLY, &input_data, sizeof( struct input_data ), user_data );
1300
+ }
1301
+
1302
+
1303
+ /********************************************************************************
1304
+ * add_event_forward_to_all_switches() tests.
1305
+ ********************************************************************************/
1306
+
1307
+
1308
+ static void
1309
+ test_add_event_forward_entry_to_all_switches_succeeds() {
1310
+
1311
+ event_forward_entry_to_all_callback callback = ( event_forward_entry_to_all_callback ) 0x12345678;
1312
+ void *user_data = ( void * ) 0xABCDEF;
1313
+
1314
+ struct expected_data {
1315
+ management_application_request mgmt;
1316
+ event_forward_operation_request efi;
1317
+ char alpha[ 6 ];
1318
+ } __attribute__( ( packed ) ) expected_data = {
1319
+ .mgmt = {
1320
+ .header = {
1321
+ .type = htons( MANAGEMENT_APPLICATION_REQUEST ),
1322
+ .length = htonl( sizeof( struct expected_data ) ),
1323
+ },
1324
+ .application_id = htonl( EVENT_FORWARD_ENTRY_ADD ),
1325
+ },
1326
+ .efi = {
1327
+ .type = EVENT_FORWARD_TYPE_PACKET_IN,
1328
+ .n_services = htonl( 1 ),
1329
+ },
1330
+ .alpha = "alpha",
1331
+ };
1332
+
1333
+ expect_string( mock_send_request_message, to_service_name, "switch_manager.m" );
1334
+ expect_string( mock_send_request_message, from_service_name, "tetris-efic-1234" );
1335
+ expect_value( mock_send_request_message, tag32, MESSENGER_MANAGEMENT_REQUEST );
1336
+ expect_memory( mock_send_request_message, data, &expected_data, sizeof( struct expected_data ) );
1337
+ expect_value( mock_send_request_message, len, sizeof( struct expected_data ) );
1338
+ expect_value( mock_send_request_message, hd->callback, _get_switch_list_after_swm_succ );
1339
+ expect_any( mock_send_request_message, hd->user_data );
1340
+
1341
+ // using send fail pattern to avoid all_request_param leak warning
1342
+ will_return( mock_send_request_message, false );
1343
+ assert_false( add_event_forward_entry_to_all_switches( EVENT_FORWARD_TYPE_PACKET_IN, "alpha", callback, user_data ) );
1344
+ }
1345
+
1346
+
1347
+ static void
1348
+ test_delete_event_forward_entry_to_all_switches_succeeds() {
1349
+
1350
+ event_forward_entry_to_all_callback callback = ( event_forward_entry_to_all_callback ) 0x12345678;
1351
+ void *user_data = ( void * ) 0xABCDEF;
1352
+
1353
+ struct expected_data {
1354
+ management_application_request mgmt;
1355
+ event_forward_operation_request efi;
1356
+ char alpha[ 6 ];
1357
+ } __attribute__( ( packed ) ) expected_data = {
1358
+ .mgmt = {
1359
+ .header = {
1360
+ .type = htons( MANAGEMENT_APPLICATION_REQUEST ),
1361
+ .length = htonl( sizeof( struct expected_data ) ),
1362
+ },
1363
+ .application_id = htonl( EVENT_FORWARD_ENTRY_DELETE ),
1364
+ },
1365
+ .efi = {
1366
+ .type = EVENT_FORWARD_TYPE_PACKET_IN,
1367
+ .n_services = htonl( 1 ),
1368
+ },
1369
+ .alpha = "alpha",
1370
+ };
1371
+
1372
+ expect_string( mock_send_request_message, to_service_name, "switch_manager.m" );
1373
+ expect_string( mock_send_request_message, from_service_name, "tetris-efic-1234" );
1374
+ expect_value( mock_send_request_message, tag32, MESSENGER_MANAGEMENT_REQUEST );
1375
+ expect_memory( mock_send_request_message, data, &expected_data, sizeof( struct expected_data ) );
1376
+ expect_value( mock_send_request_message, len, sizeof( struct expected_data ) );
1377
+ expect_value( mock_send_request_message, hd->callback, _get_switch_list_after_swm_succ );
1378
+ expect_any( mock_send_request_message, hd->user_data );
1379
+
1380
+ // using send fail pattern to avoid all_request_param leak warning
1381
+ will_return( mock_send_request_message, false );
1382
+ assert_false( delete_event_forward_entry_to_all_switches( EVENT_FORWARD_TYPE_PACKET_IN, "alpha", callback, user_data ) );
1383
+ }
1384
+
1385
+
1386
+ static void
1387
+ test__get_switch_list_after_swm_succ_succeeds() {
1388
+
1389
+ void *user_data = ( void * ) 0xABCDEF;
1390
+
1391
+ struct expected_data {
1392
+ management_application_request mgmt;
1393
+ } __attribute__( ( packed ) ) expected_data = {
1394
+ .mgmt = {
1395
+ .header = {
1396
+ .type = htons( MANAGEMENT_APPLICATION_REQUEST ),
1397
+ .length = htonl( sizeof( struct expected_data ) ),
1398
+ },
1399
+ .application_id = htonl( EFI_GET_SWLIST ),
1400
+ },
1401
+ };
1402
+
1403
+ struct event_forward_operation_to_all_request_param *param = xcalloc( 1, sizeof( struct event_forward_operation_to_all_request_param ) );
1404
+ param->add = true;
1405
+ param->type = EVENT_FORWARD_TYPE_PACKET_IN;
1406
+ param->service_name = xstrdup( "alpha" );
1407
+ param->callback = mock_event_forward_entry_to_all_callback;
1408
+ param->user_data = user_data;
1409
+
1410
+ event_forward_operation_result result;
1411
+ result.result = EFI_OPERATION_SUCCEEDED;
1412
+ result.n_services = 0;
1413
+ result.services = NULL;
1414
+
1415
+ expect_string( mock_send_request_message, to_service_name, "switch_manager.m" );
1416
+ expect_string( mock_send_request_message, from_service_name, "tetris-efic-1234" );
1417
+ expect_value( mock_send_request_message, tag32, MESSENGER_MANAGEMENT_REQUEST );
1418
+ expect_memory( mock_send_request_message, data, &expected_data, sizeof( struct expected_data ) );
1419
+ expect_value( mock_send_request_message, len, sizeof( struct expected_data ) );
1420
+ expect_value( mock_send_request_message, hd->callback, _dispatch_to_all_switch );
1421
+ expect_value( mock_send_request_message, hd->user_data, param );
1422
+ will_return( mock_send_request_message, true );
1423
+
1424
+ _get_switch_list_after_swm_succ( result, param );
1425
+
1426
+ xfree( param->service_name );
1427
+ xfree( param );
1428
+ }
1429
+
1430
+
1431
+ static void
1432
+ test__dispatch_to_all_switch_succeeds() {
1433
+ init_timer();
1434
+ uint64_t dpids[] = { 0x12345678 };
1435
+ const size_t n_dpids = 1;
1436
+
1437
+ void *user_data = ( void * ) 0xABCDEF;
1438
+
1439
+ struct event_forward_operation_to_all_request_param *param = xcalloc( 1, sizeof( struct event_forward_operation_to_all_request_param ) );
1440
+ param->add = true;
1441
+ param->type = EVENT_FORWARD_TYPE_PACKET_IN;
1442
+ param->service_name = xstrdup( "alpha" );
1443
+ param->callback = mock_event_forward_entry_to_all_callback;
1444
+ param->user_data = user_data;
1445
+
1446
+
1447
+ struct expected_data {
1448
+ management_application_request mgmt;
1449
+ event_forward_operation_request efi;
1450
+ char alpha[ 6 ];
1451
+ } __attribute__( ( packed ) ) expected_data = {
1452
+ .mgmt = {
1453
+ .header = {
1454
+ .type = htons( MANAGEMENT_APPLICATION_REQUEST ),
1455
+ .length = htonl( sizeof( struct expected_data ) ),
1456
+ },
1457
+ .application_id = htonl( EVENT_FORWARD_ENTRY_ADD ),
1458
+ },
1459
+ .efi = {
1460
+ .type = EVENT_FORWARD_TYPE_PACKET_IN,
1461
+ .n_services = htonl( 1 ),
1462
+ },
1463
+ .alpha = "alpha",
1464
+ };
1465
+
1466
+ expect_string( mock_send_request_message, to_service_name, "switch.0x12345678.m" );
1467
+ expect_string( mock_send_request_message, from_service_name, "tetris-efic-1234" );
1468
+ expect_value( mock_send_request_message, tag32, MESSENGER_MANAGEMENT_REQUEST );
1469
+ expect_memory( mock_send_request_message, data, &expected_data, sizeof( struct expected_data ) );
1470
+ expect_value( mock_send_request_message, len, sizeof( struct expected_data ) );
1471
+ expect_value( mock_send_request_message, hd->callback, _switch_response_handler );
1472
+ expect_any( mock_send_request_message, hd->user_data ); // txinfo
1473
+ will_return( mock_send_request_message, true );
1474
+
1475
+ free_user_data_member = true;
1476
+ _dispatch_to_all_switch( dpids, n_dpids, param );
1477
+
1478
+ // free all_sw_tx, param
1479
+ expect_string( mock_warn, message, "txid:0x1 was left behind." );
1480
+ _cleanup_tx_table();
1481
+
1482
+ finalize_timer();
1483
+ }
1484
+
1485
+
1486
+ static void
1487
+ test__switch_response_handler_succeeds_when_last_one_standing() {
1488
+
1489
+ void *user_data = ( void * ) 0x1234;
1490
+
1491
+ struct event_forward_operation_to_all_request_param *param = xcalloc( 1, sizeof( struct event_forward_operation_to_all_request_param ) );
1492
+ param->add = true;
1493
+ param->type = EVENT_FORWARD_TYPE_PACKET_IN;
1494
+ param->service_name = xstrdup( "alpha" );
1495
+ param->callback = mock_event_forward_entry_to_all_callback;
1496
+ param->user_data = user_data;
1497
+
1498
+ all_sw_tx *tx = _insert_tx( 1, param );
1499
+ uint64_t *dpid = xmalloc( sizeof( uint64_t ) );
1500
+ *dpid = 0x12345678;
1501
+ insert_hash_entry( tx->waiting_dpid, dpid, dpid );
1502
+
1503
+ event_forward_operation_result result;
1504
+ result.result = EFI_OPERATION_SUCCEEDED;
1505
+ result.n_services = 0;
1506
+ result.services = NULL;
1507
+
1508
+ struct txinfo *txinfo = xmalloc( sizeof( struct txinfo ) );
1509
+ txinfo->dpid = 0x12345678;
1510
+ txinfo->txid = tx->txid;
1511
+
1512
+ expect_value( mock_event_forward_entry_to_all_callback, result, EFI_OPERATION_SUCCEEDED );
1513
+ expect_value( mock_event_forward_entry_to_all_callback, user_data, user_data );
1514
+
1515
+ _switch_response_handler( result, txinfo );
1516
+ }
1517
+
1518
+
1519
+ static void
1520
+ test__switch_response_timeout_then_fails() {
1521
+
1522
+ void *user_data = ( void * ) 0x1234;
1523
+
1524
+ struct event_forward_operation_to_all_request_param *param = xcalloc( 1, sizeof( struct event_forward_operation_to_all_request_param ) );
1525
+ param->add = true;
1526
+ param->type = EVENT_FORWARD_TYPE_PACKET_IN;
1527
+ param->service_name = xstrdup( "alpha" );
1528
+ param->callback = mock_event_forward_entry_to_all_callback;
1529
+ param->user_data = user_data;
1530
+
1531
+ all_sw_tx *tx = _insert_tx( 1, param );
1532
+ uint64_t *dpid = xmalloc( sizeof( uint64_t ) );
1533
+ *dpid = 0x12345678;
1534
+ insert_hash_entry( tx->waiting_dpid, dpid, dpid );
1535
+
1536
+ struct txinfo *txinfo = xmalloc( sizeof( struct txinfo ) );
1537
+ txinfo->dpid = 0x12345678;
1538
+ txinfo->txid = tx->txid;
1539
+
1540
+ expect_value( mock_event_forward_entry_to_all_callback, result, EFI_OPERATION_FAILED );
1541
+ expect_value( mock_event_forward_entry_to_all_callback, user_data, user_data );
1542
+
1543
+ _switch_response_timeout( txinfo );
1544
+ xfree( txinfo );
1545
+ }
1546
+
1547
+
1548
+ /********************************************************************************
1549
+ * Run tests.
1550
+ ********************************************************************************/
1551
+
1552
+ int
1553
+ main() {
1554
+ const UnitTest tests[] = {
1555
+ unit_test_setup_teardown( test_init_event_forward_interface_succeeds,
1556
+ setup, teardown ),
1557
+ unit_test_setup_teardown( test_init_event_forward_interface_succeeds_even_with_long_name,
1558
+ setup, teardown ),
1559
+ unit_test_setup_teardown( test_init_event_forward_interface_fails_if_already_initialized,
1560
+ setup, teardown ),
1561
+
1562
+ unit_test_setup_teardown( test_finalize_event_forward_interface_succeeds,
1563
+ setup, teardown ),
1564
+ unit_test_setup_teardown( test_finalize_event_forward_interface_fails_if_not_initialized,
1565
+ setup, teardown ),
1566
+
1567
+ unit_test_setup_teardown( test_set_switch_manager_event_forward_entries_succeeds,
1568
+ setup_init_efi, teardown_finl_efi ),
1569
+ unit_test_setup_teardown( test_add_switch_manager_event_forward_entry_succeeds,
1570
+ setup_init_efi, teardown_finl_efi ),
1571
+ unit_test_setup_teardown( test_delete_switch_manager_event_forward_entry_succeeds,
1572
+ setup_init_efi, teardown_finl_efi ),
1573
+ unit_test_setup_teardown( test_dump_switch_manager_event_forward_entries_succeeds,
1574
+ setup_init_efi, teardown_finl_efi ),
1575
+
1576
+ unit_test_setup_teardown( test_set_switch_event_forward_entries_succeeds,
1577
+ setup_init_efi, teardown_finl_efi ),
1578
+ unit_test_setup_teardown( test_add_switch_event_forward_entry_succeeds,
1579
+ setup_init_efi, teardown_finl_efi ),
1580
+ unit_test_setup_teardown( test_delete_switch_event_forward_entry_succeeds,
1581
+ setup_init_efi, teardown_finl_efi ),
1582
+ unit_test_setup_teardown( test_dump_switch_event_forward_entries_succeeds,
1583
+ setup_init_efi, teardown_finl_efi ),
1584
+
1585
+ unit_test_setup_teardown( test_handle_efi_reply_succeeds_with_success_reply,
1586
+ setup_init_efi, teardown_finl_efi ),
1587
+ unit_test_setup_teardown( test_handle_efi_reply_succeeds_with_event_forward_entry_operation_failure_reply,
1588
+ setup_init_efi, teardown_finl_efi ),
1589
+ unit_test_setup_teardown( test_handle_efi_reply_succeeds_with_management_failure_reply,
1590
+ setup_init_efi, teardown_finl_efi ),
1591
+ unit_test_setup_teardown( test_handle_efi_reply_ignores_wrong_message_tag_reply,
1592
+ setup_init_efi, teardown_finl_efi ),
1593
+ unit_test_setup_teardown( test_handle_efi_reply_ignores_wrong_message_length_reply,
1594
+ setup_init_efi, teardown_finl_efi ),
1595
+ unit_test_setup_teardown( test_handle_efi_reply_ignores_empty_reply,
1596
+ setup_init_efi, teardown_finl_efi ),
1597
+ unit_test_setup_teardown( test_handle_efi_reply_ignores_wrong_event_forward_operation_command_reply,
1598
+ setup_init_efi, teardown_finl_efi ),
1599
+ unit_test_setup_teardown( test_handle_efi_reply_succeeds_with_wrong_event_forward_operation_result_reply,
1600
+ setup_init_efi, teardown_finl_efi ),
1601
+ unit_test_setup_teardown( test_handle_efi_reply_succeeds_with_more_service_found_then_expected_reply,
1602
+ setup_init_efi, teardown_finl_efi ),
1603
+ unit_test_setup_teardown( test_handle_efi_reply_succeeds_with_empty_service_name_reply,
1604
+ setup_init_efi, teardown_finl_efi ),
1605
+
1606
+ unit_test_setup_teardown( test_create_event_forward_operation_reply_with_null_service_list,
1607
+ setup, teardown ),
1608
+ unit_test_setup_teardown( test_create_event_forward_operation_reply_with_empty_service_list,
1609
+ setup, teardown ),
1610
+ unit_test_setup_teardown( test_create_event_forward_operation_reply_with_one_service_list,
1611
+ setup, teardown ),
1612
+ unit_test_setup_teardown( test_create_event_forward_operation_reply_with_multi_service_list,
1613
+ setup, teardown ),
1614
+
1615
+ unit_test_setup_teardown( test_send_efi_switch_list_request_succeeds,
1616
+ setup_init_efi, teardown_finl_efi ),
1617
+ unit_test_setup_teardown( test_handle_efi_reply_succeeds_with_switch_list_reply,
1618
+ setup_init_efi, teardown_finl_efi ),
1619
+ unit_test_setup_teardown( test_handle_efi_reply_succeeds_with_management_failure_on_switch_list_reply,
1620
+ setup_init_efi, teardown_finl_efi ),
1621
+
1622
+
1623
+ unit_test_setup_teardown( test_add_event_forward_entry_to_all_switches_succeeds,
1624
+ setup_init_efi, teardown_finl_efi ),
1625
+ unit_test_setup_teardown( test_delete_event_forward_entry_to_all_switches_succeeds,
1626
+ setup_init_efi, teardown_finl_efi ),
1627
+ unit_test_setup_teardown( test__get_switch_list_after_swm_succ_succeeds,
1628
+ setup_init_efi, teardown_finl_efi ),
1629
+ unit_test_setup_teardown( test__dispatch_to_all_switch_succeeds,
1630
+ setup_init_efi, teardown_finl_efi ),
1631
+ unit_test_setup_teardown( test__switch_response_handler_succeeds_when_last_one_standing,
1632
+ setup_init_efi, teardown_finl_efi ),
1633
+ unit_test_setup_teardown( test__switch_response_timeout_then_fails,
1634
+ setup_init_efi, teardown_finl_efi ),
1635
+ };
1636
+ setup_leak_detector();
1637
+ return run_tests( tests );
1638
+ }
1639
+
1640
+
1641
+ /*
1642
+ * Local variables:
1643
+ * c-basic-offset: 2
1644
+ * indent-tabs-mode: nil
1645
+ * End:
1646
+ */