group_entry *
lookup_group_entry( const uint32_t group_id ) {
  assert( table != NULL );
  assert( valid_group_id( group_id ) );

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

  group_entry *entry = NULL;
  bool found = false;
  for ( list_element *element = table->entries; element != NULL; element = element->next ) {
    if ( element->data == NULL ) {
      continue;
    }
    entry = element->data;
    if ( entry->group_id == group_id ) {
      found = true;
      break;
    }
  }

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

  return found == true ? entry : NULL;
}
Beispiel #2
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;
}
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;
}
void
decrement_reference_count( const uint32_t group_id ) {
  assert( table != NULL );
  assert( valid_group_id( group_id ) );

  if ( !lock_pipeline() ) {
    error( "Failed to lock pipeline." );
    return;
  }

  group_entry *entry = lookup_group_entry( group_id );
  if ( entry != NULL ) {
    entry->ref_count--;
  }

  if ( !unlock_pipeline() ) {
    error( "Failed to unlock pipeline." );
  }
}
OFDPE
update_group_entry( const uint32_t group_id, const uint8_t type, bucket_list *buckets ) {
  assert( table != NULL );

  if ( !valid_group_id( group_id ) ) {
    return ERROR_OFDPE_GROUP_MOD_FAILED_INVALID_GROUP;
  }

  if ( !valid_group_type( type ) ) {
    return ERROR_OFDPE_GROUP_MOD_FAILED_INVALID_GROUP;
  }

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

  OFDPE ret = OFDPE_SUCCESS;
  group_entry *entry = lookup_group_entry( group_id );
  if ( entry == NULL ) {
    ret = ERROR_OFDPE_GROUP_MOD_FAILED_UNKNOWN_GROUP;
  }

  if ( ret == OFDPE_SUCCESS ) {
    ret = validate_buckets( entry->type, buckets );
  }

  if ( ret == OFDPE_SUCCESS ) {
    if ( entry->buckets != NULL ) {
      delete_action_bucket_list( entry->buckets );
    }
    entry->type = type;
    entry->buckets = buckets;
  }

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

  return ret;
}
OFDPE
delete_group_entry( const uint32_t group_id ) {
  assert( table != NULL );

  if ( !valid_group_id( group_id ) ) {
    return ERROR_OFDPE_GROUP_MOD_FAILED_INVALID_GROUP;
  }

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

  if ( group_id != OFPG_ALL ) {
    group_entry *entry = lookup_group_entry( group_id );
    if ( entry != NULL ) {
      delete_element( &table->entries, entry );
      delete_flow_entries_by_group_id( entry->group_id );
      free_group_entry( entry );
    }
  }
  else {
    for ( list_element *element = table->entries; element != NULL; element = element->next ) {
      if ( element->data == NULL ) {
        continue;
      }
      group_entry *entry = element->data;
      delete_flow_entries_by_group_id( entry->group_id );
      free_group_entry( entry );
    }
    delete_list( table->entries );
    create_list( &table->entries );
  }

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

  return OFDPE_SUCCESS;
}
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;
}