Пример #1
0
static list_element *
lookup_flow_entries_with_table_id( const uint8_t table_id, const match *match, const uint16_t priority,
                                   const bool strict, const bool update_counters ) {
  assert( valid_table_id( table_id ) );

  if ( get_logging_level() >= LOG_DEBUG ) {
    debug( "Looking up flow entries ( table_id = %#x, match = %p, priority = %u, strict = %s, update_counters = %s ).",
           table_id, match, priority, strict ? "true" : "false", update_counters ? "true" : "false" );
    if ( match != NULL ) {
      dump_match( match, debug );
    }
  }

  flow_table *table = get_flow_table( table_id );
  if ( table == NULL ) {
    return NULL;
  }

  if ( update_counters ) {
    increment_lookup_count( table_id );
  }

  list_element *head = NULL;
  create_list( &head );

  for ( list_element *e = table->entries; e != NULL; e = e->next ) {
    flow_entry *entry = e->data;
    assert( entry != NULL );
    if ( strict ) {
      if ( entry->priority < priority ) {
        break;
      }
      if ( priority == entry->priority && compare_match_strict( match, entry->match ) ) {
        if ( update_counters ) {
          increment_matched_count( table_id );
        }
        append_to_tail( &head, entry );
        break;
      }
    }
    else {
      if ( compare_match( match, entry->match ) ) {
        if ( update_counters ) {
          increment_matched_count( table_id );
        }
        append_to_tail( &head, entry );
      }
    }
  }

  return head;
}
Пример #2
0
static list_element *
get_switch_ports_to_output( const uint32_t port_no, const uint32_t in_port ) {
  assert( port_no > 0 );
  assert( in_port <= OFPP_MAX );

  switch_port_list ports;
  create_list( &ports.list );
  ports.in_port = in_port;

  switch ( port_no ) {
    case OFPP_IN_PORT:
    {
      switch_port *port = lookup_switch_port( in_port );
      if ( port != NULL ) {
        append_to_tail( &ports.list, port );
      }
    }
    break;

    case OFPP_FLOOD:
    case OFPP_ALL:
    {
      foreach_switch_port( append_switch_port_to_list, &ports );
    }
    break;

    case OFPP_TABLE:
    case OFPP_NORMAL:
    case OFPP_CONTROLLER:
    case OFPP_LOCAL:
    case OFPP_ANY:
    {
      warn( "Invalid port number ( port_no = %u, in_port = %u ).", port_no, in_port );
    }
    break;

    default:
    {
      switch_port *port = lookup_switch_port( port_no );
      if ( port != NULL ) {
        append_to_tail( &ports.list, port );
      }
    }
    break;
  }

  return ports.list;
}
Пример #3
0
OFDPE
add_meter_entry( const uint16_t flags, const uint32_t meter_id, const list_element *bands ) {
  assert( table != NULL );

  if ( meter_id == 0 || ( meter_id > OFPM_MAX && meter_id != OFPM_CONTROLLER )) {
    return ERROR_OFDPE_METER_MOD_FAILED_INVALID_METER;
  }

  meter_entry *entry = alloc_meter_entry( flags, meter_id, bands );
  if ( entry == NULL ) {
    return ERROR_INVALID_PARAMETER;
  }

  OFDPE ret = OFDPE_SUCCESS;
  if ( !lock_pipeline() ) {
    free_meter_entry( entry );
    return ERROR_LOCK;
  }
  if ( NULL != lookup_meter_entry( entry->meter_id ) ) {
    ret = ERROR_OFDPE_METER_MOD_FAILED_METER_EXISTS;
    free_meter_entry( entry );
  } else {
    append_to_tail( &table->entries, entry );
  }
  if ( !unlock_pipeline() ) {
    free_meter_entry( entry );
    return ERROR_UNLOCK;
  }
  return ret;
}
Пример #4
0
static void
handle_packet_in( uint64_t datapath_id, uint32_t transaction_id,
                  uint32_t buffer_id, uint16_t total_len,
                  uint16_t in_port, uint8_t reason, const buffer *data,
                  void *user_data ) {
  services *services = user_data;
  list_element **list_head = &services->arp_or_unicast;

  packet_info *packet_info = data->user_data;
  if ( !packet_type_arp( data ) && ( packet_info->eth_macda[ 0 ] & 0x1 ) == 0x1 ) {
    list_head = &services->broadcast;
  }
  if ( *list_head == NULL ) {
    return;
  }
  buffer *buf = create_packet_in( transaction_id, buffer_id, total_len, in_port,
                                  reason, data );

  openflow_service_header_t *message;
  message = append_front_buffer( buf, sizeof( openflow_service_header_t ) );
  message->datapath_id = htonll( datapath_id );
  message->service_name_length = htons( 0 );
  char *service_name = ( *list_head )->data;
  if ( send_message( service_name, MESSENGER_OPENFLOW_MESSAGE, buf->data, buf->length ) ) {
    debug( "Sending a message to %s.", service_name );
  }
  free_buffer( buf );
  if ( ( *list_head )->next != NULL ) {
    //round robin
    delete_element( list_head, service_name );
    append_to_tail( list_head, service_name );
  }
}
Пример #5
0
void
add_outbound_port( list_element **switches, uint64_t dpid, uint16_t port_no ) {
  assert( port_no != 0 );

  info( "Adding a port: dpid = %#" PRIx64 ", port = %u", dpid, port_no );

  // lookup switch
  switch_info *sw = lookup_switch( *switches, dpid );
  if ( sw == NULL ) {
    sw = allocate_switch( dpid );
    append_to_tail( switches, sw );
  }

  port_info *new_port = allocate_port( dpid, port_no );
  append_to_tail( &sw->ports, new_port );
}
Пример #6
0
OFDPE
add_group_entry( group_entry *entry ) {
  assert( table != NULL );

  if ( entry == NULL ) {
    return ERROR_INVALID_PARAMETER;
  }

  if ( !valid_group_id( entry->group_id ) ) {
    return ERROR_OFDPE_GROUP_MOD_FAILED_INVALID_GROUP;
  }

  if ( group_exists( entry->group_id ) ) {
    return ERROR_OFDPE_GROUP_MOD_FAILED_GROUP_EXISTS;
  }

  if ( !lock_pipeline() ) {
    return ERROR_LOCK;
  }

  OFDPE ret = validate_group_entry( entry );
  if ( ret == OFDPE_SUCCESS ) {
    append_to_tail( &table->entries, entry );
  }

  if ( !unlock_pipeline() ) {
    return ERROR_UNLOCK;
  }

  return ret;
}
Пример #7
0
OFDPE
delete_flow_entries_by_group_id( const uint32_t group_id ) {
  assert( valid_group_id( group_id ) );

  if ( !lock_pipeline() ) {
    return ERROR_LOCK;
  }

  list_element *delete_us = NULL;
  create_list( &delete_us );

  for ( uint8_t table_id = 0; table_id <= FLOW_TABLE_ID_MAX; table_id++ ) {
    flow_table *table = get_flow_table( table_id );
    assert( table != NULL );
    for ( list_element *e = table->entries; e != NULL; e = e->next ) {
      assert( e->data != NULL );
      flow_entry *entry = e->data;
      if ( instructions_have_output_group( entry->instructions, group_id ) ) {
        append_to_tail( &delete_us, e->data );
      }
    }
  }

  delete_flow_entries_in_list( delete_us, 0, 0, OFPP_ANY, OFPG_ANY, OFPRR_GROUP_DELETE );

  if ( delete_us != NULL ) {
    delete_list( delete_us );
  }

  if ( !unlock_pipeline() ) {
    return ERROR_UNLOCK;
  }

  return OFDPE_SUCCESS;
}
Пример #8
0
static bool
insert_wildcards_match_entry( list_element **wildcards_table, struct ofp_match *match, uint16_t priority, void *data ) {
  assert( match != NULL );

  list_element *element;
  for ( element = *wildcards_table; element != NULL; element = element->next ) {
    match_entry *entry = element->data;
    if ( entry->priority < priority ) {
      break;
    }
    assert( entry != NULL );
    if ( entry->priority == priority && compare_match_strict( &entry->match, match ) ) {
      char match_string[ MATCH_STRING_LENGTH ];
      match_to_string( match, match_string, sizeof( match_string ) );
      warn( "wildcards match entry already exists ( match = [%s], priority = %u )",
            match_string, priority );
      return false;
    }
  }
  match_entry *new_entry = allocate_match_entry( match, priority, data );
  if ( element == NULL ) {
    // tail
    append_to_tail( wildcards_table, new_entry );
  }
  else if ( element == *wildcards_table ) {
    // head
    insert_in_front( wildcards_table, new_entry );
  }
  else {
    // insert before
    insert_before( wildcards_table, element->data, new_entry );
  }
  return true;
}
Пример #9
0
static void
append_switch_port_to_list( switch_port *port, void *user_data ) {
  assert( port != NULL );
  assert( user_data != NULL );

  list_element **ports = user_data;

  append_to_tail( ports, port );
}
Пример #10
0
static void
append_switch_port_to_list( switch_port *port, void *user_data ) {
  assert( port != NULL );
  assert( user_data != NULL );

  switch_port_list *ports = user_data;
  if ( ports->in_port != port->port_no ) {
    append_to_tail( &ports->list, port );
  }
}
Пример #11
0
static bool
set_match_type( int argc, char *argv[], services *services ) {
  create_list( &services->arp_or_unicast );
  create_list( &services->broadcast );
  int i;
  char *service_name;
  for ( i = 1; i < argc; i++ ) {
    if ( ( service_name = match_type( ARP_OR_UNICAST, argv[ i ] ) ) != NULL ) {
      append_to_tail( &services->arp_or_unicast, service_name );
    }
    else if ( ( service_name = match_type( BROADCAST, argv[ i ] ) ) != NULL ) {
      append_to_tail( &services->broadcast, service_name );
    }
    else {
      return false;
    }
  }

  return true;
}
Пример #12
0
static bool
append_oxm_match( oxm_matches *matches, oxm_match_header *entry ) {
  assert( matches != NULL );
  assert( entry != NULL );

  bool ret = append_to_tail( &matches->list, entry );
  if ( ret ) {
    matches->n_matches++;
  }

  return ret;
}
Пример #13
0
static void
handle_ovs_flow_removed( uint64_t datapath_id, uint32_t transaction_id, const buffer *data ) {
  assert( data != NULL );

  ovs_flow_removed *flow_removed = ( ovs_flow_removed * ) ( ( char * ) data->data - offsetof( ovs_header, subtype ) );
  uint64_t cookie = ntohll( flow_removed->cookie );
  uint16_t priority = ntohs( flow_removed->priority );
  uint8_t reason = flow_removed->reason;
  uint32_t duration_sec = ntohl( flow_removed->duration_sec );
  uint32_t duration_nsec = ntohl( flow_removed->duration_nsec );
  uint16_t idle_timeout = ntohs( flow_removed->idle_timeout );
  size_t match_length = ntohs( flow_removed->match_len );
  uint64_t packet_count = ntohll( flow_removed->packet_count );
  uint64_t byte_count = ntohll( flow_removed->byte_count );

  ovs_matches *matches = create_ovs_matches();
  size_t offset = sizeof( ovs_flow_removed );
  while ( match_length >= sizeof( ovs_match_header ) ) {
    ovs_match_header *src = ( ovs_match_header * ) ( ( char * ) flow_removed + offset );
    size_t length = get_ovs_match_length( ntohl( *src ) ) + sizeof( ovs_match_header );
    ovs_match_header *dst = xmalloc( length );
    ntoh_ovs_match( dst, src );
    append_to_tail( &matches->list, dst );
    matches->n_matches++;
    offset += length;
    match_length -= length;
  }

  char matches_str[ 256 ];
  ovs_matches_to_string( matches, matches_str, sizeof( matches_str ) );

  debug( "An Open vSwitch extended flow removed received ( datapath_id = %#" PRIx64 ", "
         "transaction_id = %#x, cookie = %#" PRIx64 ", priority = %u, reason = %#x, "
         "duration = %u.%09u, idle_timeout = %u, packet_count = %" PRIu64
         ", byte_count = %" PRIu64 ", matches = [%s], user_data = %p ).",
         datapath_id, transaction_id, cookie, priority, reason, duration_sec, duration_nsec,
         idle_timeout, packet_count, byte_count, matches_str,
         event_handlers.ovs_flow_removed_user_data );

  if ( event_handlers.ovs_flow_removed_callback != NULL ) {
    event_handlers.ovs_flow_removed_callback( datapath_id, transaction_id,
                                             cookie, priority, reason,
                                             duration_sec, duration_nsec,
                                             idle_timeout, packet_count, byte_count,
                                             matches,
                                             event_handlers.ovs_flow_removed_user_data );
  }

  delete_ovs_matches( matches );
}
Пример #14
0
OFDPE
get_port_description( const uint32_t port_no, port_description **descriptions, uint32_t *n_ports ) {
  assert( port_no > 0 || port_no == OFPP_ALL );
  assert( descriptions != NULL );
  assert( n_ports != NULL );

  if ( !lock_mutex( &mutex ) ) {
    return ERROR_LOCK;
  }

  *n_ports = 0;
  *descriptions = NULL;

  list_element *ports = NULL;
  if ( port_no != OFPP_ALL ) {
    switch_port *port = lookup_switch_port( port_no );
    if ( ports == NULL ) {
      return unlock_mutex( &mutex ) ? OFDPE_SUCCESS : ERROR_UNLOCK;
    }
    create_list( &ports );
    append_to_tail( &ports, port );
  }
  else {
    ports = get_all_switch_ports();
    if ( ports == NULL ) {
      return unlock_mutex( &mutex ) ? OFDPE_SUCCESS : ERROR_UNLOCK;
    }
  }

  *n_ports = ( uint32_t ) list_length_of( ports );
  size_t length = ( *n_ports ) * sizeof( port_description );
  *descriptions = xmalloc( length );
  memset( *descriptions, 0, length );

  port_description *description = *descriptions;
  for ( list_element *e = ports; e != NULL; e = e->next ) {
    assert( e->data != NULL );
    switch_port *port = e->data;
    assert( port->device != NULL );
    // FIXME: we assume that "port_description" is the same structure as "struct ofp_port".
    switch_port_to_ofp_port( description, port );
    description++;
  }

  if ( !unlock_mutex( &mutex ) ) {
    return ERROR_UNLOCK;
  }

  return OFDPE_SUCCESS;
}
Пример #15
0
static void
append_stat( const char *key, const uint64_t value, void *user_data ) {
  assert( key != NULL );
  assert( user_data != NULL );

  list_element **stats = user_data;

  stat_entry *entry = xmalloc( sizeof( stat_entry ) );
  memset( entry, 0, sizeof( stat_entry ) );
  memcpy( entry->key, key, sizeof( entry->key ) );
  entry->value = htonll( value );

  append_to_tail( stats, entry );
}
Пример #16
0
static OFDPE
insert_flow_entry( flow_table *table, flow_entry *entry, const uint16_t flags ) {
  assert( table != NULL );
  assert( entry != NULL );

  list_element *element = table->entries;
  while( element != NULL ) {
    list_element *next = element->next;
    flow_entry *e = element->data;
    assert( e != NULL );
    if ( e->priority < entry->priority ) {
      break;
    }
    if ( e->priority == entry->priority ) {
      if ( e->table_miss && !entry->table_miss ) {
        break;
      }
      if ( ( flags & OFPFF_CHECK_OVERLAP ) != 0 && compare_match( e->match, entry->match ) ) {
        return ERROR_OFDPE_FLOW_MOD_FAILED_OVERLAP;
      }
      if ( compare_match_strict( e->match, entry->match ) ) {
        if ( ( flags & OFPFF_RESET_COUNTS ) != 0 ) {
          entry->byte_count = e->byte_count;
          entry->packet_count = e->packet_count;
        }
        flow_table *table = get_flow_table( e->table_id );
        assert( table != NULL );
        delete_flow_entry_from_table( table, e, 0, false );
      }
    }
    element = next;
  }

  if ( element == NULL ) {
    // tail
    append_to_tail( &table->entries, entry );
  }
  else if ( element == table->entries ) {
    // head
    insert_in_front( &table->entries, entry );
  }
  else {
    // insert before
    insert_before( &table->entries, element->data, entry );
  }

  increment_active_count( table->features.table_id );

  return OFDPE_SUCCESS;
}
Пример #17
0
void
insert_match_entry( struct ofp_match *ofp_match, uint16_t priority, const char *service_name, const char *entry_name ) {
  match_entry *new_entry, *entry;
  list_element *list;

  pthread_mutex_lock( match_table_head.mutex );

  new_entry = allocate_match_entry( ofp_match, priority, service_name, entry_name );

  if ( !ofp_match->wildcards ) {
    entry = lookup_hash_entry( match_table_head.exact_table, ofp_match );
    if ( entry != NULL ) {
      warn( "insert entry exits" );
      free_match_entry( new_entry );
      pthread_mutex_unlock( match_table_head.mutex );
      return;
    }
    insert_hash_entry( match_table_head.exact_table, &new_entry->ofp_match, new_entry );
    pthread_mutex_unlock( match_table_head.mutex );
    return;
  }

  // wildcard flags are set
  for ( list = match_table_head.wildcard_table; list != NULL; list = list->next ) {
    entry = list->data;
    if ( entry->priority <= new_entry->priority ) {
      break;
    }
  }
  if ( list == NULL ) {
    // wildcard_table is null or tail
    append_to_tail( &match_table_head.wildcard_table, new_entry );
    pthread_mutex_unlock( match_table_head.mutex );
    return;
  }
  if ( list == match_table_head.wildcard_table ) {
    // head
    insert_in_front( &match_table_head.wildcard_table, new_entry );
    pthread_mutex_unlock( match_table_head.mutex );
    return;
  }

  // insert brefore
  insert_before( &match_table_head.wildcard_table, list->data, new_entry );
  pthread_mutex_unlock( match_table_head.mutex );
}
static bool
get_reflectors_to_update( list_element **reflectors_to_update, uint32_t vni ) {
  debug( "Retriving packet reflectors to update ( reflectors_to_update = %p, vni = %#x ).", reflectors_to_update, vni );

  assert( db != NULL );
  assert( reflectors_to_update != NULL );

  MYSQL_RES *result = NULL;

  bool ret = execute_query( db, "select reflectors.uri from reflectors,overlay_networks "
                            "where overlay_networks.reflector_group_id = reflectors.group_id and "
                            "overlay_networks.slice_id = %u", vni );
  if ( !ret ) {
    return false;
  }

  result = mysql_store_result( db );
  if ( result == NULL ) {
    error( "Failed to retrieve result from database ( %s ).", mysql_error( db ) );
    return false;
  }

  assert( mysql_num_fields( result ) == 1 );
  if ( mysql_num_rows( result ) == 0 ) {
    error( "Failed to retrieve packet reflector configuration ( vni = %#x ).", vni );
    mysql_free_result( result );
    return false;
  }

  create_list( reflectors_to_update );

  char *uri = NULL;
  MYSQL_ROW row;
  while ( ( row = mysql_fetch_row( result ) ) != NULL ) {
    uri = xstrdup( row[ 0 ] );
    append_to_tail( reflectors_to_update, uri );
  }

  if ( list_length_of( *reflectors_to_update ) == 0 ) {
    delete_list( *reflectors_to_update );
  }

  mysql_free_result( result );

  return true;
}
void
management_event_forward_entries_set( list_element **service_list,
                                const event_forward_operation_request *request, size_t request_len ) {
  const size_t service_name_list_len = request_len - offsetof( event_forward_operation_request, service_list );

  const char **service_name_list = xcalloc( request->n_services, sizeof( char * ) );

  // split null terminated string list.
  unsigned int n_services = 0;
  const char *name_begin = request->service_list;
  for ( size_t i = 0 ; i < service_name_list_len ; ++i ) {
    if ( request->service_list[ i ] == '\0' ) {
      service_name_list[ n_services++ ] = name_begin;
      if ( n_services == request->n_services ) {
        if ( i + 1 != service_name_list_len ) {
          warn( "Expecting %d name(s) for EVENT_FWD_ENTRY_SET, but more exist. Ignoring.", request->n_services );
        }
        break;
      }
      name_begin = &request->service_list[ i + 1 ];
    }
  }
  if ( n_services != request->n_services ) {
    warn( "Expected %d name(s) for EVENT_FWD_ENTRY_SET, but found %d.", request->n_services, n_services );
  }

  info( "Resetting event filter(s)." );
  // clear current list
  iterate_list( *service_list, xfree_data, NULL );
  delete_list( *service_list );
  create_list( service_list );

  // set new list
  for ( unsigned int i = 0 ; i < n_services ; ++i ) {
    const size_t service_name_len = strlen( service_name_list[ i ] );
    if ( service_name_len == 0 ) {
      warn( "Ignoring 0 length service name in EVENT_FWD_ENTRY_SET" );
      continue;
    }
    info( " Adding '%s' to event filter.", service_name_list[ i ] );
    append_to_tail( service_list, xstrdup( service_name_list[ i ] ) );
  }

  xfree( service_name_list );
}
Пример #20
0
/*
 * @!group Operation for existing switch
 *
 * @overload set_forward_entries_to_switch datapath_id, type, service_name, {|result, services| ... }
 * Set forwarding entries of a switch specified.
 *
 * @param [Integer] dpid Switch datapath_id
 * @param [Symbol] type Switch event type. it must be one of :vendor, :packet_in, :port_status, :state_notify
 * @param [Array<String>] service_names Name of controller to forward event.
 * @return [Boolean] true if request was sent successfully.
 *
 * @yield Callback to notify the result of operation.
 * @yieldparam result [Boolean] true if result successful.
 * @yieldparam services [Array<String>] Service Name list on forwarding entry after operation.
 */
