static void
handle_desc_stats_reply( uint64_t datapath_id, uint32_t transaction_id,
                        uint16_t type, uint16_t flags, const buffer *data,
                       void *user_data ) {
  UNUSED( transaction_id );
  UNUSED( type );
  UNUSED( flags );
  show_desc *show_desc = user_data;

  if ( data->length < SIZE_OF_OFP_DESC ) {
    error( "invalid data" );

    stop_trema();
    return;
  }
  desc_entry *entry = xmalloc( sizeof( desc_entry ) );
  entry->datapath_id = datapath_id;
#ifdef TREMA_EDGE
  create_list( &entry->port_desc );
#endif
  memcpy( &entry->desc_stats, data->data, SIZE_OF_OFP_DESC );
  insert_hash_entry( show_desc->db, &entry->datapath_id, entry );

#ifdef TREMA_EDGE
  buffer *port_desc_request = create_port_desc_multipart_request( get_transaction_id(), 0 );
  send_openflow_message( datapath_id, port_desc_request );
  free_buffer( port_desc_request );
#else
  buffer *features_request = create_features_request( get_transaction_id() );
  send_openflow_message( datapath_id, features_request );
  free_buffer( features_request );
#endif
}
static void
do_flooding( packet_in packet_in, uint32_t in_port ) {
  openflow_actions *actions = create_actions();
  append_action_output( actions, OFPP_ALL, OFPCML_NO_BUFFER );

  buffer *packet_out;
  if ( packet_in.buffer_id == OFP_NO_BUFFER ) {
    buffer *frame = duplicate_buffer( packet_in.data );
    fill_ether_padding( frame );
    packet_out = create_packet_out(
      get_transaction_id(),
      packet_in.buffer_id,
      in_port,
      actions,
      frame
    );
    free_buffer( frame );
  }
  else {
    packet_out = create_packet_out(
      get_transaction_id(),
      packet_in.buffer_id,
      in_port,
      actions,
      NULL
    );
  }
  send_openflow_message( packet_in.datapath_id, packet_out );
  free_buffer( packet_out );
  delete_actions( actions );
}
示例#3
0
文件: fdb.c 项目: mq24705/apps
static void
poison( uint64_t dpid, const uint8_t mac[ OFP_ETH_ALEN ] ) {
    struct ofp_match match;
    memset( &match, 0, sizeof( struct ofp_match ) );
    match.wildcards = ( OFPFW_ALL & ~OFPFW_DL_DST );
    memcpy( match.dl_dst, mac, OFP_ETH_ALEN );

    const uint16_t idle_timeout = 0;
    const uint16_t hard_timeout = 0;
    const uint16_t priority = 0;
    const uint32_t buffer_id = 0;
    const uint16_t flags = 0;
    buffer *flow_mod = create_flow_mod( get_transaction_id(), match, get_cookie(),
                                        OFPFC_DELETE, idle_timeout, hard_timeout,
                                        priority, buffer_id, OFPP_NONE, flags,
                                        NULL );
    send_openflow_message( dpid, flow_mod );
    free_buffer( flow_mod );

    memset( &match, 0, sizeof( struct ofp_match ) );
    match.wildcards = ( OFPFW_ALL & ~OFPFW_DL_SRC );
    memcpy( match.dl_src, mac, OFP_ETH_ALEN );
    flow_mod = create_flow_mod( get_transaction_id(), match, get_cookie(),
                                OFPFC_DELETE, idle_timeout, hard_timeout,
                                priority, buffer_id, OFPP_NONE, flags, NULL );
    send_openflow_message( dpid, flow_mod );
    free_buffer( flow_mod );

    debug( "Poisoning all entries whose dl_src or dl_dst matches %02x:%02x:%02x:%02x:%02x:%02x at dpid %#" PRIx64,
           mac[ 0 ], mac[ 1 ], mac[ 2 ], mac[ 3 ], mac[ 4 ], mac[ 5 ], dpid );

}
示例#4
0
static void
do_flooding( packet_in packet_in ) {
  openflow_actions *actions = create_actions();
  append_action_output( actions, OFPP_FLOOD, UINT16_MAX );

  buffer *packet_out;
  if ( packet_in.buffer_id == UINT32_MAX ) {
    buffer *frame = duplicate_buffer( packet_in.data );
    fill_ether_padding( frame );
    packet_out = create_packet_out(
      get_transaction_id(),
      packet_in.buffer_id,
      packet_in.in_port,
      actions,
      frame
    );
    free_buffer( frame );
  }
  else {
    packet_out = create_packet_out(
      get_transaction_id(),
      packet_in.buffer_id,
      packet_in.in_port,
      actions,
      NULL
    );
  }
  send_openflow_message( packet_in.datapath_id, packet_out );
  free_buffer( packet_out );
  delete_actions( actions );
}
示例#5
0
文件: vendor.c 项目: kazuyas/trema
/*
 * 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;
}
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;
}
示例#7
0
static void
handle_packet_in( uint64_t datapath_id, packet_in message ) {
  if ( message.data == NULL ) {
    error( "data must not be NULL" );
    return;
  }
  uint32_t in_port = get_in_port_from_oxm_matches( message.match );
  if ( in_port == 0 ) {
    return;
  }

  openflow_actions *actions = create_actions();
  append_action_output( actions, OFPP_ALL, OFPCML_NO_BUFFER );

  openflow_instructions *insts = create_instructions();
  append_instructions_apply_actions( insts, actions );

  oxm_matches *match = create_oxm_matches();
  set_match_from_packet( match, in_port, 0, message.data );

  buffer *flow_mod = create_flow_mod(
    get_transaction_id(),
    get_cookie(),
    0,
    0,
    OFPFC_ADD,
    60,
    0,
    OFP_HIGH_PRIORITY,
    message.buffer_id,
    0,
    0,
    OFPFF_SEND_FLOW_REM,
    match,
    insts
  );
  send_openflow_message( datapath_id, flow_mod );
  free_buffer( flow_mod );
  delete_oxm_matches( match );
  delete_instructions( insts );

  if ( message.buffer_id == OFP_NO_BUFFER ) {
    buffer *frame = duplicate_buffer( message.data );
    fill_ether_padding( frame );
    buffer *packet_out = create_packet_out(
      get_transaction_id(),
      message.buffer_id,
      in_port,
      actions,
      frame
    );
    send_openflow_message( datapath_id, packet_out );
    free_buffer( packet_out );
    free_buffer( frame );
  }

  delete_actions( actions );
}
示例#8
0
文件: echo.c 项目: Milstein/trema
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;
}
static void
send_packet( uint32_t destination_port, packet_in packet_in, uint32_t in_port ) {
  openflow_actions *actions = create_actions();
  append_action_output( actions, destination_port, OFPCML_NO_BUFFER );

  openflow_instructions *insts = create_instructions();
  append_instructions_apply_actions( insts, actions );

  oxm_matches *match = create_oxm_matches();
  set_match_from_packet( match, in_port, NULL, packet_in.data );

  buffer *flow_mod = create_flow_mod(
    get_transaction_id(),
    get_cookie(),
    0,
    0,
    OFPFC_ADD,
    60,
    0,
    OFP_HIGH_PRIORITY,
    packet_in.buffer_id,
    0,
    0,
    OFPFF_SEND_FLOW_REM,
    match,
    insts
  );
  send_openflow_message( packet_in.datapath_id, flow_mod );
  free_buffer( flow_mod );
  delete_oxm_matches( match );
  delete_instructions( insts );

  if ( packet_in.buffer_id == OFP_NO_BUFFER ) {
    buffer *frame = duplicate_buffer( packet_in.data );
    fill_ether_padding( frame );
    buffer *packet_out = create_packet_out(
      get_transaction_id(),
      packet_in.buffer_id,
      in_port,
      actions,
      frame
    );
    send_openflow_message( packet_in.datapath_id, packet_out );
    free_buffer( packet_out );
    free_buffer( frame );
  }

  delete_actions( actions );
}
示例#10
0
bool
send_lldp( probe_timer_entry *port ) {
  buffer *lldp;

  lldp = create_lldp_frame( port->mac, port->datapath_id, port->port_no );

  openflow_actions *actions = create_actions();
  if ( !append_action_output( actions, port->port_no, UINT16_MAX ) ) {
    free_buffer( lldp );
    error( "Failed to sent LLDP frame(%#" PRIx64 ", %u)", port->datapath_id, port->port_no );
    return false;
  }

  uint32_t transaction_id = get_transaction_id();

  buffer *packetout = create_packet_out( transaction_id, UINT32_MAX,
                                         OFPP_NONE, actions, lldp );
  if ( !send_openflow_message( port->datapath_id, packetout ) ) {
    free_buffer( lldp );
    free_buffer( packetout );
    delete_actions( actions );
    die( "send_openflow_message" );
  }

  free_buffer( lldp );
  free_buffer( packetout );
  delete_actions( actions );

  debug( "Sent LLDP frame(%#" PRIx64 ", %u)", port->datapath_id, port->port_no );
  return true;
}
示例#11
0
/*
 * Request message to retrieve configuration about a queue port setting that
 * quantifies a QoS.
 * Each flow entry contains a queue that a flow is mapped to set constraints to
 * define some restriction like maximum/minimum data rate.
 *
 * @overload initialize(options={})
 *   @example
 *     QueueGetConfigRequest.new
 *     QueueGetConfigRequest.new( :port => 1 )
 *     QueueGetConfigRequest.new( :port => 1, :transaction_id => 123 )
 *
 *   @param [Hash] options
 *     the options to create a message with.
 *
 *   @option options [Number] :port
 *     a port number to query (defaults to 1).
 *
 *   @option options [Number] :transaction_id
 *     An unsigned 32-bit integer number associated with this message.
 *     If not specified, an auto-generated value is set.
 *
 *   @raise [ArgumentError] if transaction_id is not an unsigned 32-bit integer.
 *   @raise [ArgumentError] if port is not an unsigned 16-bit integer.
 *   @raise [TypeError] if options is not a hash.
 *
 *   @return [QueueGetConfigRequest]
 *     an object that encapsulates the +OFPT_GET_CONFIG_REQUEST+ OpenFlow message.
 */
