コード例 #1
0
ファイル: lldp.c プロジェクト: amotoki/trema-sliceable-switch
bool
send_lldp( probe_timer_entry *port ) {
  buffer *lldp;

  lldp = create_lldp_frame( port->mac, port->datapath_id, port->port_no );

  openflow_actions *actions = create_actions();
  if ( !append_action_output( actions, port->port_no, UINT16_MAX ) ) {
    free_buffer( lldp );
    error( "Failed to sent LLDP frame(%#" PRIx64 ", %u)", port->datapath_id, port->port_no );
    return false;
  }

  uint32_t transaction_id = get_transaction_id();

  buffer *packetout = create_packet_out( transaction_id, UINT32_MAX,
                                         OFPP_NONE, actions, lldp );
  if ( !send_openflow_message( port->datapath_id, packetout ) ) {
    free_buffer( lldp );
    free_buffer( packetout );
    delete_actions( actions );
    die( "send_openflow_message" );
  }

  free_buffer( lldp );
  free_buffer( packetout );
  delete_actions( actions );

  debug( "Sent LLDP frame(%#" PRIx64 ", %u)", port->datapath_id, port->port_no );
  return true;
}
コード例 #2
0
static void
do_flooding( packet_in packet_in, uint32_t in_port ) {
  openflow_actions *actions = create_actions();
  append_action_output( actions, OFPP_ALL, OFPCML_NO_BUFFER );

  buffer *packet_out;
  if ( packet_in.buffer_id == OFP_NO_BUFFER ) {
    buffer *frame = duplicate_buffer( packet_in.data );
    fill_ether_padding( frame );
    packet_out = create_packet_out(
      get_transaction_id(),
      packet_in.buffer_id,
      in_port,
      actions,
      frame
    );
    free_buffer( frame );
  }
  else {
    packet_out = create_packet_out(
      get_transaction_id(),
      packet_in.buffer_id,
      in_port,
      actions,
      NULL
    );
  }
  send_openflow_message( packet_in.datapath_id, packet_out );
  free_buffer( packet_out );
  delete_actions( actions );
}
コード例 #3
0
ファイル: learning_switch.c プロジェクト: Milstein/trema
static void
send_packet( uint16_t destination_port, packet_in packet_in ) {
  openflow_actions *actions = create_actions();
  append_action_output( actions, destination_port, UINT16_MAX );

  struct ofp_match match;
  set_match_from_packet( &match, packet_in.in_port, 0, packet_in.data );

  buffer *flow_mod = create_flow_mod(
    get_transaction_id(),
    match,
    get_cookie(),
    OFPFC_ADD,
    60,
    0,
    UINT16_MAX,
    UINT32_MAX,
    OFPP_NONE,
    OFPFF_SEND_FLOW_REM,
    actions
  );
  send_openflow_message( packet_in.datapath_id, flow_mod );
  free_buffer( flow_mod );

  send_packet_out( packet_in, actions );

  delete_actions( actions );
}
コード例 #4
0
ファイル: topology_management.c プロジェクト: kazuyas/apps
static void
send_flow_mod_receiving_lldp( sw_entry *sw, uint16_t hard_timeout, uint16_t priority ) {
  struct ofp_match match;
  memset( &match, 0, sizeof( struct ofp_match ) );
  if ( !options.lldp_over_ip ) {
    match.wildcards = OFPFW_ALL & ~OFPFW_DL_TYPE;
    match.dl_type = ETH_ETHTYPE_LLDP;
  }
  else {
    match.wildcards = OFPFW_ALL & ~( OFPFW_DL_TYPE | OFPFW_NW_PROTO | OFPFW_NW_SRC_MASK | OFPFW_NW_DST_MASK );
    match.dl_type = ETH_ETHTYPE_IPV4;
    match.nw_proto = IPPROTO_ETHERIP;
    match.nw_src = options.lldp_ip_src;
    match.nw_dst = options.lldp_ip_dst;
  }

  openflow_actions *actions = create_actions();
  const uint16_t max_len = UINT16_MAX;
  append_action_output( actions, OFPP_CONTROLLER, max_len );

  const uint16_t idle_timeout = 0;
  const uint32_t buffer_id = UINT32_MAX;
  const uint16_t flags = 0;
  buffer *flow_mod = create_flow_mod( get_transaction_id(), match, get_cookie(),
                                      OFPFC_ADD, idle_timeout, hard_timeout,
                                      priority, buffer_id,
                                      OFPP_NONE, flags, actions );
  send_openflow_message( sw->datapath_id, flow_mod );
  delete_actions( actions );
  free_buffer( flow_mod );
  debug( "Sent a flow_mod for receiving LLDP frames from %#" PRIx64 ".", sw->datapath_id );
}
コード例 #5
0
ファイル: packet_in.c プロジェクト: cs470Group/sdn-controller
static void
handle_switch_ready( uint64_t datapath_id, void *user_data ) {
  UNUSED( user_data );

  openflow_actions *actions = create_actions();
  append_action_output( actions, OFPP_CONTROLLER, OFPCML_NO_BUFFER );
  openflow_instructions *insts = create_instructions();
  append_instructions_apply_actions( insts, actions );

  buffer *flow_mod = create_flow_mod(
    get_transaction_id(),
    get_cookie(),
    0,
    0,
    OFPFC_ADD,
    0,
    0,
    OFP_LOW_PRIORITY,
    OFP_NO_BUFFER,
    0,
    0,
    OFPFF_SEND_FLOW_REM,
    NULL,
    insts
  );
  send_openflow_message( datapath_id, flow_mod );
  free_buffer( flow_mod );

  delete_instructions( insts );
  delete_actions( actions );
}
コード例 #6
0
ファイル: cbench_switch.c プロジェクト: dabideen/trema-edge
static void
handle_packet_in( uint64_t datapath_id, packet_in message ) {
  openflow_actions *actions = create_actions();
  append_action_output( actions, ( uint16_t ) ( message.in_port + 1 ), OFPCML_NO_BUFFER );

  struct ofp_match match;
  set_match_from_packet( &match, message.in_port, 0, message.data );

  buffer *flow_mod = create_flow_mod(
    get_transaction_id(),
    match,
    get_cookie(),
    OFPFC_ADD,
    0,
    0,
    OFP_HIGH_PRIORITY,
    message.buffer_id,
    OFPP_NONE,
    0,
    actions
  );
  send_openflow_message( datapath_id, flow_mod );

  free_buffer( flow_mod );
  delete_actions( actions );
}
コード例 #7
0
static void
do_flooding( packet_in packet_in ) {
  openflow_actions *actions = create_actions();
  append_action_output( actions, OFPP_FLOOD, UINT16_MAX );

  buffer *packet_out;
  if ( packet_in.buffer_id == UINT32_MAX ) {
    buffer *frame = duplicate_buffer( packet_in.data );
    fill_ether_padding( frame );
    packet_out = create_packet_out(
      get_transaction_id(),
      packet_in.buffer_id,
      packet_in.in_port,
      actions,
      frame
    );
    free_buffer( frame );
  }
  else {
    packet_out = create_packet_out(
      get_transaction_id(),
      packet_in.buffer_id,
      packet_in.in_port,
      actions,
      NULL
    );
  }
  send_openflow_message( packet_in.datapath_id, packet_out );
  free_buffer( packet_out );
  delete_actions( actions );
}
コード例 #8
0
ファイル: switch.c プロジェクト: iqm/apps
static void
output_packet( const buffer *packet, uint64_t dpid, uint16_t port_no ) {
  openflow_actions *actions = create_actions();
  append_action_output( actions, port_no, UINT16_MAX );

  send_packet_out( dpid, actions, packet );
  delete_actions( actions );
}
コード例 #9
0
ファイル: repeater_hub.c プロジェクト: dabideen/trema-edge
static void
handle_packet_in( uint64_t datapath_id, packet_in message ) {
  if ( message.data == NULL ) {
    error( "data must not be NULL" );
    return;
  }
  uint32_t in_port = get_in_port_from_oxm_matches( message.match );
  if ( in_port == 0 ) {
    return;
  }

  openflow_actions *actions = create_actions();
  append_action_output( actions, OFPP_ALL, OFPCML_NO_BUFFER );

  openflow_instructions *insts = create_instructions();
  append_instructions_apply_actions( insts, actions );

  oxm_matches *match = create_oxm_matches();
  set_match_from_packet( match, in_port, 0, message.data );

  buffer *flow_mod = create_flow_mod(
    get_transaction_id(),
    get_cookie(),
    0,
    0,
    OFPFC_ADD,
    60,
    0,
    OFP_HIGH_PRIORITY,
    message.buffer_id,
    0,
    0,
    OFPFF_SEND_FLOW_REM,
    match,
    insts
  );
  send_openflow_message( datapath_id, flow_mod );
  free_buffer( flow_mod );
  delete_oxm_matches( match );
  delete_instructions( insts );

  if ( message.buffer_id == OFP_NO_BUFFER ) {
    buffer *frame = duplicate_buffer( message.data );
    fill_ether_padding( frame );
    buffer *packet_out = create_packet_out(
      get_transaction_id(),
      message.buffer_id,
      in_port,
      actions,
      frame
    );
    send_openflow_message( datapath_id, packet_out );
    free_buffer( packet_out );
    free_buffer( frame );
  }

  delete_actions( actions );
}
コード例 #10
0
ファイル: learning_switch.c プロジェクト: Milstein/trema
static void
do_flooding( packet_in packet_in ) {
  openflow_actions *actions = create_actions();
  append_action_output( actions, OFPP_FLOOD, UINT16_MAX );

  send_packet_out( packet_in, actions );

  delete_actions( actions );
}
コード例 #11
0
ファイル: switch.c プロジェクト: iqm/apps
static void
send_packet_out_for_each_switch( switch_info *sw, const buffer *packet, uint64_t dpid, uint16_t in_port ) {
  openflow_actions *actions = create_actions();
  int number_of_actions = foreach_port( sw->ports, build_packet_out_actions, actions, dpid, in_port );

  if ( number_of_actions > 0 ) {
    send_packet_out( sw->dpid, actions, packet );
  }
  delete_actions( actions );
}
コード例 #12
0
ファイル: remove_player.c プロジェクト: jsthibault/Zappy
void	remove_player(t_kernel *kernel, t_player *player)
{
  send_deconnexion_to_graphic(kernel, player);
  list_pop_func_arg(&player->team->players, &remove_player_on_team, player);
  if (!(player->from_egg))
    ++(player->team->place_left);
  delete_actions(player->actions);
  remove_player_on_map(kernel, player);
  list_pop_func_arg(&kernel->game.players, &remove_player_on_team, player);
  free(player);
}
コード例 #13
0
static void
setup_reverse_path( int status, const path *p, void *user_data ) {
  assert(user_data);

  packet_out_params *params = user_data;
  if ( status != SETUP_SUCCEEDED ) {
    error( "Failed to set up path ( status = %d ).", status );
    output_packet( params->packet, params->out_datapath_id, params->out_port_no, params->out_vid );
    free_buffer( params->packet );
    xfree( params );
    return;
  }

  struct ofp_match rmatch;
  set_ipv4_reverse_match( &rmatch, &(p->match) );
  rmatch.dl_vlan = params->out_vid;

  openflow_actions *vlan_actions;
  vlan_actions = create_openflow_actions_to_update_vid( params->out_vid, params->in_vid );

  path *rpath = create_path( rmatch, p->priority, p->idle_timeout, p->hard_timeout );
  assert( rpath != NULL );
  list_element *hops = p->hops;
  dlist_element *rhops = create_dlist();
  while ( hops != NULL ) {
    hop *h = hops->data;
    assert( h != NULL );
    hop *rh = create_hop( h->datapath_id, h->out_port, h->in_port, vlan_actions );
    if ( vlan_actions ) {
      delete_actions( vlan_actions );
      vlan_actions = NULL;
    }
    assert( rh != NULL );
    rhops = insert_before_dlist( rhops, rh );
    hops = hops->next;
  }
  while ( rhops != NULL && rhops->data != NULL ) {
    append_hop_to_path( rpath, ( hop * ) rhops->data );
    rhops = rhops->next;
  }
  bool ret = setup_path( rpath, handle_setup, params, NULL, NULL );
  if ( ret != true ) {
    error( "Failed to set up reverse path." );
    output_packet( params->packet, params->out_datapath_id, params->out_port_no, params->out_vid );
    free_buffer( params->packet );
    xfree( params );
  }

  delete_path( rpath );
  delete_dlist( rhops );
}
コード例 #14
0
static void
send_packet( uint32_t destination_port, packet_in packet_in, uint32_t in_port ) {
  openflow_actions *actions = create_actions();
  append_action_output( actions, destination_port, OFPCML_NO_BUFFER );

  openflow_instructions *insts = create_instructions();
  append_instructions_apply_actions( insts, actions );

  oxm_matches *match = create_oxm_matches();
  set_match_from_packet( match, in_port, NULL, packet_in.data );

  buffer *flow_mod = create_flow_mod(
    get_transaction_id(),
    get_cookie(),
    0,
    0,
    OFPFC_ADD,
    60,
    0,
    OFP_HIGH_PRIORITY,
    packet_in.buffer_id,
    0,
    0,
    OFPFF_SEND_FLOW_REM,
    match,
    insts
  );
  send_openflow_message( packet_in.datapath_id, flow_mod );
  free_buffer( flow_mod );
  delete_oxm_matches( match );
  delete_instructions( insts );

  if ( packet_in.buffer_id == OFP_NO_BUFFER ) {
    buffer *frame = duplicate_buffer( packet_in.data );
    fill_ether_padding( frame );
    buffer *packet_out = create_packet_out(
      get_transaction_id(),
      packet_in.buffer_id,
      in_port,
      actions,
      frame
    );
    send_openflow_message( packet_in.datapath_id, packet_out );
    free_buffer( packet_out );
    free_buffer( frame );
  }

  delete_actions( actions );
}
コード例 #15
0
static void
send_packet_out_for_each_switch( switch_info *sw, void *user_data ) {
  openflow_actions *actions = create_actions();
  port_params params;
  params.switch_params = user_data;
  params.actions = actions;
  foreach_port( sw->ports, build_packet_out_actions, &params );

  // check if no action is build
  if ( actions->n_actions > 0 ) {
    const buffer *packet = params.switch_params->packet;
    send_packet_out( sw->dpid, actions, packet );
  }

  delete_actions( actions );
}
コード例 #16
0
ファイル: routing_switch.c プロジェクト: sun-lei/trema
static void
output_packet( buffer *packet, uint64_t dpid, uint16_t port_no ) {
  openflow_actions *actions = create_actions();
  const uint16_t max_len = UINT16_MAX;
  append_action_output( actions, port_no, max_len );

  const uint32_t transaction_id = get_transaction_id();
  const uint32_t buffer_id = UINT32_MAX;
  const uint16_t in_port = OFPP_NONE;

  fill_ether_padding( packet );
  buffer *packet_out = create_packet_out( transaction_id, buffer_id, in_port,
                                          actions, packet );

  send_openflow_message( dpid, packet_out );

  free_buffer( packet_out );
  delete_actions( actions );
}
コード例 #17
0
ファイル: traffic_monitor.c プロジェクト: Darma/trema
static void
send_packet_out( uint64_t datapath_id, packet_in *message, uint16_t out_port ) {
  uint32_t buffer_id = message->buffer_id;
  uint16_t in_port = message->in_port;
  if ( datapath_id != message->datapath_id ) {
    buffer_id = UINT32_MAX;
    in_port = OFPP_NONE;
  }
  openflow_actions *actions = create_actions();
  append_action_output( actions, out_port, UINT16_MAX );
  const buffer *data = NULL;
  if ( buffer_id == UINT32_MAX ) {
    data = message->data;
  }
  buffer *packet_out = create_packet_out( get_transaction_id(), buffer_id, in_port, actions, data );
  delete_actions( actions );

  send_openflow_message( datapath_id, packet_out );
  free_buffer( packet_out );
}
コード例 #18
0
static void
send_packet( uint16_t destination_port, packet_in packet_in ) {
  openflow_actions *actions = create_actions();
  append_action_output( actions, destination_port, UINT16_MAX );

  struct ofp_match match;
  set_match_from_packet( &match, packet_in.in_port, 0, packet_in.data );

  buffer *flow_mod = create_flow_mod(
    get_transaction_id(),
    match,
    get_cookie(),
    OFPFC_ADD,
    60,
    0,
    UINT16_MAX,
    packet_in.buffer_id,
    OFPP_NONE,
    OFPFF_SEND_FLOW_REM,
    actions
  );
  send_openflow_message( packet_in.datapath_id, flow_mod );
  free_buffer( flow_mod );

  if ( packet_in.buffer_id == UINT32_MAX ) {
    buffer *frame = duplicate_buffer( packet_in.data );
    fill_ether_padding( frame );
    buffer *packet_out = create_packet_out(
      get_transaction_id(),
      packet_in.buffer_id,
      packet_in.in_port,
      actions,
      frame
    );
    send_openflow_message( packet_in.datapath_id, packet_out );
    free_buffer( packet_out );
    free_buffer( frame );
  }

  delete_actions( actions );
}
コード例 #19
0
ファイル: routing_switch.c プロジェクト: sun-lei/trema
static void
send_packet_out_for_each_switch( switch_info *sw, buffer *packet, uint64_t dpid, uint16_t in_port ) {
  openflow_actions *actions = create_actions();
  int number_of_actions = foreach_port( sw->ports, build_packet_out_actions, actions, dpid, in_port );

  // check if no action is build
  if ( number_of_actions > 0 ) {
    const uint32_t transaction_id = get_transaction_id();
    const uint32_t buffer_id = UINT32_MAX;
    const uint16_t in_port = OFPP_NONE;

    fill_ether_padding( packet );
    buffer *packet_out = create_packet_out( transaction_id, buffer_id, in_port,
                                            actions, packet );

    send_openflow_message( sw->dpid, packet_out );

    free_buffer( packet_out );
  }

  delete_actions( actions );
}
コード例 #20
0
static void
output_packet( const buffer *packet, uint64_t dpid, uint16_t port_no, uint16_t out_vid ) {

  openflow_actions *actions = create_actions();
  uint16_t in_vid = VLAN_NONE;
  if ( packet_type_eth_vtag( packet ) ) {
    packet_info packet_info = get_packet_info( packet );
    in_vid = packet_info.vlan_vid;
  }
  if ( out_vid != in_vid ) {
    if ( in_vid != VLAN_NONE && out_vid == VLAN_NONE ) {
      append_action_strip_vlan( actions );
    }
    else {
      append_action_set_vlan_vid( actions, out_vid );
    }
  }
  const uint16_t max_len = UINT16_MAX;
  append_action_output( actions, port_no, max_len );

  send_packet_out( dpid, actions, packet );
  delete_actions( actions );
}
コード例 #21
0
ファイル: traffic_monitor.c プロジェクト: Darma/trema
static void
send_flow_mod( uint64_t datapath_id, uint8_t *macsa, uint8_t *macda, uint16_t out_port ) {
  struct ofp_match match;
  memset( &match, 0, sizeof( match ) );
  match.wildcards = ( OFPFW_ALL & ~( OFPFW_DL_SRC | OFPFW_DL_DST ) );
  memcpy( match.dl_src, macsa, OFP_ETH_ALEN );
  memcpy( match.dl_dst, macda, OFP_ETH_ALEN );
  uint16_t idle_timeout = 0;
  uint16_t hard_timeout = 10;
  uint16_t priority = UINT16_MAX;
  uint32_t buffer_id = UINT32_MAX;
  uint16_t out_port_for_delete_command = OFPP_NONE;
  uint16_t flags = OFPFF_SEND_FLOW_REM;
  openflow_actions *actions = create_actions();
  append_action_output( actions, out_port, UINT16_MAX );
  buffer *flow_mod = create_flow_mod( get_transaction_id(), match, get_cookie(), OFPFC_ADD,
                                      idle_timeout, hard_timeout, priority, buffer_id,
                                      out_port_for_delete_command, flags, actions );
  delete_actions( actions );

  send_openflow_message( datapath_id, flow_mod );
  free_buffer( flow_mod );
}
コード例 #22
0
ファイル: routing_switch.c プロジェクト: sun-lei/trema
static void
modify_flow_entry( const pathresolver_hop *h, const buffer *original_packet, uint16_t idle_timeout ) {
  const uint32_t wildcards = 0;
  struct ofp_match match;
  set_match_from_packet( &match, h->in_port_no, wildcards, original_packet );

  uint32_t transaction_id = get_transaction_id();
  openflow_actions *actions = create_actions();
  const uint16_t max_len = UINT16_MAX;
  append_action_output( actions, h->out_port_no, max_len );

  const uint16_t hard_timeout = 0;
  const uint16_t priority = UINT16_MAX;
  const uint32_t buffer_id = UINT32_MAX;
  const uint16_t flags = 0;
  buffer *flow_mod = create_flow_mod( transaction_id, match, get_cookie(),
                                      OFPFC_ADD, idle_timeout, hard_timeout,
                                      priority, buffer_id, 
                                      h->out_port_no, flags, actions );

  send_openflow_message( h->dpid, flow_mod );
  delete_actions( actions );
  free_buffer( flow_mod );
}
コード例 #23
0
static void
recv_packet_from_tun() {
  char data[ PKT_BUF_SIZE ];
  ssize_t ret;

  ret = read( fd, data, PKT_BUF_SIZE );

  if ( ret <= 0 ) {
    return;
  }

  debug( "%zd bytes packet received from tun interface (fd = %d).", ret, fd );

  // FIXME: we need to parse the ipv4 packet.

  ipv4_header_t *ip_header = ( ipv4_header_t * ) data;
  host_entry *entry = lookup_host( ntohl( ip_header->daddr ) );
  struct in_addr addr;
  addr.s_addr = ip_header->daddr;

  if ( entry == NULL ) {
    error( "Failed to resolve host location (ip = %s).",
           inet_ntoa( addr ) );
    return;
  }

  // create an Ethernet frame and send a packet-out
  void *p;
  uint16_t *type;
  buffer *frame;
  buffer *pout;
  openflow_actions *actions;
  size_t frame_length = ETH_ADDRLEN * 2 + 2 + ( size_t ) ret;

  frame = alloc_buffer_with_length( frame_length );

  p = append_back_buffer( frame, ETH_ADDRLEN );
  memcpy( p, entry->mac, ETH_ADDRLEN );
  p = append_back_buffer( frame, ETH_ADDRLEN );
  memcpy( p, redirector_mac, ETH_ADDRLEN );

  type = append_back_buffer( frame, 2 );
  *type = htons( ETH_ETHTYPE_IPV4 );

  p = append_back_buffer( frame, ( size_t ) ret );
  memcpy( p, data, ( size_t ) ret );

  debug( "Sending a packet-out to a switch (ip = %s, dpid = %#" PRIx64 ", port = %u).",
         inet_ntoa( addr ), entry->dpid, entry->port );

  actions = create_actions();
  append_action_output( actions, entry->port, UINT16_MAX );

  pout = create_packet_out( get_transaction_id(), UINT32_MAX, OFPP_NONE,
                            actions, frame );

  send_openflow_message( entry->dpid, pout );

  free_buffer( frame );
  free_buffer( pout );
  delete_actions( actions );
}
コード例 #24
0
ファイル: controller.c プロジェクト: aigamo/trema
static VALUE
controller_send_flow_mod( uint16_t command, int argc, VALUE *argv, VALUE self ) {
  VALUE datapath_id = Qnil;
  VALUE options = Qnil;
  rb_scan_args( argc, argv, "11", &datapath_id, &options );

  // Defaults
  struct ofp_match default_match;
  memset( &default_match, 0, sizeof( struct ofp_match ) );
  default_match.wildcards = OFPFW_ALL;
  struct ofp_match *match = &default_match;
  uint64_t cookie = get_cookie();
  uint16_t idle_timeout = 0;
  uint16_t hard_timeout = 0;
  uint16_t priority = UINT16_MAX;
  uint32_t buffer_id = UINT32_MAX;
  uint16_t out_port = OFPP_NONE;
  uint16_t flags = OFPFF_SEND_FLOW_REM;
  openflow_actions *actions = create_actions();

  // Options
  if ( options != Qnil ) {
    VALUE opt_match = rb_hash_aref( options, ID2SYM( rb_intern( "match" ) ) );
    if ( opt_match != Qnil ) {
      Data_Get_Struct( opt_match, struct ofp_match, match );
    }

    VALUE opt_cookie = rb_hash_aref( options, ID2SYM( rb_intern( "cookie" ) ) );
    if ( opt_cookie != Qnil ) {
      cookie = NUM2ULL( opt_cookie );
    }

    VALUE opt_idle_timeout = rb_hash_aref( options, ID2SYM( rb_intern( "idle_timeout" ) ) );
    if ( opt_idle_timeout != Qnil ) {
      idle_timeout = ( uint16_t ) NUM2UINT( opt_idle_timeout );
    }

    VALUE opt_hard_timeout = rb_hash_aref( options, ID2SYM( rb_intern( "hard_timeout" ) ) );
    if ( opt_hard_timeout != Qnil ) {
      hard_timeout = ( uint16_t ) NUM2UINT( opt_hard_timeout );
    }

    VALUE opt_priority = rb_hash_aref( options, ID2SYM( rb_intern( "priority" ) ) );
    if ( opt_priority != Qnil ) {
      priority = ( uint16_t ) NUM2UINT( opt_priority );
    }

    VALUE opt_buffer_id = rb_hash_aref( options, ID2SYM( rb_intern( "buffer_id" ) ) );
    if ( opt_buffer_id != Qnil ) {
      buffer_id = ( uint32_t ) NUM2ULONG( opt_buffer_id );
    }

    VALUE opt_out_port = rb_hash_aref( options, ID2SYM( rb_intern( "out_port" ) ) );
    if ( opt_out_port != Qnil ) {
      out_port = ( uint16_t ) NUM2UINT( opt_out_port );
    }

    VALUE opt_send_flow_rem = rb_hash_aref( options, ID2SYM( rb_intern( "send_flow_rem" ) ) );
    if ( opt_send_flow_rem == Qfalse ) {
      flags &= ( uint16_t ) ~OFPFF_SEND_FLOW_REM;
    }

    VALUE opt_check_overlap = rb_hash_aref( options, ID2SYM( rb_intern( "check_overlap" ) ) );
    if ( opt_check_overlap != Qnil ) {
      flags |= OFPFF_CHECK_OVERLAP;
    }

    VALUE opt_emerg = rb_hash_aref( options, ID2SYM( rb_intern( "emerg" ) ) );
    if ( opt_emerg != Qnil ) {
      flags |= OFPFF_EMERG;
    }

    VALUE opt_actions = rb_hash_aref( options, ID2SYM( rb_intern( "actions" ) ) );
    if ( opt_actions != Qnil ) {
      form_actions( opt_actions, actions );
    }
  }

  buffer *flow_mod = create_flow_mod(
    get_transaction_id(),
    *match,
    cookie,
    command,
    idle_timeout,
    hard_timeout,
    priority,
    buffer_id,
    out_port,
    flags,
    actions
  );
  send_openflow_message( NUM2ULL( datapath_id ), flow_mod );

  free_buffer( flow_mod );
  delete_actions( actions );

  return self;
}
コード例 #25
0
ファイル: controller.c プロジェクト: aigamo/trema
/*
 * @overload send_packet_out(datapath_id, options={})
 *   Sends a packet_out message to have a packet processed by the datapath.
 *
 *   @example
 *     send_packet_out(
 *       datapath_id,
 *       :packet_in => message,
 *       :actions => Trema::SendOutPort.new(port_no)
 *     )
 *
 *
 *   @param [Number] datapath_id
 *     the datapath to which a message is sent.
 *
 *   @param [Hash] options
 *     the options to create a message with.
 *
 *
 *   @option options [PacketIn] :packet_in (nil)
 *     The {PacketIn} object received by packet_in handler. If this
 *     option is not nil, :buffer_id, :data, and :in_port option is
 *     set automatically according to the value of :packet_in.
 *
 *   @option options [Number] :in_port (OFPP_NONE)
 *     The port from which the frame is to be sent. OFPP_NONE if
 *     none. OFPP_TABLE to perform the actions defined in the flow
 *     table.
 *
 *   @option options [Number] :buffer_id (0xffffffff)
 *     The buffer ID assigned by the datapath. If 0xffffffff, the
 *     frame is not buffered, and the entire frame must be passed in
 *     :data.
 *
 *   @option options [String, nil] :data (nil)
 *     The entire Ethernet frame. Should be of length 0 if buffer_id
 *     is 0xffffffff, and should be of length >0 otherwise.
 *
 *   @option options [Action, Array<Action>, nil] :actions (nil)
 *     The sequence of actions specifying the actions to perform on
 *     the frame.
 *
 *   @option options [Boolean] :zero_padding (false)
 *     If true, fill up to minimum ethernet frame size.
 */
