Ejemplo n.º 1
0
static void
handle_flow_mod_mod( const uint32_t transaction_id, const uint64_t cookie, 
                     const uint64_t cookie_mask, const uint8_t table_id,
                     const uint16_t idle_timeout, const uint16_t hard_timeout,
                     const uint16_t priority, const uint32_t buffer_id,
                     const uint16_t flags, const oxm_matches *oxm,
                     const openflow_instructions *instructions,
                     const bool strict, struct protocol *protocol ) {

  match *match = create_match( );
  if ( oxm != NULL && oxm->n_matches > 0 ) {
    for ( list_element *e = oxm->list; e != NULL; e = e->next ) {
      oxm_match_header *hdr = e->data;
      assign_match( match, hdr );
    }
  }

  instruction_set *ins_set = create_instruction_set();
  if ( instructions != NULL ) {
    OFDPE ret = assign_instructions( ins_set, instructions->list );
    if ( ret != OFDPE_SUCCESS ) {
      send_error_message( transaction_id, OFPET_FLOW_MOD_FAILED, OFPBIC_UNSUP_INST );
      delete_instruction_set( ins_set );
      delete_match( match );
      return;
    }
  }

  OFDPE ret = update_or_add_flow_entry( table_id, match, cookie, cookie_mask, priority, idle_timeout, hard_timeout,
                                        flags, strict, ins_set );
  delete_instruction_set( ins_set );
  delete_match( match );
  if ( ret != OFDPE_SUCCESS ) {
    uint16_t type = OFPET_FLOW_MOD_FAILED;
    uint16_t code = OFPFMFC_UNKNOWN;
    get_ofp_error( ret, &type, &code );
    send_error_message( transaction_id, type, code );
    return;
  }

  if ( buffer_id != OFP_NO_BUFFER ) {
    action_list *actions = create_action_list();
    action *action = create_action_output( OFPP_TABLE, UINT16_MAX );
    append_action( actions, action );
    ret = execute_packet_out( buffer_id, 0, actions, NULL );
    delete_action_list( actions );
    if ( ret != OFDPE_SUCCESS ) {
      uint16_t type = OFPET_FLOW_MOD_FAILED;
      uint16_t code = OFPFMFC_UNKNOWN;
      get_ofp_error( ret, &type, &code );
      send_error_message( transaction_id, type, code );
      return;
    }
    wakeup_datapath( protocol );
  }
}
Ejemplo n.º 2
0
static void
_handle_meter_mod_add( const uint32_t transaction_id, const uint16_t flags, const uint32_t meter_id, const list_element *bands ) {
    OFDPE ret = add_meter_entry( flags, meter_id, bands );
    if ( ret != OFDPE_SUCCESS ) {
        uint16_t type, code;
        if ( get_ofp_error( ret, &type, &code ) == true ) {
            send_error_message( transaction_id, type, code );
        } else {
            send_error_message( transaction_id, OFPET_METER_MOD_FAILED, OFPMMFC_UNKNOWN );
        }
    }
}
Ejemplo n.º 3
0
static void
_handle_meter_mod_delete( const uint32_t transaction_id, const uint32_t meter_id ) {
    OFDPE ret = delete_meter_entry( meter_id );
    if ( ret != OFDPE_SUCCESS ) {
        uint16_t type, code;
        if ( get_ofp_error( ret, &type, &code ) == true ) {
            send_error_message( transaction_id, type, code );
        } else {
            send_error_message( transaction_id, OFPET_METER_MOD_FAILED, OFPMMFC_UNKNOWN );
        }
    }
}
Ejemplo n.º 4
0
// protocol to datapath message.
static void
_handle_set_config( const uint32_t transaction_id, const uint16_t flags, uint16_t miss_send_len, void *user_data ) {
  UNUSED( user_data );

  switch_config config;
  memset( &config, 0, sizeof( switch_config ) );
  config.flags = flags;
  config.miss_send_len = miss_send_len;
  OFDPE ret = set_switch_config( &config );
  if ( ret != OFDPE_SUCCESS ) {
    uint16_t type = OFPET_SWITCH_CONFIG_FAILED;
    uint16_t code = OFPSCFC_EPERM;
    get_ofp_error( ret, &type, &code );
    send_error_message( transaction_id, type, code );
  }
}
Ejemplo n.º 5
0
static void
_handle_port_mod( uint32_t transaction_id, uint32_t port_no, uint8_t hw_addr[],
                  uint32_t config, uint32_t mask, uint32_t advertise, void *user_data ) {
  UNUSED( hw_addr );
  UNUSED( advertise );
  UNUSED( user_data );
  
  /*
   * the update_port_config() performs a port lookup.
   */
  OFDPE ret = update_port( port_no, config, mask );
  if ( ret != OFDPE_SUCCESS ) {
    uint16_t type = OFPET_PORT_MOD_FAILED;
    uint16_t code = OFPPMFC_EPERM;
    get_ofp_error( ret, &type, &code );
    send_error_message( transaction_id, type, code );
  }
}
Ejemplo n.º 6
0
static void
_handle_get_config_request( const uint32_t transaction_id, void * user_data ) {
  UNUSED( user_data );
  
  switch_config config;
  memset( &config, 0, sizeof( switch_config ) );

  OFDPE ret = get_switch_config( &config );
  if ( ret != OFDPE_SUCCESS ) {
    uint16_t type = OFPET_BAD_REQUEST;
    uint16_t code = OFPBRC_EPERM;
    get_ofp_error( ret, &type, &code );
    send_error_message( transaction_id, type, code );
  }

  buffer *get_config_reply = create_get_config_reply( transaction_id, config.flags, config.miss_send_len );
  switch_send_openflow_message( get_config_reply );
  free_buffer( get_config_reply );
}
Ejemplo n.º 7
0
static void
handle_flow_mod_delete( const uint32_t transaction_id, const uint64_t cookie,
                        const uint64_t cookie_mask, const uint8_t table_id,
                        const uint16_t idle_timeout, const uint16_t hard_timeout,
                        const uint16_t priority, const uint32_t buffer_id,
                        const uint32_t out_port, const uint32_t out_group,
                        const uint16_t flags, const oxm_matches *oxm_match,
                        const openflow_instructions *instructions,
                        const bool strict ) {

  UNUSED( idle_timeout );
  UNUSED( hard_timeout );
  UNUSED( priority );
  UNUSED( buffer_id );
  UNUSED( flags );
  UNUSED( instructions );
  
  match *match = create_match();
  if ( oxm_match != NULL && oxm_match->n_matches > 0 ) {
    for ( list_element *e = oxm_match->list; e != NULL; e = e->next ) {
      oxm_match_header *hdr = e->data;
      assign_match( match, hdr );
    }
  }

  OFDPE ret = OFDPE_FAILED;
  if ( strict ) {
    ret = delete_flow_entry_strict( table_id, match, cookie, cookie_mask, priority, out_port, out_group );
  }
  else {
    ret = delete_flow_entries( table_id, match, cookie, cookie_mask, out_port, out_group );
  }

  if ( ret != OFDPE_SUCCESS ) {
    uint16_t type = OFPET_FLOW_MOD_FAILED;
    uint16_t code = OFPFMFC_UNKNOWN;
    get_ofp_error( ret, &type, &code );
    send_error_message( transaction_id, type, code );
  }

  delete_match( match );
}
Ejemplo n.º 8
0
static void
handle_flow_mod_add( const uint32_t transaction_id, const uint64_t cookie, 
                     const uint64_t cookie_mask, const uint8_t table_id,
                     const uint16_t idle_timeout, const uint16_t hard_timeout,
                     const uint16_t priority, const uint32_t buffer_id,
                     const uint16_t flags, const oxm_matches *oxm,
                     const openflow_instructions *instructions,
                     struct protocol *protocol ) {
  UNUSED( cookie_mask );
  /*
   * currently if flags set OFPFF_SEND_FLOW_REM and OFPFF_RESET_COUNTS are the only allowed value.
   */
  if ( ( flags & ~( OFPFF_SEND_FLOW_REM | OFPFF_RESET_COUNTS ) ) != 0 ) {
    send_error_message( transaction_id, OFPET_FLOW_MOD_FAILED, OFPFMFC_BAD_FLAGS );
    return;
  }
  /*
   * The use of OFPTT_ALL is only valid for delete requests.
   */
  if ( table_id == OFPTT_ALL ) {
    send_error_message( transaction_id, OFPET_FLOW_MOD_FAILED, OFPFMFC_BAD_TABLE_ID );
    return;
  }

  /*
   * If no buffered packet is associated with a flow mod it must be set
   * to OFP_NO_BUFFER otherwise it must be equal to the buffer_id sent to
   * controller by a packet-in message.
   */

  match *match = create_match();
  if ( oxm != NULL && oxm->n_matches > 0 ) {
    
#ifdef DEBUG    
    char oxm_str[ 2048 ];
    match_to_string( oxm, oxm_str, sizeof( oxm_str ) );
    printf( "%s\n", oxm_str );
#endif
    
    for ( list_element *e = oxm->list; e != NULL; e = e->next ) {
      oxm_match_header *hdr = e->data;
      assign_match( match, hdr );
    }
  }

  instruction_set *instruction_set = create_instruction_set();
  if ( instructions != NULL ) {
    OFDPE ret = assign_instructions( instruction_set, instructions->list );
    if ( ret != OFDPE_SUCCESS ) {
      send_error_message( transaction_id, OFPET_FLOW_MOD_FAILED, OFPBIC_UNSUP_INST );
      delete_instruction_set( instruction_set );
      delete_match( match );
      return;
    }
  }

  /*
   * When a flow entry is inserted in a table, its flags field is set with the
   * values from the message.
   * When a flow entry is inserted in a table, its idle_timeout and
   * hard_timeout fields are set with the values from the message.
   * When a flow entry is inserted in a table through an OFPFC_ADD message,
   * its cookie field is set to the provided value
   */
  flow_entry *new_entry = alloc_flow_entry( match, instruction_set, priority,
                                            idle_timeout, hard_timeout, flags, cookie );
  if ( new_entry == NULL ) {
    /*
     * TODO we should send a more appropriate error once we worked out the
     * datapath errors.
     */
    delete_instruction_set( instruction_set );
    delete_match( match );
    send_error_message( transaction_id, OFPET_FLOW_MOD_FAILED, OFPFMFC_UNKNOWN );
    return;
  }

  OFDPE ret = add_flow_entry( table_id, new_entry, flags );
  if ( ret != OFDPE_SUCCESS ) {
    error( "Failed to add a flow entry ( ret = %d ).", ret );
    delete_instruction_set( instruction_set );
    delete_match( match );

    uint16_t type = OFPET_FLOW_MOD_FAILED;
    uint16_t code = OFPFMFC_UNKNOWN;
    get_ofp_error( ret, &type, &code );
    send_error_message( transaction_id, type, code );
    return;
  }

  if ( buffer_id != OFP_NO_BUFFER ) {
    action_list *actions = create_action_list();
    action *action = create_action_output( OFPP_TABLE, UINT16_MAX );
    append_action( actions, action );
    ret = execute_packet_out( buffer_id, 0, actions, NULL );
    delete_action_list( actions );
    if ( ret != OFDPE_SUCCESS ) {
      uint16_t type = OFPET_FLOW_MOD_FAILED;
      uint16_t code = OFPFMFC_UNKNOWN;
      get_ofp_error( ret, &type, &code );
      send_error_message( transaction_id, type, code );
      return;
    }
    wakeup_datapath( protocol );
  }
}