static VALUE
queue_get_config_request_init( int argc, VALUE *argv, VALUE self ) {
  buffer *queue_get_config_request;
  Data_Get_Struct( self, buffer, queue_get_config_request );
  uint32_t xid = get_transaction_id();
  uint16_t port = 1;

  VALUE options;

  if ( rb_scan_args( argc, argv, "01", &options ) == 1 ) {
    Check_Type( options, T_HASH );
    VALUE xid_ruby;
    if ( ( xid_ruby = rb_hash_aref( options, ID2SYM( rb_intern( "transaction_id" ) ) ) ) != Qnil ) {
      if ( rb_funcall( xid_ruby, rb_intern( "unsigned_32bit?" ), 0 ) == Qfalse ) {
        rb_raise( rb_eArgError, "Transaction ID must be an unsigned 32-bit integer" );
      }
      xid = ( uint32_t ) NUM2UINT( xid_ruby );
    }
    VALUE port_ruby;
    if ( ( port_ruby = rb_hash_aref( options, ID2SYM( rb_intern( "port" ) ) ) ) != Qnil ) {
      if ( rb_funcall( port_ruby, rb_intern( "unsigned_16bit?" ), 0 ) == Qfalse ) {
        rb_raise( rb_eArgError, "Port must be an unsigned 16-bit integer" );
      }
      port = ( uint16_t ) NUM2UINT( port_ruby );
    }
  }
  ( ( struct ofp_header * ) ( queue_get_config_request->data ) )->xid = htonl( xid );
  ( ( struct ofp_queue_get_config_request * ) ( queue_get_config_request->data ) )->port = htons( port );
  return self;
}
示例#12
0
static void
handle_packet_in( uint64_t datapath_id, packet_in message ) {
  openflow_actions *actions = create_actions();
  append_action_output( actions, ( uint16_t ) ( message.in_port + 1 ), OFPCML_NO_BUFFER );

  struct ofp_match match;
  set_match_from_packet( &match, message.in_port, 0, message.data );

  buffer *flow_mod = create_flow_mod(
    get_transaction_id(),
    match,
    get_cookie(),
    OFPFC_ADD,
    0,
    0,
    OFP_HIGH_PRIORITY,
    message.buffer_id,
    OFPP_NONE,
    0,
    actions
  );
  send_openflow_message( datapath_id, flow_mod );

  free_buffer( flow_mod );
  delete_actions( actions );
}
static void
discard_packet_in( uint64_t datapath_id, uint16_t in_port, const buffer *packet ) {
  const uint32_t wildcards = 0;
  struct ofp_match match;
  set_match_from_packet( &match, in_port, wildcards, packet );
  char match_str[ 1024 ];
  match_to_string( &match, match_str, sizeof( match_str ) );

  const uint16_t idle_timeout = 0;
  const uint16_t hard_timeout = PACKET_IN_DISCARD_DURATION;
  const uint16_t priority = UINT16_MAX;
  const uint32_t buffer_id = UINT32_MAX;
  const uint16_t flags = 0;

  info( "Discarding packets for a certain period ( datapath_id = %#" PRIx64
        ", match = [%s], duration = %u [sec] ).", datapath_id, match_str, hard_timeout );

  buffer *flow_mod = create_flow_mod( get_transaction_id(), match, get_cookie(),
                                      OFPFC_ADD, idle_timeout, hard_timeout,
                                      priority, buffer_id,
                                      OFPP_NONE, flags, NULL );

  send_openflow_message( datapath_id, flow_mod );
  free_buffer( flow_mod );
}
示例#14
0
static void
send_packet( uint16_t destination_port, packet_in packet_in ) {
  openflow_actions *actions = create_actions();
  append_action_output( actions, destination_port, UINT16_MAX );

  struct ofp_match match;
  set_match_from_packet( &match, packet_in.in_port, 0, packet_in.data );

  buffer *flow_mod = create_flow_mod(
    get_transaction_id(),
    match,
    get_cookie(),
    OFPFC_ADD,
    60,
    0,
    UINT16_MAX,
    UINT32_MAX,
    OFPP_NONE,
    OFPFF_SEND_FLOW_REM,
    actions
  );
  send_openflow_message( packet_in.datapath_id, flow_mod );
  free_buffer( flow_mod );

  send_packet_out( packet_in, actions );

  delete_actions( actions );
}
示例#15
0
static void
handle_switch_ready( uint64_t datapath_id, void *user_data ) {
  UNUSED( user_data );

  openflow_actions *actions = create_actions();
  append_action_output( actions, OFPP_CONTROLLER, OFPCML_NO_BUFFER );
  openflow_instructions *insts = create_instructions();
  append_instructions_apply_actions( insts, actions );

  buffer *flow_mod = create_flow_mod(
    get_transaction_id(),
    get_cookie(),
    0,
    0,
    OFPFC_ADD,
    0,
    0,
    OFP_LOW_PRIORITY,
    OFP_NO_BUFFER,
    0,
    0,
    OFPFF_SEND_FLOW_REM,
    NULL,
    insts
  );
  send_openflow_message( datapath_id, flow_mod );
  free_buffer( flow_mod );

  delete_instructions( insts );
  delete_actions( actions );
}
示例#16
0
static void
send_flow_mod_receiving_lldp( sw_entry *sw, uint16_t hard_timeout, uint16_t priority ) {
  struct ofp_match match;
  memset( &match, 0, sizeof( struct ofp_match ) );
  if ( !options.lldp_over_ip ) {
    match.wildcards = OFPFW_ALL & ~OFPFW_DL_TYPE;
    match.dl_type = ETH_ETHTYPE_LLDP;
  }
  else {
    match.wildcards = OFPFW_ALL & ~( OFPFW_DL_TYPE | OFPFW_NW_PROTO | OFPFW_NW_SRC_MASK | OFPFW_NW_DST_MASK );
    match.dl_type = ETH_ETHTYPE_IPV4;
    match.nw_proto = IPPROTO_ETHERIP;
    match.nw_src = options.lldp_ip_src;
    match.nw_dst = options.lldp_ip_dst;
  }

  openflow_actions *actions = create_actions();
  const uint16_t max_len = UINT16_MAX;
  append_action_output( actions, OFPP_CONTROLLER, max_len );

  const uint16_t idle_timeout = 0;
  const uint32_t buffer_id = UINT32_MAX;
  const uint16_t flags = 0;
  buffer *flow_mod = create_flow_mod( get_transaction_id(), match, get_cookie(),
                                      OFPFC_ADD, idle_timeout, hard_timeout,
                                      priority, buffer_id,
                                      OFPP_NONE, flags, actions );
  send_openflow_message( sw->datapath_id, flow_mod );
  delete_actions( actions );
  free_buffer( flow_mod );
  debug( "Sent a flow_mod for receiving LLDP frames from %#" PRIx64 ".", sw->datapath_id );
}
示例#17
0
文件: port-mod.c 项目: amotoki/trema
/*
 * A {PortMod} instance a request object to perform operations on a physical port.
 *
 * @overload initialize(options={})
 *   @example
 *     PortMod.new(
 *       :port_no => 1,
 *       :hw_addr => "11:22:33:44:55:66",
 *       :config => 1,
 *       :mask => 1,
 *       :advertise => 0
 *     )
 *
 *   @param [Hash] options
 *     the options to create a message with.
 *
 *   @param [Number] :port_no
 *     an index into datapath's ports list.
 *
 *   @param [String,Number,Trema::Mac] :hw_addr
 *     the hardware address of a port.
 *     Unique for each port. Obtained from +OFPT_FEATURES_REPLY+ message.
 *     Can be supplied as a string, number or as a Mac object.
 *
 *   @param [Number] :config
 *     a bitmap that can be set to configure a port.
 *
 *   @param [Number] :mask
 *     set the bits of the +config+ flag to change.
 *
 *   @param [Number] :advertise
 *     bitmap of +ofp_port_features+ set to zero to prevent
 *     any changes. Or can be copied from +OFPT_FEATURES_REPLY+ message.
 *
 *   @return [PortMod]
 *     an object that encapsulates the +OFPT_PORT_MOD+ OpenFlow message.
 */
