Пример #1
0
static VALUE
pack_ipv6_nd_sll( VALUE self, VALUE actions, VALUE options ) {
  VALUE r_mac_address = HASH_REF( options, mac_address );
  uint8_t *dl_addr = ( uint8_t * ) xmalloc( sizeof( uint8_t ) * OFP_ETH_ALEN );

  if ( rb_obj_is_kind_of( actions, basic_action_eval ) ) {
    append_action_set_field_ipv6_nd_sll( openflow_actions_ptr( actions ), dl_addr_to_a( r_mac_address, dl_addr ) );
  }
  else if ( rb_obj_is_kind_of( actions, flexible_action_eval ) ) {
    append_oxm_match_ipv6_nd_sll( oxm_match_ptr( actions ), dl_addr_to_a( r_mac_address, dl_addr ) );
  }
  xfree( dl_addr );

  return self;
}
Пример #2
0
/*
 * 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;
}
Пример #3
0
uint8_t *
mac_addr_to_cstr( VALUE mac_addr ) {
  static __thread uint8_t dl_addr[ OFP_ETH_ALEN ];
  return dl_addr_to_a( mac_addr, dl_addr );
}
Пример #4
0
static void
append_action( openflow_actions *actions, VALUE action ) {
  if ( rb_funcall( action, rb_intern( "is_a?" ), 1, rb_path2class( "Trema::Enqueue" ) ) == Qtrue ) {
    uint32_t queue_id = ( uint32_t ) NUM2UINT( rb_funcall( action, rb_intern( "queue_id" ), 0 ) );
    uint16_t port_number = ( uint16_t ) NUM2UINT( rb_funcall( action, rb_intern( "port_number" ), 0 ) );
    append_action_enqueue( actions, port_number, queue_id );
  }
  else if ( rb_funcall( action, rb_intern( "is_a?" ), 1, rb_path2class( "Trema::SendOutPort" ) ) == Qtrue ) {
    uint16_t port_number = ( uint16_t ) NUM2UINT( rb_funcall( action, rb_intern( "port_number" ), 0 ) );
    uint16_t max_len = ( uint16_t ) NUM2UINT( rb_funcall( action, rb_intern( "max_len" ), 0 ) );
    append_action_output( actions, port_number, max_len );
  }
  else if ( rb_funcall( action, rb_intern( "is_a?" ), 1, rb_path2class( "Trema::SetEthDstAddr" ) ) == Qtrue ) {
    uint8_t dl_dst[ OFP_ETH_ALEN ];
    uint8_t *ptr = ( uint8_t * ) dl_addr_to_a( rb_funcall( action, rb_intern( "mac_address" ), 0 ), dl_dst );
    append_action_set_dl_dst( actions, ptr );
  }
  else if ( rb_funcall( action, rb_intern( "is_a?" ), 1, rb_path2class( "Trema::SetEthSrcAddr" ) ) == Qtrue ) {
    uint8_t dl_src[ OFP_ETH_ALEN ];
    uint8_t *ptr = ( uint8_t * ) dl_addr_to_a( rb_funcall( action, rb_intern( "mac_address" ), 0 ), dl_src );
    append_action_set_dl_src( actions, ptr );
  }
  else if ( rb_funcall( action, rb_intern( "is_a?" ), 1, rb_path2class( "Trema::SetIpDstAddr" ) ) == Qtrue ) {
    append_action_set_nw_dst( actions, nw_addr_to_i( rb_funcall( action, rb_intern( "ip_address" ), 0 ) ) );
  }
  else if ( rb_funcall( action, rb_intern( "is_a?" ), 1, rb_path2class( "Trema::SetIpSrcAddr" ) ) == Qtrue ) {
    append_action_set_nw_src( actions, nw_addr_to_i( rb_funcall( action, rb_intern( "ip_address" ), 0 ) ) );
  }
  else if ( rb_funcall( action, rb_intern( "is_a?" ), 1, rb_path2class( "Trema::SetIpTos" ) ) == Qtrue ) {
    append_action_set_nw_tos( actions, ( uint8_t ) NUM2UINT( rb_funcall( action, rb_intern( "type_of_service" ), 0 ) ) );
  }
  else if ( rb_funcall( action, rb_intern( "is_a?" ), 1, rb_path2class( "Trema::SetTransportDstPort" ) ) == Qtrue ) {
    append_action_set_tp_dst( actions, ( uint16_t ) NUM2UINT( rb_funcall( action, rb_intern( "port_number" ), 0 ) ) );
  }
  else if ( rb_funcall( action, rb_intern( "is_a?" ), 1, rb_path2class( "Trema::SetTransportSrcPort" ) ) == Qtrue ) {
    append_action_set_tp_src( actions, ( uint16_t ) NUM2UINT( rb_funcall( action, rb_intern( "port_number" ), 0 ) ) );
  }
  else if ( rb_funcall( action, rb_intern( "is_a?" ), 1, rb_path2class( "Trema::SetVlanPriority" ) ) == Qtrue ) {
    append_action_set_vlan_pcp( actions, ( uint8_t ) NUM2UINT( rb_funcall( action, rb_intern( "vlan_priority" ), 0 ) ) );
  }
  else if ( rb_funcall( action, rb_intern( "is_a?" ), 1, rb_path2class( "Trema::SetVlanVid" ) ) == Qtrue ) {
    append_action_set_vlan_vid( actions, ( uint16_t ) NUM2UINT( rb_funcall( action, rb_intern( "vlan_id" ), 0 ) ) );
  }
  else if ( rb_funcall( action, rb_intern( "is_a?" ), 1, rb_path2class( "Trema::StripVlanHeader" ) ) == Qtrue ) {
    append_action_strip_vlan( actions );
  }
  else if ( rb_funcall( action, rb_intern( "is_a?" ), 1, rb_path2class( "Trema::VendorAction" ) ) == Qtrue ) {
    VALUE vendor_id = rb_funcall( action, rb_intern( "vendor_id" ), 0 );
    VALUE rbody = rb_funcall( action, rb_intern( "body" ), 0 );
    if ( rbody != Qnil ) {
      Check_Type( rbody, T_ARRAY );
      uint16_t length = ( uint16_t ) RARRAY_LEN( rbody );
      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( rbody )[ i ] );
      }
      append_action_vendor( actions, ( uint32_t ) NUM2UINT( vendor_id ), body );
      free_buffer( body );
    }
    else {
      append_action_vendor( actions, ( uint32_t ) NUM2UINT( vendor_id ), NULL );
    }
  }
  else {
    rb_raise( rb_eTypeError, "actions argument must be an Array of Action objects" );
  }
}
Пример #5
0
uint8_t *
mac_addr_to_cstr( VALUE mac_addr ) {
  uint8_t dl_addr[ OFP_ETH_ALEN ];
  return dl_addr_to_a( mac_addr, dl_addr );
}