Exemplo n.º 1
0
/*
 * Appends its action(set_nw_src) to the list of actions.
 *
 * @return [ActionSetNwSrc] self
 */
static VALUE
action_set_nw_src_append( VALUE self, VALUE action_ptr ) {
    openflow_actions *actions;

    Data_Get_Struct( action_ptr, openflow_actions, actions );

    append_action_set_nw_src( actions, nw_addr_to_i( action_get_nw_src( self ) ) );

    return self;
}
Exemplo n.º 2
0
/*
 * Creates a {Match} instance which describe fields such as MAC addresses, IP
 * addresses, TCP/UDP ports of a flow to match against. An exact match 
 * flow would match on all fields whereas don't care bits are wildcarded and
 * ignored.
 *
 * @overload initialize(options={})
 *
 *   @example 
 *     Match.new(
 *       :in_port => port_no,
 *       :dl_src => "xx:xx:xx;xx:xx:xx",
 *       :dl_dst => "xx:xx:xx:xx:xx:xx",
 *       :dl_type => ethertype,
 *       :dl_vlan => vlan,
 *       :dl_vlan_pcp => priority,
 *       :nw_tos => tos,
 *       :nw_proto => proto,
 *       :nw_src => ip_address/netmask,
 *       :nw_dst => ip_address/netmask,
 *       :tp_src => port,
 *       :tp_dst => port,
 *     )
 *
 *   @param [Hash] options the options hash.
 *
 *   @option options [Symbol] :inport
 *     the physical port number to match.
 *
 *   @option options [Symbol] :dl_src
 *     the source ethernet address to match specified either as 6 pairs of
 *     hexadecimal digits delimited by colon or as a hexadecimal number.
 *     (eg. "00:11:22:33:44:55" or 0x001122334455).
 *
 *   @option options [Symbol] :dl_dst
 *     the destination ethernet address to match specified either as a 6 pairs of
 *     hexadecimal digits delimited by colon or as a hexadecimal number.
 *     (eg. "00:11:22:33:44:55" or 0x001122334455).
 *
 *   @option options [Symbol] :dl_type
 *     the Ethernet protocol type to match. Can be specified either as a decimal
 *     or hexadecimal number. (eg 0x0800 to match IP packets, 0x08006 to match
 *     ARP packets, 0x88cc for LLDP packets).
 *
 *   @option options [Symbol] :dl_vlan
 *     the IEEE 802.1q virtual VLAN tag to match specified as a 12-bit number
 *     0 to 4095 inclusive.
 *
 *   @option options [Symbol] :dl_vlan_pcp
 *     the IEEE 802.1q Priority Code Point (PCP) to match specified as a value of
 *     0 to 7 inclusive. A higher value indicates a higher priority frame.
 *
 *   @option options [Symbol] :nw_tos
 *     the IP ToS/DSCP field to match specified as a decimal number between 0 and
 *     255 inclusive.
 *
 *   @option options [Symbol] :nw_proto
 *     Depending on the dl_type the IP protocol type to match. (eg if dl_type
 *     equals 0x0800 UDP packets can be match by setting nw_proto to 17.)
 *     to match TCP packets). When dl_type = 0x0806 is set to arp it matches the
 *     lower 8 bits of the ARP opcode.
 *
 *   @option options [Symbol] :nw_src
 *     the IPv4 source address to match if dl_type is set to 0x0800.
 *
 *   @option options [Symbol] :nw_dst
 *     the IPv4 destination address to match if dl_type is set to 0x0800.
 *
 *   @option options [Symbol] :tp_src
 *     the source TCP/UDP port number to match specified as a decimal number
 *     between 0 and 65535 inclusive. The value dl_type and nw_proto must be set
 *     to specify TCP or UDP.
 *
 *   @option options [Symbol] :tp_dst
 *     the destination TCP/UDP port number to match specified as a decimal number
 *     between 0 and 65535 inclusive.
 *
 * @return [Match] self
 *   an object that encapsulates and wraps the +struct ofp_match+
 */