static VALUE
port_mod_init( int argc, VALUE *argv, VALUE self ) {
  VALUE options;

  if ( rb_scan_args( argc, argv, "01", &options ) == 1 ) {
    Check_Type( options, T_HASH );
    buffer *port_mod;
    Data_Get_Struct( self, buffer, port_mod );
    VALUE mac;
    VALUE hw_addr;
    uint8_t *ptr;
    uint8_t haddr[ OFP_ETH_ALEN ];

    if ( ( hw_addr = rb_hash_aref( options, ID2SYM( rb_intern( "hw_addr" ) ) ) ) != Qnil ) {
      mac = hw_addr;
      if ( rb_obj_is_kind_of( hw_addr, rb_cString ) == Qtrue ||
        rb_obj_is_kind_of( hw_addr, rb_cInteger ) == Qtrue ) {
        mac = rb_funcall( rb_eval_string( "Trema::Mac" ), rb_intern( "new" ), 1, hw_addr );
      }
      else if ( rb_obj_is_instance_of( hw_addr, rb_eval_string( "Trema::Mac" ) ) == Qfalse ) {
        rb_raise( rb_eArgError, "hw_addr must be a string or an integer or Mac object" );
      }
      ptr = ( uint8_t * ) dl_addr_to_a( mac, haddr );
      rb_iv_set( self, "@hw_addr", mac );
    }
    VALUE port_no;
    if ( ( port_no = rb_hash_aref( options, ID2SYM( rb_intern( "port_no" ) ) ) ) != Qnil ) {
      if ( rb_funcall( port_no, rb_intern( "unsigned_16bit?" ), 0 ) == Qfalse ) {
        rb_raise( rb_eArgError, "Port number must be an unsigned 16-bit integer" );
      }
      rb_iv_set( self, "@port_no", port_no );
    }
    VALUE config;
    if ( ( config = rb_hash_aref( options, ID2SYM( rb_intern( "config" ) ) ) ) != Qnil ) {
      rb_iv_set( self, "@config", config );
    }
    VALUE  mask;
    if ( ( mask = rb_hash_aref( options, ID2SYM( rb_intern( "mask" ) ) ) ) != Qnil ) {
      rb_iv_set( self, "@mask", mask );
    }
    VALUE advertise;
    if ( ( advertise = rb_hash_aref( options, ID2SYM( rb_intern( "advertise" ) ) ) ) != Qnil ) {
      rb_iv_set( self, "@advertise", advertise );
    }
    uint32_t xid = get_transaction_id();
    rb_iv_set( self, "@transaction_id", UINT2NUM( xid ) );

    ( ( struct ofp_header * ) ( port_mod->data ) )->xid = htonl( xid );
    ( ( struct ofp_port_mod * ) ( port_mod->data ) )->port_no = htons( ( uint16_t ) NUM2UINT( port_no ) );
    memcpy( ( ( struct ofp_port_mod * ) ( port_mod->data ) )->hw_addr, ptr, OFP_ETH_ALEN );
    ( ( struct ofp_port_mod * ) ( port_mod->data ) )->config = htonl( ( uint32_t ) NUM2UINT( config ) );
    ( ( struct ofp_port_mod * ) ( port_mod->data ) )->mask = htonl( ( uint32_t ) NUM2UINT( mask ) );
    ( ( struct ofp_port_mod * ) ( port_mod->data ) )->advertise = htonl( ( uint32_t ) NUM2UINT( advertise ) );
  }
  else {
    rb_raise( rb_eArgError, "Port no, hw_addr, config, mask, advertise are mandatory options" );
  }
  return self;
}
示例#18
0
文件: switch_info.c 项目: Darma/trema
static void
handle_switch_ready( uint64_t datapath_id, void *user_data ) {
  UNUSED( user_data );

  buffer *message = create_features_request( get_transaction_id() );
  send_openflow_message( datapath_id, message );
  free_buffer( message );
}
示例#19
0
static void
send_features_request( sw_entry *sw ) {
  uint32_t id = get_transaction_id();
  buffer *buf = create_features_request( id );
  send_openflow_message( sw->datapath_id, buf );
  free_buffer( buf );
  debug( "Sent switch features request to %#" PRIx64 ".", sw->datapath_id );
}
示例#20
0
static void
handle_switch_ready( uint64_t datapath_id, void *user_data ) {
  UNUSED( user_data );

  uint32_t id = get_transaction_id();
  buffer *buf = create_features_request( id );
  send_openflow_message( datapath_id, buf );
  free_buffer( buf );
}
示例#21
0
/*
 * Creates a {GetConfigRequest} instance to query configuration parameters
 * from the switch.
 *
 * @overload initialize()
 *   @example
 *     GetConfigRequest.new
 *
 * @overload initialize(transaction_id)
 *   @example
 *     GetConfigRequest.new( 123 )
 *   @param [Integer] transaction_id
 *     An unsigned 32-bit integer number associated with this message.
 *
 * @overload initialize(options)
 *   @example
 *     GetConfigRequest.new( :xid => 123 )
 *     GetConfigRequest.new( :transaction_id => 123 )
 *   @param [Hash] options
 *     the options to create a message with.
 *   @option options [Number] :xid an alias to transaction_id.
 *   @option options [Number] :transaction_id
 *     An unsigned 32-bit integer number associated with this message.
 *     If not specified, an auto-generated value is set.
 *
 * @raise [ArgumentError] if transaction ID is not an unsigned 32-bit integer.
 * @raise [TypeError] if argument is not a Integer or a Hash.
 * @return [GetConfigRequest]
 *     an object that encapsulates the +OFPT_GET_CONFIG+ OpenFlow message.
 */
