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 ); 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 ); for ( dlist_element *e = get_first_element( hops ); e != NULL; e = e->next ) { pathresolver_hop *rh = e->data; hop *h = create_hop( rh->dpid, rh->in_port_no, rh->out_port_no, NULL ); assert( h != NULL ); append_hop_to_path( p, h ); } // for(;;) 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; bool 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 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 ); }