static void test_packet_type_arp() { buffer *buf = alloc_buffer_with_length( sizeof( struct iphdr ) ); calloc_packet_info( buf ); assert_false( packet_type_arp( buf ) ); packet_info *packet_info = buf->user_data; packet_info->format |= NW_ARP; assert_true( packet_type_arp( buf ) ); free_buffer( buf ); }
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 handle_packet_in( uint64_t datapath_id, uint32_t transaction_id, uint32_t buffer_id, uint16_t total_len, uint16_t in_port, uint8_t reason, const buffer *data, void *user_data ) { services *services = user_data; list_element **list_head = &services->arp_or_unicast; packet_info *packet_info = data->user_data; if ( !packet_type_arp( data ) && ( packet_info->eth_macda[ 0 ] & 0x1 ) == 0x1 ) { list_head = &services->broadcast; } if ( *list_head == NULL ) { return; } buffer *buf = create_packet_in( transaction_id, buffer_id, total_len, in_port, reason, data ); openflow_service_header_t *message; message = append_front_buffer( buf, sizeof( openflow_service_header_t ) ); message->datapath_id = htonll( datapath_id ); message->service_name_length = htons( 0 ); char *service_name = ( *list_head )->data; if ( send_message( service_name, MESSENGER_OPENFLOW_MESSAGE, buf->data, buf->length ) ) { debug( "Sending a message to %s.", service_name ); } free_buffer( buf ); if ( ( *list_head )->next != NULL ) { //round robin delete_element( list_head, service_name ); append_to_tail( list_head, service_name ); } }
static void handle_packet_in( uint64_t datapath_id, uint32_t transaction_id, uint32_t buffer_id, uint16_t total_len, uint16_t in_port, uint8_t reason, const buffer *data, void *user_data ) { assert( in_port != 0 ); assert( data != NULL ); assert( user_data != NULL ); routing_switch *routing_switch = user_data; debug( "Packet-In received ( datapath_id = %#" PRIx64 ", transaction_id = %#lx, " "buffer_id = %#lx, total_len = %u, in_port = %u, reason = %#x, " "data_len = %u ).", datapath_id, transaction_id, buffer_id, total_len, in_port, reason, data->length ); const port_info *port = lookup_port( routing_switch->switches, datapath_id, in_port ); if ( port == NULL ) { debug( "Ignoring Packet-In from unknown port." ); return; } packet_info packet_info = get_packet_info( data ); const uint8_t *src = packet_info.eth_macsa; const uint8_t *dst = packet_info.eth_macda; if ( in_port > OFPP_MAX && in_port != OFPP_LOCAL ) { error( "Packet-In from invalid port ( in_port = %u ).", in_port ); return; } if ( !port->external_link || port->switch_to_switch_reverse_link ) { if ( !port->external_link && port->switch_to_switch_link && port->switch_to_switch_reverse_link && !is_ether_multicast( dst ) && lookup_fdb( routing_switch->fdb, src, &datapath_id, &in_port ) ) { debug( "Found a Packet-In from switch-to-switch link." ); } else { debug( "Ignoring Packet-In from not external link." ); return; } } if ( !update_fdb( routing_switch->fdb, src, datapath_id, in_port ) ) { return; } if ( !authenticate( src ) ) { if ( packet_type_ipv4( data ) ) { if ( packet_type_ipv4_udp( data ) ) { if ( ( packet_info.udp_src_port == 67 ) || ( packet_info.udp_src_port == 68 ) || ( packet_info.udp_dst_port == 67 ) || ( packet_info.udp_dst_port == 68 ) ) { // DHCP/BOOTP is allowed by default goto authenticated; } if ( ( packet_info.udp_src_port == 53 ) || ( packet_info.udp_dst_port == 53 ) ) { // DNS is allowed by default goto authenticated; } } else if ( packet_type_ipv4_tcp( data ) ) { if ( ( packet_info.tcp_src_port == 53 ) || ( packet_info.tcp_dst_port == 53 ) ) { // DNS is allowed by default goto authenticated; } } redirect( datapath_id, in_port, data ); } else if ( packet_type_arp( data ) ) { // ARP request/reply is allowed goto authenticated; } return; } authenticated: { uint16_t out_port; uint64_t out_datapath_id; if ( lookup_fdb( routing_switch->fdb, dst, &out_datapath_id, &out_port ) ) { // Host is located, so resolve path and send flowmod if ( ( datapath_id == out_datapath_id ) && ( in_port == out_port ) ) { // in and out are same return; } make_path( routing_switch, datapath_id, in_port, out_datapath_id, out_port, data ); } else { // Host's location is unknown, so flood packet flood_packet( datapath_id, in_port, data, routing_switch->switches ); } } }