OFDPE get_meter_stats( const uint32_t meter_id, meter_entry** entries, uint32_t *count ) { OFDPE ret = OFDPE_SUCCESS; if ( !lock_pipeline() ) { return ERROR_UNLOCK; } *entries = NULL; *count = 0; if ( meter_id == OFPM_ALL ) { *count = list_length_of(table->entries); meter_entry *head = xcalloc(*count, sizeof(meter_entry)); int i=0; for ( list_element *e = table->entries; e != NULL; e=e->next,i++ ) { clone_meter_entry( head+i, e->data ); } *entries = head; } else { meter_entry *entry = lookup_meter_entry( meter_id ); if ( entry == NULL ) { ret = ERROR_OFDPE_METER_MOD_FAILED_UNKNOWN_METER; } else { *count = 1; *entries = clone_meter_entry( NULL, entry ); } } if ( !unlock_pipeline() ) { return ERROR_UNLOCK; } return ret; }
bool get_ofp_group_stats( const group_stats *stats, struct ofp_group_stats **translated, size_t *length ) { assert( stats != NULL ); assert( translated != NULL ); assert( length != NULL ); unsigned int n_buckets = 0; if ( stats->bucket_stats != NULL ) { n_buckets = list_length_of( stats->bucket_stats ); } *length = offsetof( struct ofp_group_stats, bucket_stats ) + sizeof( struct ofp_bucket_counter ) * n_buckets; *translated = xmalloc( *length ); struct ofp_bucket_counter *counter = ( *translated )->bucket_stats; for ( list_element *e = stats->bucket_stats; e != NULL; e = e->next ) { if ( e->data == NULL ) { continue; } bucket_counter *bucket_counter = e->data; counter->packet_count = bucket_counter->packet_count; counter->byte_count = bucket_counter->byte_count; counter++; } ( *translated )->length = ( uint16_t ) *length; ( *translated )->group_id = stats->group_id; ( *translated )->ref_count = stats->ref_count; ( *translated )->packet_count = stats->packet_count; ( *translated )->byte_count = stats->byte_count; ( *translated )->duration_sec = stats->duration_sec; ( *translated )->duration_nsec = stats->duration_nsec; return true; }
meter_entry * alloc_meter_entry( const uint16_t flags, const uint32_t meter_id, const list_element *bands ) { meter_band *bands_array = NULL; unsigned int bands_count = list_length_of( bands ); if ( bands_count > 0 ) { bands_array = xcalloc( bands_count, sizeof( meter_entry ) ); int i=0; for ( const list_element *e = bands; e != NULL; e = e->next, i++ ) { struct ofp_meter_band_header *band = e->data; meter_band *target = bands_array+i; target->type = band->type; target->rate = band->rate; target->burst_size = band->burst_size; if (band->type == OFPMBT_DSCP_REMARK ){ target->prec_level = ((struct ofp_meter_band_dscp_remark *)band)->prec_level; } } } meter_entry *entry = xcalloc( 1, sizeof( meter_entry ) ); entry->meter_id = meter_id; entry->flags = flags; entry->bands_count = bands_count; entry->bands = bands_array; struct timespec now = { 0, 0 }; time_now( &now ); entry->created_at = now; entry->meter_at = now; return entry; }
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; }
static void handle_list_switches_reply( const list_element *switches, void *user_data ) { UNUSED( user_data ); unsigned int num_switch = list_length_of( switches ); char *list = xmalloc( 20 * num_switch + 1 ); // 20 = dpid string (18 chars) + ", " list[ 0 ] = '\0'; join( list, switches ); info( "switches = %s", list ); xfree( list ); stop_trema(); }
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; }
static void handle_features_reply ( uint64_t datapath_id, uint32_t transaction_id, uint32_t n_buffers, uint8_t n_tables, uint32_t capabilities, uint32_t actions, const list_element *phy_ports, void *user_data ) { UNUSED( user_data ); info( "datapath_id: %#" PRIx64, datapath_id ); info( "transaction_id: %#lx", transaction_id ); info( "n_buffers: %lu", n_buffers ); info( "n_tables: %u", n_tables ); info( "capabilities: %lu", capabilities ); info( "actions: %lu", actions ); info( "#ports: %d", list_length_of( phy_ports ) ); stop_trema(); }
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; }
static void handle_show_stats_request( const messenger_context_handle *handle, management_show_stats_request *request ) { assert( handle != NULL ); assert( request != NULL ); assert( ntohs( request->header.type ) == MANAGEMENT_SHOW_STATS_REQUEST ); assert( ntohl( request->header.length ) == sizeof( management_show_stats_request ) ); debug( "Handling a show stats request from %s.", handle->service_name ); list_element *stats = NULL; create_list( &stats ); foreach_stat( append_stat, &stats ); unsigned int n_stats = list_length_of( stats ); const size_t send_queue_length = 400000; // MESSENGER_RECV_BUFFER * 4 const size_t send_queue_margin = 256; // headroom for various headers unsigned int n_max_entries = ( unsigned int ) ( send_queue_length - send_queue_margin ) / sizeof( stat_entry ); management_show_stats_reply *reply = NULL; size_t length = 0; if ( n_stats <= n_max_entries ) { length = offsetof( management_show_stats_reply, entries ) + sizeof( stat_entry ) * n_stats; reply = xmalloc( length ); memset( reply, 0, length ); reply->header.type = htons( MANAGEMENT_SHOW_STATS_REPLY ); reply->header.length = htonl( ( uint32_t ) length ); reply->header.status = MANAGEMENT_REQUEST_SUCCEEDED; stat_entry *p = reply->entries; for ( list_element *e = stats; e != NULL; e = e->next ) { assert( e->data != NULL ); memcpy( p, e->data, sizeof( stat_entry ) ); p++; } } else { // TODO: Send statistics via out-of-band channel or by multiple replies. error( "Too many statistic entries ( %u > %u ).", n_stats, n_max_entries ); length = offsetof( management_show_stats_reply, entries ); reply = xmalloc( length ); memset( reply, 0, length ); reply->header.type = htons( MANAGEMENT_SHOW_STATS_REPLY ); reply->header.length = htonl( ( uint32_t ) length ); reply->header.status = MANAGEMENT_REQUEST_FAILED; } if ( stats != NULL ) { for ( list_element *e = stats; e != NULL; e = e->next ) { assert( e->data != NULL ); xfree( e->data ); } delete_list( stats ); } bool ret = send_reply_message( handle, MESSENGER_MANAGEMENT_REPLY, reply, length ); if ( ret == false ) { error( "Failed to send a show stats reply." ); } xfree( reply ); }