ruby/trema/vendor.c in trema-0.2.2.1 vs ruby/trema/vendor.c in trema-0.2.3
- old
+ new
@@ -1,8 +1,6 @@
/*
- * Author: Nick Karanatsios <nickkaranatsios@gmail.com>
- *
* Copyright (C) 2008-2012 NEC Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2, as
* published by the Free Software Foundation.
@@ -16,116 +14,187 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#include "trema.h"
#include "ruby.h"
+#include "trema-ruby-utils.h"
+#include "trema.h"
extern VALUE mTrema;
VALUE cVendor;
+static VALUE
+vendor_alloc( VALUE klass ) {
+ buffer *vendor = create_vendor( 0, 0, NULL );
+ return Data_Wrap_Struct( klass, NULL, free_buffer, vendor );
+}
+
+
/*
- * Creates a {Vendor} instance that encapsulates the handling of vendor's messages.
+ * Creates a Vendor Reqeust message. This message can be used
+ * to facilitate sending of vendor-defined arbitrary data.
*
- * @overload initialize(options={})
+ * @overload initialize
+ * @example
+ * Vendor.new
*
- * @example
+ * @overload initialize(options)
+ * @example
* Vendor.new(
- * :datapath_id => 0xabc,
- * :transaction_id => 123,
- * :vendor => vendor_id,
- * :buffer => data
+ * :vendor => 0x3000,
+ * :data => "deadbeef".unpack( "C*" ),
+ * :transaction_id => 123
* )
*
* @param [Hash] options
* the options to create a message with.
- *
- * @option options [Number] :datapath_id
- * message originator identifier.
- *
+ * @option options [Number] :xid
* @option options [Number] :transaction_id
- * zero for unsolicited message otherwise a positive number.
+ * 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.
*
- * @option options [Number] :vendor_id
- * the vendor identifier. if MSB is zero low order bytes are IEEE OUI.
- * If MSB not equal to zero defined by openflow.
- *
- * @option options [String] :buffer
- * a String that holds vendor's defined arbitrary length data.
- *
- * @return [Vendor]
- * an object that encapsulates the +OFPT_VENDOR+ OpenFlow symmetric message.
+ * @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( VALUE self, VALUE options ) {
- rb_iv_set( self, "@attribute", options );
+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;
}
-/*
- * Message originator identifier.
- *
- * @return [Number] the value of datapath_id.
- */
-static VALUE
-vendor_datapath_id( VALUE self ) {
- return rb_hash_aref( rb_iv_get( self, "@attribute" ), ID2SYM( rb_intern( "datapath_id" ) ) );
-}
-
/*
- * Zero for unsolicited message otherwise a positive number copied from request
- * message.
+ * Transaction ids, message sequence numbers matching requests to replies.
*
- * @return [Number] the value of transaction_id.
+ * @return [Number] the value of transaction id.
*/
static VALUE
vendor_transaction_id( VALUE self ) {
- return rb_hash_aref( rb_iv_get( self, "@attribute" ), ID2SYM( rb_intern( "transaction_id" ) ) );
+ return get_xid( self );
}
/*
- * (see VendorRequest#vendor)
+ * A 32-bit value that uniquely identifies the vendor.
+ *
+ * @return [Number] the value of vendor id.
*/
static VALUE
vendor_vendor( VALUE self ) {
- return rb_hash_aref( rb_iv_get( self, "@attribute" ), ID2SYM( rb_intern( "vendor" ) ) );
+ buffer *vendor_message;
+ Data_Get_Struct( self, buffer, vendor_message );
+ uint32_t vendor = ntohl( ( ( struct ofp_vendor_header * ) ( vendor_message->data ) )->vendor );
+ return UINT2NUM( vendor );
}
/*
- * Vendor's arbitrary length data.
+ * Vendor specific data payload.
*
- * @return [Buffer] the value of buffer.
+ * @return [Array] an array of data payload bytes.
+ * @return [nil] vendor specific data not found.
*/
static VALUE
-vendor_buffer( VALUE self ) {
- return rb_hash_aref( rb_iv_get( self, "@attribute" ), ID2SYM( rb_intern( "buffer" ) ) );
+vendor_data( VALUE self ) {
+ buffer *vendor;
+ Data_Get_Struct( self, buffer, vendor );
+ uint16_t length = get_length( vendor );
+
+ if ( length > 0 ) {
+ VALUE data_array = rb_ary_new2( length );
+ uint8_t *data = ( uint8_t * ) ( ( char * ) vendor->data + sizeof( struct ofp_vendor_header ) );
+ int i;
+ for ( i = 0; i < length; i++ ) {
+ rb_ary_push( data_array, INT2FIX( data[ i ] ) );
+ }
+ return data_array;
+ }
+ return Qnil;
}
void
Init_vendor() {
cVendor = rb_define_class_under( mTrema, "Vendor", rb_cObject );
- rb_define_method( cVendor, "initialize", vendor_init, 1 );
- rb_define_method( cVendor, "datapath_id", vendor_datapath_id, 0 );
+ rb_define_alloc_func( cVendor, vendor_alloc );
+ rb_define_method( cVendor, "initialize", vendor_init, -1 );
rb_define_method( cVendor, "transaction_id", vendor_transaction_id, 0 );
+ rb_alias( cVendor, rb_intern( "xid" ), rb_intern( "transaction_id" ) );
rb_define_method( cVendor, "vendor", vendor_vendor, 0 );
- rb_define_method( cVendor, "buffer", vendor_buffer, 0 );
+ rb_define_method( cVendor, "data", vendor_data, 0 );
}
void
handle_vendor(
uint64_t datapath_id,
uint32_t transaction_id,
uint32_t vendor,
- buffer *body,
+ buffer *data,
void *user_data
) {
VALUE controller = ( VALUE ) user_data;
if ( rb_respond_to( controller, rb_intern( "vendor" ) ) == Qfalse ) {
return;
@@ -134,11 +203,11 @@
rb_hash_aset( attributes, ID2SYM( rb_intern( "datapath_id" ) ), ULL2NUM( datapath_id ) );
rb_hash_aset( attributes, ID2SYM( rb_intern( "transaction_id" ) ), UINT2NUM( transaction_id ) );
rb_hash_aset( attributes, ID2SYM( rb_intern( "vendor" ) ), UINT2NUM( vendor ) );
- if ( body->length ) {
- rb_hash_aset( attributes, ID2SYM( rb_intern( "buffer" ) ), rb_str_new( body->data, ( long ) body->length ) );
+ if ( data->length ) {
+ rb_hash_aset( attributes, ID2SYM( rb_intern( "data" ) ), rb_str_new( data->data, ( long ) data->length ) );
}
VALUE vendor_r = rb_funcall( cVendor, rb_intern( "new" ), 1, attributes );
rb_funcall( controller, rb_intern( "vendor" ), 1, vendor_r );
}