static VALUE
controller_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 );

  // Defaults.
  uint32_t buffer_id = UINT32_MAX;
  uint16_t in_port = OFPP_NONE;
  openflow_actions *actions = create_actions();
  const buffer *data = NULL;
  buffer *allocated_data = NULL;
  VALUE opt_zero_padding = Qnil;

  if ( options != Qnil ) {
    VALUE opt_message = rb_hash_aref( options, ID2SYM( rb_intern( "packet_in" ) ) );
    if ( opt_message != Qnil ) {
      packet_in *message;
      Data_Get_Struct( opt_message, packet_in, message );

      if ( NUM2ULL( datapath_id ) == message->datapath_id ) {
        buffer_id = message->buffer_id;
        in_port = message->in_port;
      }
      data = ( buffer_id == UINT32_MAX ? message->data : NULL );
    }

    VALUE opt_buffer_id = rb_hash_aref( options, ID2SYM( rb_intern( "buffer_id" ) ) );
    if ( opt_buffer_id != Qnil ) {
      buffer_id = ( uint32_t ) NUM2ULONG( opt_buffer_id );
    }

    VALUE opt_in_port = rb_hash_aref( options, ID2SYM( rb_intern( "in_port" ) ) );
    if ( opt_in_port != Qnil ) {
      in_port = ( uint16_t ) NUM2UINT( opt_in_port );
    }

    VALUE opt_action = rb_hash_aref( options, ID2SYM( rb_intern( "actions" ) ) );
    if ( opt_action != Qnil ) {
      form_actions( opt_action, actions );
    }

    VALUE opt_data = rb_hash_aref( options, ID2SYM( rb_intern( "data" ) ) );
    if ( opt_data != Qnil ) {
      Check_Type( opt_data, T_STRING );
      uint16_t length = ( uint16_t ) RSTRING_LEN( opt_data );
      allocated_data = alloc_buffer_with_length( length );
      memcpy( append_back_buffer( allocated_data, length ), RSTRING_PTR( opt_data ), length );
      data = allocated_data;
    }

    opt_zero_padding = rb_hash_aref( options, ID2SYM( rb_intern( "zero_padding" ) ) );
    if ( opt_zero_padding != Qnil ) {
      if ( TYPE( opt_zero_padding ) != T_TRUE && TYPE( opt_zero_padding ) != T_FALSE ) {
        rb_raise( rb_eTypeError, ":zero_padding must be true or false" );
      }
    }
  }

  if ( data != NULL && data->length + ETH_FCS_LENGTH < ETH_MINIMUM_LENGTH &&
       opt_zero_padding != Qnil && TYPE( opt_zero_padding ) == T_TRUE ) {
    if ( allocated_data == NULL ) {
      allocated_data = duplicate_buffer( data );
      data = allocated_data;
    }
    fill_ether_padding( allocated_data );
  }

  buffer *packet_out = create_packet_out(
    get_transaction_id(),
    buffer_id,
    in_port,
    actions,
    data
  );
  send_openflow_message( NUM2ULL( datapath_id ), packet_out );

  if ( allocated_data != NULL ) {
    free_buffer( allocated_data );
  }
  free_buffer( packet_out );
  delete_actions( actions );
  return self;
}
コード例 #26
0
static void
make_path( sliceable_switch *sliceable_switch, uint64_t in_datapath_id, uint16_t in_port, uint16_t in_vid,
           uint64_t out_datapath_id, uint16_t out_port, uint16_t out_vid, const buffer *packet ) {
  dlist_element *hops = resolve_path( sliceable_switch->pathresolver, in_datapath_id, in_port, out_datapath_id, out_port );
  if ( hops == NULL ) {
    warn( "No available path found ( %#" PRIx64 ":%u -> %#" PRIx64 ":%u ).",
          in_datapath_id, in_port, out_datapath_id, out_port );
    discard_packet_in( in_datapath_id, in_port, packet, DISCARD_DURATION_NO_PATH );
    return;
  }

  // check if the packet is ARP or not
  if ( sliceable_switch->handle_arp_with_packetout && packet_type_arp( packet ) ) {
    // send packet out for tail switch
    free_hop_list( hops );
    output_packet( packet, out_datapath_id, out_port, out_vid );
    return;
  }

  const uint32_t wildcards = 0;
  struct ofp_match match;
  set_match_from_packet( &match, in_port, wildcards, packet );

  if ( lookup_path( in_datapath_id, match, PRIORITY ) != NULL ) {
    warn( "Duplicated path found." );
    output_packet( packet, out_datapath_id, out_port, out_vid );
    return;
  }

  const uint16_t hard_timeout = 0;
  path *p = create_path( match, PRIORITY, sliceable_switch->idle_timeout, hard_timeout );
  assert( p != NULL );
  openflow_actions *vlan_actions = create_openflow_actions_to_update_vid( in_vid, out_vid );
  for ( dlist_element *e = get_first_element( hops ); e != NULL; e = e->next ) {
    pathresolver_hop *rh = e->data;
    openflow_actions *actions = NULL;
    if ( e->next == NULL ) {
      actions = vlan_actions;
    }
    hop *h = create_hop( rh->dpid, rh->in_port_no, rh->out_port_no, actions );
    assert( h != NULL );
    append_hop_to_path( p, h );
  } // for(;;)
  if ( vlan_actions ) {
    delete_actions( vlan_actions );
  }

  dlist_element *e = get_last_element( hops );
  pathresolver_hop *last_hop = e->data;
  packet_out_params *params = xmalloc( sizeof( struct packet_out_params ) );
  params->packet = duplicate_buffer( packet );
  params->out_datapath_id = last_hop->dpid;
  params->out_port_no = last_hop->out_port_no;
  params->out_vid = out_vid;
  params->in_vid = in_vid;

  bool ret;
  if ( sliceable_switch->setup_reverse_flow && packet_to_set_reverse_path( packet ) ) {
    ret = setup_path( p, setup_reverse_path, params, NULL, NULL );
  }
  else {
    ret = setup_path( p, handle_setup, params, NULL, NULL );
  }
  if ( ret != true ) {
    error( "Failed to set up path." );
    output_packet( packet, out_datapath_id, out_port, out_vid );
    free_buffer( params->packet );
    xfree( params );
  }

  delete_path( p );

  // free them
  free_hop_list( hops );
}
コード例 #27
0
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 );
    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 );
    }
    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 ) )) {
      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;
}