static VALUE
match_init( int argc, VALUE *argv, VALUE self ) {
  struct ofp_match *match;
  VALUE options;

  // Always clear the memory as the unused memory locations are
  // exposed to both the user and the OpenFlow controller.
  Data_Get_Struct( self, struct ofp_match, match );
  memset( match, 0, sizeof ( *match ) );

  // Default matches all packets.
  match->wildcards = ( OFPFW_ALL & ~( OFPFW_NW_SRC_MASK | OFPFW_NW_DST_MASK ) )
    | OFPFW_NW_SRC_ALL | OFPFW_NW_DST_ALL;

  if ( rb_scan_args( argc, argv, "01", &options ) >= 1 ) {
    if ( options != Qnil ) {
      VALUE in_port = rb_hash_aref( options, ID2SYM( rb_intern( "in_port" ) ) );
      if ( in_port != Qnil ) {
        match->in_port = ( uint16_t ) NUM2UINT( in_port );
        match->wildcards &= ( uint32_t ) ~OFPFW_IN_PORT;
      }

      VALUE dl_src = rb_hash_aref( options, ID2SYM( rb_intern( "dl_src" ) ) );
      if ( dl_src != Qnil ) {
        VALUE dl_addr = rb_funcall( rb_eval_string( "Trema::Mac" ), rb_intern( "new" ), 1, dl_src );
        dl_addr_short( dl_addr, match->dl_src );
        match->wildcards &= ( uint32_t ) ~OFPFW_DL_SRC;
      }

      VALUE dl_dst = rb_hash_aref( options, ID2SYM( rb_intern( "dl_dst" ) ) );
      if ( dl_dst != Qnil ) {
        VALUE dl_addr = rb_funcall( rb_eval_string( "Trema::Mac" ), rb_intern( "new" ), 1, dl_dst );
        dl_addr_short( dl_addr, match->dl_dst );
        match->wildcards &= ( uint32_t ) ~OFPFW_DL_DST;
      }

      VALUE dl_type = rb_hash_aref( options, ID2SYM( rb_intern( "dl_type" ) ) );
      if ( dl_type != Qnil ) {
        match->dl_type = ( uint16_t ) NUM2UINT( dl_type );
        match->wildcards &= ( uint32_t ) ~OFPFW_DL_TYPE;
      }

      VALUE dl_vlan = rb_hash_aref( options, ID2SYM( rb_intern( "dl_vlan" ) ) );
      if ( dl_vlan != Qnil ) {
        match->dl_vlan = ( uint16_t ) NUM2UINT( dl_vlan );
        match->wildcards &= ( uint32_t ) ~OFPFW_DL_VLAN;
      }

      VALUE dl_vlan_pcp = rb_hash_aref( options, ID2SYM( rb_intern( "dl_vlan_pcp" ) ) );
      if ( dl_vlan_pcp != Qnil ) {
        match->dl_vlan_pcp = ( uint8_t ) NUM2UINT( dl_vlan_pcp );
        match->wildcards &= ( uint32_t ) ~OFPFW_DL_VLAN_PCP;
      }

      VALUE nw_tos = rb_hash_aref( options, ID2SYM( rb_intern( "nw_tos" ) ) );
      if ( nw_tos != Qnil ) {
        match->nw_tos = ( uint8_t ) NUM2UINT( nw_tos );
        match->wildcards &= ( uint32_t ) ~OFPFW_NW_TOS;
      }

      VALUE nw_proto = rb_hash_aref( options, ID2SYM( rb_intern( "nw_proto" ) ) );
      if ( nw_proto != Qnil ) {
        match->nw_proto = ( uint8_t ) NUM2UINT( nw_proto );
        match->wildcards &= ( uint32_t ) ~OFPFW_NW_PROTO;
      }

      VALUE nw_src = rb_hash_aref( options, ID2SYM( rb_intern( "nw_src" ) ) );
      if ( nw_src != Qnil ) {
        VALUE nw_addr = rb_funcall( rb_eval_string( "Trema::IP" ), rb_intern( "new" ), 1, nw_src );
        match->nw_src = nw_addr_to_i( nw_addr );
        match->wildcards &= ( uint32_t ) ~OFPFW_NW_SRC_MASK;
      }

      VALUE nw_dst = rb_hash_aref( options, ID2SYM( rb_intern( "nw_dst" ) ) );
      if ( nw_dst != Qnil ) {
        VALUE nw_addr = rb_funcall( rb_eval_string( "Trema::IP" ), rb_intern( "new" ), 1, nw_dst );
        match->nw_dst = nw_addr_to_i( nw_addr );
        match->wildcards &= ( uint32_t ) ~OFPFW_NW_DST_MASK;
      }

      VALUE tp_src = rb_hash_aref( options, ID2SYM( rb_intern( "tp_src" ) ) );
      if ( tp_src != Qnil ) {
        match->tp_src = ( uint16_t ) NUM2UINT( tp_src );
        match->wildcards &= ( uint32_t ) ~OFPFW_TP_SRC;
      }

      VALUE tp_dst = rb_hash_aref( options, ID2SYM( rb_intern( "tp_dst" ) ) );
      if ( tp_dst != Qnil ) {
        match->tp_dst = ( uint16_t ) NUM2UINT( tp_dst );
        match->wildcards &= ( uint32_t ) ~OFPFW_TP_DST;
      }
    }
  }
  return self;
}
Exemplo n.º 3
0
static uint32_t
ip_addr_to_i( VALUE ip_addr ) {
  return nw_addr_to_i( ip_addr );
}
Exemplo n.º 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" );
  }
}