src/switch_manager/switch_manager.c in trema-0.3.16 vs src/switch_manager/switch_manager.c in trema-0.3.17
- old
+ new
@@ -25,14 +25,17 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
+#include <assert.h>
#include "trema.h"
#include "secure_channel_listener.h"
#include "switch_manager.h"
#include "dpid_table.h"
+#include "switch_option.h"
+#include "event_forward_entry_manipulation.h"
#ifdef UNIT_TESTING
#define static
@@ -153,11 +156,11 @@
void
usage() {
printf(
"OpenFlow Switch Manager.\n"
- "Usage: %s [OPTION]... [-- SWITCH_MANAGER_OPTION]...\n"
+ "Usage: %s [OPTION]... [-- SWITCH_DAEMON_OPTION]...\n"
"\n"
" -s, --switch=PATH the command path of switch\n"
" -n, --name=SERVICE_NAME service name\n"
" -p, --port=PORT server listen port (default %u)\n"
" -d, --daemonize run in the background\n"
@@ -251,10 +254,14 @@
init_listener_info( struct listener_info *listener_info ) {
memset( listener_info, 0, sizeof( struct listener_info ) );
listener_info->switch_daemon = xconcatenate_path( get_trema_home(), SWITCH_MANAGER_PATH );
listener_info->listen_port = OFP_TCP_PORT;
listener_info->listen_fd = -1;
+ create_list( &listener_info->vendor_service_name_list );
+ create_list( &listener_info->packetin_service_name_list );
+ create_list( &listener_info->portstatus_service_name_list );
+ create_list( &listener_info->state_service_name_list );
}
static void
finalize_listener_info( struct listener_info *listener_info ) {
@@ -267,10 +274,29 @@
delete_fd_handler( listener_info->listen_fd );
close( listener_info->listen_fd );
listener_info->listen_fd = -1;
}
+ for ( int i = 0; i < listener_info->switch_daemon_argc; ++i ) {
+ xfree( listener_info->switch_daemon_argv[ i ] );
+ listener_info->switch_daemon_argv[ i ] = NULL;
+ }
+ xfree( listener_info->switch_daemon_argv );
+ listener_info->switch_daemon_argv = NULL;
+
+ iterate_list( listener_info->vendor_service_name_list, xfree_data, NULL );
+ delete_list( listener_info->vendor_service_name_list );
+ listener_info->vendor_service_name_list = NULL;
+ iterate_list( listener_info->packetin_service_name_list, xfree_data, NULL );
+ delete_list( listener_info->packetin_service_name_list );
+ listener_info->packetin_service_name_list = NULL;
+ iterate_list( listener_info->portstatus_service_name_list, xfree_data, NULL );
+ delete_list( listener_info->portstatus_service_name_list );
+ listener_info->portstatus_service_name_list = NULL;
+ iterate_list( listener_info->state_service_name_list, xfree_data, NULL );
+ delete_list( listener_info->state_service_name_list );
+ listener_info->state_service_name_list = NULL;
}
static uint16_t
strtoport( const char *str ) {
@@ -308,13 +334,53 @@
return false;
break;
}
}
- listener_info->switch_daemon_argc = argc - optind;
- listener_info->switch_daemon_argv = &argv[ optind ];
+ debug( "Start parsing switch daemon arguments." );
+ // index of first switch daemon arguments in argv
+ const int switch_arg_begin = optind;
+ // reorder switch daemon arguments
+ while ( getopt_long( argc, argv, switch_short_options, switch_long_options, NULL ) != -1 );
+
+ // index of first packet_in::..., etc. in argv
+ const int switch_arg_option_begin = optind;
+
+ // deep copy switch daemon arguments excluding packet_in::..., etc.
+ listener_info->switch_daemon_argc = switch_arg_option_begin - switch_arg_begin;
+ listener_info->switch_daemon_argv = xcalloc( ( size_t ) listener_info->switch_daemon_argc + 1,
+ sizeof( char * ) );
+ for ( int i = 0; i < listener_info->switch_daemon_argc; ++i ) {
+ debug( "switch daemon option: %s\n", argv[switch_arg_begin + i] );
+ listener_info->switch_daemon_argv[ i ] = xstrdup( argv[ switch_arg_begin + i ] );
+ }
+
+ // set service lists for each event type
+ for ( int i = switch_arg_option_begin; i < argc; i++ ) {
+ if ( strncmp( argv[ i ], VENDOR_PREFIX, strlen( VENDOR_PREFIX ) ) == 0 ) {
+ char *service_name = xstrdup( argv[ i ] + strlen( VENDOR_PREFIX ) );
+ debug( "event: " VENDOR_PREFIX "%s", service_name );
+ insert_in_front( &listener_info->vendor_service_name_list, service_name );
+ }
+ else if ( strncmp( argv[ i ], PACKET_IN_PREFIX, strlen( PACKET_IN_PREFIX ) ) == 0 ) {
+ char *service_name = xstrdup( argv[ i ] + strlen( PACKET_IN_PREFIX ) );
+ debug( "event: " PACKET_IN_PREFIX "%s", service_name );
+ insert_in_front( &listener_info->packetin_service_name_list, service_name );
+ }
+ else if ( strncmp( argv[ i ], PORTSTATUS_PREFIX, strlen( PORTSTATUS_PREFIX ) ) == 0 ) {
+ char *service_name = xstrdup( argv[ i ] + strlen( PORTSTATUS_PREFIX ) );
+ debug( "event: " PORTSTATUS_PREFIX "%s", service_name );
+ insert_in_front( &listener_info->portstatus_service_name_list, service_name );
+ }
+ else if ( strncmp( argv[ i ], STATE_PREFIX, strlen( STATE_PREFIX ) ) == 0 ) {
+ char *service_name = xstrdup( argv[ i ] + strlen( STATE_PREFIX ) );
+ debug( "event: " STATE_PREFIX "%s", service_name );
+ insert_in_front( &listener_info->state_service_name_list, service_name );
+ }
+ }
+
return true;
}
static void
@@ -357,10 +423,116 @@
send_reply_message( handle, 0, reply->data, reply->length );
free_buffer( reply );
}
+static void
+management_event_forward_entry_operation( const messenger_context_handle *handle, uint32_t command, event_forward_operation_request *req, size_t data_len ) {
+
+ debug( "management efi command:%#x, type:%#x, n_services:%d", command, req->type, req->n_services );
+
+ list_element **subject = NULL;
+ switch ( req->type ) {
+ case EVENT_FORWARD_TYPE_VENDOR:
+ info( "Managing vendor event." );
+ subject = &listener_info.vendor_service_name_list;
+ break;
+
+ case EVENT_FORWARD_TYPE_PACKET_IN:
+ info( "Managing packet_in event." );
+ subject = &listener_info.packetin_service_name_list;
+ break;
+
+ case EVENT_FORWARD_TYPE_PORT_STATUS:
+ info( "Managing port_status event." );
+ subject = &listener_info.portstatus_service_name_list;
+ break;
+
+ case EVENT_FORWARD_TYPE_STATE_NOTIFY:
+ info( "Managing state_notify event." );
+ subject = &listener_info.state_service_name_list;
+ break;
+
+ default:
+ error( "Invalid EVENT_FWD_TYPE ( %#x )", req->type );
+ event_forward_operation_reply res;
+ memset( &res, 0, sizeof( event_forward_operation_reply ) );
+ res.type = req->type;
+ res.result = EFI_OPERATION_FAILED;
+ management_application_reply *reply = create_management_application_reply( MANAGEMENT_REQUEST_FAILED, command, &res, sizeof( event_forward_operation_reply ) );
+ send_management_application_reply( handle, reply );
+ xfree( reply );
+ return;
+ }
+ assert( subject != NULL );
+
+ switch ( command ) {
+ case EVENT_FORWARD_ENTRY_ADD:
+ management_event_forward_entry_add( subject, req, data_len );
+ break;
+
+ case EVENT_FORWARD_ENTRY_DELETE:
+ management_event_forward_entry_delete( subject, req, data_len );
+ break;
+
+ case EVENT_FORWARD_ENTRY_DUMP:
+ info( "Dumping current event filter." );
+ // do nothing
+ break;
+
+ case EVENT_FORWARD_ENTRY_SET:
+ management_event_forward_entries_set( subject, req, data_len );
+ break;
+ }
+
+ buffer *buf = create_event_forward_operation_reply( req->type, EFI_OPERATION_SUCCEEDED, *subject );
+ management_application_reply *reply = create_management_application_reply( MANAGEMENT_REQUEST_SUCCEEDED, command, buf->data, buf->length );
+ free_buffer( buf );
+ send_management_application_reply( handle, reply );
+ xfree( reply );
+}
+
+
+static void
+management_recv( const messenger_context_handle *handle, uint32_t command, void *data, size_t data_len, void *user_data ) {
+ UNUSED( user_data );
+
+ switch ( command ) {
+ case EVENT_FORWARD_ENTRY_ADD:
+ case EVENT_FORWARD_ENTRY_DELETE:
+ case EVENT_FORWARD_ENTRY_DUMP:
+ case EVENT_FORWARD_ENTRY_SET:
+ {
+ event_forward_operation_request *req = data;
+ req->n_services = ntohl( req->n_services );
+ management_event_forward_entry_operation( handle, command, req, data_len );
+ return;
+ }
+ break;
+
+ case EFI_GET_SWLIST:
+ {
+ buffer *buf = get_switches();
+ management_application_reply *reply = create_management_application_reply( MANAGEMENT_REQUEST_SUCCEEDED, command, buf->data, buf->length );
+ free_buffer( buf );
+ send_management_application_reply( handle, reply );
+ xfree( reply );
+ }
+ break;
+
+ default:
+ {
+ error( "Undefined management command ( %#x )", command );
+ management_application_reply *reply = create_management_application_reply( MANAGEMENT_REQUEST_FAILED, command, NULL, 0 );
+ send_management_application_reply( handle, reply );
+ xfree( reply );
+ return;
+ }
+ }
+}
+
+
static bool
start_service_management( void ) {
return add_message_requested_callback( get_trema_name(), recv_request );
}
@@ -404,9 +576,10 @@
ret = parse_argument( &listener_info, argc, argv );
if ( !ret ) {
finalize_listener_info( &listener_info );
exit( EXIT_FAILURE );
}
+ set_management_application_request_handler( management_recv, NULL );
init_dpid_table();
start_service_management();
start_switch_management();