Class: Trema::Match

Inherits:
Object
  • Object
show all
Defined in:
ruby/trema/match.c

Constant Summary collapse

OFPFW_IN_PORT =
INT2NUM( OFPFW_IN_PORT )
OFPFW_DL_VLAN =
INT2NUM( OFPFW_DL_VLAN )
OFPFW_DL_SRC =
INT2NUM( OFPFW_DL_SRC )
OFPFW_DL_DST =
INT2NUM( OFPFW_DL_DST )
OFPFW_DL_TYPE =
INT2NUM( OFPFW_DL_TYPE )
OFPFW_NW_PROTO =
INT2NUM( OFPFW_NW_PROTO )
OFPFW_TP_SRC =
INT2NUM( OFPFW_TP_SRC )
OFPFW_TP_DST =
INT2NUM( OFPFW_TP_DST )
OFPFW_NW_SRC_SHIFT =
INT2NUM( OFPFW_NW_SRC_SHIFT )
OFPFW_NW_SRC_BITS =
INT2NUM( OFPFW_NW_SRC_BITS )
OFPFW_NW_SRC_MASK =
INT2NUM( OFPFW_NW_SRC_MASK )
OFPFW_NW_SRC_ALL =
INT2NUM( OFPFW_NW_SRC_ALL )
OFPFW_NW_DST_SHIFT =
INT2NUM( OFPFW_NW_DST_SHIFT )
OFPFW_NW_DST_BITS =
INT2NUM( OFPFW_NW_DST_BITS )
OFPFW_NW_DST_MASK =
INT2NUM( OFPFW_NW_DST_MASK )
OFPFW_NW_DST_ALL =
INT2NUM( OFPFW_NW_DST_ALL )
OFPFW_DL_VLAN_PCP =
INT2NUM( OFPFW_DL_VLAN_PCP )
OFPFW_NW_TOS =
INT2NUM( OFPFW_NW_TOS )
OFPFW_ALL =
INT2NUM( OFPFW_ALL )

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Match

Creates a Trema::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.

Returns self an object that encapsulates and wraps the struct ofp_match.

Examples:

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,
)

Parameters:

  • options (Hash) (defaults to: {})

    the options hash.

Options Hash (options):

  • :in_port (Number)

    the physical port number to match.

  • :dl_src (String, Number, Trema::Mac)

    the source ethernet address to match specified either as 6 pairs of hexadecimal digits delimited by colon or as a hexadecimal number or as a Trema::Mac object. (eg. “00:11:22:33:44:55” or 0x001122334455 or Mac.new(“00:11:22:33:44:55”)).

  • :dl_dst (String, Number)

    the destination ethernet address to match specified either as a 6 pairs of hexadecimal digits delimited by colon or as a hexadecimal number or as a Trema::Mac object. (eg. “00:11:22:33:44:55” or 0x001122334455 or Mac.new(“00:11:22:33:44:55”)).

  • :dl_type (Number)

    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).

  • :dl_vlan (Number)

    the IEEE 802.1q virtual VLAN tag to match specified as a 12-bit number 0 to 4095 inclusive.

  • :dl_vlan_pcp (Number)

    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.

  • :nw_tos (Number)

    the IP ToS/DSCP field to match specified as a decimal number between 0 and 255 inclusive.

  • :nw_proto (Number)

    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.

  • :nw_src (String)

    the IPv4 source address to match if dl_type is set to 0x0800.

  • :nw_dst (String)

    the IPv4 destination address to match if dl_type is set to 0x0800.

  • :tp_src (Number)

    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.

  • :tp_dst (Number)

    the destination TCP/UDP port number to match specified as a decimal number between 0 and 65535 inclusive.



446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
# File 'ruby/trema/match.c', line 446

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;
        if ( rb_obj_is_kind_of( dl_src, rb_eval_string( "Trema::Mac" ) ) ) {
          dl_addr = dl_src;
        }
        else {
          dl_addr = rb_funcall( rb_eval_string( "Trema::Mac" ), rb_intern( "new" ), 1, dl_src );
        }
        dl_addr_to_a( 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;
        if ( rb_obj_is_kind_of( dl_dst, rb_eval_string( "Trema::Mac" ) ) ) {
          dl_addr = dl_dst;
        }
        else {
          dl_addr = rb_funcall( rb_eval_string( "Trema::Mac" ), rb_intern( "new" ), 1, dl_dst );
        }
        dl_addr_to_a( 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 );
        uint32_t prefixlen = ( uint32_t ) NUM2UINT( rb_funcall( nw_addr, rb_intern( "prefixlen" ), 0 ) );
        if ( prefixlen > 0 ) {
          match->nw_src = nw_addr_to_i( nw_addr );
          match->wildcards &= ( uint32_t ) ~OFPFW_NW_SRC_MASK;
          match->wildcards |= ( uint32_t ) ( ( 32 - prefixlen ) << OFPFW_NW_SRC_SHIFT );
        }
      }

      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 );
        uint32_t prefixlen = ( uint32_t ) NUM2UINT( rb_funcall( nw_addr, rb_intern( "prefixlen" ), 0 ) );
        if ( prefixlen > 0 ) {
          match->nw_dst = nw_addr_to_i( nw_addr );
          match->wildcards &= ( uint32_t ) ~OFPFW_NW_DST_MASK;
          match->wildcards |= ( uint32_t ) ( ( 32 - prefixlen ) << OFPFW_NW_DST_SHIFT );
        }
      }

      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;
}

