Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

生成したフレームをpacket_outのdata:として指定した際にエラーが出力される #52

Open
shun159 opened this issue Jul 8, 2013 · 5 comments
Assignees

Comments

@shun159
Copy link
Member

shun159 commented Jul 8, 2013

#サンプルコードは以下の通りです。

def handle_arp_request( datapath_id, message )
    @arp_table.learn message.arp_spa.to_s, message.arp_sha.to_s, message.in_port.to_i
    daddr = message.arp_tpa
    interface = @interface.find_by_ipaddr( daddr )
    if interface.class.name != "SQLite3::Statement" and @interface.has?( message.eth_dst )
        puts "send a arp reply to #{ message.arp_spa.to_s }"
        packet_out datapath_id, create_arp_reply_from( message, interface["hwaddr"] ), Actions::SendOutPort.new( port_number: interface["port"] )
    end
end

def packet_out datapath_id, message, action
    send_packet_out(
        p message
        datapath_id,
        data: message,
        actions: action
    )
end

#messageの内容は以下の通りです。
p message => "d1PT\x01\x14\0\x90\xFB-\xDCi\b\x06\0\x01\b\0\x06\x04\0\x02\0\x90\xFB-\xDCi\xC0\xA8\0\xFEd1PT\x01\x14\xC0\xA8\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"

#出力されるエラーは以下の通りです。
An Ethernet frame must be provided if buffer_id is equal to 0xffffffff

@sugyo
Copy link
Member

sugyo commented Jul 10, 2013

ついでにですが、
message-helper.cにあるsend_message(send_controller_message)以外のsend_xxxは、
message-helper.rbにもっていくのはだめですか?(rubyで書いた方がいいような気がするためです)

@sugyo
Copy link
Member

sugyo commented Jul 10, 2013

send_messageもmessage-helper.rbにいれてみました。
私のイメージは下記のような感じです
https://github.com/sugyo/trema-edge/commit/902f9616719224d3a166133c377501db5fc81909

@proshiba
Copy link

以下2つを実行して、とりあえず回避が出来ました。
PacketDataをStringで渡せれば、もっとスマートなのですが、そうはいかず。。。
(STR2CSTRなど試しましたが、NGでした。。。)

・ send_packet_outにて、:data => packet.unpack("C*") (unpackして渡す)
・ /ruby/trema/message-helper.cに以下を追記してrake

// 以下1行を追記(add)
VALUE r_opt_data = HASH_REF( options, data );
// 以下110行目から9行は変更無し
if ( !NIL_P( r_opt_message ) ) {

  if ( datapath_id == rb_iv_get( r_opt_message, "@datapath_id" ) ) {
    buffer_id = NUM2UINT( rb_iv_get( r_opt_message, "@buffer_id" ) );
    VALUE match = rb_iv_get( r_opt_message, "@match" );
    in_port = NUM2UINT( rb_iv_get( match, "@in_port" ) );
  }
  VALUE r_data = rb_iv_get( r_opt_message, "@data" );
  data = r_array_to_buffer( r_data );
}

// 以下3行を追記(add)
else if( !NIL_P(r_opt_data) ){
data = r_array_to_buffer( r_opt_data );
}
buffer *packet_out;
// 以下の判定条件を追加( || !NIL_P(r_opt_data) )
if ( buffer_id == OFP_NO_BUFFER &&
( !NIL_P( r_opt_message ) || !NIL_P(r_opt_data) )) {
// 以下省略

一応send_packet_out全体もそのまま載せておきます。

static VALUE
send_packet_out( int argc, VALUE *argv, VALUE self ) {
VALUE datapath_id = Qnil;
VALUE options = Qnil;
rb_scan_args( argc, argv, "11", &datapath_id, &options );

uint32_t buffer_id = OFP_NO_BUFFER;
buffer *data = NULL;
openflow_actions *actions = NULL;
uint32_t in_port = OFPP_ANY;
if ( !NIL_P( options ) ) {

VALUE r_opt_action = HASH_REF( options, actions );
if ( !NIL_P( r_opt_action ) ) {
  actions = pack_basic_action( r_opt_action );
}

VALUE r_opt_message = HASH_REF( options, packet_in );
VALUE r_opt_data = HASH_REF( options, data ); //add
if ( !NIL_P( r_opt_message ) ) {

  if ( datapath_id == rb_iv_get( r_opt_message, "@datapath_id" ) ) {
    buffer_id = NUM2UINT( rb_iv_get( r_opt_message, "@buffer_id" ) );
    VALUE match = rb_iv_get( r_opt_message, "@match" );
    in_port = NUM2UINT( rb_iv_get( match, "@in_port" ) );
  }
  VALUE r_data = rb_iv_get( r_opt_message, "@data" );
  data = r_array_to_buffer( r_data );
}
// add following els if
else if( !NIL_P(r_opt_data) ){
    data = r_array_to_buffer( r_opt_data );
}
buffer *packet_out;
if ( buffer_id == OFP_NO_BUFFER &&
   ( !NIL_P( r_opt_message )  || !NIL_P(r_opt_data) )) {  // add more 1 condition
  buffer *frame = duplicate_buffer( data );
  fill_ether_padding( frame );
  packet_out = create_packet_out(
    get_transaction_id(),
    buffer_id,
    in_port,
    actions,
    frame
  );
  free_buffer( data );
  free_buffer( frame );
} 
else {
  packet_out = create_packet_out(
    get_transaction_id(),
    buffer_id, 
    in_port,
    actions,
    NULL
  );
}
send_openflow_message( NUM2ULL( datapath_id ), packet_out );

free_buffer( packet_out );
delete_actions( actions );

}
return self;
}

@yasuhito yasuhito self-assigned this Nov 26, 2014
@yasuhito
Copy link
Member

@proshiba @sugyo @shun159 すみません遅くなりました。
この修正がすぐ欲しいという人がいるので、とりあえず大芝さんの修正を入れておいて、のちほどすぎょうさん方式で修正します。

yasuhito added a commit that referenced this issue Nov 28, 2014
Fix errors when passing :data option to send_packet_out (refs #52).
@yasuhito
Copy link
Member

ひとまず @proshiba さんの修正を入れておきました。@shun159 @sugyo

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants