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 ) { UNUSED( user_data ); char match_str[ 1024 ]; struct ofp_match ofp_match; // host order buffer *copy = NULL; packet_info *packet_info = data->user_data; debug( "Receive packet. ethertype=0x%04x, ipproto=0x%x", packet_info->eth_type, packet_info->ipv4_protocol ); if ( packet_type_ipv4_etherip( data ) ) { copy = parse_etherip( data ); } set_match_from_packet( &ofp_match, in_port, 0, copy != NULL ? copy : data ); if ( copy != NULL ) { free_buffer( copy ); copy = NULL; } match_to_string( &ofp_match, match_str, sizeof( match_str ) ); list_element *services = lookup_match_entry( ofp_match ); if ( services == NULL ) { debug( "match entry not found" ); 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 ); list_element *element; for ( element = services; element != NULL; element = element->next ) { const char *service_name = element->data; if ( !send_message( service_name, MESSENGER_OPENFLOW_MESSAGE, buf->data, buf->length ) ) { error( "Failed to send a message to %s ( match = %s ).", service_name, match_str ); free_buffer( buf ); return; } debug( "Sending a message to %s ( match = %s ).", service_name, match_str ); } free_buffer( buf ); }
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 ) { UNUSED( user_data ); char match_str[ 1024 ]; struct ofp_match ofp_match; // host order set_match_from_packet( &ofp_match, in_port, 0, data ); match_to_string( &ofp_match, match_str, sizeof( match_str ) ); match_entry *match_entry = lookup_match_entry( &ofp_match ); if ( match_entry == NULL ) { debug( "No match entry found." ); 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 ); if ( !send_message( match_entry->service_name, MESSENGER_OPENFLOW_MESSAGE, buf->data, buf->length ) ) { error( "Failed to send a message to %s ( entry_name = %s, match = %s ).", match_entry->service_name, match_entry->entry_name, match_str ); free_buffer( buf ); return; } debug( "Sending a message to %s ( entry_name = %s, match = %s ).", match_entry->service_name, match_entry->entry_name, match_str ); free_buffer( buf ); }
static void receive_frame( int fd, void *user_data ) { UNUSED( fd ); ether_device *device = user_data; assert( device != NULL ); if ( !device->status.up ) { return; } if ( get_max_packet_buffers_length( device->recv_queue ) <= get_packet_buffers_length( device->recv_queue ) ) { warn( "Receive queue is full ( device = %s, usage = %u/%u ).", device->name, get_packet_buffers_length( device->recv_queue ), get_max_packet_buffers_length( device->recv_queue ) ); return; } unsigned int count = 0; const unsigned int max_queue_length = get_max_packet_buffers_length( device->recv_queue ); const unsigned int max_loop_count = max_queue_length < 256 ? max_queue_length : 256; while ( count < max_loop_count ) { buffer *frame = get_buffer_from_free_buffers( device->recv_queue ); if ( frame == NULL ) { warn( "Failed to retrieve a receive buffer ( device = %s, queue usage = %u/%u ).", device->name, get_packet_buffers_length( device->recv_queue ), max_queue_length ); frame = device->recv_buffer; // Use recv_buffer as a trash. } reset_buffer( frame ); append_back_buffer( frame, device->mtu ); #if WITH_PCAP size_t length = 0; struct pcap_pkthdr *header = NULL; const u_char *packet = NULL; int ret = pcap_next_ex( device->pcap, &header, &packet ); if ( ret == 1 ) { length = header->caplen; if ( length > frame->length ) { append_back_buffer( frame, length - frame->length ); } memcpy( frame->data, packet, length ); } else { if ( frame != device->recv_buffer ) { mark_packet_buffer_as_used( device->recv_queue, frame ); } if ( ret == -1 ) { error( "Receive error ( device = %s, pcap_err = %s ).", device->name, pcap_geterr( device->pcap ) ); } break; } #else // WITH_PCAP struct msghdr msg; msg.msg_name = NULL; msg.msg_namelen = 0; struct iovec iovec; size_t headroom_length = sizeof( vlantag_header_t ); char *head = ( char * ) frame->data + headroom_length; iovec.iov_base = head; iovec.iov_len = frame->length - headroom_length; msg.msg_iov = &iovec; msg.msg_iovlen = 1; char cmsg_buf[ CMSG_SPACE( sizeof( struct tpacket_auxdata ) ) ]; msg.msg_control = cmsg_buf; msg.msg_controllen = sizeof( cmsg_buf ); msg.msg_flags = 0; ssize_t length = recvmsg( device->fd, &msg, MSG_DONTWAIT ); assert( length != 0 ); if ( length < 0 ) { if ( frame != device->recv_buffer ) { mark_packet_buffer_as_used( device->recv_queue, frame ); } if ( ( errno == EINTR ) || ( errno == EAGAIN ) || ( errno == EWOULDBLOCK ) || ( errno == ENETDOWN ) ) { break; } char error_string[ ERROR_STRING_SIZE ]; error( "Receive error ( device = %s, errno = %s [%d] ).", device->name, safe_strerror_r( errno, error_string, sizeof( error_string ) ), errno ); break; } for ( struct cmsghdr *cmsg = CMSG_FIRSTHDR( &msg ); cmsg != NULL; cmsg = CMSG_NXTHDR( &msg, cmsg ) ) { if ( cmsg->cmsg_len < CMSG_LEN( sizeof( struct tpacket_auxdata ) ) ) { continue; } if ( cmsg->cmsg_level != SOL_PACKET || cmsg->cmsg_type != PACKET_AUXDATA ) { continue; } struct tpacket_auxdata *auxdata = ( struct tpacket_auxdata * ) CMSG_DATA( cmsg ); if ( auxdata->tp_vlan_tci == 0 ) { continue; } head -= sizeof( vlantag_header_t ); if ( ( void * ) head < frame->data ) { append_front_buffer( frame, sizeof( vlantag_header_t ) ); head = frame->data; } length += ( ssize_t ) sizeof( vlantag_header_t ); memmove( head, head + sizeof( vlantag_header_t ), ETH_ADDRLEN * 2 ); uint16_t *eth_type = ( uint16_t * ) ( head + ETH_ADDRLEN * 2 ); *eth_type = htons( ETH_ETHTYPE_TPID ); uint16_t *tci = ++eth_type; *tci = htons( auxdata->tp_vlan_tci ); } frame->data = head; #endif if ( frame != device->recv_buffer ) { frame->length = ( size_t ) length; enqueue_packet_buffer( device->recv_queue, frame ); } count++; } handle_received_frames( device ); }