Beispiel #1
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_short( 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;
}
/*
 * Appends its action(set_dl_src) to the list of actions.
 *
 * @return [ActionSetDlSrc] self
 */
static VALUE
action_set_dl_src_append( VALUE self, VALUE action_ptr ) {
  openflow_actions *actions;
  Data_Get_Struct( action_ptr, openflow_actions, actions );

  uint8_t dl_src[ OFP_ETH_ALEN ];
  uint8_t *ptr;
  ptr = ( uint8_t* ) dl_addr_short( action_get_dl_src( self ), dl_src );
  append_action_set_dl_src( actions, ptr );
  return self;
}
Beispiel #3
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;
}