bool execute_transaction( uint64_t datapath_id, const buffer *message, succeeded_handler succeeded_callback, void *succeeded_user_data, failed_handler failed_callback, void *failed_user_data ) { assert( message != NULL ); assert( message->length >= sizeof( struct ofp_header ) ); transaction_entry *entry = alloc_transaction_entry(); entry->datapath_id = datapath_id; entry->message = duplicate_buffer( message ); entry->xid = get_transaction_id(); entry->barrier_xid = get_transaction_id(); struct ofp_header *header = entry->message->data; entry->original_xid = ntohl( header->xid ); header->xid = htonl( entry->xid ); // Override xid for keeping uniqueness entry->completed = false; entry->error_received = false; entry->timeout = false; debug( "Executing a transaction ( xid = %#x, barrier_xid = %#x, original_xid = %#x ).", entry->xid, entry->barrier_xid, entry->original_xid ); bool ret = send_openflow_message( datapath_id, entry->message ); if ( !ret ) { // FIXME: send queue may be full. We may need to retry for sending the message. error( "Failed to send an OpenFlow message ( datapath_id = %#" PRIx64 ", transaction_id = %#x ).", datapath_id, entry->original_xid ); free_transaction_entry( entry ); return false; } buffer *barrier = create_barrier_request( entry->barrier_xid ); ret = send_openflow_message( datapath_id, barrier ); free_buffer( barrier ); if ( !ret ) { error( "Failed to send a barrier request ( datapath_id = %#" PRIx64 ", transaction_id = %#x ).", datapath_id, entry->barrier_xid ); free_transaction_entry( entry ); return false; } entry->succeeded_callback = succeeded_callback; entry->succeeded_user_data = succeeded_user_data; entry->failed_callback = failed_callback; entry->failed_user_data = failed_user_data; ret = add_transaction_entry( entry ); if ( !ret ) { error( "Failed to save transaction entry ( %p ).", entry ); dump_transaction_entry( error, entry ); free_transaction_entry( entry ); return false; } debug( "OpenFlow messages are put into a send queue and a transaction entry is saved." ); return true; }
static VALUE barrier_request_alloc( VALUE klass ) { buffer *barrier_request = create_barrier_request( get_transaction_id() ); return Data_Wrap_Struct( klass, NULL, free_buffer, barrier_request ); }