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; }
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 ); }
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 ); }
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 ); }
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 ); }
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 ); }
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 ); }
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 ); }
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 ); }
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 ); }
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 ); }
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); }
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 ); }
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 ); }
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, ¶ms ); // 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 ); }
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 ); }
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 ); }
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 ); }
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 ); }
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 ); }
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 ); }
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 ); }
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 ); }
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; }
/* * @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; }
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 ); }
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; }