Example #1
0
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 );
  }
}
Example #2
0
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 );
}
Example #3
0
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 );
}
Example #4
0
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 );
}