int pfring_bundle_read(pfring_bundle *bundle,
		       u_char** buffer, u_int buffer_len,
		       struct pfring_pkthdr *hdr,
		       u_int8_t wait_for_incoming_packet) {
  u_int i, sock_id = 0, num_found, rc;
  struct timeval ts = { 0 };

 redo_pfring_bundle_read:

  switch(bundle->policy) {
  case pick_round_robin:
    for(i=0; i<bundle->num_sockets; i++) {
      bundle->last_read_socket = (bundle->last_read_socket + 1) % bundle->num_sockets;

      if(pfring_there_is_pkt_available(bundle->sockets[bundle->last_read_socket])) {
	return(pfring_recv(bundle->sockets[bundle->last_read_socket], buffer,
			   buffer_len, hdr, wait_for_incoming_packet));
      }
    }
    break;

  case pick_fifo:
    num_found = 0;

    for(i=0; i<bundle->num_sockets; i++) {
      pfring *ring = bundle->sockets[i];

      if(pfring_there_is_pkt_available(ring)) {
	struct pfring_pkthdr *header = (struct pfring_pkthdr*)&ring->slots[ring->slots_info->remove_off];

	if((num_found == 0) || is_before(&header->ts, &ts)) {
	  memcpy(&ts, &header->ts, sizeof(struct timeval));
	  num_found++, sock_id = i;
	}
      }
    }

    if(num_found > 0) {
      return(pfring_recv(bundle->sockets[sock_id], buffer,
			 buffer_len, hdr, wait_for_incoming_packet));
    }
    break;
  }

  if(wait_for_incoming_packet) {
    rc = pfring_bundle_poll(bundle, bundle->sockets[0]->poll_duration);

    if(rc > 0) {
      goto redo_pfring_bundle_read;
    } else
      return(rc);
  }

  return(0);
}
Exemple #2
0
int pfring_mod_next_pkt_time(pfring *ring, struct timespec *ts) {
  struct pfring_pkthdr *header = (struct pfring_pkthdr*) &ring->slots[ring->slots_info->remove_off];

  if(!pfring_there_is_pkt_available(ring))
    return PF_RING_ERROR_NO_PKT_AVAILABLE;

  if(!header->ts.tv_sec)
    return PF_RING_ERROR_WRONG_CONFIGURATION;

  ts->tv_sec = header->ts.tv_sec;
  ts->tv_nsec = header->ts.tv_usec * 1000;

  /* TODO In order to use ns from hw ts we should make sure that
   * hw ts is in sync with sys time. */
  //if(header->extended_hdr.timestamp_ns)
  //  ts->tv_nsec = header->extended_hdr.timestamp_ns % 1000000000;

  return 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(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 */
}
int pfring_mod_is_pkt_available(pfring *ring) {
  return(pfring_there_is_pkt_available(ring));
}
Exemple #5
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 */
}