src/switch_manager/switch.c in trema-0.4.3 vs src/switch_manager/switch.c in trema-0.4.4

- old
+ new

@@ -55,12 +55,18 @@ struct switch_info switch_info; static const time_t COOKIE_TABLE_AGING_INTERVAL = 3600; // sec. static const time_t ECHO_REQUEST_INTERVAL = 60; // sec. -static const time_t ECHO_REPLY_TIMEOUT = 2; // ses. +static const time_t ECHO_REPLY_TIMEOUT = 2; // sec. static const time_t WARNING_ECHO_RTT = 500; // msec. The value must is less than 1000. +static const time_t REGISTRATION_RETRY = 1; // sec. +static const int REGISTRATION_RETRY_COUNT = 1; +static const time_t REGISTRATION_TIMEOUT = 1; // sec. +static const time_t UNREGISTRATION_RETRY = 1; // sec. +static const int UNREGISTRATION_RETRY_COUNT = 1; +static const time_t UNREGISTRATION_TIMEOUT = 1; // sec. static bool age_cookie_table_enabled = false; #define SWITCH_MANAGER "switch_manager" @@ -306,10 +312,11 @@ static void echo_reply_timeout( void *user_data ) { UNUSED( user_data ); + switch_info.running_timer = false; error( "Echo request timeout ( datapath id %#" PRIx64 ").", switch_info.datapath_id ); switch_event_disconnected( &switch_info ); } @@ -366,35 +373,46 @@ switch_set_timeout( ECHO_REPLY_TIMEOUT, echo_reply_timeout, NULL ); } static void -confirm_self_dpid_is_registerd( uint64_t* dpids, size_t n_dpids, void *user_data ); +registration_timeout( void *user_data ) { + struct switch_info *sw_info = user_data; + sw_info->running_timer = false; + error( "Registration timeout ( datapath id %#" PRIx64 " ).", sw_info->datapath_id ); + switch_event_disconnected( sw_info ); +} + + +static void +confirm_self_dpid_is_registered( uint64_t* dpids, size_t n_dpids, void *user_data ); + + int switch_event_recv_featuresreply( struct switch_info *sw_info, uint64_t *dpid ) { int ret; char new_service_name[ SWITCH_MANAGER_PREFIX_STR_LEN + SWITCH_MANAGER_DPID_STR_LEN + 1 ]; const uint16_t new_service_name_len = SWITCH_MANAGER_PREFIX_STR_LEN + SWITCH_MANAGER_DPID_STR_LEN + 1; switch ( sw_info->state ) { case SWITCH_STATE_WAIT_FEATURES_REPLY: sw_info->datapath_id = *dpid; - sw_info->state = SWITCH_STATE_COMPLETED; + sw_info->state = SWITCH_STATE_WAIT_REGISTRATION; // cancel to features_reply_wait-timeout timer switch_unset_timeout( switch_event_timeout_features_reply, NULL ); // TODO: set keepalive-timeout snprintf( new_service_name, new_service_name_len, "%s%#" PRIx64, SWITCH_MANAGER_PREFIX, sw_info->datapath_id ); // checking duplicate service pid_t pid = get_pid_by_trema_name( new_service_name ); if ( pid > 0 ) { - // duplicated + debug( "duplicated datapath-id %#" PRIx64, sw_info->datapath_id ); if ( !terminate_trema_process( pid ) ) { return -1; } } // rename service_name of messenger @@ -438,16 +456,21 @@ service_send_to_application( &switch_manager_only_list, MESSENGER_OPENFLOW_READY, &sw_info->datapath_id, NULL ); init_event_forward_interface(); // Check switch_manager registration debug( "Checking switch manager's switch list." ); - if ( !send_efi_switch_list_request( confirm_self_dpid_is_registerd, sw_info ) ) { + sw_info->retry_count = REGISTRATION_RETRY_COUNT; + if ( send_efi_switch_list_request( confirm_self_dpid_is_registered, sw_info ) ) { + switch_set_timeout( REGISTRATION_TIMEOUT, registration_timeout, sw_info ); + } + else { error( "Failed to send switch list request to switch manager." ); return -1; } break; + case SWITCH_STATE_WAIT_REGISTRATION: case SWITCH_STATE_COMPLETED: // NOP break; default: @@ -460,51 +483,122 @@ return 0; } static void -notify_state_to_controllers( struct switch_info *sw_info ); +registration_retry( void *user_data ) { + struct switch_info *sw_info = user_data; + if ( sw_info->retry_count == 0 ) { + switch_event_disconnected( sw_info ); + return; + } + sw_info->retry_count--; + sw_info->running_timer = false; + debug( "Checking switch manager's switch list." ); + if ( send_efi_switch_list_request( confirm_self_dpid_is_registered, sw_info ) ) { + switch_set_timeout( REGISTRATION_TIMEOUT, registration_timeout, sw_info ); + } + else { + error( "Failed to send switch list request to switch manager." ); + switch_event_disconnected( sw_info ); + } +} + static void -confirm_self_dpid_is_registerd( uint64_t* dpids, size_t n_dpids, void *user_data ) { +confirm_self_dpid_is_registered( uint64_t* dpids, size_t n_dpids, void *user_data ) { struct switch_info *sw_info = user_data; + switch_unset_timeout( registration_timeout, sw_info ); + debug( "Received switch manager's switch list." ); + bool found = false; for ( size_t i = 0 ; i < n_dpids ; ++i ) { if ( sw_info->datapath_id == dpids[ i ] ) { // self dpid registered debug( "Self dpid found" ); - return notify_state_to_controllers( sw_info ); + found = true; + break; } } + if ( found ) { + sw_info->state = SWITCH_STATE_COMPLETED; - debug( "Self dpid not found. Retrying..." ); - if ( !send_efi_switch_list_request( confirm_self_dpid_is_registerd, sw_info ) ){ - error( "Failed to send switch list request to switch manager on retry." ); + // notify state and datapath_id to controllers + service_send_state( sw_info, &sw_info->datapath_id, MESSENGER_OPENFLOW_READY ); + debug( "send ready state" ); + + add_periodic_event_callback( ECHO_REQUEST_INTERVAL, echo_request_interval, sw_info ); } + else { + debug( "Self dpid not found. Retrying..." ); + switch_set_timeout( REGISTRATION_RETRY, registration_retry, sw_info ); + } } static void -notify_state_to_controllers( struct switch_info *sw_info ) { - // notify state and datapath_id to controllers - service_send_state( sw_info, &sw_info->datapath_id, MESSENGER_OPENFLOW_READY ); - debug( "send ready state" ); +stop_switch( struct switch_info *sw_info ) { + if ( sw_info->secure_channel_fd >= 0 ) { + close( sw_info->secure_channel_fd ); + sw_info->secure_channel_fd = -1; + } + uint8_t state = MESSENGER_OPENFLOW_DISCONNECTED; + if ( sw_info->state == SWITCH_STATE_CONNECTION_FAILED ) { + state = MESSENGER_OPENFLOW_FAILD_TO_CONNECT; + } + service_send_state( sw_info, &sw_info->datapath_id, state ); + flush_messenger(); - add_periodic_event_callback( ECHO_REQUEST_INTERVAL, echo_request_interval, sw_info ); - } + // free service name list + iterate_list( sw_info->vendor_service_name_list, xfree_data, NULL ); + delete_list( sw_info->vendor_service_name_list ); + sw_info->vendor_service_name_list = NULL; + iterate_list( sw_info->packetin_service_name_list, xfree_data, NULL ); + delete_list( sw_info->packetin_service_name_list ); + sw_info->packetin_service_name_list = NULL; + iterate_list( sw_info->portstatus_service_name_list, xfree_data, NULL ); + delete_list( sw_info->portstatus_service_name_list ); + sw_info->portstatus_service_name_list = NULL; + iterate_list( sw_info->state_service_name_list, xfree_data, NULL ); + delete_list( sw_info->state_service_name_list ); + sw_info->state_service_name_list = NULL; + stop_trema(); +} + +static void +unregistration_timeout( void *user_data ) { + struct switch_info *sw_info = user_data; + + sw_info->running_timer = false; + + warn( "Unregistration timeout ( datapath id %#" PRIx64 " ).", sw_info->datapath_id ); + + stop_switch( sw_info ); +} + + +static void +confirm_self_dpid_is_unregistered( uint64_t* dpids, size_t n_dpids, void *user_data ); + + int switch_event_disconnected( struct switch_info *sw_info ) { int old_state = sw_info->state; - sw_info->state = SWITCH_STATE_DISCONNECTED; + if ( sw_info->state == SWITCH_STATE_COMPLETED ) { + sw_info->state = SWITCH_STATE_DISCONNECTED; + } + else { + sw_info->state = SWITCH_STATE_CONNECTION_FAILED; + } if ( old_state == SWITCH_STATE_COMPLETED ) { - delete_timer_event( echo_request_interval, sw_info ); + switch_unset_timeout( echo_reply_timeout, NULL ); } if ( sw_info->fragment_buf != NULL ) { free_buffer( sw_info->fragment_buf ); sw_info->fragment_buf = NULL; @@ -522,40 +616,83 @@ if ( sw_info->secure_channel_fd >= 0 ) { set_readable( switch_info.secure_channel_fd, false ); set_writable( switch_info.secure_channel_fd, false ); delete_fd_handler( switch_info.secure_channel_fd ); + } - close( sw_info->secure_channel_fd ); - sw_info->secure_channel_fd = -1; + uint8_t state = MESSENGER_OPENFLOW_DISCONNECTED; + if ( sw_info->state == SWITCH_STATE_CONNECTION_FAILED ) { + state = MESSENGER_OPENFLOW_FAILD_TO_CONNECT; } - if ( old_state != SWITCH_STATE_COMPLETED ) { - service_send_state( sw_info, &sw_info->datapath_id, MESSENGER_OPENFLOW_FAILD_TO_CONNECT ); + debug( "Notify switch_disconnected to switch manager." ); + char switch_manager[] = SWITCH_MANAGER; + list_element switch_manager_only_list; + switch_manager_only_list.next = NULL; + switch_manager_only_list.data = switch_manager; + service_send_to_application( &switch_manager_only_list, state, &sw_info->datapath_id, NULL ); + + // Check switch_manager registration + debug( "Checking switch manager's switch list." ); + sw_info->retry_count = UNREGISTRATION_RETRY_COUNT; + if ( send_efi_switch_list_request( confirm_self_dpid_is_unregistered, sw_info ) ) { + switch_set_timeout( UNREGISTRATION_TIMEOUT, unregistration_timeout, sw_info ); } else { - // send secure channle disconnect state to application - service_send_state( sw_info, &sw_info->datapath_id, MESSENGER_OPENFLOW_DISCONNECTED ); + error( "Failed to send switch list request to switch manager." ); + stop_switch( sw_info ); } - flush_messenger(); - // free service name list - iterate_list( sw_info->vendor_service_name_list, xfree_data, NULL ); - delete_list( sw_info->vendor_service_name_list ); - sw_info->vendor_service_name_list = NULL; - iterate_list( sw_info->packetin_service_name_list, xfree_data, NULL ); - delete_list( sw_info->packetin_service_name_list ); - sw_info->packetin_service_name_list = NULL; - iterate_list( sw_info->portstatus_service_name_list, xfree_data, NULL ); - delete_list( sw_info->portstatus_service_name_list ); - sw_info->portstatus_service_name_list = NULL; - iterate_list( sw_info->state_service_name_list, xfree_data, NULL ); - delete_list( sw_info->state_service_name_list ); - sw_info->state_service_name_list = NULL; + return 0; +} - stop_trema(); - return 0; +static void +unregistration_retry( void *user_data ) { + struct switch_info *sw_info = user_data; + + if ( sw_info->retry_count == 0 ) { + stop_switch( sw_info ); + return; + } + sw_info->retry_count--; + sw_info->running_timer = false; + debug( "Checking switch manager's switch list." ); + if ( send_efi_switch_list_request( confirm_self_dpid_is_unregistered, sw_info ) ) { + switch_set_timeout( UNREGISTRATION_TIMEOUT, unregistration_timeout, sw_info ); + } + else { + error( "Failed to send switch list request to switch manager." ); + stop_switch( sw_info ); + } +} + + +static void +confirm_self_dpid_is_unregistered( uint64_t* dpids, size_t n_dpids, void *user_data ) { + struct switch_info *sw_info = user_data; + + switch_unset_timeout( unregistration_timeout, sw_info ); + + debug( "Received switch manager's switch list." ); + bool found = false; + for ( size_t i = 0 ; i < n_dpids ; ++i ) { + if ( sw_info->datapath_id == dpids[ i ] ) { + // self dpid registered + debug( "Self dpid found" ); + found = true; + break; + } + } + if ( found ) { + debug( "Self dpid found. Retrying..." ); + switch_set_timeout( UNREGISTRATION_RETRY, unregistration_retry, sw_info ); + } + else { + // The switch has been deleted from the switch list + stop_switch( sw_info ); + } } int switch_event_recv_from_application( uint64_t *datapath_id, char *application_service_name, buffer *buf ) {