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;
}
Beispiel #2
0
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 );
}