static bool packet_to_set_reverse_path( const buffer *packet ) { packet_info *pinfo = ( packet_info * ) packet->user_data; if ( is_ether_multicast( pinfo->eth_macsa ) || is_ether_multicast( pinfo->eth_macda ) ) { return false; } if ( packet_type_ipv4_tcp( packet ) || packet_type_ipv4_udp( packet ) || packet_type_icmpv4_echo_request( packet ) ) { return true; } return false; }
bool lookup_fdb( hash_table *fdb, const uint8_t mac[ OFP_ETH_ALEN ], uint64_t *dpid, uint16_t *port ) { assert( fdb != NULL ); assert( mac != NULL ); assert( dpid != NULL ); assert( port != NULL ); if ( is_ether_multicast( mac ) ) { debug( "Skip looking up fdb. Because multicast/broadcast frame is received" ); return false; } fdb_entry *entry = lookup_hash_entry( fdb, mac ); debug( "Lookup mac:%02x:%02x:%02x:%02x:%02x:%02x", mac[ 0 ], mac[ 1 ], mac[ 2 ], mac[ 3 ], mac[ 4 ], mac[ 5 ] ); if ( entry != NULL ) { *dpid = entry->dpid; *port = entry->port; debug( "Found at dpid = %#" PRIx64 ", port = %u", *dpid, *port ); return true; } debug( "Not found" ); return false; }
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 ); sliceable_switch *sliceable_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 ); if ( in_port > OFPP_MAX && in_port != OFPP_LOCAL ) { error( "Packet-In from invalid port ( in_port = %u ).", in_port ); return; } const port_info *port = lookup_port( sliceable_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 ( !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( sliceable_switch->fdb, src, &datapath_id, &in_port ) ) { debug( "Found a Packet-In from switch-to-switch link." ); } else { debug( "Ignoring Packet-In from non-external link." ); return; } } uint16_t vid = VLAN_NONE; if ( packet_type_eth_vtag( data ) ) { vid = packet_info.vlan_vid; } if ( !update_fdb( sliceable_switch->fdb, src, datapath_id, in_port ) ) { return; } char match_str[ 1024 ]; struct ofp_match match; set_match_from_packet( &match, in_port, 0, data ); match_to_string( &match, match_str, sizeof( match_str ) ); uint16_t slice = lookup_slice( datapath_id, in_port, vid, src ); if ( slice == SLICE_NOT_FOUND ) { warn( "No slice found ( dpid = %#" PRIx64 ", vid = %u, match = [%s] ).", datapath_id, vid, match_str ); goto deny; } int action = filter( datapath_id, in_port, slice, data ); switch ( action ) { case ALLOW: debug( "Filter: ALLOW ( dpid = %#" PRIx64 ", slice = %#x, match = [%s] ).", datapath_id, slice, match_str ); goto allow; case DENY: debug( "Filter: DENY ( dpid = %#" PRIx64 ", slice = %#x, match = [%s] ).", datapath_id, slice, match_str ); goto deny; case LOCAL: debug( "Filter: LOCAL ( dpid = %#" PRIx64 ", slice = %#x, match = [%s] ).", datapath_id, slice, match_str ); goto local; default: error( "Undefined filter action ( action = %#x ).", action ); goto deny; } allow: { uint16_t out_port; uint64_t out_datapath_id; if ( lookup_fdb( sliceable_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 ) ) { debug( "Input port and out port are the same ( datapath_id = %#llx, port = %u ).", datapath_id, in_port ); return; } uint16_t out_vid = vid; bool found = get_port_vid( slice, out_datapath_id, out_port, &out_vid ); if ( found == false ) { uint16_t out_slice = lookup_slice_by_mac( dst ); if ( out_slice != slice ) { debug( "Destination is on different slice ( slice = %#x, out_slice = %#x ).", slice, out_slice ); goto deny; } } make_path( sliceable_switch, datapath_id, in_port, vid, out_datapath_id, out_port, out_vid, data ); } else { if ( lookup_path( datapath_id, match, PRIORITY ) != NULL ) { teardown_path( datapath_id, match, PRIORITY ); } // Host's location is unknown, so flood packet flood_packet( datapath_id, in_port, slice, data, sliceable_switch->switches ); } return; } deny: { // Drop packets for a certain period buffer *flow_mod = create_flow_mod( transaction_id, match, get_cookie(), OFPFC_ADD, 0, FLOW_TIMER, UINT16_MAX, UINT32_MAX, OFPP_NONE, 0, NULL ); send_openflow_message( datapath_id, flow_mod ); free_buffer( flow_mod ); return; } local: { // Redirect to controller's local IP stack redirect( datapath_id, in_port, data ); return; } }
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 ); } } }
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 non-external link." ); return; } } if ( !update_fdb( routing_switch->fdb, src, datapath_id, in_port ) ) { return; } uint16_t out_port; uint64_t out_datapath_id; if ( lookup_fdb( routing_switch->fdb, dst, &out_datapath_id, &out_port ) ) { if ( ( datapath_id == out_datapath_id ) && ( in_port == out_port ) ) { // in and out are same return; } // Host is located, so resolve path and install flow entries 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 ); } }