int pfring_mod_recv(pfring *ring, u_char** buffer, u_int buffer_len,
		    struct pfring_pkthdr *hdr,
		    u_int8_t wait_for_incoming_packet) {
  int rc = 0;

  if(ring->is_shutting_down || (ring->buffer == NULL))
    return(-1);

  ring->break_recv_loop = 0;

  do_pfring_recv:
    if(ring->break_recv_loop)
      return(0);

    if(ring->reentrant)
      pthread_spin_lock(&ring->spinlock);

    //rmb();

    if(pfring_there_is_pkt_available(ring)) {
      char *bucket = &ring->slots[ring->slots_info->remove_off];
      u_int32_t next_off, real_slot_len, insert_off, bktLen;

      memcpy(hdr, bucket, ring->slot_header_len);

      if(ring->slot_header_len != sizeof(struct pfring_pkthdr))
	bktLen = hdr->caplen;
      else
	bktLen = hdr->caplen+hdr->extended_hdr.parsed_header_len;

      real_slot_len = ring->slot_header_len + bktLen;
      insert_off = ring->slots_info->insert_off;
      if(bktLen > buffer_len) bktLen = buffer_len;

      if(buffer_len == 0)
	*buffer = (u_char*)&bucket[ring->slot_header_len];
      else
	memcpy(*buffer, &bucket[ring->slot_header_len], bktLen);

      next_off = ring->slots_info->remove_off + real_slot_len;
      if((next_off + ring->slots_info->slot_len) > (ring->slots_info->tot_mem - sizeof(FlowSlotInfo))) {
        next_off = 0;
      }

#ifdef USE_MB
      /* This prevents the compiler from reordering instructions.
       * http://en.wikipedia.org/wiki/Memory_ordering#Compiler_memory_barrier */
      gcc_mb();
#endif

      ring->slots_info->tot_read++;
      ring->slots_info->remove_off = next_off;

      /* Ugly safety check */
      if((ring->slots_info->tot_insert == ring->slots_info->tot_read)
	 && (ring->slots_info->remove_off > ring->slots_info->insert_off)) {
	ring->slots_info->remove_off = ring->slots_info->insert_off;
      }

      if(ring->reentrant) pthread_spin_unlock(&ring->spinlock);
      return(1);
    }

    /* Nothing to do: we need to wait */
    if(ring->reentrant) pthread_spin_unlock(&ring->spinlock);

    if(wait_for_incoming_packet) {
      rc = pfring_poll(ring, ring->poll_duration);

      if((rc == -1) && (errno != EINTR))
	return(-1);
      else
	goto do_pfring_recv;
    }

  return(0); /* non-blocking, no packet */
}
Example #2
0
int pfring_mod_recv(pfring *ring, u_char** buffer, u_int buffer_len,
		    struct pfring_pkthdr *hdr,
		    u_int8_t wait_for_incoming_packet) {
  int rc = 0;

  if(ring->is_shutting_down || (ring->buffer == NULL))
    return(-1);

  ring->break_recv_loop = 0;

  do_pfring_recv:
    if(ring->break_recv_loop)
      return(0);

    if(unlikely(ring->reentrant))
      pthread_rwlock_wrlock(&ring->rx_lock);

    //rmb();

    if(pfring_there_is_pkt_available(ring)) {
      char *bucket = &ring->slots[ring->slots_info->remove_off];
      u_int32_t next_off, real_slot_len, bktLen;

      /* Keep it for packet sending */
      ring->tx.last_received_hdr = (struct pfring_pkthdr*)bucket;

      memcpy(hdr, bucket, ring->slot_header_len);

      //if((hdr->caplen > 1518) || (hdr->len > 1518)) 
      //  fprintf(stderr, "%s:%d-----> Invalid packet length [caplen: %u][len: %u]"
      //                  "[hdr len: %u][slot len: %u][real slot len: %u]"
      //                  "[insert_off: %u][remove_off: %u][tot_insert: %lu][tot_read: %lu]\n", 
      //          __FUNCTION__, __LINE__, hdr->caplen, hdr->len, ring->slot_header_len, 
      //          ring->slots_info->slot_len, ring->slot_header_len+hdr->caplen, 
      //          ring->slots_info->insert_off, ring->slots_info->remove_off, 
      //          ring->slots_info->tot_insert, ring->slots_info->tot_read);

      if(ring->slot_header_len != sizeof(struct pfring_pkthdr)) /* using short_pkt_header, parsed_header_len is not available */
	bktLen = hdr->caplen;
      else
	bktLen = hdr->caplen + hdr->extended_hdr.parsed_header_len;

      real_slot_len = ring->slot_header_len + bktLen;
      if(bktLen > buffer_len) bktLen = buffer_len;

      if(buffer_len == 0)
	*buffer = (u_char*)&bucket[ring->slot_header_len];
      else
	memcpy(*buffer, &bucket[ring->slot_header_len], bktLen);

      next_off = ring->slots_info->remove_off + real_slot_len;
      if((next_off + ring->slots_info->slot_len) > (ring->slots_info->tot_mem - sizeof(FlowSlotInfo)))
        next_off = 0;
      
#ifdef USE_MB
      /* This prevents the compiler from reordering instructions.
       * http://en.wikipedia.org/wiki/Memory_ordering#Compiler_memory_barrier */
      gcc_mb();
#endif

      ring->slots_info->tot_read++, ring->slots_info->remove_off = next_off;

      /* Ugly safety check */
      if(unlikely((ring->slots_info->tot_insert == ring->slots_info->tot_read)
	 && (ring->slots_info->remove_off > ring->slots_info->insert_off))) {
	ring->slots_info->remove_off = ring->slots_info->insert_off;
        fprintf(stderr, " *** corrupted ring buffer indexes (recovered) ***\n");
      }

      if(unlikely(ring->reentrant)) pthread_rwlock_unlock(&ring->rx_lock);
      return(1);
    }

    /* Nothing to do: we need to wait */
    if(unlikely(ring->reentrant)) pthread_rwlock_unlock(&ring->rx_lock);

    if(wait_for_incoming_packet) {
      rc = pfring_poll(ring, ring->poll_duration);

      if((rc == -1) && (errno != EINTR))
	return(-1);
      else
	goto do_pfring_recv;
    }

  return(0); /* non-blocking, no packet */
}