trema/trema-edge

View on GitHub
ruby/trema/action-common.c

Summary

Maintainability
Test Coverage
/*
 * Copyright (C) 2008-2013 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.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */


#include <stdint.h>
#include "trema.h"
#include "ruby.h"


uint32_t
nw_addr_to_i( VALUE nw_addr ) {
  return ( uint32_t ) NUM2UINT( rb_funcall( nw_addr, rb_intern( "to_i" ), 0 ) );
}


uint8_t *
dl_addr_to_a( VALUE dl_addr, uint8_t *ret_dl_addr ) {
  VALUE mac_arr = rb_funcall( dl_addr, rb_intern( "to_a" ), 0 );
  int i;

  for ( i = 0; i < RARRAY_LEN( mac_arr ); i++ ) {
    ret_dl_addr[ i ] = ( uint8_t ) ( NUM2INT( rb_ary_entry( mac_arr,  i ) ) );
  }
  return ret_dl_addr;
}


struct in6_addr
ipv6_addr_to_in6_addr( VALUE ipv6_addr, struct in6_addr *in6_addr ) {

  VALUE ipv6_addr_str = rb_funcall( ipv6_addr, rb_intern( "to_s" ), 0 );
  const char *dst = rb_string_value_cstr( &ipv6_addr_str );
  inet_pton( AF_INET6, dst, in6_addr );

  return *in6_addr;
}


openflow_actions *
pack_basic_action( VALUE r_action ) {
  openflow_actions *actions = create_actions();
  VALUE r_action_ins = Qnil;
  VALUE r_id = rb_intern( "pack_basic_action" );

  if ( !NIL_P( r_action ) ) {
    switch ( TYPE( r_action ) ) {
      case T_ARRAY: {
          r_action_ins = Data_Wrap_Struct( rb_obj_class( r_action ), NULL, NULL, actions );

          for ( int i = 0; i < RARRAY_LEN( r_action ); i++ ) {
            if ( rb_respond_to( rb_ary_entry( r_action, i ), r_id ) ) {
              r_action_ins = Data_Wrap_Struct( rb_obj_class( rb_ary_entry( r_action, i ) ), NULL, NULL, actions );
              rb_funcall( rb_ary_entry( r_action, i ), r_id, 1, r_action_ins );
            }
          }
      }
      break;
      case T_OBJECT:
        if ( rb_respond_to( r_action, r_id ) ) {
          r_action_ins = Data_Wrap_Struct( rb_obj_class( r_action ), NULL, NULL, actions );
          rb_funcall( r_action, r_id, 1, r_action_ins );
        }
      break;
      default:
        rb_raise( rb_eTypeError, "Action argument must be either an Array or an Action object" );
      break;
    }
  }
  Data_Get_Struct( r_action_ins, openflow_actions, actions );
  return actions;
}


oxm_matches *
pack_flexible_action( VALUE r_action ) {
  oxm_matches *oxm_match = create_oxm_matches();
  VALUE r_oxm_ins = Qnil;
  VALUE r_id = rb_intern( "flexible_action" );

  if ( !NIL_P( r_action ) ) {
    switch ( TYPE( r_action ) ) {
      case T_ARRAY: {
          for ( int i = 0; i < RARRAY_LEN( r_action ); i++ ) {
            if ( rb_respond_to( rb_ary_entry( r_action, i ), r_id ) ) {
              r_oxm_ins = Data_Wrap_Struct( rb_obj_class( rb_ary_entry( r_action, i ) ), NULL, NULL, oxm_match );
              rb_funcall( rb_ary_entry( r_action, i ), r_id, 1, r_oxm_ins );
            }
          }
      }
      break;
      case T_OBJECT:
        if ( rb_respond_to( r_action, r_id ) ) {
          r_oxm_ins = Data_Wrap_Struct( rb_obj_class( r_action ), NULL, NULL, oxm_match );
          rb_funcall( r_action, r_id, 1, r_oxm_ins );
        }
      break;
      default:
        rb_raise( rb_eTypeError, "Action argument must be either an Array or an Action object" );
      break;
    }
  }
  Data_Get_Struct( r_oxm_ins, oxm_matches, oxm_match );
  return oxm_match;
}


openflow_instructions *
pack_instruction( VALUE r_instruction ) {
  openflow_instructions *instructions = create_instructions();
  VALUE r_ins_instance = Qnil;
  VALUE r_id = rb_intern( "pack_instruction" );

  if ( !NIL_P( r_instruction ) ) {
    switch ( TYPE( r_instruction ) ) {
      case T_ARRAY: {
        for ( int i = 0; i < RARRAY_LEN( r_instruction ); i++ ) {
          if ( rb_respond_to( rb_ary_entry( r_instruction, i ), r_id ) ) {
            r_ins_instance = Data_Wrap_Struct( rb_obj_class( rb_ary_entry( r_instruction, i ) ), NULL, NULL, instructions );
            rb_funcall( rb_ary_entry( r_instruction, i ), r_id, 1, r_ins_instance );
          }
        }
      }
      break;
      case T_OBJECT:
        if ( rb_respond_to( rb_obj_class( r_instruction ), r_id ) ) {
          r_ins_instance = Data_Wrap_Struct( r_instruction, NULL, NULL, instructions );
          rb_funcall( r_instruction, r_id, 1, r_ins_instance );
        }
      break;
      default:
        rb_raise( rb_eTypeError, "Instruction argument must be either an Array or an Instruction object" );
      break;
    }
  }
  Data_Get_Struct( r_ins_instance, openflow_instructions, instructions );
  return instructions;
}


/*
 * Local variables:
 * c-basic-offset: 2
 * indent-tabs-mode: nil
 * End:
 */