Esempio n. 1
0
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 );
  }
}
Esempio n. 2
0
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 );
  }
}
Esempio n. 3
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 );

  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;
}
Esempio n. 4
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;
}
Esempio n. 5
0
File: switch.c Progetto: Darma/trema
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;
}
Esempio n. 6
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;
}
Esempio n. 7
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 );
}
Esempio n. 8
0
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 );
}
Esempio n. 9
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_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;
}
Esempio n. 10
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;
}
Esempio n. 11
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;
}