PF_RING patch for libpcap 0.8.1 (tested with 0.8.3) made by
Georg Lukas <g.lukas@intergenia.de>

This patch is based on work by Luca Deri (see http://luca.ntop.org/Ring.pdf
for more details).

diff -uNr libpcap-0.8.1/pcap-int.h libpcap-0.8.1-pfring/pcap-int.h
--- libpcap-0.8.1/pcap-int.h	2003-12-15 02:42:24.000000000 +0100
+++ libpcap-0.8.1-pfring/pcap-int.h	2004-04-20 20:01:55.606526568 +0200
@@ -30,7 +30,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * @(#) $Header: /tcpdump/master/libpcap/pcap-int.h,v 1.55.2.4 2003/12/15 01:42:24 guy Exp $ (LBL)
+ * @(#) $Header: /export/home/ntop-priv/ring/libpcap-0.8.1-ring/pcap-int.h,v 1.2 2004/02/06 14:13:11 deri Exp $ (LBL)
  */
 
 #ifndef pcap_int_h
@@ -46,6 +46,8 @@
 #include <packet32.h>
 #endif /* WIN32 */
 
+#define RING /* L.Deri */
+
 /*
  * Savefile
  */
@@ -93,6 +95,22 @@
 #endif
 };
 
+/* **************************** */
+
+#ifdef  RING
+
+#include <unistd.h>
+#include <sys/mman.h>
+#include <errno.h>
+#include <sys/poll.h>
+
+#define PAGE_SIZE         4096
+
+#define HAVE_PCAP
+#include <linux/ring.h>
+#endif
+
+
 struct pcap {
 #ifdef WIN32
 	ADAPTER *adapter;
@@ -121,6 +139,12 @@
 	u_char *bp;
 	int cc;
 
+#ifdef RING
+	char *ring_buffer, *slots_buffer;
+	int  ring_fd;
+	FlowSlotInfo *slots_info;
+        u_int page_id, slot_id, pkts_per_page;
+#endif
 	/*
 	 * Place holder for pcap_next().
 	 */
diff -uNr libpcap-0.8.1/pcap-linux.c libpcap-0.8.1-pfring/pcap-linux.c
--- libpcap-0.8.1/pcap-linux.c	2003-11-21 11:20:46.000000000 +0100
+++ libpcap-0.8.1-pfring/pcap-linux.c	2004-04-20 20:01:55.609523112 +0200
@@ -27,7 +27,7 @@
 
 #ifndef lint
 static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.98.2.4 2003/11/21 10:20:46 guy Exp $ (LBL)";
+    "@(#) $Header: /export/home/ntop-priv/ring/libpcap-0.8.1-ring/pcap-linux.c,v 1.3 2004/02/06 14:13:11 deri Exp $ (LBL)";
 #endif
 
 /*
@@ -217,6 +217,20 @@
 	= { 1, &total_insn };
 #endif
 
+#define RING /* L.Deri */
+
+#ifdef RING
+static struct pcap_stat ringStats;
+u_int  numPollCalls = 0;
+
+unsigned long long rdtsc() {
+  unsigned long long a;
+  asm volatile("rdtsc":"=A" (a));
+  return(a);
+}
+
+#endif
+
 /*
  *  Get a handle for a live capture from the given device. You can
  *  pass NULL as device to get all packages (without link level
@@ -258,6 +272,73 @@
 	handle->snapshot	= snaplen;
 	handle->md.timeout	= to_ms;
 
+#ifdef RING
+	handle->ring_fd = socket(PF_RING, SOCK_RAW, htons(ETH_P_ALL));
+
+	if(handle->ring_fd > 0) {
+	  struct sockaddr sa;
+	  int             rc;
+	  u_int memSlotsLen;
+	  
+	  sa.sa_family   = PF_RING;
+	  snprintf(sa.sa_data, sizeof(sa.sa_data), "%s", device);
+	  rc = bind(handle->ring_fd, (struct sockaddr *)&sa, sizeof(sa));
+ 
+	  if(rc == 0) {
+	    handle->ring_buffer = (char *)mmap(NULL, PAGE_SIZE,
+					       PROT_READ|PROT_WRITE,
+					       MAP_SHARED, 
+					       handle->ring_fd, 0);
+
+	    if(handle->ring_buffer == MAP_FAILED) {
+	      sprintf(ebuf, "mmap() failed");
+	      return (NULL);
+	    }
+
+	    handle->slots_info = (FlowSlotInfo *)handle->ring_buffer;
+	    memSlotsLen = handle->slots_info->tot_num_pages*PAGE_SIZE;
+	    munmap(handle->ring_buffer, PAGE_SIZE);
+	  
+	    handle->ring_buffer = (char *)mmap(NULL, memSlotsLen,
+					      PROT_READ|PROT_WRITE,
+					      MAP_SHARED, handle->ring_fd, 0);
+	  
+	    if(handle->ring_buffer == MAP_FAILED) {
+	      sprintf(ebuf, "mmap() failed");
+	      return (NULL);
+	    }
+	  
+	    handle->slots_info   = (FlowSlotInfo *)handle->ring_buffer;
+	  
+	    /* Safety check */
+	    if(handle->slots_info->remove_idx >= handle->slots_info->tot_slots)
+	      handle->slots_info->remove_idx = 0;
+
+	    handle->page_id = PAGE_SIZE, handle->slot_id = 0,
+	      handle->pkts_per_page = 0;
+
+	    /* Set defaults */
+	    handle->linktype = DLT_EN10MB;
+	    handle->offset = 2;
+
+	    printf("RING: tot_slots=%d/slot_len=%d/"
+		   "insertIdx=%d/remove_idx=%d/dropped=%d\n",
+		   handle->slots_info->tot_slots,
+		   handle->slots_info->slot_len, 
+		   handle->slots_info->insert_idx,
+		   handle->slots_info->remove_idx,
+		   handle->slots_info->tot_lost);
+	  
+	    ringStats.ps_recv = handle->slots_info->tot_pkts;
+	    ringStats.ps_drop = handle->slots_info->tot_lost;
+
+	    goto open_open_live_final;
+	  } else {
+	    close(handle->ring_fd);
+	    /* Continue without ring support */
+	  }
+	}
+#endif
 	/*
 	 * NULL and "any" are special devices which give us the hint to
 	 * monitor all devices.
@@ -397,6 +478,9 @@
 		return NULL;
 	}
 
+#ifdef RING
+ open_open_live_final:
+#endif
 	/*
 	 * "handle->fd" is a socket, so "select()" and "poll()"
 	 * should work on it.
@@ -449,6 +533,59 @@
 	int			packet_len, caplen;
 	struct pcap_pkthdr	pcap_header;
 
+#ifdef RING
+	if(handle->ring_buffer != NULL) {	  
+	  u_int idx, numRuns = 0;
+	  FlowSlot *slot;
+
+	  /*
+	    printf("page_id=%d - slot_id=%d\n",
+	    handle->page_id, handle->slot_id);
+	  */
+
+	  slot = (FlowSlot*)&handle->ring_buffer[handle->page_id+handle->slot_id];
+
+	  while(1) {
+	    if(slot->slot_state == 1) {
+	      char *bucket = &slot->bucket;
+
+	      handle->md.stat.ps_recv++;
+	      callback(userdata, 
+		       (const struct pcap_pkthdr*)bucket,
+		       (const u_char*)&bucket[sizeof(struct pcap_pkthdr)]);
+	      slot->slot_state = 0;
+	      
+	      if(handle->slots_info->remove_idx >= 
+		 (handle->slots_info->tot_slots-1)) {
+		handle->slots_info->remove_idx = 0;
+		handle->page_id = PAGE_SIZE, handle->slot_id = 0,
+		  handle->pkts_per_page = 0;
+	      } else {
+		handle->slots_info->remove_idx++;
+		handle->pkts_per_page++,
+		  handle->slot_id += handle->slots_info->slot_len;
+		
+		if(handle->pkts_per_page >= handle->slots_info->pkts_per_page) {
+		  handle->page_id += PAGE_SIZE, handle->slot_id = 0,
+		    handle->pkts_per_page = 0;
+		}
+	      }
+	      
+	      return(1);
+	    } else {
+	      struct pollfd pfd;
+
+	      /* Sleep when nothing is happening */
+	      pfd.fd      = handle->ring_fd;
+	      pfd.events  = POLLIN|POLLERR;
+	      pfd.revents = 0;
+	      poll(&pfd, 1, -1);
+	      numPollCalls++;
+	    }
+	  } /* while() */
+	}
+#endif
+
 #ifdef HAVE_PF_PACKET_SOCKETS
 	/*
 	 * If this is a cooked device, leave extra room for a
@@ -688,6 +825,17 @@
 	socklen_t len = sizeof (struct tpacket_stats);
 #endif
 
+#ifdef RING
+	if(handle->ring_fd > 0) {
+	  stats->ps_recv = handle->slots_info->tot_pkts-ringStats.ps_recv;
+	  stats->ps_drop = handle->slots_info->tot_lost-ringStats.ps_drop;
+
+	  printf("RING: numPollCalls=%d [%.1f packets/call]\n", 
+		 numPollCalls, (float)stats->ps_recv/(float)numPollCalls);
+	  return(0);
+	}
+#endif
+
 #ifdef HAVE_TPACKET_STATS
 	/*
 	 * Try to get the packet counts from the kernel.
@@ -879,6 +1027,11 @@
 		}
 	}
 
+
+#ifdef RING
+	if(handle->ring_fd <= 0) can_filter_in_kernel = 0;
+#endif
+
 	if (can_filter_in_kernel) {
 		if ((err = set_kernel_filter(handle, &fcode)) == 0)
 		{
