static void test_packet_type_ipv4() { buffer *buf = alloc_buffer_with_length( sizeof( struct iphdr ) ); calloc_packet_info( buf ); assert_false( packet_type_ipv4( buf ) ); packet_info *packet_info = buf->user_data; packet_info->format |= NW_IPV4; assert_true( packet_type_ipv4( buf ) ); free_buffer( buf ); }
void redirect( uint64_t datapath_id, uint16_t in_port, const buffer *data ) { debug( "A message received (dpid = %#" PRIx64 ", in_port = %u, length = %zu).", datapath_id, in_port, data->length ); packet_info packet_info = get_packet_info( data ); if ( !packet_type_ipv4( data ) ) { debug( "Cannot redirect the packet which is not IPv4." ); return; } uint8_t *mac = packet_info.eth_macsa; uint32_t ip = packet_info.ipv4_saddr; add_host( mac, ip, datapath_id, in_port ); debug( "Redirecting an IP packet to tun interface." ); assert( packet_info.l3_header != NULL ); // redirect an IP packet to a tun interface send_packet_to_tun( packet_info.l3_header, packet_info.ipv4_tot_len ); }
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 ); } } }