remove pfring patches
[openwrt/svn-archive/archive.git] / openwrt / target / linux / generic-2.6 / patches / 104-pf_ring.patch
diff --git a/openwrt/target/linux/generic-2.6/patches/104-pf_ring.patch b/openwrt/target/linux/generic-2.6/patches/104-pf_ring.patch
deleted file mode 100644 (file)
index 527e5d5..0000000
+++ /dev/null
@@ -1,1833 +0,0 @@
-diff --unified --recursive --new-file linux-2.6.15-rc6/include/linux/ring.h linux-2.6.15-rc6-1-686-smp-ring3/include/linux/ring.h
---- linux-2.6.15-rc6/include/linux/ring.h      1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.15-rc6-1-686-smp-ring3/include/linux/ring.h      2005-12-24 00:24:01.000000000 +0100
-@@ -0,0 +1,107 @@
-+/*
-+ * Definitions for packet ring
-+ *
-+ * 2004 - Luca Deri <deri@ntop.org>
-+ */
-+#ifndef __RING_H
-+#define __RING_H
-+
-+
-+#define INCLUDE_MAC_INFO
-+
-+#ifdef INCLUDE_MAC_INFO
-+#define SKB_DISPLACEMENT    14 /* Include MAC address information */
-+#else
-+#define SKB_DISPLACEMENT    0  /* Do NOT include MAC address information */
-+#endif
-+
-+#define RING_MAGIC
-+#define RING_MAGIC_VALUE      0x88
-+#define RING_FLOWSLOT_VERSION    6
-+#define RING_VERSION          "3.1"
-+
-+#define SO_ADD_TO_CLUSTER        99
-+#define SO_REMOVE_FROM_CLUSTER  100
-+#define SO_SET_REFLECTOR        101
-+
-+/* *********************************** */
-+
-+#ifndef HAVE_PCAP
-+struct pcap_pkthdr {
-+  struct timeval ts;    /* time stamp */
-+  u_int32_t caplen;     /* length of portion present */
-+  u_int32_t len;        /* length this packet (off wire) */
-+};
-+#endif
-+
-+/* *********************************** */
-+
-+enum cluster_type {
-+  cluster_per_flow = 0,
-+  cluster_round_robin
-+};
-+
-+/* *********************************** */
-+
-+#define RING_MIN_SLOT_SIZE    (60+sizeof(struct pcap_pkthdr))
-+#define RING_MAX_SLOT_SIZE    (1514+sizeof(struct pcap_pkthdr))
-+
-+/* *********************************** */
-+
-+typedef struct flowSlotInfo {
-+  u_int16_t version, sample_rate;
-+  u_int32_t tot_slots, slot_len, data_len, tot_mem;
-+  
-+  u_int64_t tot_pkts, tot_lost;
-+  u_int64_t tot_insert, tot_read;  
-+  u_int32_t insert_idx, remove_idx;
-+} FlowSlotInfo;
-+
-+/* *********************************** */
-+
-+typedef struct flowSlot {
-+#ifdef RING_MAGIC
-+  u_char     magic;      /* It must alwasy be zero */
-+#endif
-+  u_char     slot_state; /* 0=empty, 1=full   */
-+  u_char     bucket;     /* bucket[bucketLen] */
-+} FlowSlot;
-+
-+/* *********************************** */
-+
-+#ifdef __KERNEL__ 
-+
-+FlowSlotInfo* getRingPtr(void);
-+int allocateRing(char *deviceName, u_int numSlots,
-+               u_int bucketLen, u_int sampleRate);
-+unsigned int pollRing(struct file *fp, struct poll_table_struct * wait);
-+void deallocateRing(void);
-+
-+/* ************************* */
-+
-+typedef int (*handle_ring_skb)(struct sk_buff *skb,
-+                             u_char recv_packet, u_char real_skb);
-+extern handle_ring_skb get_skb_ring_handler(void);
-+extern void set_skb_ring_handler(handle_ring_skb the_handler);
-+extern void do_skb_ring_handler(struct sk_buff *skb,
-+                              u_char recv_packet, u_char real_skb);
-+
-+typedef int (*handle_ring_buffer)(struct net_device *dev, 
-+                                   char *data, int len);
-+extern handle_ring_buffer get_buffer_ring_handler(void);
-+extern void set_buffer_ring_handler(handle_ring_buffer the_handler);
-+extern int do_buffer_ring_handler(struct net_device *dev,
-+                                char *data, int len);
-+#endif /* __KERNEL__  */
-+
-+/* *********************************** */
-+
-+#define PF_RING          27      /* Packet Ring */
-+#define SOCK_RING        PF_RING
-+
-+/* ioctl() */
-+#define SIORINGPOLL      0x8888
-+
-+/* *********************************** */
-+
-+#endif /* __RING_H */
-diff --unified --recursive --new-file linux-2.6.15-rc6/net/core/dev.c linux-2.6.15-rc6-1-686-smp-ring3/net/core/dev.c
---- linux-2.6.15-rc6/net/core/dev.c    2005-12-19 01:36:54.000000000 +0100
-+++ linux-2.6.15-rc6-1-686-smp-ring3/net/core/dev.c    2005-12-24 00:24:02.000000000 +0100
-@@ -115,6 +115,56 @@
- #endif        /* CONFIG_NET_RADIO */
- #include <asm/current.h>
-+#if defined (CONFIG_RING) || defined(CONFIG_RING_MODULE)
-+
-+/* #define RING_DEBUG */
-+
-+#include <linux/ring.h>
-+#include <linux/version.h>
-+
-+static handle_ring_skb ring_handler = NULL;
-+
-+handle_ring_skb get_skb_ring_handler() { return(ring_handler); }
-+
-+void set_skb_ring_handler(handle_ring_skb the_handler) {
-+  ring_handler = the_handler;
-+}
-+
-+void do_skb_ring_handler(struct sk_buff *skb,
-+                       u_char recv_packet, u_char real_skb) {
-+  if(ring_handler)
-+    ring_handler(skb, recv_packet, real_skb);
-+}
-+
-+/* ******************* */
-+
-+static handle_ring_buffer buffer_ring_handler = NULL;
-+
-+handle_ring_buffer get_buffer_ring_handler() { return(buffer_ring_handler); }
-+
-+void set_buffer_ring_handler(handle_ring_buffer the_handler) {
-+  buffer_ring_handler = the_handler;
-+}
-+
-+int do_buffer_ring_handler(struct net_device *dev, char *data, int len) {
-+  if(buffer_ring_handler) {
-+    buffer_ring_handler(dev, data, len);
-+    return(1);
-+  } else 
-+    return(0);
-+}
-+
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
-+EXPORT_SYMBOL(get_skb_ring_handler);
-+EXPORT_SYMBOL(set_skb_ring_handler);
-+EXPORT_SYMBOL(do_skb_ring_handler);
-+
-+EXPORT_SYMBOL(get_buffer_ring_handler);
-+EXPORT_SYMBOL(set_buffer_ring_handler);
-+EXPORT_SYMBOL(do_buffer_ring_handler);
-+#endif
-+
-+#endif
- /*
-  *    The list of packet types we will receive (as opposed to discard)
-  *    and the routines to invoke.
-@@ -1296,6 +1346,10 @@
-       skb->tc_verd = SET_TC_AT(skb->tc_verd,AT_EGRESS);
- #endif
-       if (q->enqueue) {
-+#if defined (CONFIG_RING) || defined(CONFIG_RING_MODULE)
-+      if(ring_handler) ring_handler(skb, 0, 1);
-+#endif /* CONFIG_RING */
-+
-               /* Grab device queue */
-               spin_lock(&dev->queue_lock);
-@@ -1437,6 +1491,13 @@
-       preempt_disable();
-       err = netif_rx(skb);
-+#if defined (CONFIG_RING) || defined(CONFIG_RING_MODULE)
-+      if(ring_handler && ring_handler(skb, 1, 1)) {
-+        /* The packet has been copied into a ring */
-+        return(NET_RX_SUCCESS);
-+      }
-+#endif /* CONFIG_RING */
-+
-       if (local_softirq_pending())
-               do_softirq();
-       preempt_enable();
-@@ -1582,6 +1643,13 @@
-       struct net_device *orig_dev;
-       int ret = NET_RX_DROP;
-       unsigned short type;
-+#if defined (CONFIG_RING) || defined(CONFIG_RING_MODULE)
-+      if(ring_handler && ring_handler(skb, 1, 1)) {
-+        /* The packet has been copied into a ring */
-+        return(NET_RX_SUCCESS);
-+      }
-+#endif /* CONFIG_RING */
-+
-       /* if we've gotten here through NAPI, check netpoll */
-       if (skb->dev->poll && netpoll_rx(skb))
-diff --unified --recursive --new-file linux-2.6.15-rc6/net/Kconfig linux-2.6.15-rc6-1-686-smp-ring3/net/Kconfig
---- linux-2.6.15-rc6/net/Kconfig       2005-12-19 01:36:54.000000000 +0100
-+++ linux-2.6.15-rc6-1-686-smp-ring3/net/Kconfig       2005-12-24 00:24:02.000000000 +0100
-@@ -31,6 +31,7 @@
- source "net/unix/Kconfig"
- source "net/xfrm/Kconfig"
-+source "net/ring/Kconfig"
- config INET
-       bool "TCP/IP networking"
-       ---help---
-diff --unified --recursive --new-file linux-2.6.15-rc6/net/Makefile linux-2.6.15-rc6-1-686-smp-ring3/net/Makefile
---- linux-2.6.15-rc6/net/Makefile      2005-12-19 01:36:54.000000000 +0100
-+++ linux-2.6.15-rc6-1-686-smp-ring3/net/Makefile      2005-12-24 00:24:02.000000000 +0100
-@@ -42,6 +42,7 @@
- obj-$(CONFIG_DECNET)          += decnet/
- obj-$(CONFIG_ECONET)          += econet/
- obj-$(CONFIG_VLAN_8021Q)      += 8021q/
-+obj-$(CONFIG_RING)            += ring/
- obj-$(CONFIG_IP_DCCP)         += dccp/
- obj-$(CONFIG_IP_SCTP)         += sctp/
- obj-$(CONFIG_IEEE80211)               += ieee80211/
-diff --unified --recursive --new-file linux-2.6.15-rc6/net/ring/Kconfig linux-2.6.15-rc6-1-686-smp-ring3/net/ring/Kconfig
---- linux-2.6.15-rc6/net/ring/Kconfig  1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.15-rc6-1-686-smp-ring3/net/ring/Kconfig  2005-12-24 00:24:02.000000000 +0100
-@@ -0,0 +1,14 @@
-+config RING
-+      tristate "PF_RING sockets (EXPERIMENTAL)"
-+      depends on EXPERIMENTAL
-+      ---help---
-+        PF_RING socket family, optimized for packet capture.
-+          If a PF_RING socket is bound to an adapter (via the bind() system
-+          call), such adapter will be used in read-only mode until the socket
-+          is destroyed. Whenever an incoming packet is received from the adapter
-+          it will not passed to upper layers, but instead it is copied to a ring
-+          buffer, which in turn is exported to user space applications via mmap.
-+          Please refer to http://luca.ntop.org/Ring.pdf for more.
-+
-+        Say N unless you know what you are doing.
-+
-diff --unified --recursive --new-file linux-2.6.15-rc6/net/ring/Makefile linux-2.6.15-rc6-1-686-smp-ring3/net/ring/Makefile
---- linux-2.6.15-rc6/net/ring/Makefile 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.15-rc6-1-686-smp-ring3/net/ring/Makefile 2005-12-24 00:24:02.000000000 +0100
-@@ -0,0 +1,7 @@
-+#
-+# Makefile for the ring driver.
-+#
-+
-+obj-m += ring.o
-+
-+ring-objs := ring_packet.o
-diff --unified --recursive --new-file linux-2.6.15-rc6/net/ring/ring_packet.c linux-2.6.15-rc6-1-686-smp-ring3/net/ring/ring_packet.c
---- linux-2.6.15-rc6/net/ring/ring_packet.c    1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.15-rc6-1-686-smp-ring3/net/ring/ring_packet.c    2005-12-24 00:24:02.000000000 +0100
-@@ -0,0 +1,1568 @@
-+/*
-+ *
-+ * (C) 2004-05 - Luca Deri <deri@ntop.org>
-+ *
-+ * This code includes contributions courtesy of
-+ * - Jeff Randall <jrandall@nexvu.com>
-+ * - Helmut Manck <helmut.manck@secunet.com>
-+ * - Brad Doctor <brad@stillsecure.com>
-+ * - Amit D. Chaudhary <amit_ml@rajgad.com>
-+ *
-+ */
-+
-+/* 
-+   TO DO:
-+   add an entry inside the /proc filesystem 
-+*/
-+
-+#include <linux/version.h>
-+#include <linux/config.h>
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/socket.h>
-+#include <linux/skbuff.h>
-+#include <linux/rtnetlink.h>
-+#include <linux/in.h>
-+#include <linux/in6.h>
-+#include <linux/init.h>
-+#include <linux/filter.h>
-+#include <linux/ring.h>
-+#include <linux/ip.h>
-+#include <linux/tcp.h>
-+#include <linux/udp.h>
-+#include <linux/list.h>
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
-+#include <net/xfrm.h>
-+#else
-+#include <linux/poll.h>
-+#endif
-+#include <net/sock.h>
-+#include <asm/io.h>   /* needed for virt_to_phys() */
-+
-+/* #define RING_DEBUG */
-+
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11))
-+static inline int remap_page_range(struct vm_area_struct *vma,
-+                                 unsigned long uvaddr,
-+                                 unsigned long paddr,
-+                                 unsigned long size,
-+                                 pgprot_t prot) {
-+  return(remap_pfn_range(vma, uvaddr, paddr >> PAGE_SHIFT,
-+                       size, prot));
-+}
-+#endif
-+
-+/* ************************************************* */
-+
-+#define CLUSTER_LEN       8
-+
-+struct ring_cluster {
-+  u_short             cluster_id; /* 0 = no cluster */
-+  u_short             num_cluster_elements;
-+  enum cluster_type   hashing_mode;
-+  u_short             hashing_id;
-+  struct sock         *sk[CLUSTER_LEN];
-+  struct ring_cluster *next;      /* NULL = last element of the cluster */
-+};
-+
-+/* ************************************************* */
-+
-+struct ring_element {
-+  struct list_head  list;
-+  struct sock      *sk;
-+};
-+
-+/* ************************************************* */
-+
-+struct ring_opt {
-+  struct net_device *ring_netdev;
-+
-+  /* Cluster */
-+  u_short cluster_id; /* 0 = no cluster */
-+
-+  /* Reflector */
-+  struct net_device *reflector_dev;
-+
-+  /* Packet buffers */
-+  unsigned long order;
-+
-+  /* Ring Slots */
-+  unsigned long ring_memory;
-+  FlowSlotInfo *slots_info; /* Basically it points to ring_memory */
-+  char *ring_slots;  /* Basically it points to ring_memory
-+                      +sizeof(FlowSlotInfo) */
-+
-+  /* Packet Sampling */
-+  u_int pktToSample, sample_rate;
-+
-+  /* BPF Filter */
-+  struct sk_filter *bpfFilter;
-+
-+  /* Locks */
-+  atomic_t num_ring_slots_waiters;
-+  wait_queue_head_t ring_slots_waitqueue;
-+  rwlock_t ring_index_lock;
-+
-+  /* Indexes (Internal) */
-+  u_int insert_page_id, insert_slot_id;
-+};
-+
-+/* ************************************************* */
-+
-+/* List of all ring sockets. */
-+static struct list_head ring_table;
-+
-+/* List of all clusters */
-+static struct ring_cluster *ring_cluster_list;
-+
-+static rwlock_t ring_mgmt_lock = RW_LOCK_UNLOCKED;
-+
-+/* ********************************** */
-+
-+/* Forward */
-+static struct proto_ops ring_ops;
-+
-+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,11))
-+static struct proto ring_proto;
-+#endif
-+
-+static int skb_ring_handler(struct sk_buff *skb, u_char recv_packet,
-+                          u_char real_skb);
-+static int buffer_ring_handler(struct net_device *dev, char *data, int len);
-+static int remove_from_cluster(struct sock *sock, struct ring_opt *pfr);
-+
-+/* Extern */
-+
-+/* ********************************** */
-+
-+/* Defaults */
-+static u_int bucket_len = 128, num_slots = 4096, sample_rate = 1,
-+  transparent_mode = 1, enable_tx_capture = 0;
-+
-+MODULE_PARM(bucket_len, "i");
-+MODULE_PARM_DESC(bucket_len, "Number of ring buckets");
-+MODULE_PARM(num_slots,  "i");
-+MODULE_PARM_DESC(num_slots,  "Number of ring slots");
-+MODULE_PARM(sample_rate, "i");
-+MODULE_PARM_DESC(sample_rate, "Ring packet sample rate");
-+MODULE_PARM(transparent_mode, "i");
-+MODULE_PARM_DESC(transparent_mode,
-+               "Set to 1 to set transparent mode "
-+               "(slower but backwards compatible)");
-+MODULE_PARM(enable_tx_capture, "i");
-+MODULE_PARM_DESC(enable_tx_capture, "Set to 1 to capture outgoing packets");
-+
-+/* ********************************** */
-+
-+#define MIN_QUEUED_PKTS      64
-+#define MAX_QUEUE_LOOPS      64
-+
-+
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
-+#define ring_sk_datatype(__sk) ((struct ring_opt *)__sk)
-+#define ring_sk(__sk) ((__sk)->sk_protinfo)
-+#else
-+#define ring_sk_datatype(a) (a)
-+#define ring_sk(__sk) ((__sk)->protinfo.pf_ring)
-+#endif
-+
-+#define _rdtsc() ({ uint64_t x; asm volatile("rdtsc" : "=A" (x)); x; })
-+
-+/*
-+  int dev_queue_xmit(struct sk_buff *skb)
-+  skb->dev;
-+  struct net_device *dev_get_by_name(const char *name)
-+*/
-+
-+/* ********************************** */
-+
-+static void ring_sock_destruct(struct sock *sk) {
-+
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
-+  skb_queue_purge(&sk->sk_receive_queue);
-+
-+  if (!sock_flag(sk, SOCK_DEAD)) {
-+#if defined(RING_DEBUG)
-+    printk("Attempt to release alive ring socket: %p\n", sk);
-+#endif
-+    return;
-+  }
-+
-+  BUG_TRAP(!atomic_read(&sk->sk_rmem_alloc));
-+  BUG_TRAP(!atomic_read(&sk->sk_wmem_alloc));
-+#else
-+
-+  BUG_TRAP(atomic_read(&sk->rmem_alloc)==0);
-+  BUG_TRAP(atomic_read(&sk->wmem_alloc)==0);
-+
-+  if (!sk->dead) {
-+#if defined(RING_DEBUG)
-+    printk("Attempt to release alive ring socket: %p\n", sk);
-+#endif
-+    return;
-+  }
-+#endif
-+
-+  kfree(ring_sk(sk));
-+
-+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
-+  MOD_DEC_USE_COUNT;
-+#endif
-+}
-+
-+/* ********************************** */
-+/*
-+ * ring_insert()
-+ *
-+ * store the sk in a new element and add it
-+ * to the head of the list.
-+ */
-+static inline void ring_insert(struct sock *sk) {
-+  struct ring_element *next;
-+
-+#if defined(RING_DEBUG)
-+  printk("RING: ring_insert()\n");
-+#endif
-+
-+  next = kmalloc(sizeof(struct ring_element), GFP_ATOMIC);
-+  if(next != NULL) {
-+    next->sk = sk;
-+    write_lock_irq(&ring_mgmt_lock);
-+    list_add(&next->list, &ring_table);
-+    write_unlock_irq(&ring_mgmt_lock);
-+  } else {
-+    if (net_ratelimit())
-+      printk("RING: could not kmalloc slot!!\n");
-+  }
-+}
-+
-+/* ********************************** */
-+/*
-+ * ring_remove()
-+ *
-+ * For each of the elements in the list:
-+ *  - check if this is the element we want to delete
-+ *  - if it is, remove it from the list, and free it.
-+ *
-+ * stop when we find the one we're looking for (break),
-+ * or when we reach the end of the list.
-+ */
-+static inline void ring_remove(struct sock *sk) {
-+  struct list_head *ptr;
-+  struct ring_element *entry;
-+
-+
-+  for(ptr = ring_table.next; ptr != &ring_table; ptr = ptr->next) {
-+    entry = list_entry(ptr, struct ring_element, list);
-+
-+    if(entry->sk == sk) {
-+      write_lock_irq(&ring_mgmt_lock);
-+      list_del(ptr);
-+      kfree(ptr);
-+      write_unlock_irq(&ring_mgmt_lock);
-+      break;
-+    }
-+  }
-+
-+}
-+
-+/* ********************************** */
-+
-+static u_int32_t num_queued_pkts(struct ring_opt *pfr) {
-+
-+  if(pfr->ring_slots != NULL) {
-+
-+    u_int32_t tot_insert = pfr->slots_info->insert_idx,
-+#if defined(RING_DEBUG)
-+      tot_read = pfr->slots_info->tot_read, tot_pkts;
-+#else
-+    tot_read = pfr->slots_info->tot_read;
-+#endif
-+
-+    if(tot_insert >= tot_read) {
-+#if defined(RING_DEBUG)
-+      tot_pkts = tot_insert-tot_read;
-+#endif
-+      return(tot_insert-tot_read);
-+    } else {
-+#if defined(RING_DEBUG)
-+      tot_pkts = ((u_int32_t)-1)+tot_insert-tot_read;
-+#endif
-+      return(((u_int32_t)-1)+tot_insert-tot_read);
-+    }
-+
-+#if defined(RING_DEBUG)
-+    printk("-> num_queued_pkts=%d [tot_insert=%d][tot_read=%d]\n",
-+         tot_pkts, tot_insert, tot_read);
-+#endif
-+
-+  } else
-+    return(0);
-+}
-+
-+/* ********************************** */
-+
-+static inline FlowSlot* get_insert_slot(struct ring_opt *pfr) {
-+#if defined(RING_DEBUG)
-+  printk("get_insert_slot(%d)\n", pfr->slots_info->insert_idx);
-+#endif
-+
-+  if(pfr->ring_slots != NULL) {
-+    FlowSlot *slot = (FlowSlot*)&(pfr->ring_slots[pfr->slots_info->insert_idx
-+                                                *pfr->slots_info->slot_len]);
-+    return(slot);
-+  } else
-+    return(NULL);
-+}
-+
-+/* ********************************** */
-+
-+static inline FlowSlot* get_remove_slot(struct ring_opt *pfr) {
-+#if defined(RING_DEBUG)
-+  printk("get_remove_slot(%d)\n", pfr->slots_info->remove_idx);
-+#endif
-+
-+  if(pfr->ring_slots != NULL)
-+    return((FlowSlot*)&(pfr->ring_slots[pfr->slots_info->remove_idx*
-+                                      pfr->slots_info->slot_len]));
-+  else
-+    return(NULL);
-+}
-+
-+/* ********************************** */
-+
-+static void add_skb_to_ring(struct sk_buff *skb,
-+                          struct ring_opt *pfr,
-+                          u_char recv_packet,
-+                          u_char real_skb /* 1=skb 0=faked skb */) {
-+  FlowSlot *theSlot;
-+  int idx, displ;
-+
-+  if(recv_packet) {
-+    /* Hack for identifying a packet received by the e1000 */
-+    if(real_skb) {
-+      displ = SKB_DISPLACEMENT;
-+    } else
-+      displ = 0; /* Received by the e1000 wrapper */
-+  } else
-+    displ = 0;
-+
-+  write_lock(&pfr->ring_index_lock);
-+  pfr->slots_info->tot_pkts++;
-+  write_unlock(&pfr->ring_index_lock);
-+
-+  /* BPF Filtering (from af_packet.c) */
-+  if(pfr->bpfFilter != NULL) {
-+    unsigned res = 1, len;
-+
-+    len = skb->len-skb->data_len;
-+
-+    write_lock(&pfr->ring_index_lock);
-+    skb->data -= displ;
-+    res = sk_run_filter(skb, pfr->bpfFilter->insns, pfr->bpfFilter->len);
-+    skb->data += displ;
-+    write_unlock(&pfr->ring_index_lock);
-+
-+    if(res == 0) {
-+      /* Filter failed */
-+
-+#if defined(RING_DEBUG)
-+      printk("add_skb_to_ring(skb): Filter failed [len=%d][tot=%llu]"
-+           "[insertIdx=%d][pkt_type=%d][cloned=%d]\n",
-+           (int)skb->len, pfr->slots_info->tot_pkts,
-+           pfr->slots_info->insert_idx,
-+           skb->pkt_type, skb->cloned);
-+#endif
-+
-+      return;
-+    }
-+  }
-+
-+  /* ************************** */
-+
-+  if(pfr->sample_rate > 1) {
-+    if(pfr->pktToSample == 0) {
-+      write_lock(&pfr->ring_index_lock);
-+      pfr->pktToSample = pfr->sample_rate;
-+      write_unlock(&pfr->ring_index_lock);
-+    } else {
-+      write_lock(&pfr->ring_index_lock);
-+      pfr->pktToSample--;
-+      write_unlock(&pfr->ring_index_lock);
-+
-+#if defined(RING_DEBUG)
-+      printk("add_skb_to_ring(skb): sampled packet [len=%d]"
-+           "[tot=%llu][insertIdx=%d][pkt_type=%d][cloned=%d]\n",
-+           (int)skb->len, pfr->slots_info->tot_pkts,
-+           pfr->slots_info->insert_idx,
-+           skb->pkt_type, skb->cloned);
-+#endif
-+      return;
-+    }
-+  }
-+
-+  /* ************************************* */
-+
-+  if((pfr->reflector_dev != NULL)
-+     && (!netif_queue_stopped(pfr->reflector_dev))) {
-+    int cpu = smp_processor_id();
-+
-+    /* increase reference counter so that this skb is not freed */
-+    atomic_inc(&skb->users);
-+
-+    skb->data -= displ;
-+
-+    /* send it */
-+    if (pfr->reflector_dev->xmit_lock_owner != cpu) {
-+      spin_lock_bh(&pfr->reflector_dev->xmit_lock);
-+      pfr->reflector_dev->xmit_lock_owner = cpu;
-+      spin_unlock_bh(&pfr->reflector_dev->xmit_lock);
-+
-+      if (pfr->reflector_dev->hard_start_xmit(skb,
-+                                            pfr->reflector_dev) == 0) {
-+        spin_lock_bh(&pfr->reflector_dev->xmit_lock);
-+      pfr->reflector_dev->xmit_lock_owner = -1;
-+      skb->data += displ;
-+      spin_unlock_bh(&pfr->reflector_dev->xmit_lock);
-+#if defined(RING_DEBUG)
-+      printk("++ hard_start_xmit succeeded\n");
-+#endif
-+      return; /* OK */
-+      }
-+
-+      spin_lock_bh(&pfr->reflector_dev->xmit_lock);
-+      pfr->reflector_dev->xmit_lock_owner = -1;
-+      spin_unlock_bh(&pfr->reflector_dev->xmit_lock);
-+    }
-+
-+#if defined(RING_DEBUG)
-+    printk("++ hard_start_xmit failed\n");
-+#endif
-+    skb->data += displ;
-+    return; /* -ENETDOWN */
-+  }
-+
-+  /* ************************************* */
-+
-+#if defined(RING_DEBUG)
-+  printk("add_skb_to_ring(skb) [len=%d][tot=%llu][insertIdx=%d]"
-+       "[pkt_type=%d][cloned=%d]\n",
-+       (int)skb->len, pfr->slots_info->tot_pkts,
-+       pfr->slots_info->insert_idx,
-+       skb->pkt_type, skb->cloned);
-+#endif
-+
-+  idx = pfr->slots_info->insert_idx;
-+  theSlot = get_insert_slot(pfr);
-+
-+  if((theSlot != NULL) && (theSlot->slot_state == 0)) {
-+    struct pcap_pkthdr *hdr;
-+    char *bucket;
-+
-+    /* Update Index */
-+    idx++;
-+
-+    if(idx == pfr->slots_info->tot_slots) {
-+      write_lock(&pfr->ring_index_lock);
-+      pfr->slots_info->insert_idx = 0;
-+      write_unlock(&pfr->ring_index_lock);
-+    } else {
-+      write_lock(&pfr->ring_index_lock);
-+      pfr->slots_info->insert_idx = idx;
-+      write_unlock(&pfr->ring_index_lock);
-+    }
-+
-+    bucket = &theSlot->bucket;
-+    hdr = (struct pcap_pkthdr*)bucket;
-+
-+    /* BD - API changed for time keeping */
-+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14))
-+    if(skb->stamp.tv_sec == 0) do_gettimeofday(&skb->stamp);
-+
-+    hdr->ts.tv_sec = skb->stamp.tv_sec, hdr->ts.tv_usec = skb->stamp.tv_usec;
-+#else
-+    if(skb->tstamp.off_sec == 0) __net_timestamp(skb);
-+
-+    hdr->ts.tv_sec = skb->tstamp.off_sec, hdr->ts.tv_usec = skb->tstamp.off_usec;
-+#endif
-+
-+    hdr->caplen    = skb->len+displ;
-+
-+    if(hdr->caplen > pfr->slots_info->data_len)
-+      hdr->caplen = pfr->slots_info->data_len;
-+
-+    hdr->len = skb->len+displ;
-+    memcpy(&bucket[sizeof(struct pcap_pkthdr)],
-+         skb->data-displ, hdr->caplen);
-+
-+#if defined(RING_DEBUG)
-+    {
-+      static unsigned int lastLoss = 0;
-+
-+      if(pfr->slots_info->tot_lost
-+       && (lastLoss != pfr->slots_info->tot_lost)) {
-+      printk("add_skb_to_ring(%d): [data_len=%d]"
-+             "[hdr.caplen=%d][skb->len=%d]"
-+             "[pcap_pkthdr=%d][removeIdx=%d]"
-+             "[loss=%lu][page=%u][slot=%u]\n",
-+             idx-1, pfr->slots_info->data_len, hdr->caplen, skb->len,
-+             sizeof(struct pcap_pkthdr),
-+             pfr->slots_info->remove_idx,
-+             (long unsigned int)pfr->slots_info->tot_lost,
-+             pfr->insert_page_id, pfr->insert_slot_id);
-+
-+      lastLoss = pfr->slots_info->tot_lost;
-+      }
-+    }
-+#endif
-+
-+    write_lock(&pfr->ring_index_lock);
-+    pfr->slots_info->tot_insert++;
-+    theSlot->slot_state = 1;
-+    write_unlock(&pfr->ring_index_lock);
-+  } else {
-+    write_lock(&pfr->ring_index_lock);
-+    pfr->slots_info->tot_lost++;
-+    write_unlock(&pfr->ring_index_lock);
-+
-+#if defined(RING_DEBUG)
-+    printk("add_skb_to_ring(skb): packet lost [loss=%lu]"
-+         "[removeIdx=%u][insertIdx=%u]\n",
-+         (long unsigned int)pfr->slots_info->tot_lost,
-+         pfr->slots_info->remove_idx, pfr->slots_info->insert_idx);
-+#endif
-+  }
-+
-+  /* wakeup in case of poll() */
-+  if(waitqueue_active(&pfr->ring_slots_waitqueue))
-+    wake_up_interruptible(&pfr->ring_slots_waitqueue);
-+}
-+
-+/* ********************************** */
-+
-+static u_int hash_skb(struct ring_cluster *cluster_ptr,
-+                    struct sk_buff *skb, u_char recv_packet) {
-+  u_int idx;
-+  int displ;
-+  struct iphdr *ip;
-+
-+  if(cluster_ptr->hashing_mode == cluster_round_robin) {
-+    idx = cluster_ptr->hashing_id++;
-+  } else {
-+    /* Per-flow clustering */
-+    if(skb->len > sizeof(struct iphdr)+sizeof(struct tcphdr)) {
-+      if(recv_packet)
-+      displ = 0;
-+      else
-+      displ = SKB_DISPLACEMENT;
-+
-+      /*
-+      skb->data+displ
-+
-+      Always points to to the IP part of the packet
-+      */
-+
-+      ip = (struct iphdr*)(skb->data+displ);
-+
-+      idx = ip->saddr+ip->daddr+ip->protocol;
-+
-+      if(ip->protocol == IPPROTO_TCP) {
-+      struct tcphdr *tcp = (struct tcphdr*)(skb->data+displ
-+                                            +sizeof(struct iphdr));
-+      idx += tcp->source+tcp->dest;
-+      } else if(ip->protocol == IPPROTO_UDP) {
-+      struct udphdr *udp = (struct udphdr*)(skb->data+displ
-+                                            +sizeof(struct iphdr));
-+      idx += udp->source+udp->dest;
-+      }
-+    } else
-+      idx = skb->len;
-+  }
-+
-+  return(idx % cluster_ptr->num_cluster_elements);
-+}
-+
-+/* ********************************** */
-+
-+static int skb_ring_handler(struct sk_buff *skb,
-+                          u_char recv_packet,
-+                          u_char real_skb /* 1=skb 0=faked skb */) {
-+  struct sock *skElement;
-+  int rc = 0;
-+  struct list_head *ptr;
-+  struct ring_cluster *cluster_ptr;
-+
-+#ifdef PROFILING
-+  uint64_t rdt = _rdtsc(), rdt1, rdt2;
-+#endif
-+
-+  if((!skb) /* Invalid skb */
-+     || ((!enable_tx_capture) && (!recv_packet))) {
-+    /*
-+      An outgoing packet is about to be sent out
-+      but we decided not to handle transmitted
-+      packets.
-+    */
-+    return(0);
-+  }
-+
-+#if defined(RING_DEBUG)
-+  if(0) {
-+    printk("skb_ring_handler() [len=%d][dev=%s]\n", skb->len,
-+         skb->dev->name == NULL ? "<NULL>" : skb->dev->name);
-+  }
-+#endif
-+
-+#ifdef PROFILING
-+  rdt1 = _rdtsc();
-+#endif
-+
-+  /* [1] Check unclustered sockets */
-+  for (ptr = ring_table.next; ptr != &ring_table; ptr = ptr->next) {
-+    struct ring_opt *pfr;
-+    struct ring_element *entry;
-+
-+    entry = list_entry(ptr, struct ring_element, list);
-+
-+    read_lock(&ring_mgmt_lock);
-+    skElement = entry->sk;
-+    pfr = ring_sk(skElement);
-+    read_unlock(&ring_mgmt_lock);
-+
-+    if((pfr != NULL)
-+       && (pfr->cluster_id == 0 /* No cluster */)
-+       && (pfr->ring_slots != NULL)
-+       && (pfr->ring_netdev == skb->dev)) {
-+      /* We've found the ring where the packet can be stored */
-+      read_lock(&ring_mgmt_lock);
-+      add_skb_to_ring(skb, pfr, recv_packet, real_skb);
-+      read_unlock(&ring_mgmt_lock);
-+
-+      rc = 1; /* Ring found: we've done our job */
-+    }
-+  }
-+
-+  /* [2] Check socket clusters */
-+  cluster_ptr = ring_cluster_list;
-+
-+  while(cluster_ptr != NULL) {
-+    struct ring_opt *pfr;
-+
-+    if(cluster_ptr->num_cluster_elements > 0) {
-+      u_int skb_hash = hash_skb(cluster_ptr, skb, recv_packet);
-+
-+      read_lock(&ring_mgmt_lock);
-+      skElement = cluster_ptr->sk[skb_hash];
-+      read_unlock(&ring_mgmt_lock);
-+
-+      if(skElement != NULL) {
-+      pfr = ring_sk(skElement);
-+
-+      if((pfr != NULL)
-+         && (pfr->ring_slots != NULL)
-+         && (pfr->ring_netdev == skb->dev)) {
-+        /* We've found the ring where the packet can be stored */
-+          read_lock(&ring_mgmt_lock);
-+        add_skb_to_ring(skb, pfr, recv_packet, real_skb);
-+          read_unlock(&ring_mgmt_lock);
-+
-+        rc = 1; /* Ring found: we've done our job */
-+      }
-+      }
-+    }
-+
-+    cluster_ptr = cluster_ptr->next;
-+  }
-+
-+#ifdef PROFILING
-+  rdt1 = _rdtsc()-rdt1;
-+#endif
-+
-+#ifdef PROFILING
-+  rdt2 = _rdtsc();
-+#endif
-+
-+  if(transparent_mode) rc = 0;
-+
-+  if((rc != 0) && real_skb)
-+    dev_kfree_skb(skb); /* Free the skb */
-+
-+#ifdef PROFILING
-+  rdt2 = _rdtsc()-rdt2;
-+  rdt = _rdtsc()-rdt;
-+
-+#if defined(RING_DEBUG)
-+  printk("# cycles: %d [lock costed %d %d%%][free costed %d %d%%]\n",
-+       (int)rdt, rdt-rdt1,
-+       (int)((float)((rdt-rdt1)*100)/(float)rdt),
-+       rdt2,
-+       (int)((float)(rdt2*100)/(float)rdt));
-+#endif
-+#endif
-+
-+  return(rc); /*  0 = packet not handled */
-+}
-+
-+/* ********************************** */
-+
-+struct sk_buff skb;
-+
-+static int buffer_ring_handler(struct net_device *dev,
-+                             char *data, int len) {
-+
-+#if defined(RING_DEBUG)
-+  printk("buffer_ring_handler: [dev=%s][len=%d]\n",
-+       dev->name == NULL ? "<NULL>" : dev->name, len);
-+#endif
-+
-+  /* BD - API changed for time keeping */
-+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14))
-+  skb.dev = dev, skb.len = len, skb.data = data,
-+    skb.data_len = len, skb.stamp.tv_sec = 0; /* Calculate the time */
-+#else
-+  skb.dev = dev, skb.len = len, skb.data = data,
-+    skb.data_len = len, skb.tstamp.off_sec = 0; /* Calculate the time */
-+#endif
-+
-+  skb_ring_handler(&skb, 1, 0 /* fake skb */);
-+
-+  return(0);
-+}
-+
-+/* ********************************** */
-+
-+static int ring_create(struct socket *sock, int protocol) {
-+  struct sock *sk;
-+  struct ring_opt *pfr;
-+  int err;
-+
-+#if defined(RING_DEBUG)
-+  printk("RING: ring_create()\n");
-+#endif
-+
-+  /* Are you root, superuser or so ? */
-+  if(!capable(CAP_NET_ADMIN))
-+    return -EPERM;
-+
-+  if(sock->type != SOCK_RAW)
-+    return -ESOCKTNOSUPPORT;
-+
-+  if(protocol != htons(ETH_P_ALL))
-+    return -EPROTONOSUPPORT;
-+
-+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
-+  MOD_INC_USE_COUNT;
-+#endif
-+
-+  err = -ENOMEM;
-+
-+  // BD: -- broke this out to keep it more simple and clear as to what the
-+  // options are.
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
-+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,11))
-+  sk = sk_alloc(PF_RING, GFP_KERNEL, 1, NULL);
-+#else
-+  // BD: API changed in 2.6.12, ref:
-+  // http://svn.clkao.org/svnweb/linux/revision/?rev=28201
-+  sk = sk_alloc(PF_RING, GFP_ATOMIC, &ring_proto, 1);
-+#endif
-+#else
-+  /* Kernel 2.4 */
-+  sk = sk_alloc(PF_RING, GFP_KERNEL, 1);
-+#endif
-+
-+  if (sk == NULL)
-+    goto out;
-+
-+  sock->ops = &ring_ops;
-+  sock_init_data(sock, sk);
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
-+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,11))
-+  sk_set_owner(sk, THIS_MODULE);
-+#endif
-+#endif
-+
-+  err = -ENOMEM;
-+  ring_sk(sk) = ring_sk_datatype(kmalloc(sizeof(*pfr), GFP_KERNEL));
-+
-+  if (!(pfr = ring_sk(sk))) {
-+    sk_free(sk);
-+    goto out;
-+  }
-+  memset(pfr, 0, sizeof(*pfr));
-+  init_waitqueue_head(&pfr->ring_slots_waitqueue);
-+  pfr->ring_index_lock = RW_LOCK_UNLOCKED;
-+  atomic_set(&pfr->num_ring_slots_waiters, 0);
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
-+  sk->sk_family       = PF_RING;
-+  sk->sk_destruct     = ring_sock_destruct;
-+#else
-+  sk->family          = PF_RING;
-+  sk->destruct        = ring_sock_destruct;
-+  sk->num             = protocol;
-+#endif
-+
-+  ring_insert(sk);
-+
-+#if defined(RING_DEBUG)
-+  printk("RING: ring_create() - created\n");
-+#endif
-+
-+  return(0);
-+ out:
-+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
-+  MOD_DEC_USE_COUNT;
-+#endif
-+  return err;
-+}
-+
-+/* *********************************************** */
-+
-+static int ring_release(struct socket *sock)
-+{
-+  struct sock *sk = sock->sk;
-+  struct ring_opt *pfr = ring_sk(sk);
-+
-+  if(!sk)
-+    return 0;
-+
-+#if defined(RING_DEBUG)
-+  printk("RING: called ring_release\n");
-+#endif
-+
-+#if defined(RING_DEBUG)
-+  printk("RING: ring_release entered\n");
-+#endif
-+
-+  ring_remove(sk);
-+
-+  sock_orphan(sk);
-+  sock->sk = NULL;
-+
-+  /* Free the ring buffer */
-+  if(pfr->ring_memory) {
-+    struct page *page, *page_end;
-+
-+    page_end = virt_to_page(pfr->ring_memory + (PAGE_SIZE << pfr->order) - 1);
-+    for(page = virt_to_page(pfr->ring_memory); page <= page_end; page++)
-+      ClearPageReserved(page);
-+
-+    free_pages(pfr->ring_memory, pfr->order);
-+  }
-+
-+  kfree(pfr);
-+  ring_sk(sk) = NULL;
-+
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
-+  skb_queue_purge(&sk->sk_write_queue);
-+#endif
-+  sock_put(sk);
-+
-+#if defined(RING_DEBUG)
-+  printk("RING: ring_release leaving\n");
-+#endif
-+
-+  return 0;
-+}
-+
-+/* ********************************** */
-+/*
-+ * We create a ring for this socket and bind it to the specified device
-+ */
-+static int packet_ring_bind(struct sock *sk, struct net_device *dev)
-+{
-+  u_int the_slot_len;
-+  u_int32_t tot_mem;
-+  struct ring_opt *pfr = ring_sk(sk);
-+  struct page *page, *page_end;
-+
-+  if(!dev) return(-1);
-+
-+#if defined(RING_DEBUG)
-+  printk("RING: packet_ring_bind(%s) called\n", dev->name);
-+#endif
-+
-+  /* **********************************************
-+
-+  *************************************
-+  *                                   *
-+  *        FlowSlotInfo               *
-+  *                                   *
-+  ************************************* <-+
-+  *        FlowSlot                   *   |
-+  *************************************   |
-+  *        FlowSlot                   *   |
-+  *************************************   +- num_slots
-+  *        FlowSlot                   *   |
-+  *************************************   |
-+  *        FlowSlot                   *   |
-+  ************************************* <-+
-+
-+  ********************************************** */
-+
-+  the_slot_len = sizeof(u_char)    /* flowSlot.slot_state */
-+#ifdef RING_MAGIC
-+    + sizeof(u_char)
-+#endif
-+    + sizeof(struct pcap_pkthdr)
-+    + bucket_len      /* flowSlot.bucket */;
-+
-+  tot_mem = sizeof(FlowSlotInfo) + num_slots*the_slot_len;
-+
-+  /*
-+    Calculate the value of the order parameter used later.
-+    See http://www.linuxjournal.com/article.php?sid=1133
-+  */
-+  for(pfr->order = 0;(PAGE_SIZE << pfr->order) < tot_mem; pfr->order++)  ;
-+
-+  /*
-+    We now try to allocate the memory as required. If we fail
-+    we try to allocate a smaller amount or memory (hence a
-+    smaller ring).
-+  */
-+  while((pfr->ring_memory = __get_free_pages(GFP_ATOMIC, pfr->order)) == 0)
-+    if(pfr->order-- == 0)
-+      break;
-+
-+  if(pfr->order == 0) {
-+    printk("RING: ERROR not enough memory for ring\n");
-+    return(-1);
-+  } else {
-+    printk("RING: succesfully allocated %lu KB [tot_mem=%d][order=%ld]\n",
-+         PAGE_SIZE >> (10 - pfr->order), tot_mem, pfr->order);
-+  }
-+
-+  tot_mem = PAGE_SIZE << pfr->order;
-+  memset((char*)pfr->ring_memory, 0, tot_mem);
-+
-+  /* Now we need to reserve the pages */
-+  page_end = virt_to_page(pfr->ring_memory + (PAGE_SIZE << pfr->order) - 1);
-+  for(page = virt_to_page(pfr->ring_memory); page <= page_end; page++)
-+    SetPageReserved(page);
-+
-+  pfr->slots_info = (FlowSlotInfo*)pfr->ring_memory;
-+  pfr->ring_slots = (char*)(pfr->ring_memory+sizeof(FlowSlotInfo));
-+
-+  pfr->slots_info->version     = RING_FLOWSLOT_VERSION;
-+  pfr->slots_info->slot_len    = the_slot_len;
-+  pfr->slots_info->data_len    = bucket_len;
-+  pfr->slots_info->tot_slots   = (tot_mem-sizeof(FlowSlotInfo))/the_slot_len;
-+  pfr->slots_info->tot_mem     = tot_mem;
-+  pfr->slots_info->sample_rate = sample_rate;
-+
-+  printk("RING: allocated %d slots [slot_len=%d][tot_mem=%u]\n",
-+       pfr->slots_info->tot_slots, pfr->slots_info->slot_len,
-+       pfr->slots_info->tot_mem);
-+
-+#ifdef RING_MAGIC
-+  {
-+    int i;
-+
-+    for(i=0; i<pfr->slots_info->tot_slots; i++) {
-+      unsigned long idx = i*pfr->slots_info->slot_len;
-+      FlowSlot *slot = (FlowSlot*)&pfr->ring_slots[idx];
-+      slot->magic = RING_MAGIC_VALUE; slot->slot_state = 0;
-+    }
-+  }
-+#endif
-+
-+  pfr->insert_page_id = 1, pfr->insert_slot_id = 0;
-+
-+  /*
-+    IMPORTANT
-+    Leave this statement here as last one. In fact when
-+    the ring_netdev != NULL the socket is ready to be used.
-+  */
-+  pfr->ring_netdev = dev;
-+
-+  return(0);
-+}
-+
-+/* ************************************* */
-+
-+/* Bind to a device */
-+static int ring_bind(struct socket *sock,
-+                   struct sockaddr *sa, int addr_len)
-+{
-+  struct sock *sk=sock->sk;
-+  struct net_device *dev = NULL;
-+
-+#if defined(RING_DEBUG)
-+  printk("RING: ring_bind() called\n");
-+#endif
-+
-+  /*
-+   *  Check legality
-+   */
-+  if (addr_len != sizeof(struct sockaddr))
-+    return -EINVAL;
-+  if (sa->sa_family != PF_RING)
-+    return -EINVAL;
-+
-+  /* Safety check: add trailing zero if missing */
-+  sa->sa_data[sizeof(sa->sa_data)-1] = '\0';
-+
-+#if defined(RING_DEBUG)
-+  printk("RING: searching device %s\n", sa->sa_data);
-+#endif
-+
-+  if((dev = __dev_get_by_name(sa->sa_data)) == NULL) {
-+#if defined(RING_DEBUG)
-+    printk("RING: search failed\n");
-+#endif
-+    return(-EINVAL);
-+  } else
-+    return(packet_ring_bind(sk, dev));
-+}
-+
-+/* ************************************* */
-+
-+static int ring_mmap(struct file *file,
-+                   struct socket *sock,
-+                   struct vm_area_struct *vma)
-+{
-+  struct sock *sk = sock->sk;
-+  struct ring_opt *pfr = ring_sk(sk);
-+  unsigned long size, start;
-+  u_int pagesToMap;
-+  char *ptr;
-+
-+#if defined(RING_DEBUG)
-+  printk("RING: ring_mmap() called\n");
-+#endif
-+
-+  if(pfr->ring_memory == 0) {
-+#if defined(RING_DEBUG)
-+    printk("RING: ring_mmap() failed: mapping area to an unbound socket\n");
-+#endif
-+    return -EINVAL;
-+  }
-+
-+  size = (unsigned long)(vma->vm_end-vma->vm_start);
-+
-+  if(size % PAGE_SIZE) {
-+#if defined(RING_DEBUG)
-+    printk("RING: ring_mmap() failed: len is not multiple of PAGE_SIZE\n");
-+#endif
-+    return(-EINVAL);
-+  }
-+
-+  /* if userspace tries to mmap beyond end of our buffer, fail */
-+  if(size > pfr->slots_info->tot_mem) {
-+#if defined(RING_DEBUG)
-+    printk("proc_mmap() failed: area too large [%ld > %d]\n", size, pfr->slots_info->tot_mem);
-+#endif
-+    return(-EINVAL);
-+  }
-+
-+  pagesToMap = size/PAGE_SIZE;
-+
-+#if defined(RING_DEBUG)
-+  printk("RING: ring_mmap() called. %d pages to map\n", pagesToMap);
-+#endif
-+
-+#if defined(RING_DEBUG)
-+  printk("RING: mmap [slot_len=%d][tot_slots=%d] for ring on device %s\n",
-+       pfr->slots_info->slot_len, pfr->slots_info->tot_slots,
-+       pfr->ring_netdev->name);
-+#endif
-+
-+  /* we do not want to have this area swapped out, lock it */
-+  vma->vm_flags |= VM_LOCKED;
-+  start = vma->vm_start;
-+
-+  /* Ring slots start from page 1 (page 0 is reserved for FlowSlotInfo) */
-+  ptr = (char*)(start+PAGE_SIZE);
-+
-+  if(remap_page_range(
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
-+                    vma,
-+#endif
-+                    start,
-+                    __pa(pfr->ring_memory),
-+                    PAGE_SIZE*pagesToMap, vma->vm_page_prot)) {
-+#if defined(RING_DEBUG)
-+    printk("remap_page_range() failed\n");
-+#endif
-+    return(-EAGAIN);
-+  }
-+
-+#if defined(RING_DEBUG)
-+  printk("proc_mmap(pagesToMap=%d): success.\n", pagesToMap);
-+#endif
-+
-+  return 0;
-+}
-+
-+/* ************************************* */
-+
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
-+static int ring_recvmsg(struct kiocb *iocb, struct socket *sock,
-+                      struct msghdr *msg, size_t len, int flags)
-+#else
-+  static int ring_recvmsg(struct socket *sock, struct msghdr *msg, int len,
-+                        int flags, struct scm_cookie *scm)
-+#endif
-+{
-+  FlowSlot* slot;
-+  struct ring_opt *pfr = ring_sk(sock->sk);
-+  u_int32_t queued_pkts, num_loops = 0;
-+
-+#if defined(RING_DEBUG)
-+  printk("ring_recvmsg called\n");
-+#endif
-+
-+  slot = get_remove_slot(pfr);
-+
-+  while((queued_pkts = num_queued_pkts(pfr)) < MIN_QUEUED_PKTS) {
-+    wait_event_interruptible(pfr->ring_slots_waitqueue, 1);
-+
-+#if defined(RING_DEBUG)
-+    printk("-> ring_recvmsg returning %d [queued_pkts=%d][num_loops=%d]\n",
-+         slot->slot_state, queued_pkts, num_loops);
-+#endif
-+
-+    if(queued_pkts > 0) {
-+      if(num_loops++ > MAX_QUEUE_LOOPS)
-+      break;
-+    }
-+  }
-+
-+#if defined(RING_DEBUG)
-+  if(slot != NULL)
-+    printk("ring_recvmsg is returning [queued_pkts=%d][num_loops=%d]\n",
-+         queued_pkts, num_loops);
-+#endif
-+
-+  return(queued_pkts);
-+}
-+
-+/* ************************************* */
-+
-+unsigned int ring_poll(struct file * file,
-+                     struct socket *sock, poll_table *wait)
-+{
-+  FlowSlot* slot;
-+  struct ring_opt *pfr = ring_sk(sock->sk);
-+
-+#if defined(RING_DEBUG)
-+  printk("poll called\n");
-+#endif
-+
-+  slot = get_remove_slot(pfr);
-+
-+  if((slot != NULL) && (slot->slot_state == 0))
-+    poll_wait(file, &pfr->ring_slots_waitqueue, wait);
-+
-+#if defined(RING_DEBUG)
-+  printk("poll returning %d\n", slot->slot_state);
-+#endif
-+
-+  if((slot != NULL) && (slot->slot_state == 1))
-+    return(POLLIN | POLLRDNORM);
-+  else
-+    return(0);
-+}
-+
-+/* ************************************* */
-+
-+int add_to_cluster_list(struct ring_cluster *el,
-+                      struct sock *sock) {
-+
-+  if(el->num_cluster_elements == CLUSTER_LEN)
-+    return(-1); /* Cluster full */
-+
-+  ring_sk_datatype(ring_sk(sock))->cluster_id = el->cluster_id;
-+  el->sk[el->num_cluster_elements] = sock;
-+  el->num_cluster_elements++;
-+  return(0);
-+}
-+
-+/* ************************************* */
-+
-+int remove_from_cluster_list(struct ring_cluster *el,
-+                           struct sock *sock) {
-+  int i, j;
-+
-+  for(i=0; i<CLUSTER_LEN; i++)
-+    if(el->sk[i] == sock) {
-+      el->num_cluster_elements--;
-+
-+      if(el->num_cluster_elements > 0) {
-+      /* The cluster contains other elements */
-+      for(j=i; j<CLUSTER_LEN-1; j++)
-+        el->sk[j] = el->sk[j+1];
-+
-+      el->sk[CLUSTER_LEN-1] = NULL;
-+      } else {
-+      /* Empty cluster */
-+      memset(el->sk, 0, sizeof(el->sk));
-+      }
-+
-+      return(0);
-+    }
-+
-+  return(-1); /* Not found */
-+}
-+
-+/* ************************************* */
-+
-+static int remove_from_cluster(struct sock *sock,
-+                             struct ring_opt *pfr)
-+{
-+  struct ring_cluster *el;
-+
-+#if defined(RING_DEBUG)
-+  printk("--> remove_from_cluster(%d)\n", pfr->cluster_id);
-+#endif
-+
-+  if(pfr->cluster_id == 0 /* 0 = No Cluster */)
-+    return(0); /* Noting to do */
-+
-+  el = ring_cluster_list;
-+
-+  while(el != NULL) {
-+    if(el->cluster_id == pfr->cluster_id) {
-+      return(remove_from_cluster_list(el, sock));
-+    } else
-+      el = el->next;
-+  }
-+
-+  return(-EINVAL); /* Not found */
-+}
-+
-+/* ************************************* */
-+
-+static int add_to_cluster(struct sock *sock,
-+                        struct ring_opt *pfr,
-+                        u_short cluster_id)
-+{
-+  struct ring_cluster *el;
-+
-+#ifndef RING_DEBUG
-+  printk("--> add_to_cluster(%d)\n", cluster_id);
-+#endif
-+
-+  if(cluster_id == 0 /* 0 = No Cluster */) return(-EINVAL);
-+
-+  if(pfr->cluster_id != 0)
-+    remove_from_cluster(sock, pfr);
-+
-+  el = ring_cluster_list;
-+
-+  while(el != NULL) {
-+    if(el->cluster_id == cluster_id) {
-+      return(add_to_cluster_list(el, sock));
-+    } else
-+      el = el->next;
-+  }
-+
-+  /* There's no existing cluster. We need to create one */
-+  if((el = kmalloc(sizeof(struct ring_cluster), GFP_KERNEL)) == NULL)
-+    return(-ENOMEM);
-+
-+  el->cluster_id = cluster_id;
-+  el->num_cluster_elements = 1;
-+  el->hashing_mode = cluster_per_flow; /* Default */
-+  el->hashing_id   = 0;
-+
-+  memset(el->sk, 0, sizeof(el->sk));
-+  el->sk[0] = sock;
-+  el->next = ring_cluster_list;
-+  ring_cluster_list = el;
-+  pfr->cluster_id = cluster_id;
-+
-+  return(0); /* 0 = OK */
-+}
-+
-+/* ************************************* */
-+
-+/* Code taken/inspired from core/sock.c */
-+static int ring_setsockopt(struct socket *sock,
-+                         int level, int optname,
-+                         char *optval, int optlen)
-+{
-+  struct ring_opt *pfr = ring_sk(sock->sk);
-+  int val, found, ret = 0;
-+  u_int cluster_id;
-+  char devName[8];
-+
-+  if((optlen<sizeof(int)) || (pfr == NULL))
-+    return(-EINVAL);
-+
-+  if (get_user(val, (int *)optval))
-+    return -EFAULT;
-+
-+  found = 1;
-+
-+  switch(optname)
-+    {
-+    case SO_ATTACH_FILTER:
-+      ret = -EINVAL;
-+      if (optlen == sizeof(struct sock_fprog)) {
-+      unsigned int fsize;
-+      struct sock_fprog fprog;
-+      struct sk_filter *filter;
-+
-+      ret = -EFAULT;
-+
-+      /*
-+        NOTE
-+
-+        Do not call copy_from_user within a held
-+        splinlock (e.g. ring_mgmt_lock) as this caused
-+        problems when certain debugging was enabled under
-+        2.6.5 -- including hard lockups of the machine.
-+      */
-+      if(copy_from_user(&fprog, optval, sizeof(fprog)))
-+        break;
-+
-+      fsize = sizeof(struct sock_filter) * fprog.len;
-+      filter = kmalloc(fsize, GFP_KERNEL);
-+
-+      if(filter == NULL) {
-+        ret = -ENOMEM;
-+        break;
-+      }
-+
-+      if(copy_from_user(filter->insns, fprog.filter, fsize))
-+        break;
-+
-+      filter->len = fprog.len;
-+
-+      if(sk_chk_filter(filter->insns, filter->len) != 0) {
-+        /* Bad filter specified */
-+        kfree(filter);
-+        pfr->bpfFilter = NULL;
-+        break;
-+      }
-+
-+      /* get the lock, set the filter, release the lock */
-+      write_lock(&ring_mgmt_lock);
-+      pfr->bpfFilter = filter;
-+      write_unlock(&ring_mgmt_lock);
-+      }
-+      ret = 0;
-+      break;
-+
-+    case SO_DETACH_FILTER:
-+      write_lock(&ring_mgmt_lock);
-+      found = 1;
-+      if(pfr->bpfFilter != NULL) {
-+      kfree(pfr->bpfFilter);
-+      pfr->bpfFilter = NULL;
-+      write_unlock(&ring_mgmt_lock);
-+      break;
-+      }
-+      ret = -ENONET;
-+      break;
-+
-+    case SO_ADD_TO_CLUSTER:
-+      if (optlen!=sizeof(val))
-+      return -EINVAL;
-+
-+      if (copy_from_user(&cluster_id, optval, sizeof(cluster_id)))
-+      return -EFAULT;
-+
-+      write_lock(&ring_mgmt_lock);
-+      ret = add_to_cluster(sock->sk, pfr, cluster_id);
-+      write_unlock(&ring_mgmt_lock);
-+      break;
-+
-+    case SO_REMOVE_FROM_CLUSTER:
-+      write_lock(&ring_mgmt_lock);
-+      ret = remove_from_cluster(sock->sk, pfr);
-+      write_unlock(&ring_mgmt_lock);
-+      break;
-+
-+    case SO_SET_REFLECTOR:
-+      if(optlen >= (sizeof(devName)-1))
-+      return -EINVAL;
-+
-+      if(optlen > 0) {
-+      if(copy_from_user(devName, optval, optlen))
-+        return -EFAULT;
-+      }
-+
-+      devName[optlen] = '\0';
-+
-+#if defined(RING_DEBUG)
-+      printk("+++ SO_SET_REFLECTOR(%s)\n", devName);
-+#endif
-+
-+      write_lock(&ring_mgmt_lock);
-+      pfr->reflector_dev = dev_get_by_name(devName);
-+      write_unlock(&ring_mgmt_lock);
-+
-+#if defined(RING_DEBUG)
-+      if(pfr->reflector_dev != NULL)
-+      printk("SO_SET_REFLECTOR(%s): succeded\n", devName);
-+      else
-+      printk("SO_SET_REFLECTOR(%s): device unknown\n", devName);
-+#endif
-+      break;
-+
-+    default:
-+      found = 0;
-+      break;
-+    }
-+
-+  if(found)
-+    return(ret);
-+  else
-+    return(sock_setsockopt(sock, level, optname, optval, optlen));
-+}
-+
-+/* ************************************* */
-+
-+static int ring_ioctl(struct socket *sock,
-+                    unsigned int cmd, unsigned long arg)
-+{
-+  switch(cmd)
-+    {
-+    case SIOCGIFFLAGS:
-+    case SIOCSIFFLAGS:
-+    case SIOCGIFCONF:
-+    case SIOCGIFMETRIC:
-+    case SIOCSIFMETRIC:
-+    case SIOCGIFMEM:
-+    case SIOCSIFMEM:
-+    case SIOCGIFMTU:
-+    case SIOCSIFMTU:
-+    case SIOCSIFLINK:
-+    case SIOCGIFHWADDR:
-+    case SIOCSIFHWADDR:
-+    case SIOCSIFMAP:
-+    case SIOCGIFMAP:
-+    case SIOCSIFSLAVE:
-+    case SIOCGIFSLAVE:
-+    case SIOCGIFINDEX:
-+    case SIOCGIFNAME:
-+    case SIOCGIFCOUNT:
-+    case SIOCSIFHWBROADCAST:
-+      return(dev_ioctl(cmd,(void *) arg));
-+
-+    default:
-+      return -EOPNOTSUPP;
-+    }
-+
-+  return 0;
-+}
-+
-+/* ************************************* */
-+
-+static struct proto_ops ring_ops = {
-+  .family     =       PF_RING,
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
-+  .owner      =       THIS_MODULE,
-+#endif
-+
-+  /* Operations that make no sense on ring sockets. */
-+  .connect    =       sock_no_connect,
-+  .socketpair =       sock_no_socketpair,
-+  .accept     =       sock_no_accept,
-+  .getname    =       sock_no_getname,
-+  .listen     =       sock_no_listen,
-+  .shutdown   =       sock_no_shutdown,
-+  .sendpage   =       sock_no_sendpage,
-+  .sendmsg    =       sock_no_sendmsg,
-+  .getsockopt =       sock_no_getsockopt,
-+
-+  /* Now the operations that really occur. */
-+  .release    =       ring_release,
-+  .bind               =       ring_bind,
-+  .mmap               =       ring_mmap,
-+  .poll               =       ring_poll,
-+  .setsockopt =       ring_setsockopt,
-+  .ioctl      =       ring_ioctl,
-+  .recvmsg    =       ring_recvmsg,
-+};
-+
-+/* ************************************ */
-+
-+static struct net_proto_family ring_family_ops = {
-+  .family     =       PF_RING,
-+  .create     =       ring_create,
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
-+  .owner      =       THIS_MODULE,
-+#endif
-+};
-+
-+// BD: API changed in 2.6.12, ref:
-+// http://svn.clkao.org/svnweb/linux/revision/?rev=28201
-+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,11))
-+static struct proto ring_proto = {
-+  .name               =       "PF_RING",
-+  .owner      =       THIS_MODULE,
-+  .obj_size   =       sizeof(struct sock),
-+};
-+#endif
-+
-+/* ************************************ */
-+
-+static void __exit ring_exit(void)
-+{
-+  struct list_head *ptr;
-+  struct ring_element *entry;
-+
-+  for(ptr = ring_table.next; ptr != &ring_table; ptr = ptr->next) {
-+    entry = list_entry(ptr, struct ring_element, list);
-+    kfree(entry);
-+  }
-+
-+  while(ring_cluster_list != NULL) {
-+    struct ring_cluster *next = ring_cluster_list->next;
-+    kfree(ring_cluster_list);
-+    ring_cluster_list = next;
-+  }
-+
-+  set_skb_ring_handler(NULL);
-+  set_buffer_ring_handler(NULL);
-+  sock_unregister(PF_RING);
-+
-+  printk("PF_RING shut down.\n");
-+}
-+
-+/* ************************************ */
-+
-+static int __init ring_init(void)
-+{
-+  printk("Welcome to PF_RING %s\n(C) 2004-05 L.Deri <deri@ntop.org>\n",
-+       RING_VERSION);
-+
-+  INIT_LIST_HEAD(&ring_table);
-+  ring_cluster_list = NULL;
-+
-+  sock_register(&ring_family_ops);
-+
-+  set_skb_ring_handler(skb_ring_handler);
-+  set_buffer_ring_handler(buffer_ring_handler);
-+
-+  if(get_buffer_ring_handler() != buffer_ring_handler) {
-+    printk("PF_RING: set_buffer_ring_handler FAILED\n");
-+
-+    set_skb_ring_handler(NULL);
-+    set_buffer_ring_handler(NULL);
-+    sock_unregister(PF_RING);
-+    return -1;
-+  } else {
-+    printk("PF_RING: bucket length    %d bytes\n", bucket_len);
-+    printk("PF_RING: ring slots       %d\n", num_slots);
-+    printk("PF_RING: sample rate      %d [1=no sampling]\n", sample_rate);
-+    printk("PF_RING: capture TX       %s\n",
-+         enable_tx_capture ? "Yes [RX+TX]" : "No [RX only]");
-+    printk("PF_RING: transparent mode %s\n",
-+         transparent_mode ? "Yes" : "No");
-+
-+    printk("PF_RING initialized correctly.\n");
-+    return 0;
-+  }
-+}
-+
-+module_init(ring_init);
-+module_exit(ring_exit);
-+MODULE_LICENSE("GPL");
-+
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
-+MODULE_ALIAS_NETPROTO(PF_RING);
-+#endif