static void recv_request( const messenger_context_handle *handle, uint16_t tag, void *data, size_t len ) { UNUSED( tag ); UNUSED( data ); UNUSED( len ); buffer *reply = get_switches(); send_reply_message( handle, 0, reply->data, reply->length ); free_buffer( reply ); }
bool _send_management_application_reply( const messenger_context_handle *handle, const management_application_reply *reply ) { if ( handle == NULL || reply == NULL ) { error( "Both context handle and reply message must not be NULL ( handle = %p, reply = %p ).", handle, reply ); return false; } bool ret = send_reply_message( handle, MESSENGER_MANAGEMENT_REPLY, reply, ( size_t ) ntohl( reply->header.length ) ); if ( !ret ) { error( "Failed to send an application specific management reply." ); return false; } return true; }
static void handle_dump_filter_request( const messenger_context_handle *handle, dump_packetin_filter_request *request ) { assert( handle != NULL ); assert( request != NULL ); buffer *buf = alloc_buffer_with_length( 2048 ); dump_packetin_filter_reply *reply = append_back_buffer( buf, offsetof( dump_packetin_filter_reply, entries ) ); reply->status = PACKETIN_FILTER_OPERATION_SUCCEEDED; reply->n_entries = 0; struct ofp_match match; ntoh_match( &match, &request->criteria.match ); uint16_t priority = ntohs( request->criteria.priority ); if ( request->flags & PACKETIN_FILTER_FLAG_MATCH_STRICT ) { list_element *services = lookup_match_strict_entry( match, priority ); while ( services != NULL ) { if ( strcmp( services->data, request->criteria.service_name ) == 0 ) { packetin_filter_entry *entry = append_back_buffer( buf, sizeof( packetin_filter_entry ) ); reply->n_entries++; entry->match = request->criteria.match; entry->priority = request->criteria.priority; strncpy( entry->service_name, services->data, sizeof( entry->service_name ) ); entry->service_name[ sizeof( entry->service_name ) - 1 ] = '\0'; } services = services->next; } } else { map_match_table( match, dump_filter_walker, buf ); } reply->n_entries = htonl( reply->n_entries ); bool ret = send_reply_message( handle, MESSENGER_DUMP_PACKETIN_FILTER_REPLY, buf->data, buf->length ); free_buffer( buf ); if ( ret == false ) { error( "Failed to send a dump packetin filter reply." ); } }
static void handle_add_filter_request( const messenger_context_handle *handle, add_packetin_filter_request *request ) { assert( handle != NULL ); assert( request != NULL ); request->entry.service_name[ MESSENGER_SERVICE_NAME_LENGTH - 1 ] = '\0'; if ( strlen( request->entry.service_name ) == 0 ) { error( "Service name must be specified." ); return; } struct ofp_match match; ntoh_match( &match, &request->entry.match ); bool ret = add_packetin_match_entry( match, ntohs( request->entry.priority ), request->entry.service_name ); add_packetin_filter_reply reply; memset( &reply, 0, sizeof( add_packetin_filter_reply ) ); reply.status = ( uint8_t ) ( ret ? PACKETIN_FILTER_OPERATION_SUCCEEDED : PACKETIN_FILTER_OPERATION_FAILED ); ret = send_reply_message( handle, MESSENGER_ADD_PACKETIN_FILTER_REPLY, &reply, sizeof( add_packetin_filter_reply ) ); if ( ret == false ) { error( "Failed to send an add filter reply." ); } }
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 ); }