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; }
/* * 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; }
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 ); }
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" ); } }
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 ); }