static void confirm_self_dpid_is_registered( const list_element *switches, 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 ( const list_element *e = switches; e != NULL; e = e->next ) { if ( sw_info->datapath_id == *( uint64_t * ) e->data ) { // self dpid registered debug( "Self dpid found" ); found = true; break; } } if ( found ) { sw_info->state = SWITCH_STATE_COMPLETED; finalize_openflow_application_interface(); // 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 confirm_self_dpid_is_unregistered( const list_element *switches, 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 ( const list_element *e = switches; e != NULL; e = e->next ) { if ( sw_info->datapath_id == *( uint64_t * ) e->data ) { // 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 finalize_openflow_application_interface(); push_external_callback( stop_switch ); } }
int switch_event_recv_echoreply( struct switch_info *sw_info, buffer *buf ) { if ( buf->length != sizeof( struct ofp_header ) + sizeof( echo_body ) ) { return 0; } struct ofp_header *header = buf->data; if ( ntohl( header->xid ) != sw_info->echo_request_xid ) { return 0; } echo_body *body = ( echo_body * ) ( header + 1 ); if ( ntohll( body->datapath_id ) != sw_info->datapath_id ) { return 0; } switch_unset_timeout( echo_reply_timeout, NULL ); struct timespec now, tim; clock_gettime( CLOCK_MONOTONIC, &now ); tim.tv_sec = ( time_t ) ntohl( body->sec ); tim.tv_nsec = ( long ) ntohl( body->nsec ); SUB_TIMESPEC( &now, &tim, &tim ); if ( tim.tv_sec > 0 || tim.tv_nsec > ( ( long ) WARNING_ECHO_RTT * 1000000 ) ) { warn( "echo round-trip time is greater then %ld ms ( round-trip time = %" PRId64 ".%09ld ).", ( long ) WARNING_ECHO_RTT, ( int64_t ) tim.tv_sec, tim.tv_nsec ); } return 0; }
int switch_event_recv_hello( struct switch_info *sw_info ) { int ret; if ( sw_info->state == SWITCH_STATE_WAIT_HELLO ) { // cancel to hello_wait-timeout timer switch_unset_timeout( switch_event_timeout_hello, NULL ); if ( sw_info->deny_packet_in_on_startup ) { ret = ofpmsg_send_deny_all( sw_info ); if ( ret < 0 ) { return ret; } } ret = ofpmsg_send_featuresrequest( sw_info ); if ( ret < 0 ) { return ret; } sw_info->state = SWITCH_STATE_WAIT_FEATURES_REPLY; switch_set_timeout( SWITCH_STATE_TIMEOUT_FEATURES_REPLY, switch_event_timeout_features_reply, NULL ); } return 0; }
int switch_event_recv_echoreply( struct switch_info *sw_info, buffer *buf ) { if ( buf->length != sizeof( struct ofp_header ) + sizeof( echo_body ) ) { return 0; } struct ofp_header *header = buf->data; if ( ntohl( header->xid ) != sw_info->echo_request_xid ) { return 0; } echo_body *body = ( echo_body * ) ( header + 1 ); if ( ntohll( body->datapath_id ) != sw_info->datapath_id ) { return 0; } switch_unset_timeout( echo_reply_timeout, NULL ); struct timespec now, tim; clock_gettime( CLOCK_MONOTONIC, &now ); tim.tv_sec = ( time_t ) ntohl( body->sec ); tim.tv_nsec = ( long ) ntohl( body->nsec ); SUB_TIMESPEC( &now, &tim, &tim ); info( "echo round-trip time %u.%09u.", ( uint32_t ) tim.tv_sec, ( uint32_t ) tim.tv_nsec ); return 0; }
int switch_event_recv_featuresreply( struct switch_info *sw_info, uint64_t *dpid ) { int ret; uint16_t new_service_name_len; char *new_service_name; switch ( sw_info->state ) { case SWITCH_STATE_WAIT_FEATURES_REPLY: sw_info->datapath_id = *dpid; sw_info->state = SWITCH_STATE_COMPLETED; // cancel to features_reply_wait-timeout timer switch_unset_timeout( switch_event_timeout_features_reply ); // TODO: change process name // TODO: set keepalive-timeout new_service_name_len = SWITCH_MANAGER_PREFIX_STR_LEN + SWITCH_MANAGER_DPID_STR_LEN + 1; new_service_name = xmalloc( new_service_name_len ); snprintf( new_service_name, new_service_name_len, "%s%" PRIx64, SWITCH_MANAGER_PREFIX, sw_info->datapath_id ); // rename service_name of messenger rename_message_received_callback( get_trema_name(), new_service_name ); debug( "Rename service name to %s from %s.", new_service_name, get_trema_name() ); if ( messenger_dump_enabled() ) { stop_messenger_dump(); start_messenger_dump( new_service_name, DEFAULT_DUMP_SERVICE_NAME ); } // notify state and datapath_id service_send_state( sw_info, &sw_info->datapath_id, MESSENGER_OPENFLOW_READY ); debug( "send ready state" ); ret = ofpmsg_send_setconfig( sw_info ); if ( ret < 0 ) { return ret; } ret = ofpmsg_send_delete_all_flows( sw_info ); if ( ret < 0 ) { return ret; } break; case SWITCH_STATE_COMPLETED: // NOP break; default: notice( "Invalid event 'features reply' from a switch." ); return -1; break; } return 0; }
static void switch_event_timeout_features_reply( void *user_data ) { UNUSED( user_data ); if ( switch_info.state != SWITCH_STATE_WAIT_FEATURES_REPLY ) { return; } // delete to features_reply_wait-timeout timer switch_unset_timeout( switch_event_timeout_features_reply ); error( "Features Reply timeout. state:%d, dpid:%#" PRIx64 ", fd:%d.", switch_info.state, switch_info.datapath_id, switch_info.secure_channel_fd ); switch_event_disconnected( &switch_info ); }
static void switch_event_timeout_hello( void *user_data ) { UNUSED( user_data ); if ( switch_info.state != SWITCH_STATE_WAIT_HELLO ) { return; } // delete to hello_wait-timeout timer switch_unset_timeout( switch_event_timeout_hello ); error( "Hello timeout. state:%d, dpid:%#" PRIx64 ", fd:%d.", switch_info.state, switch_info.datapath_id, switch_info.secure_channel_fd ); switch_event_disconnected( &switch_info ); }
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; // 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_trema_process_from_name( new_service_name ); if ( pid > 0 ) { // duplicated if ( !terminate_trema_process( pid ) ) { return -1; } } // rename service_name of messenger rename_message_received_callback( get_trema_name(), new_service_name ); debug( "Rename service name from %s to %s.", get_trema_name(), new_service_name ); if ( messenger_dump_enabled() ) { stop_messenger_dump(); start_messenger_dump( new_service_name, DEFAULT_DUMP_SERVICE_NAME ); } set_trema_name( new_service_name ); // notify state and datapath_id service_send_state( sw_info, &sw_info->datapath_id, MESSENGER_OPENFLOW_READY ); debug( "send ready state" ); ret = ofpmsg_send_setconfig( sw_info ); if ( ret < 0 ) { return ret; } if ( switch_info.flow_cleanup ) { ret = ofpmsg_send_delete_all_flows( sw_info ); if ( ret < 0 ) { return ret; } } break; case SWITCH_STATE_COMPLETED: // NOP break; default: notice( "Invalid event 'features reply' from a switch." ); return -1; break; } return 0; }
int switch_event_disconnected( struct switch_info *sw_info ) { int old_state = sw_info->state; if ( sw_info->state == SWITCH_STATE_DISCONNECTED || sw_info->state == SWITCH_STATE_CONNECTION_FAILED ) { debug( "already disconnected" ); return -1; } 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 ) { switch_unset_timeout( echo_reply_timeout, NULL ); } if ( sw_info->fragment_buf != NULL ) { free_buffer( sw_info->fragment_buf ); sw_info->fragment_buf = NULL; } if ( sw_info->send_queue != NULL ) { delete_message_queue( sw_info->send_queue ); sw_info->send_queue = NULL; } if ( sw_info->recv_queue != NULL ) { delete_message_queue( sw_info->recv_queue ); sw_info->recv_queue = NULL; } 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 ); } uint8_t state = MESSENGER_OPENFLOW_DISCONNECTED; if ( sw_info->state == SWITCH_STATE_CONNECTION_FAILED ) { state = 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; set_list_switches_reply_handler( confirm_self_dpid_is_unregistered ); if ( send_list_switches_request( sw_info ) ) { switch_set_timeout( UNREGISTRATION_TIMEOUT, unregistration_timeout, sw_info ); } else { error( "Failed to send switch list request to switch manager." ); stop_switch(); } return 0; }
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_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 ) { debug( "duplicated datapath-id %#" PRIx64, sw_info->datapath_id ); if ( !terminate_trema_process( pid ) ) { return -1; } } // rename service_name of messenger rename_message_received_callback( get_trema_name(), new_service_name ); // rename management service name char *management_service_name = xstrdup( get_management_service_name( get_trema_name() ) ); char *new_management_service_name = xstrdup( get_management_service_name( new_service_name ) ); rename_message_requested_callback( management_service_name, new_management_service_name ); xfree( management_service_name ); xfree( new_management_service_name ); debug( "Rename service name from %s to %s.", get_trema_name(), new_service_name ); if ( messenger_dump_enabled() ) { stop_messenger_dump(); start_messenger_dump( new_service_name, DEFAULT_DUMP_SERVICE_NAME ); } set_trema_name( new_service_name ); // reset to default config ret = ofpmsg_send_setconfig( sw_info ); if ( ret < 0 ) { error( "Failed to send setconfig." ); return ret; } if ( switch_info.flow_cleanup ) { debug( "Deleting all flows." ); ret = ofpmsg_send_delete_all_flows( sw_info ); if ( ret < 0 ) { error( "Failed to send delete all flows." ); return ret; } } // switch_ready to switch_manager debug( "Notify switch_ready 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, MESSENGER_OPENFLOW_READY, &sw_info->datapath_id, NULL ); init_event_forward_interface(); // Check switch_manager registration debug( "Checking switch manager's switch list." ); sw_info->retry_count = REGISTRATION_RETRY_COUNT; set_list_switches_reply_handler( confirm_self_dpid_is_registered ); if ( send_list_switches_request( 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: notice( "Invalid event 'features reply' from a switch." ); return -1; break; } return 0; }