static VALUE
set_forward_entries_to_switch( VALUE self, VALUE dpid, VALUE type,
                               VALUE service_names ) {
  debug( "%s", __func__ );
  enum efi_event_type c_type;
  if ( !event_type_symbol_to_enum( type, &c_type ) ) {
    warn( "Invalid event type was specified" );
    return Qfalse;
  }

  const uint64_t c_dpid = NUM2ULL( dpid );
  list_element *service_list = NULL;
  create_list( &service_list );
  for ( long i = 0 ; i < RARRAY( service_names )->len ; ++i ) {
    VALUE ruby_service_name = rb_ary_entry( service_names, i );
    char *c_service_name = StringValuePtr( ruby_service_name );
    if ( strlen( c_service_name ) == 0 ) {
      warn( "Ignoring empty service_name" );
      continue;
    }
    append_to_tail( &service_list, c_service_name );
  }

  callback_info *cb = xcalloc( 1, sizeof( callback_info ) );
  cb->self = self;
  cb->block = Qnil;
  if ( rb_block_given_p() == Qtrue ) {
    cb->block = rb_block_proc();
  }
  bool succ = set_switch_event_forward_entries(
                                c_dpid, c_type, service_list,
                                handle_event_forward_entry_operation_callback,
                                cb );

  delete_list( service_list );

  if ( succ ) {
    return Qtrue;
  }
  else {
    xfree( cb );
    return Qfalse;
  }
}
static void
handle_port_desc_reply( uint64_t datapath_id, uint32_t transaction_id,
                        uint16_t type, uint16_t flags, const buffer *data,
                       void *user_data ) {
  UNUSED( transaction_id );
  UNUSED( type );
  UNUSED( flags );
  show_desc *show_desc = user_data;

  desc_entry *desc = lookup_hash_entry( show_desc->db, &datapath_id );
  if ( desc == NULL ) {
    return;
  }
  append_to_tail( &desc->port_desc, duplicate_buffer( data ) );

  if ( more_requests( flags ) ) {
    return;
  }

  display_desc( &desc->desc_stats );
  display_datapath_id( datapath_id );
  for ( list_element *e = desc->port_desc; e != NULL; e = e->next ) {
    buffer *data = e->data;
    struct ofp_port *port = ( struct ofp_port  * ) data->data;
    size_t length = data->length;
    while ( length >= sizeof( struct ofp_port ) ) {
      display_port( port );
      length -= ( uint16_t ) sizeof( struct ofp_port );
      port++;
    }
    free_buffer( e->data );
  }
  delete_list( desc->port_desc );
  delete_hash_entry( show_desc->db, &datapath_id );
  show_desc->count--;
  xfree( desc );

  if ( show_desc->count == 0 ) {
    stop_trema();
  }
}
Пример #22
0
OFDPE
replace_meter_entry( const uint16_t flags, const uint32_t meter_id, const list_element *bands ) {
  assert( table != NULL );

  if ( meter_id == 0 || ( meter_id > OFPM_MAX && meter_id != OFPM_CONTROLLER )) {
    return ERROR_OFDPE_METER_MOD_FAILED_INVALID_METER;
  }

  meter_entry *entry = alloc_meter_entry( flags, meter_id, bands );
  if ( entry == NULL ) {
    return ERROR_INVALID_PARAMETER;
  }

  OFDPE ret = OFDPE_SUCCESS;
  if ( !lock_pipeline() ) {
    free_meter_entry( entry );
    return ERROR_LOCK;
  }
  meter_entry *old_entry = lookup_meter_entry( entry->meter_id );
  if ( NULL == old_entry ) {
    ret = ERROR_OFDPE_METER_MOD_FAILED_UNKNOWN_METER;
    free_meter_entry( entry );
  } else {
    entry->ref_count = old_entry->ref_count;
    entry->packet_count = old_entry->packet_count;
    entry->byte_count = old_entry->byte_count;
    entry->estimated_rate = old_entry->estimated_rate;
    entry->created_at = old_entry->created_at;
    entry->meter_at = old_entry->meter_at;
    
    delete_element( &table->entries, old_entry );
    append_to_tail( &table->entries, entry );
    free_meter_entry( old_entry );
  }
  if ( !unlock_pipeline() ) {
    free_meter_entry( entry );
    return ERROR_UNLOCK;
  }
  return ret;
}
void
management_event_forward_entry_add( list_element **service_list,
                             const event_forward_operation_request *request, size_t request_len ) {
  if ( request->n_services == 0 ) return;
  if ( request->n_services > 1 ) {
    warn( "Only 1 service name expected for EVENT_FWD_ENTRY_ADD. Ignoring others." );
  }
  const size_t service_name_len = request_len - offsetof( event_forward_operation_request, service_list );
  if ( service_name_len == 0 ) return;

  char *service_name = xcalloc( service_name_len + 1, sizeof( char ) );
  strncpy( service_name, request->service_list, service_name_len );

  const char *match = find_list_custom( *service_list, string_equal, service_name );
  if ( match == NULL ) {
    info( "Adding '%s' to event filter.", service_name );
    append_to_tail( service_list, service_name );
  }
  else {
    // already there
    xfree( service_name );
  }
}
static void
insert_data( list_element **head, const topology_link_status *s ) {
  list_element *element;
  for ( element = *head; element != NULL; element = element->next ) {
    const topology_link_status *entry = element->data;
    if ( entry->from_dpid > s->from_dpid ) {
      break;
    }
    if ( entry->from_dpid < s->from_dpid ) {
      continue;
    }
    if ( entry->from_portno > s->from_portno ) {
      break;
    }
    if ( entry->from_portno < s->from_portno ) {
      continue;
    }
    if ( entry->to_dpid > s->to_dpid ) {
      break;
    }
    if ( entry->to_dpid < s->to_dpid ) {
      continue;
    }
    if ( entry->to_portno > s->to_portno ) {
      break;
    }
  }
  if ( element == NULL ) {
    append_to_tail( head, ( void * ) ( intptr_t ) s );
  }
  else if ( element == *head ) {
    insert_in_front( head, ( void * ) ( intptr_t ) s );
  }
  else {
    insert_before( head, element->data, ( void * ) ( intptr_t ) s );
  }
}
Пример #25
0
static bool
add_packetin_match_entry( struct ofp_match match, uint16_t priority, const char *service_name ) {
  bool ( *insert_or_update_match_entry )( struct ofp_match, uint16_t, void * ) = update_match_entry;
  list_element *services = lookup_match_strict_entry( match, priority );
  if ( services == NULL ) {
    insert_or_update_match_entry = insert_match_entry;
    create_list( &services );
  }
  else {
    list_element *element;
    for ( element = services; element != NULL; element = element->next ) {
      if ( strcmp( element->data, service_name ) == 0 ) {
        char match_string[ 256 ];
        match_to_string( &match, match_string, sizeof( match_string ) );
        warn( "match entry already exists ( match = [%s], service_name = [%s] )", match_string, service_name );
        return false;
      }
    }
  }
  append_to_tail( &services, xstrdup( service_name ) );
  insert_or_update_match_entry( match, priority, services );

  return true;
}
Пример #26
0
OFDPE
get_flow_stats( const uint8_t table_id, const match *match, const uint64_t cookie, const uint64_t cookie_mask,
                const uint32_t out_port, const uint32_t out_group, flow_stats **stats, uint32_t *n_entries ) {
  assert( valid_table_id( table_id ) || table_id == FLOW_TABLE_ALL );
  assert( stats != NULL );
  assert( n_entries != NULL );

  if ( !lock_pipeline() ) {
    return ERROR_LOCK;
  }

  list_element *list = NULL;
  if ( table_id != FLOW_TABLE_ALL ) {
    list = lookup_flow_entries_with_table_id( table_id, match, 0, false, false );
  }
  else {
    list = lookup_flow_entries_from_all_tables( match, 0, false, false );
  }

  *n_entries = 0;
  list_element *entries = NULL;
  create_list( &entries );

  for ( list_element *e = list; e != NULL; e = e->next ) {
    flow_entry *entry = e->data;
    assert( entry != NULL );

    bool matched = true;

    if ( out_port != OFPP_ANY ) {
      if ( !instructions_have_output_port( entry->instructions, out_port ) ) {
        matched = false;
      }
    }
    if ( out_group != OFPG_ANY ) {
      if ( !instructions_have_output_group( entry->instructions, out_group ) ) {
        matched = false;
      }
    }

    if ( matched && cookie_mask != 0 ) {
      if ( ( entry->cookie & cookie_mask ) != ( cookie & cookie_mask ) ) {
        matched = false;
      }
    }

    if ( matched ) {
      ( *n_entries )++;
      append_to_tail( &entries, entry );
    }
  }

  if ( list != NULL ) {
    delete_list( list );
  }

  *stats = NULL;
  if ( *n_entries > 0 ) {
    *stats = xmalloc( sizeof( flow_stats ) * ( *n_entries ) );
    memset( *stats, 0, sizeof( flow_stats ) * ( *n_entries ) );
  }

  struct timespec now = { 0, 0 };
  time_now( &now );
  struct timespec diff = { 0, 0 };
  flow_stats *stat = *stats;

  for ( list_element *e = entries; e != NULL; e = e->next ) {
    flow_entry *entry = e->data;
    stat->table_id = entry->table_id;
    timespec_diff( entry->created_at, now, &diff );
    stat->duration_sec = ( uint32_t ) diff.tv_sec;
    stat->duration_nsec = ( uint32_t ) diff.tv_nsec;
    stat->priority = entry->priority;
    stat->idle_timeout = entry->idle_timeout;
    stat->hard_timeout = entry->hard_timeout;
    stat->flags = entry->flags;
    stat->cookie = entry->cookie;
    stat->packet_count = entry->packet_count;
    stat->byte_count = entry->byte_count;
    stat->match = *entry->match;
    stat->instructions = *entry->instructions;

    stat++;
  }

  if ( entries != NULL ) {
    delete_list( entries );
  }

  if ( !unlock_pipeline() ) {
    return ERROR_UNLOCK;
  }

  return OFDPE_SUCCESS;
}
Пример #27
0
OFDPE
get_port_stats( const uint32_t port_no, port_stats **stats, uint32_t *n_ports ) {
  assert( ( port_no > 0 && port_no <= OFPP_MAX ) || port_no == OFPP_ANY );
  assert( stats != NULL );
  assert( n_ports != NULL );

  if ( !lock_mutex( &mutex ) ) {
    return ERROR_LOCK;
  }

  list_element *ports = NULL;
  *n_ports = 0;
  *stats = NULL;
  if ( port_no != OFPP_ANY ) {
    switch_port *port = lookup_switch_port( port_no );
    if ( port == NULL ) {
      if ( unlock_mutex( &mutex ) !=  OFDPE_SUCCESS ) {
        return ERROR_UNLOCK;
      }
      return ERROR_OFDPE_BAD_REQUEST_BAD_PORT;
    }
    create_list( &ports );
    append_to_tail( &ports, port );
  }
  else {
    ports = get_all_switch_ports();
    if ( ports == NULL ) {
      return unlock_mutex( &mutex ) ? OFDPE_SUCCESS : ERROR_UNLOCK;
    }
  }


  *n_ports = ( uint32_t ) list_length_of( ports );
  size_t length = ( *n_ports ) * sizeof( port_stats );
  *stats = xmalloc( length );
  memset( *stats, 0, length );

  port_stats *stat = *stats;
  for ( list_element *e = ports; e != NULL; e = e->next ) {
    assert( e->data != NULL );
    switch_port *port = e->data;
    stat->port_no = port->port_no;
    assert( port->device != NULL );
    stat->rx_packets = port->device->stats.rx_packets;
    stat->tx_packets = port->device->stats.tx_packets;
    stat->rx_bytes = port->device->stats.rx_bytes;
    stat->tx_bytes = port->device->stats.tx_bytes;
    stat->rx_dropped = port->device->stats.rx_dropped;
    stat->tx_dropped = port->device->stats.tx_dropped;
    stat->rx_errors = port->device->stats.rx_errors;
    stat->tx_errors = port->device->stats.tx_errors;
    stat->rx_frame_err = port->device->stats.rx_frame_err;
    stat->rx_over_err = port->device->stats.rx_over_err;
    stat->rx_crc_err = port->device->stats.rx_crc_err;
    stat->collisions = port->device->stats.collisions;
    struct timespec duration = get_switch_port_uptime( port );
    stat->duration_sec = ( uint32_t ) duration.tv_sec;
    stat->duration_nsec = ( uint32_t ) duration.tv_nsec;
    stat++;
  }

  if ( !unlock_mutex( &mutex ) ) {
    return ERROR_UNLOCK;
  }

  return OFDPE_SUCCESS;
}
Пример #28
0
static void
append_physical_port( void *port, void *physical_ports ) {
  if ( ( ( struct ofp_phy_port * ) port )->port_no <= OFPP_MAX ) {
    append_to_tail( ( list_element ** ) physical_ports, port );
  }
}
Пример #29
0
OFDPE
get_group_stats( const uint32_t group_id, group_stats **stats, uint32_t *n_groups ) {
  assert( table != NULL );
  assert( stats != NULL );
  assert( n_groups != NULL );

  if ( !valid_group_id( group_id ) && group_id != OFPG_ALL ) {
    return ERROR_OFDPE_BAD_REQUEST_BAD_TABLE_ID;
  }

  if ( !lock_pipeline() ) {
    return ERROR_LOCK;
  }

  OFDPE ret = OFDPE_SUCCESS;

  list_element *groups = NULL;
  create_list( &groups );
  *n_groups = 0;
  if ( group_id != OFPG_ALL ) {
    group_entry *entry = lookup_group_entry( group_id );
    if ( entry == NULL ) {
      if ( !unlock_pipeline() ) {
        return ERROR_UNLOCK;
      }
      return ERROR_OFDPE_BAD_REQUEST_BAD_TABLE_ID;
    }
    append_to_tail( &groups, entry );
    ( *n_groups )++;
  }
  else {
    for ( list_element *e = table->entries; e != NULL; e = e->next ) {
      if ( e->data == NULL ) {
        continue;
      }
      group_entry *entry = e->data;
      append_to_tail( &groups, entry );
      ( *n_groups )++;
    }
  }

  *stats = NULL;
  if ( *n_groups > 0 ) {
    *stats = xmalloc( sizeof( group_stats ) * ( *n_groups ) );
    memset( *stats, 0, sizeof( group_stats ) * ( *n_groups ) );
  }

  group_stats *stat = *stats;
  for ( list_element *e = groups; e != NULL; e = e->next ) {
    assert( e->data != NULL );
    group_entry *entry = e->data;
    stat->group_id = entry->group_id;
    stat->ref_count = entry->ref_count;
    stat->packet_count = entry->packet_count;
    stat->byte_count = entry->byte_count;
    struct timespec now = { 0, 0 };
    time_now( &now );
    struct timespec diff = { 0, 0 };
    timespec_diff( entry->created_at, now, &diff );
    stat->duration_sec = ( uint32_t ) diff.tv_sec;
    stat->duration_nsec = ( uint32_t ) diff.tv_nsec;
    create_list( &stat->bucket_stats );
    for ( dlist_element *b = get_first_element( entry->buckets ); b != NULL; b = b->next ) {
      if ( b->data == NULL ) {
        continue;
      }
      bucket *bucket = b->data;
      bucket_counter *counter = xmalloc( sizeof( bucket_counter ) );
      memset( counter, 0, sizeof( bucket_counter ) );
      counter->packet_count = bucket->packet_count;
      counter->byte_count = bucket->byte_count;
      append_to_tail( &stat->bucket_stats, counter );
    }
    stat++;
  }

  if ( groups != NULL ) {
    delete_list( groups );
  }

  if ( !unlock_pipeline() ) {
    return ERROR_UNLOCK;
  }

  return ret;
}
Пример #30
0
static bool
parse_argument( int argc, char *argv[] ) {

  bool type_specified = false;

  create_list( &service_names );

  int c;
  while ( ( c = getopt_long( argc, argv, short_options, long_options, NULL ) ) != -1 ) {
    switch ( c ) {
      case 'm':
        sw_manager = true;
        break;

      case 's':
        sw_manager = false;
        if ( !string_to_datapath_id( optarg, &dpid ) ) {
          error( "Invalid dpid '%s' specified. ", optarg );
          usage();
          exit( EXIT_FAILURE );
          return false;
        }
        break;

      case 't': // add
        type_specified = true;
        if ( false ) {
        }
        else if ( strcasecmp( "vendor", optarg ) == 0 ) {
          type = EVENT_FORWARD_TYPE_VENDOR;
        }
        else if ( strcasecmp( "packet_in", optarg ) == 0 ) {
          type = EVENT_FORWARD_TYPE_PACKET_IN;
        }
        else if ( strcasecmp( "port_status", optarg ) == 0 ) {
          type = EVENT_FORWARD_TYPE_PORT_STATUS;
        }
        else if ( strcasecmp( "state_notify", optarg ) == 0 ) {
          type = EVENT_FORWARD_TYPE_STATE_NOTIFY;
        }
        else {
          error( "Invalid type '%s' specified. Must e one of vendor, packet_in, port_status, or state_notify\n", optarg );
          usage();
          exit( EXIT_FAILURE );
          return false;
        }
        break;

      default:
        error( "Encountered unknown option." );
        usage();
        exit( EXIT_FAILURE );
        return false;
        break;
    }
  }

  if ( !type_specified ) {
    error( "Event Type was not specified with -t option.\n" );
    usage();
    exit( EXIT_FAILURE );
    return false;
  }

  if ( optind >= argc ) {
    error( "Service names were not specified.\n" );
    usage();
    exit( EXIT_FAILURE );
    return false;
  }

  int i;
  for ( i = optind; i < argc; ++i ) {
    char *service_name = strtok( argv[ i ], "," );
    if ( service_name != NULL ) {
      append_to_tail( &service_names, service_name );
      while ( ( service_name = strtok( NULL, "," ) ) != NULL ) {
        append_to_tail( &service_names, service_name );
      }
    }
  }

  return true;
}