From b5d2ac8df7680ff37232a639d2ffa8f6e42bc0d7 Mon Sep 17 00:00:00 2001 From: SUGYO Date: Thu, 18 Jul 2013 15:34:45 +0900 Subject: [PATCH] correct ExactMatch (issue #53) --- ruby/trema/exact-match.rb | 2 +- ruby/trema/match.c | 61 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/ruby/trema/exact-match.rb b/ruby/trema/exact-match.rb index fbc172f4..72844410 100644 --- a/ruby/trema/exact-match.rb +++ b/ruby/trema/exact-match.rb @@ -21,7 +21,7 @@ module Trema class ExactMatch def self.from message - message.match + Match.from message end end end diff --git a/ruby/trema/match.c b/ruby/trema/match.c index f033205d..806d5f5a 100644 --- a/ruby/trema/match.c +++ b/ruby/trema/match.c @@ -25,10 +25,71 @@ extern VALUE mTrema; VALUE cMatch; +/* + * Creates a {Match} instance from packet_in's data. + * + * @overload match_from(message) + * + * @example + * def packet_in datapath_id, message + * send_flow_mod( + * datapath_id, + * :match => Match.from( message ), + * :actions => Trema::ActionOutput.new( 2 ) + * ) + * end + * + * @param [PacketIn] message + * the {PacketIn}'s message content. + * + * @return [Match] self + * the match from packet_in's data. + */ +static VALUE +match_from( VALUE self, VALUE message ) { + uint32_t in_port = OFPP_CONTROLLER; + VALUE r_match = rb_iv_get( message, "@match" ); + if ( !NIL_P( r_match ) ) { + VALUE r_in_port = rb_iv_get( r_match, "@in_port" ); + if ( !NIL_P( r_in_port ) ) { + in_port = NUM2UINT( r_in_port ); + if ( in_port == 0 ) { + rb_raise( rb_eArgError, "The in_port value must be greater than 0." ); + } + if ( in_port > OFPP_MAX ) { + if ( in_port != OFPP_CONTROLLER && in_port != OFPP_LOCAL ) { + rb_raise( rb_eArgError, "The in_port value must be less than or equal to OFPP_MAX." ); + } + } + } + } + + VALUE r_data = rb_iv_get( message, "@data" ); + if ( NIL_P( r_data ) ) { + rb_raise( rb_eArgError, "The data is a mandatory option" ); + } + buffer *data = r_array_to_buffer( r_data ); + bool ret = parse_packet( data ); + if ( !ret ) { + rb_raise( rb_eArgError, "The data must be a Ethernet frame." ); + } + + oxm_matches *matches = create_oxm_matches(); + set_match_from_packet( matches, in_port, NULL, data ); + VALUE r_new = oxm_match_to_r_match( matches ); + delete_oxm_matches( matches ); + + free_buffer( data ); + + return r_new; +} + + void Init_match( void ) { cMatch = rb_define_class_under( mTrema, "Match", rb_eval_string( "Trema::Message" ) ); rb_require( "trema/match" ); + rb_define_singleton_method( cMatch, "from", match_from, 1 ); }