static VALUE
get_config_request_init( int argc, VALUE *argv, VALUE self ) {
  buffer *get_config_request;
  Data_Get_Struct( self, buffer, get_config_request );
  VALUE options = Qnil;


  if ( rb_scan_args( argc, argv, "01", &options ) == 0 ) {
    set_xid( get_config_request, get_transaction_id() );
  }
  else {
    if ( options == Qnil ) {
      set_xid( get_config_request, get_transaction_id() );
    }
    else if ( rb_obj_is_kind_of( options, rb_cInteger ) == Qtrue ) {
      validate_xid( options );
      set_xid( get_config_request, ( 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( get_config_request, ( uint32_t ) NUM2UINT( xid ) );
      }
      else {
        set_xid( get_config_request, get_transaction_id() );
      }
    }
  }

  return self;
}
static void
handle_list_switches_reply( const list_element *switches, void *user_data ) {
  show_desc *show_desc = user_data;

#ifdef TREMA_EDGE
  buffer *desc_stats_request = create_desc_multipart_request( get_transaction_id(), 0 );
#else
  buffer *desc_stats_request = create_desc_stats_request( get_transaction_id(), 0 );
#endif

  const list_element *element;
  for ( element = switches; element != NULL; element = element->next ) {
    uint64_t datapath_id = * ( uint64_t *) element->data;
    send_openflow_message( datapath_id, desc_stats_request );
    show_desc->count++;
  }

  free_buffer( desc_stats_request );
}
示例#23
0
static void
set_miss_send_len_maximum( uint64_t datapath_id ) {
  uint32_t id = get_transaction_id();
  const uint16_t config_flags = OFPC_FRAG_NORMAL;
  const uint16_t miss_send_len = UINT16_MAX;
  buffer *buf = create_set_config( id, config_flags, miss_send_len );
  send_openflow_message( datapath_id, buf );

  free_buffer( buf );
}
示例#24
0
文件: error.c 项目: nhst/trema
/*
 * @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 );
}
示例#25
0
static void
send_echo_requests( uint64_t datapath_id, void *count ) {
  for ( int i = 0; i < *( ( int * ) count ); i++ ) {
    buffer *echo_request = create_echo_request( get_transaction_id(), NULL );
    bool ret = send_openflow_message( datapath_id, echo_request );
    if ( !ret ) {
      error( "Failed to send an echo request message to the switch with datapath ID = %#" PRIx64 ".", datapath_id );
    }
    free_buffer( echo_request );
  }
}
示例#26
0
static void
send_hello( uint64_t datapath_id, void *count ) {
  for ( int i = 0; i < *( ( int * ) count ); i++ ) {
    buffer *hello = create_hello( get_transaction_id(), NULL );
    bool ret = send_openflow_message( datapath_id, hello );
    if ( !ret ) {
      error( "Failed to send an hello message to the switch with datapath ID = %#" PRIx64 ".", datapath_id );
    }
    free_buffer( hello );
  }
}
示例#27
0
static void
send_packet( uint16_t destination_port, packet_in packet_in ) {
  openflow_actions *actions = create_actions();
  append_action_output( actions, destination_port, UINT16_MAX );

  struct ofp_match match;
  set_match_from_packet( &match, packet_in.in_port, 0, packet_in.data );

  buffer *flow_mod = create_flow_mod(
    get_transaction_id(),
    match,
    get_cookie(),
    OFPFC_ADD,
    60,
    0,
    UINT16_MAX,
    packet_in.buffer_id,
    OFPP_NONE,
    OFPFF_SEND_FLOW_REM,
    actions
  );
  send_openflow_message( packet_in.datapath_id, flow_mod );
  free_buffer( flow_mod );

  if ( packet_in.buffer_id == UINT32_MAX ) {
    buffer *frame = duplicate_buffer( packet_in.data );
    fill_ether_padding( frame );
    buffer *packet_out = create_packet_out(
      get_transaction_id(),
      packet_in.buffer_id,
      packet_in.in_port,
      actions,
      frame
    );
    send_openflow_message( packet_in.datapath_id, packet_out );
    free_buffer( packet_out );
    free_buffer( frame );
  }

  delete_actions( actions );
}
示例#28
0
static void
send_features_request( uint64_t datapath_id, void *user_data ) {
  UNUSED( user_data );

  buffer *features_request = create_features_request( get_transaction_id() );
  bool ret = send_openflow_message( datapath_id, features_request );
  if ( !ret ) {
    error( "Failed to send a features request message to the switch with datapath ID = %#" PRIx64 ".", datapath_id );
    stop_trema();
  }
  free_buffer( features_request );
}
示例#29
0
文件: error.c 项目: Milstein/trema
/*
 * @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 );
    }
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;
}