buffer* create_event_forward_operation_reply( enum efi_event_type type, enum efi_result result, list_element *service_list ) { buffer *buf = alloc_buffer_with_length( sizeof( event_forward_operation_reply ) + MESSENGER_SERVICE_NAME_LENGTH ); event_forward_operation_reply *rep = append_back_buffer( buf, sizeof( event_forward_operation_reply ) ); memset( rep, 0, sizeof( event_forward_operation_reply ) ); rep->type = ( uint8_t ) type; rep->result = ( uint8_t ) result; size_t reply_head_offset = sizeof( event_forward_operation_reply ); uint32_t n_services = 0; if ( service_list != NULL ) { for ( list_element *e = service_list; e != NULL; e = e->next ) { const size_t len = strlen( e->data ); char *dst = append_back_buffer( buf, len + 1 ); rep = ( event_forward_operation_reply * )( dst - reply_head_offset ); reply_head_offset += len + 1; strcpy( dst, e->data ); dst[ len ] = '\0'; ++n_services; } } rep->n_services = htonl( n_services ); return buf; }
buffer * create_pcap_packet( void* pcap_header, size_t pcap_len, void* dump_header, size_t dump_len, void* data, size_t data_len ) { size_t length = pcap_len + dump_len + data_len; assert( length != 0 ); assert( pcap_header != NULL && dump_header != NULL ); buffer *buf = alloc_buffer_with_length( length ); assert( buf != NULL ); if ( pcap_header != NULL && pcap_len > 0 ) { void *d = append_back_buffer( buf, pcap_len ); assert( d != NULL ); memcpy( d, pcap_header, pcap_len ); } if ( dump_header != NULL && dump_len > 0 ) { void *d = append_back_buffer( buf, dump_len ); assert( d != NULL ); memcpy( d, dump_header, dump_len ); } if ( data != NULL && data_len > 0 ) { void *d = append_back_buffer( buf, data_len ); assert( d != NULL ); memcpy( d, data, data_len ); } return buf; }
static buffer * create_openflow_application_message( uint64_t *datapath_id, buffer *data ) { openflow_service_header_t *message; buffer *buf; void *append; size_t append_len = 0; if ( data != NULL ) { append_len = data->length; } buf = alloc_buffer_with_length( sizeof( openflow_service_header_t ) + append_len ); message = append_back_buffer( buf, sizeof( openflow_service_header_t ) ); if ( datapath_id == NULL ) { message->datapath_id = ~0U; // FIXME: defined invalid datapath_id } else { message->datapath_id = htonll( *datapath_id ); } message->service_name_length = htons( 0 ); // TODO: append ipaddress and port if ( append_len > 0 ) { append = append_back_buffer( buf, append_len ); memcpy( append, data->data, append_len ); } return buf; }
static void read_stdin( int fd, void *data ) { UNUSED( data ); char buf[ 1024 ]; memset( buf, '\0', sizeof( buf ) ); ssize_t ret = read( fd, buf, sizeof( buf ) ); if ( ret < 0 ) { if ( errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK ) { return; } set_readable( fd, false ); error( "Read error ( errno = %s [%d] ).", strerror( errno ), errno ); return; } else if ( ret == 0 ) { return; } if ( stdin_read_buffer == NULL ) { set_readable( fd, false ); error( "Read buffer is not allocated yet" ); return; } char *p = append_back_buffer( stdin_read_buffer, ( size_t ) ret ); memcpy( p, buf, ( size_t ) ret ); char *lf = find_character( stdin_read_buffer->data, stdin_read_buffer->length, '\n' ); while ( lf != NULL ) { size_t length = ( size_t ) ( lf - ( char * ) stdin_read_buffer->data ); if ( length > 0 ) { buffer *string = alloc_buffer_with_length( length ); p = append_back_buffer( string, length ); memcpy( p, stdin_read_buffer->data, length ); relay_string( string ); free_buffer( string ); remove_front_buffer( stdin_read_buffer, length + 1 ); } else { if ( stdin_read_buffer->length > 0 ) { remove_front_buffer( stdin_read_buffer, 1 ); } } if ( stdin_read_buffer->length == 0 ) { break; } lf = find_character( stdin_read_buffer->data, stdin_read_buffer->length, '\n' ); } // truncate head room manually buffer *truncated = duplicate_buffer( stdin_read_buffer ); free_buffer( stdin_read_buffer ); stdin_read_buffer = truncated; }
static void recv_syslog_message( int fd, void *data ) { UNUSED( data ); char buf[ 1024 ]; ssize_t ret = read( fd, buf, sizeof( buf ) ); if ( ret < 0 ) { if ( errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK ) { return; } error( "Receive error ( errno = %s [%d] ).", strerror( errno ), errno ); set_readable( fd, false ); delete_fd_handler( fd ); return; } buffer *message = alloc_buffer_with_length( ( size_t ) ret ); void *p = append_back_buffer( message, ( size_t ) ret ); memcpy( p, buf, ( size_t ) ret ); relay_syslog_message( message ); free_buffer( message ); }
static void handle_delete_filter_request( const messenger_context_handle *handle, delete_packetin_filter_request *request ) { assert( handle != NULL ); assert( request != NULL ); buffer *buf = alloc_buffer_with_length( sizeof( delete_packetin_filter_reply ) ); delete_packetin_filter_reply *reply = append_back_buffer( buf, sizeof( delete_packetin_filter_reply ) ); reply->status = PACKETIN_FILTER_OPERATION_SUCCEEDED; reply->n_deleted = 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 ) { int n_deleted = delete_packetin_match_entry( match, priority, request->criteria.service_name ); reply->n_deleted += ( uint32_t ) n_deleted; } else { map_match_table( match, delete_filter_walker, buf ); } reply->n_deleted = htonl( reply->n_deleted ); bool ret = send_reply_message( handle, MESSENGER_DELETE_PACKETIN_FILTER_REPLY, buf->data, buf->length ); free_buffer( buf ); if ( ret == false ) { error( "Failed to send a dump filter reply." ); } }
/* * Creates a Vendor Request message. This message can be used * to facilitate sending of vendor-defined arbitrary data. * * @overload initialize * @example * Vendor.new * * @overload initialize(options) * @example * Vendor.new( * :vendor => 0x3000, * :data => "deadbeef".unpack( "C*" ), * :transaction_id => 123 * ) * * @param [Hash] options * the options to create a message with. * @option options [Number] :xid * @option options [Number] :transaction_id * an unsigned 32bit integer number associated with this message. * if not specified, an auto-generated value is set. * @option options [Number] :vendor * the vendor identifier. If MSB is zero low order bytes are IEEE OUI. Otherwise defined by openflow. * @option options [Array] :data * a String that holds vendor's defined arbitrary length data. * * @raise [ArgumentError] if transaction ID is not an unsigned 32-bit integer. * @raise [ArgumentError] if user data is not an array of bytes. * @raise [TypeError] if options is not a hash. * @return [Vendor] */ static VALUE vendor_init( int argc, VALUE *argv, VALUE self ) { buffer *vendor = NULL; Data_Get_Struct( self, buffer, vendor ); VALUE options = Qnil; if ( rb_scan_args( argc, argv, "01", &options ) == 0 ) { set_xid( vendor, get_transaction_id() ); } else { if ( options == Qnil ) { set_xid( vendor, get_transaction_id() ); } else { if ( rb_scan_args( argc, argv, "01", &options ) == 1 ) { Check_Type( options, T_HASH ); VALUE tmp = Qnil; VALUE xid = Qnil; tmp = rb_hash_aref( options, ID2SYM( rb_intern( "transaction_id" ) ) ); if ( tmp != Qnil ) { xid = tmp; } tmp = rb_hash_aref( options, ID2SYM( rb_intern( "xid" ) ) ); if ( tmp != Qnil ) { xid = tmp; } if ( xid != Qnil ) { validate_xid( xid ); set_xid( vendor, ( uint32_t ) NUM2UINT( xid ) ); } else { set_xid( vendor, get_transaction_id() ); } tmp = rb_hash_aref( options, ID2SYM( rb_intern( "vendor" ) ) ); if ( tmp != Qnil ) { ( ( struct ofp_vendor_header * ) ( vendor->data ) )->vendor = htonl( ( uint32_t ) NUM2UINT( tmp ) ); } tmp = rb_hash_aref( options, ID2SYM( rb_intern( "data" ) ) ); if ( tmp != Qnil ) { Check_Type( tmp, T_ARRAY ); uint16_t length = ( uint16_t ) RARRAY_LEN( tmp ); append_back_buffer( vendor, length ); set_length( vendor, length ); uint8_t *data = ( uint8_t * ) ( ( char * ) vendor->data + sizeof( struct ofp_vendor_header ) ); int i; for ( i = 0; i < length; i++ ) { data[ i ] = ( uint8_t ) FIX2INT( RARRAY_PTR( tmp )[ i ] ); } } } } } return self; }
static VALUE vendor_stats_request_alloc( VALUE klass ) { uint16_t length = 128; buffer *body = alloc_buffer_with_length( length ); void *p = append_back_buffer( body, length ); memset( p, 0xaf, length ); buffer *vendor_stats_request = create_vendor_stats_request( MY_TRANSACTION_ID, VENDOR_STATS_FLAG, VENDOR_ID, body ); return Data_Wrap_Struct( klass, NULL, free_buffer, vendor_stats_request ); }
void fill_ether_padding( buffer *buf ) { assert( buf != NULL ); if ( buf->length + ETH_FCS_LENGTH < ETH_MINIMUM_LENGTH ) { size_t padding_length = ETH_MINIMUM_LENGTH - buf->length - ETH_FCS_LENGTH; debug( "Adding %u octets padding ( original frame length = %u ).", buf->length, padding_length ); append_back_buffer( buf, padding_length ); } }
static void receive_frame( int fd, void *user_data ) { UNUSED( fd ); ether_device *device = user_data; assert( device != NULL ); if ( !device->status.up ) { return; } if ( get_max_packet_buffers_length( device->recv_queue ) <= get_packet_buffers_length( device->recv_queue ) ) { warn( "Receive queue is full ( device = %s, usage = %u/%u ).", device->name, get_packet_buffers_length( device->recv_queue ), get_max_packet_buffers_length( device->recv_queue ) ); return; } unsigned int count = 0; const unsigned int max_queue_length = get_max_packet_buffers_length( device->recv_queue ); const unsigned int max_loop_count = max_queue_length < 256 ? max_queue_length : 256; while ( count < max_loop_count ) { buffer *frame = get_buffer_from_free_buffers( device->recv_queue ); if ( frame == NULL ) { warn( "Failed to retrieve a receive buffer ( device = %s, queue usage = %u/%u ).", device->name, get_packet_buffers_length( device->recv_queue ), max_queue_length ); frame = device->recv_buffer; // Use recv_buffer as a trash. } append_back_buffer( frame, device->mtu ); ssize_t length = recv( device->fd, frame->data, frame->length, MSG_DONTWAIT ); assert( length != 0 ); if ( length < 0 ) { if ( frame != device->recv_buffer ) { mark_packet_buffer_as_used( device->recv_queue, frame ); } if ( ( errno == EINTR ) || ( errno == EAGAIN ) || ( errno == EWOULDBLOCK ) || ( errno == ENETDOWN ) ) { break; } char error_string[ ERROR_STRING_SIZE ]; error( "Receive error ( device = %s, errno = %s [%d] ).", device->name, safe_strerror_r( errno, error_string, sizeof( error_string ) ), errno ); break; } if ( frame != device->recv_buffer ) { frame->length = ( size_t ) length; enqueue_packet_buffer( device->recv_queue, frame ); } else { reset_buffer( frame ); } count++; } handle_received_frames( device ); }
static void recv_from_secure_channel( int fd, void *user_data ) { UNUSED( fd ); UNUSED( user_data ); // all queued messages should be processed before receiving new messages from remote if ( recv_queue->length > 0 ) { return; } if ( fragment_buf == NULL ) { fragment_buf = alloc_buffer_with_length( RECEIVE_BUFFFER_SIZE ); } size_t remaining_length = RECEIVE_BUFFFER_SIZE - fragment_buf->length; char *recv_buf = ( char * ) fragment_buf->data + fragment_buf->length; ssize_t recv_length = read( connection.fd, recv_buf, remaining_length ); if ( recv_length < 0 ) { if ( errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK ) { return; } error( "Receive error ( errno = %s [%d] ).", strerror( errno ), errno ); return; } if ( recv_length == 0 ) { debug( "Connection closed by peer." ); disconnected(); reconnect( NULL ); return; } fragment_buf->length += ( size_t ) recv_length; size_t read_total = 0; while ( fragment_buf->length >= sizeof( struct ofp_header ) ) { struct ofp_header *header = fragment_buf->data; uint16_t message_length = ntohs( header->length ); if ( message_length > fragment_buf->length ) { break; } buffer *message = alloc_buffer_with_length( message_length ); char *p = append_back_buffer( message, message_length ); memcpy( p, fragment_buf->data, message_length ); remove_front_buffer( fragment_buf, message_length ); enqueue_message( recv_queue, message ); read_total += message_length; } // remove headroom manually for next call if ( read_total > 0 ) { memmove( ( char * ) fragment_buf->data - read_total, fragment_buf->data, fragment_buf->length ); fragment_buf->data = ( char * ) fragment_buf->data - read_total; } while ( recv_message_from_secure_channel() == true ); }
/* * @overload initialize(transaction_id=nil, type=OFPET_HELLO_FAILED, code=OFPHFC_INCOMPATIBLE, user_data=nil) * * @param [Number] transaction_id * a positive number, not recently attached to any previous pending commands to * guarantee message integrity auto-generated if not specified. * * @param [Number] type * a command or action that failed. Defaults to +OFPET_HELLO_FAILED+ if * not specified. * * @param [Number] code * the reason of the failed type error. Defaults to +OFPHFC_INCOMPATIBLE+ if * not specified. * * @param [String] user_data * a more user friendly explanation of the error. Defaults to nil if not * specified. * * @example Instantiate with type and code * Error.new(OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE) * * @example Instantiate with transaction_id, type and code. * Error.new(1234, OFPET_BAD_ACTION, OFPBAC_BAD_VENDOR) * * @example Instantiate with transaction_id, type, code, user_data * Error.new(6789, OFPET_FLOW_MOD_FAILED, OFPFMFC_BAD_EMERG_TIMEOUT, "this is a test") * * @raise [ArgumentError] if transaction id is negative. * @raise [ArgumentError] if user data is not a string. * * @return [Error] * an object that encapsulates the +OFPT_ERROR+ openflow message. */ static VALUE error_new( int argc, VALUE *argv, VALUE klass ) { buffer *data = NULL; uint32_t xid = get_transaction_id(); VALUE xid_r; VALUE user_data; VALUE type_r; VALUE code_r; uint16_t type; uint16_t code; switch ( argc ) { case 2: // type, code specified. rb_scan_args( argc, argv, "02", &type_r, &code_r ); type = ( uint16_t ) NUM2UINT( type_r ); code = ( uint16_t ) NUM2UINT( code_r ); break; case 3: // transaction id, type, code specified. rb_scan_args( argc, argv, "03", &xid_r, &type_r, &code_r ); if ( NUM2INT( xid_r ) < 0 ) { rb_raise( rb_eArgError, "Transaction ID must be >= 0" ); } xid = ( uint32_t ) NUM2UINT( xid_r ); type = ( uint16_t ) NUM2UINT( type_r ); code = ( uint16_t ) NUM2UINT( code_r ); break; case 4: rb_scan_args( argc, argv, "04", &xid_r, &type_r, &code_r, &user_data ); if ( NUM2INT( xid_r ) < 0 ) { rb_raise( rb_eArgError, "Transaction ID must be >= 0" ); } if ( rb_obj_is_kind_of( user_data, rb_cString ) == Qfalse ) { rb_raise( rb_eArgError, "User data must be a string" ); } xid = ( uint32_t ) NUM2UINT( xid_r ); type = ( uint16_t ) NUM2UINT( type_r ); code = ( uint16_t ) NUM2UINT( code_r ); uint16_t length = ( u_int16_t ) RSTRING_LEN( user_data ); data = alloc_buffer_with_length( length ); void *p = append_back_buffer( data, length ); memcpy( p, RSTRING_PTR( user_data ), length ); break; default: type = OFPET_HELLO_FAILED; code = OFPHFC_INCOMPATIBLE; break; } buffer *error = create_error( xid, type, code, data ); if ( data != NULL ) { free_buffer( data ); } return Data_Wrap_Struct( klass, NULL, free_buffer, error ); }
static void relay_string( buffer *string ) { // retrieve current time struct timespec now; if ( clock_gettime( CLOCK_REALTIME, &now ) == -1 ) { error( "Failed to retrieve system-wide real-time clock ( %s [%d] ).", strerror( errno ), errno ); return; } // allocate buffer char *service_name = xstrdup( get_trema_name() ); uint16_t service_name_length = ( uint16_t ) ( strlen( service_name ) + 1 ); size_t buffer_length = sizeof( message_dump_header ) + service_name_length + sizeof( syslog_dump_header ) + string->length + 1; buffer *buf = alloc_buffer_with_length( buffer_length ); // syslog_dump_header + service_name message_dump_header *mdh = append_back_buffer( buf, sizeof( message_dump_header ) ); mdh->sent_time.sec = htonl( ( uint32_t ) now.tv_sec ); mdh->sent_time.nsec = htonl( ( uint32_t ) now.tv_nsec ); mdh->app_name_length = htons( 0 ); mdh->service_name_length = htons( service_name_length ); mdh->data_length = htonl( ( uint32_t ) ( sizeof( text_dump_header ) + string->length + 1 ) ); void *svn = append_back_buffer( buf, service_name_length ); memcpy( svn, service_name, service_name_length ); xfree( service_name ); // text_dump_header text_dump_header *tdh = append_back_buffer( buf, sizeof( text_dump_header ) ); tdh->sent_time.sec = htonl( ( uint32_t ) now.tv_sec ); tdh->sent_time.nsec = htonl( ( uint32_t ) now.tv_nsec ); // message void *p = append_back_buffer( buf, string->length + 1 ); memset( p, '\0', string->length + 1 ); memcpy( p, string->data, string->length ); bool ret = send_message( dump_service_name, MESSENGER_DUMP_TEXT, buf->data, buf->length ); if ( !ret ) { error( "Failed to relay syslog message." ); } free_buffer( buf ); }
void test_fill_ether_padding_succeeds_if_length_is_less_than_ETH_MINIMUM_LENGTH() { buffer *buffer = alloc_buffer_with_length( ( size_t ) ETH_MINIMUM_LENGTH - ETH_FCS_LENGTH - 1 ); append_back_buffer( buffer, ETH_MINIMUM_LENGTH - ETH_FCS_LENGTH - 1 ); fill_ether_padding( buffer ); assert_int_equal ( ( int ) buffer->length, ETH_MINIMUM_LENGTH - ETH_FCS_LENGTH ); free_buffer( buffer ); }
static void service_recv( uint16_t message_type, void *data, size_t data_len ) { buffer *buf; void *msg; buf = alloc_buffer_with_length( data_len ); msg = append_back_buffer( buf, data_len ); memcpy( msg, data, data_len ); service_recv_from_application( message_type, buf ); }
uint16_t fill_ether_padding( buffer *buf ) { die_if_NULL( buf ); size_t padding_length = 0; if ( buf->length + ETH_FCS_LENGTH < ETH_MINIMUM_LENGTH ) { padding_length = ETH_MINIMUM_LENGTH - buf->length - ETH_FCS_LENGTH; debug( "Adding %u octets padding ( original frame length = %u ).", buf->length, padding_length ); append_back_buffer( buf, padding_length ); } return ( uint16_t ) padding_length; }
static buffer * setup_dummy_ether_packet( size_t length ) { buffer *ether_buffer = alloc_buffer_with_length( length ); alloc_packet( ether_buffer ); append_back_buffer( ether_buffer, length ); packet_info( ether_buffer )->l2_data.eth = ether_buffer->data; memcpy( ( char * ) packet_info( ether_buffer )->l2_data.eth->macda, macda, ETH_ADDRLEN ); memcpy( ( char * ) packet_info( ether_buffer )->l2_data.eth->macsa, macsa, ETH_ADDRLEN ); packet_info( ether_buffer )->l2_data.eth->type = htons( ETH_ETHTYPE_ARP ); return ether_buffer; }
VALUE echo_init( int argc, VALUE *argv, VALUE self ) { buffer *echo = NULL; Data_Get_Struct( self, buffer, echo ); VALUE options = Qnil; if ( rb_scan_args( argc, argv, "01", &options ) == 0 ) { set_xid( echo, get_transaction_id() ); } else { if ( options == Qnil ) { set_xid( echo, get_transaction_id() ); } else if ( rb_obj_is_kind_of( options, rb_cInteger ) == Qtrue ) { validate_xid( options ); set_xid( echo, ( uint32_t ) NUM2UINT( options ) ); } else { Check_Type( options, T_HASH ); VALUE tmp = Qnil; VALUE xid = Qnil; tmp = rb_hash_aref( options, ID2SYM( rb_intern( "transaction_id" ) ) ); if ( tmp != Qnil ) { xid = tmp; } tmp = rb_hash_aref( options, ID2SYM( rb_intern( "xid" ) ) ); if ( tmp != Qnil ) { xid = tmp; } if ( xid != Qnil ) { validate_xid( xid ); set_xid( echo, ( uint32_t ) NUM2UINT( xid ) ); } else { set_xid( echo, get_transaction_id() ); } VALUE user_data = rb_hash_aref( options, ID2SYM( rb_intern( "user_data" ) ) ); if ( user_data != Qnil ) { Check_Type( user_data, T_STRING ); uint16_t length = ( uint16_t ) RSTRING_LEN( user_data ); append_back_buffer( echo, length ); set_length( echo, ( uint16_t ) ( sizeof( struct ofp_header ) + length ) ); memcpy( ( char * ) echo->data + sizeof( struct ofp_header ), RSTRING_PTR( user_data ), length ); } } } return self; }
/* * @overload initialize(options) * @example * Error.new( * :type => OFPET_BAD_REQUEST, * :code => OFPBRC_BAD_TYPE, * ) * Error.new( * :type => OFPET_BAD_REQUEST, * :code => OFPBRC_BAD_TYPE, * :transcation_id => 123 * ) * Error.new( * :type => OFPET_BAD_REQUEST, * :code => OFPBRC_BAD_TYPE, * :transcation_id => 123 * :data => "Error!!" * ) * @param [Hash] options * the options to create a message with. * @option options [Number] :type * a command or action that failed. * @option options [Number] :code * the reason of the failed type error. * @option options [String] :data * a more user friendly explanation of the error. Defaults to nil * if not specified. * @option options [Number] :xid * @option options [Number] :transaction_id * An unsigned 32bit integer number associated with this message. * If not specified, an auto-generated value is set. * @raise [ArgumentError] if transaction ID is not an unsigned 32bit integer. * @raise [ArgumentError] if type and code are not supplied. * @raise [ArgumentError] if user data is not a string. * @raise [TypeError] if options is not a hash. * @return [Error] */ static VALUE error_init( int argc, VALUE *argv, VALUE self ) { buffer *error = NULL; Data_Get_Struct( self, buffer, error ); VALUE options; if ( rb_scan_args( argc, argv, "01", &options ) == 1 ) { Check_Type( options, T_HASH ); VALUE tmp = Qnil; tmp = rb_hash_aref( options, ID2SYM( rb_intern( "type" ) ) ); if ( tmp != Qnil ) { ( ( struct ofp_error_msg * ) error->data )->type = htons( ( uint16_t ) NUM2UINT( tmp ) ); } else { rb_raise( rb_eArgError, "Type is a mandatory option" ); } tmp = rb_hash_aref( options, ID2SYM( rb_intern( "code" ) ) ); if ( tmp != Qnil ) { ( ( struct ofp_error_msg * ) error->data )->code = htons( ( uint16_t ) NUM2UINT( tmp ) ); } else { rb_raise( rb_eArgError, "Code is a mandatory option" ); } VALUE xid = Qnil; tmp = rb_hash_aref( options, ID2SYM( rb_intern( "transaction_id" ) ) ); if ( tmp != Qnil ) { xid = tmp; } tmp = rb_hash_aref( options, ID2SYM( rb_intern( "xid" ) ) ); if ( tmp != Qnil ) { xid = tmp; } if ( xid != Qnil ) { validate_xid( xid ); set_xid( error, ( uint32_t ) NUM2UINT( xid ) ); } else { set_xid( error, get_transaction_id() ); } VALUE data = rb_hash_aref( options, ID2SYM( rb_intern( "data" ) ) ); if ( data != Qnil ) { Check_Type( data, T_STRING ); uint16_t length = ( uint16_t ) RSTRING_LEN( data ); append_back_buffer( error, length ); ( ( struct ofp_header * ) ( error->data ) )->length = htons( ( uint16_t ) ( offsetof( struct ofp_error_msg, data ) + length ) ); memcpy( ( char * ) error->data + offsetof( struct ofp_error_msg, data ), RSTRING_PTR( data ), length ); }
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." ); } }
buffer * pack_experimenter_multipart_request( VALUE options ) { uint32_t xid = get_transaction_id(); VALUE r_xid = HASH_REF( options, transaction_id ); if ( !NIL_P( r_xid ) ) { xid = NUM2UINT( r_xid ); } uint16_t flags = 0; VALUE r_flags = HASH_REF( options, flags ); if ( !NIL_P( r_flags ) ) { flags = ( uint16_t ) NUM2UINT( r_flags ); } uint32_t experimenter = 0; VALUE r_experimenter = HASH_REF( options, experimenter ); if ( !NIL_P( r_experimenter ) ) { experimenter = NUM2UINT( r_experimenter ); } uint32_t exp_type = 0; VALUE r_exp_type = HASH_REF( options, exp_type ); if ( !NIL_P( r_exp_type ) ) { exp_type = NUM2UINT( r_exp_type ); } VALUE r_body = HASH_REF( options, user_data ); buffer *body = NULL; if ( !NIL_P( r_body ) ) { if ( TYPE( r_body ) == T_ARRAY ) { uint16_t buffer_len = ( uint16_t ) RARRAY_LEN( r_body ); body = alloc_buffer_with_length( ( size_t ) RARRAY_LEN( r_body ) ); append_back_buffer( body, buffer_len ); uint8_t *buf = body->data; for ( int i = 0; i < buffer_len && i < RARRAY_LEN( r_body ); i++ ) { buf[ i ]= ( uint8_t ) FIX2INT( rb_ary_entry( r_body , i ) ); } } else { rb_raise( rb_eTypeError, "experimenter user data must be specified as an array of bytes" ); } } buffer *experimenter_multipart_request = create_experimenter_multipart_request( xid, flags, experimenter, exp_type, body ); return experimenter_multipart_request; }
buffer * create_ovs_set_flow_format( const uint32_t transaction_id, const uint32_t format ) { size_t length = sizeof( ovs_set_flow_format ); buffer *message = alloc_buffer_with_length( length ); ovs_set_flow_format *sff = append_back_buffer( message, length ); sff->header.version = OFP_VERSION; sff->header.type = OFPT_VENDOR; sff->header.length = htons( sizeof( ovs_set_flow_format ) ); sff->header.xid = htonl( transaction_id ); sff->vendor = htonl( OVS_VENDOR_ID ); sff->subtype = htonl( OVST_SET_FLOW_FORMAT ); sff->format = htonl( format ); return message; }
buffer * create_ovs_flow_mod_table_id( const uint32_t transaction_id, const uint8_t set ) { uint16_t length = ( uint16_t ) sizeof( ovs_flow_mod_table_id ); buffer *buf = alloc_buffer_with_length( length ); ovs_flow_mod_table_id *flow_mod_table_id = append_back_buffer( buf, length ); flow_mod_table_id->header.version = OFP_VERSION; flow_mod_table_id->header.type = OFPT_VENDOR; flow_mod_table_id->header.length = htons( length ); flow_mod_table_id->header.xid = htonl( transaction_id ); flow_mod_table_id->vendor = ntohl( OVS_VENDOR_ID ); flow_mod_table_id->subtype = ntohl( OVST_FLOW_MOD_TABLE_ID ); flow_mod_table_id->set = set; return buf; }
buffer * get_switches( void ) { assert( dpid_table != NULL ); buffer *buf = alloc_buffer_with_length( sizeof( uint64_t ) ); hash_iterator iter; hash_entry *entry; init_hash_iterator( dpid_table, &iter ); while ( ( entry = iterate_hash_next( &iter ) ) != NULL ) { uint64_t *dpid = append_back_buffer( buf, sizeof( uint64_t ) ); *dpid = htonll( *( uint64_t * )( entry->value ) ); } return buf; }
static size_t write_to_buffer( void *contents, size_t size, size_t nmemb, void *user_data ) { debug( "Writing contents ( contents = %p, size = %zu, nmemb = %zu, user_data = %p ).", contents, size, nmemb, user_data ); assert( user_data != NULL ); size_t real_size = size * nmemb; buffer *buf = user_data; void *p = append_back_buffer( buf, real_size ); memcpy( p, contents, real_size ); debug( "%zu bytes data is written into buffer ( buf = %p, length = %zu ).", real_size, buf, buf->length ); return real_size; }
static void dump_filter_walker( struct ofp_match match, uint16_t priority, void *data, void *user_data ) { buffer *reply_buffer = user_data; assert( reply_buffer != NULL ); dump_packetin_filter_reply *reply = reply_buffer->data; list_element *services = data; while ( services != NULL ) { reply->n_entries++; packetin_filter_entry *entry = append_back_buffer( reply_buffer, sizeof( packetin_filter_entry ) ); hton_match( &entry->match, &match ); entry->priority = htons( priority ); strncpy( entry->service_name, services->data, sizeof( entry->service_name ) ); entry->service_name[ sizeof( entry->service_name ) - 1 ] = '\0'; services = services->next; } }
buffer * r_array_to_buffer( VALUE r_array ) { buffer *data = NULL; if ( !NIL_P( r_array ) ) { Check_Type( r_array, T_ARRAY ); uint32_t length = ( uint32_t ) RARRAY_LEN( r_array ); data = alloc_buffer_with_length( length ); append_back_buffer( data, length ); uint8_t *data_ptr = data->data; for ( uint32_t i = 0; i < length; i++ ) { data_ptr[ i ] = ( uint8_t ) FIX2INT( RARRAY_PTR( r_array ) [ i ] ); } } return data; }
static buffer * setup_dummy_ether_packet( size_t length, uint16_t type ) { buffer *buf = alloc_buffer_with_length( length ); alloc_packet( buf ); append_back_buffer( buf, length ); packet_info( buf )->l2_data.eth = buf->data; packet_info( buf )->ethtype = type; ether_header_t *ether = packet_info( buf )->l2_data.eth; ether->type = htons( type ); memcpy( ( char * ) ether->macda, macda, ETH_ADDRLEN ); memcpy( ( char * ) ether->macsa, macsa, ETH_ADDRLEN ); packet_info( buf )->l3_data.l3 = ( char * ) packet_info( buf )->l2_data.l2 + sizeof( ether_header_t ); vlantag_header_t *vtag = ( vlantag_header_t * ) ( ( void * ) ( ether + 1 ) ); packet_info( buf )->vtag = vtag; return buf; }
static void echo_request_interval( void *user_data ) { struct switch_info *sw_info = user_data; buffer *buf = alloc_buffer(); echo_body *body = append_back_buffer( buf, sizeof( echo_body ) ); body->datapath_id = htonll( switch_info.datapath_id ); struct timespec now; clock_gettime( CLOCK_MONOTONIC, &now ); body->sec = htonl( ( uint32_t ) now.tv_sec ); body->nsec = htonl( ( uint32_t ) now.tv_nsec ); sw_info->echo_request_xid = generate_xid(); int err = ofpmsg_send_echorequest( sw_info, sw_info->echo_request_xid, buf ); if ( err < 0 ) { switch_event_disconnected( &switch_info ); return; } switch_set_timeout( ECHO_REPLY_TIMEOUT, echo_reply_timeout, NULL ); }
static VALUE pack_experimenter( VALUE self, VALUE actions, VALUE options ) { VALUE r_experimenter = HASH_REF( options, experimenter ); VALUE r_body = Qnil; if ( ( r_body = HASH_REF( options, body ) ) != Qnil ) { Check_Type( r_body, T_ARRAY ); uint16_t length = ( uint16_t ) RARRAY_LEN( r_body ); buffer *body = alloc_buffer_with_length( length ); void *p = append_back_buffer( body, length ); for ( int i = 0; i < length; i++ ) { ( ( uint8_t * ) p )[ i ] = ( uint8_t ) FIX2INT( RARRAY_PTR( r_body )[ i ] ); } append_action_experimenter( openflow_actions_ptr( actions ), NUM2UINT( r_experimenter ), body ); free_buffer( body ); } else { append_action_experimenter( openflow_actions_ptr( actions ), NUM2UINT( r_experimenter ), NULL ); } return self; }