Class Method Details

.match_from(message, *options) ⇒ Match

Creates a Trema::Match instance from packet_in’s data, the method accepts an additional list of symbols to wildcard set and ignore while matching flow entries.

Examples:

def packet_in datapath_id, message
  send_flow_mod(
    datapath_id,
    :match => Match.from( message, :dl_type, :nw_proto ),
    :actions => Trema::ActionOutput.new( 2 )
  )
end

Parameters:

  • message (PacketIn)

    the PacketIn‘s message content.

  • options (optional, list)

    If supplied a comma-separated list of symbol ids indicating fields to be wildcarded.

    :in_port

    the physical port number to wildcard.

    :dl_src

    the source Ethernet address to wildcard.

    :dl_dst

    the destination Ethernet address to wildcard.

    :dl_vlan

    the IEEE 802.1q virtual VLAN tag to wildcard.

    :dl_vlan_pcp

    the IEEE 802.1q priority code point to wildcard.

    :dl_type

    the Ethernet protocol type to wildcard.

    :nw_tos

    the IP ToS /DSCP field to wildcard.

    :nw_proto

    the IP protocol type to wildcard.

    :nw_src

    the IPv4 source address to wildcard.

    :nw_dst

    the IPv4 destination address to wildcard.

    :tp_src

    the source TCP/UDP port number to wildcard.

    :tp_dst

    the destination TCP/UDP port number to wildcard.

Returns:

  • (Match)

    self the modified or exact match from packet depending on whether the options argument supplied or not.



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'ruby/trema/match.c', line 105

static VALUE
match_from( int argc, VALUE *argv, VALUE self ) {
  VALUE message, obj, wildcard_id, options;
  struct ofp_match *match;
  packet_in *packet;
  uint32_t wildcards = 0;

  if ( rb_scan_args( argc, argv, "1*", &message, &options ) >= 1 ) {
    obj = rb_funcall( self, rb_intern( "new" ), 0 );
    match = get_match( obj );
    Data_Get_Struct( message, packet_in, packet );
    int i;
    for ( i = 0; i < RARRAY_LEN( options ); i++ ) {
      wildcard_id = SYM2ID( RARRAY_PTR( options )[ i ] );
      if ( rb_intern( "in_port" ) == wildcard_id ) {
        wildcards |= OFPFW_IN_PORT;
      }
      if ( rb_intern( "dl_src" ) == wildcard_id ) {
        wildcards |= OFPFW_DL_SRC;
      }
      if ( rb_intern( "dl_dst" ) == wildcard_id ) {
        wildcards |= OFPFW_DL_DST;
      }
      if ( rb_intern( "dl_vlan" ) == wildcard_id ) {
        wildcards |= OFPFW_DL_VLAN;
      }
      if ( rb_intern( "dl_vlan_pcp" ) == wildcard_id ) {
        wildcards |= OFPFW_DL_VLAN_PCP;
      }
      if ( rb_intern( "dl_type" ) == wildcard_id ) {
        wildcards |= OFPFW_DL_TYPE;
      }
      if ( rb_intern( "nw_tos" ) == wildcard_id ) {
        wildcards |= OFPFW_NW_TOS;
      }
      if ( rb_intern( "nw_proto" ) == wildcard_id ) {
        wildcards |= OFPFW_NW_PROTO;
      }
      if ( rb_intern( "nw_src" ) == wildcard_id ) {
        wildcards |= OFPFW_NW_SRC_ALL;
      }
      if ( rb_intern( "nw_dst" ) == wildcard_id ) {
        wildcards |= OFPFW_NW_DST_ALL;
      }
      if ( rb_intern( "tp_src" ) == wildcard_id ) {
        wildcards |= OFPFW_TP_SRC;
      }
      if ( rb_intern( "tp_dst" ) == wildcard_id ) {
        wildcards |= OFPFW_TP_DST;
      }
    }
  }
  set_match_from_packet( match, packet->in_port, wildcards, packet->data );
  return obj;
}

Instance Method Details

#compare(other) ⇒ Boolean

Compare context of Trema::Match self with Trema::Match other.

Examples:

def packet_in datapath_id, message
  match = Match.new( :dl_type => 0x0800, :nw_src => "192.168.0.1" )
  if match.compare( ExactMatch.from( message ) )
    info "Received packet from 192.168.0.1"
  end
end

Returns:



175
176
177
178
# File 'ruby/trema/match.c', line 175

static VALUE
match_compare( VALUE self, VALUE other ) {
  return compare_match( get_match( self ), get_match( other ) ) ? Qtrue : Qfalse;
}

#dl_dstMac

Returns the value of dl_dst.

Returns:

  • (Mac)

    the value of dl_dst.



254
255
256
257
# File 'ruby/trema/match.c', line 254

static VALUE
match_dl_dst( VALUE self ) {
  return match_dl( self, 0 );
}

#dl_srcMac

Returns the value of dl_src.

Returns:

  • (Mac)

    the value of dl_src.



245
246
247
248
# File 'ruby/trema/match.c', line 245

static VALUE
match_dl_src( VALUE self ) {
  return match_dl( self, 1 );
}

#dl_typeNumber

Returns the value of dl_type.

Returns:

  • (Number)

    the value of dl_type.



281
282
283
284
# File 'ruby/trema/match.c', line 281

static VALUE
match_dl_type( VALUE self ) {
  return UINT2NUM( ( get_match( self ) )->dl_type );
}

#dl_vlanNumber

Returns the value of dl_vlan.

Returns:

  • (Number)

    the value of dl_vlan.



263
264
265
266
# File 'ruby/trema/match.c', line 263

static VALUE
match_dl_vlan( VALUE self ) {
  return UINT2NUM( ( get_match( self ) )->dl_vlan );
}

#dl_vlan_pcpNumber

Returns the value of dl_vlan_pcp.

Returns:

  • (Number)

    the value of dl_vlan_pcp.



272
273
274
275
# File 'ruby/trema/match.c', line 272

static VALUE
match_dl_vlan_pcp( VALUE self ) {
  return UINT2NUM( ( get_match( self ) )->dl_vlan_pcp );
}

#in_portNumber

Returns the value of in_port.

Returns:

  • (Number)

    the value of in_port.



220
221
222
223
# File 'ruby/trema/match.c', line 220

static VALUE
match_in_port( VALUE self ) {
  return UINT2NUM( ( get_match( self ) )->in_port );
}

#nw_dstIP

An IPv4 destination address in its numeric representation.

Returns:

  • (IP)

    the value of nw_dst.



341
342
343
344
# File 'ruby/trema/match.c', line 341

static VALUE
match_nw_dst( VALUE self ) {
  return match_nw( self, 0 );
}

#nw_protoNumber

Returns the value of nw_proto.

Returns:

  • (Number)

    the value of nw_proto.



299
300
301
302
# File 'ruby/trema/match.c', line 299

static VALUE
match_nw_proto( VALUE self ) {
  return UINT2NUM( ( get_match( self ) )->nw_proto );
}

#nw_srcIP

An IPv4 source address in its numeric representation.

Returns:

  • (IP)

    the value of nw_src.



330
331
332
333
# File 'ruby/trema/match.c', line 330

static VALUE
match_nw_src( VALUE self ) {
  return match_nw( self, 1 );
}

#nw_tosNumber

Returns the value of nw_tos.

Returns:

  • (Number)

    the value of nw_tos.



290
291
292
293
# File 'ruby/trema/match.c', line 290

static VALUE
match_nw_tos( VALUE self ) {
  return UINT2NUM( ( get_match( self ) )->nw_tos );
}

#replace(other) ⇒ Match

Replaces context of Trema::Match self with Trema::Match other.

Returns:

  • (Match)

    self the modified object instance.



187
188
189
190
191
# File 'ruby/trema/match.c', line 187

static VALUE
match_replace( VALUE self, VALUE other ) {
  memcpy( get_match( self ), get_match( other ), sizeof( struct ofp_match ) );
  return self;
}

#to_sObject



197
198
199
200
201
202
203
# File 'ruby/trema/match.c', line 197

static VALUE
match_to_s( VALUE self ) {
  char match_str[ 1024 ];

  match_to_string( get_match( self ), match_str, sizeof( match_str ) );
  return rb_str_new2( match_str );
}

#tp_dstNumber

Returns the value of tp_dst.

Returns:

  • (Number)

    the value of tp_dst.



359
360
361
362
# File 'ruby/trema/match.c', line 359

static VALUE
match_tp_dst( VALUE self ) {
  return UINT2NUM( ( get_match( self ) )->tp_dst );
}

#tp_srcNumber

Returns the value of tp_src.

Returns:

  • (Number)

    the value of tp_src.



350
351
352
353
# File 'ruby/trema/match.c', line 350

static VALUE
match_tp_src( VALUE self ) {
  return UINT2NUM( ( get_match( self ) )->tp_src );
}

#wildcardsNumber

The wildcard field expressed as a 32-bit bitmap,

Returns:

  • (Number)

    the value of wildcards.



211
212
213
214
# File 'ruby/trema/match.c', line 211

static VALUE
match_wildcards( VALUE self ) {
  return UINT2NUM( ( get_match( self ) )->wildcards );
}