@@ -1,6 +1,6 @@
/* ***************************************************************
*
- * (C) 2004-10 - Luca Deri <deri@ntop.org>
+ * (C) 2004-11 - Luca Deri <deri@ntop.org>
*
* This code includes contributions courtesy of
* - Amit D. Chaudhary <amit_ml@rajgad.com>
@@ -35,6 +35,11 @@
* - Dan Kruchinin <dkruchinin@acm.org>
* - Andreas Tsopelas <tsopelas@kth.se>
* - Alfredo Cardigliano <cardigliano@ntop.org>
+ * - Alex Aronson <alexa@silicom.co.il>
+ * - Piotr Romanus <promanus@crossbeamsys.com>
+ * - Lior Okman <lior.okman@insightix.com>
+ * - Fedor Sakharov <fedor.sakharov@gmail.com>
+ * - Daniel Christopher <Chris.Daniel@visualnetworksystems.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -53,6 +58,13 @@
*/
#include <linux/version.h>
+
+#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18))
+#error **********************************************************************
+#error * PF_RING works on kernel 2.6.18 or newer. Please update your kernel *
+#error **********************************************************************
+#endif
+
#if(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18))
#if(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
#include <generated/autoconf.h>
@@ -91,9 +103,12 @@
#include <net/ip.h>
#include <net/ipv6.h>
-#include <linux/pf_ring.h>
+#if(LINUX_VERSION_CODE > KERNEL_VERSION(2,6,30))
+#include <linux/eventfd.h>
+#define VPFRING_SUPPORT
+#endif
-/* #define RING_DEBUG */
+#include <linux/pf_ring.h>
#ifndef SVN_REV
#define SVN_REV ""
@@ -122,8 +137,7 @@
static u_int8_t pfring_enabled = 0;
/* Dummy 'any' device */
-static struct net_device any_dev, none_dev;
-
+static ring_device_element any_device_element, none_device_element;
/* List of all ring sockets. */
static struct list_head ring_table;
@@ -140,13 +154,22 @@
*/
static struct list_head device_ring_list[MAX_NUM_DEVICES];
+/* List of virtual filtering devices */
+static struct list_head virtual_filtering_devices_list;
+static rwlock_t virtual_filtering_lock = RW_LOCK_UNLOCKED;
+
/* List of all clusters */
static struct list_head ring_cluster_list;
/* List of all devices on which PF_RING has been registered */
-static struct list_head ring_aware_device_list;
+static struct list_head ring_aware_device_list; /* List of ring_device_element */
-/* List of all dna (direct nic access) devices */
+/* Keep track of number of rings per device (plus any) */
+static u_int8_t num_rings_per_device[MAX_NUM_IFIDX] = { 0 };
+static struct pf_ring_socket* device_rings[MAX_NUM_IFIDX][MAX_NUM_RX_CHANNELS] = { { NULL } };
+static u_int8_t num_any_rings = 0;
+
+/* List of all DNA (direct nic access) devices */
static struct list_head ring_dna_devices_list;
static u_int dna_devices_list_size = 0;
@@ -154,7 +177,10 @@
static u_int plugin_registration_size = 0;
static struct pfring_plugin_registration *plugin_registration[MAX_PLUGIN_ID] = { NULL };
static u_short max_registered_plugin_id = 0;
-static rwlock_t ring_mgmt_lock = RW_LOCK_UNLOCKED;
+
+/* Dumy buffer used for loopback_test */
+u_int32_t loobpack_test_buffer_len = 4*1024*1024;
+u_char *loobpack_test_buffer = NULL;
/* ********************************** */
@@ -166,15 +192,65 @@
static int ring_proc_get_info(char *, char **, off_t, int, int *, void *);
static int ring_proc_get_plugin_info(char *, char **, off_t, int, int *,
void *);
-static void ring_proc_add(struct ring_opt *pfr);
-static void ring_proc_remove(struct ring_opt *pfr);
+static void ring_proc_add(struct pf_ring_socket *pfr);
+static void ring_proc_remove(struct pf_ring_socket *pfr);
static void ring_proc_init(void);
static void ring_proc_term(void);
static int reflect_packet(struct sk_buff *skb,
- struct ring_opt *pfr,
+ struct pf_ring_socket *pfr,
struct net_device *reflector_dev,
- int displ);
+ int displ, rule_action_behaviour behaviour);
+
+/* ********************************** */
+
+#if 1
+
+static rwlock_t ring_mgmt_lock;
+
+inline void init_ring_readers(void) { ring_mgmt_lock = RW_LOCK_UNLOCKED; }
+inline void ring_write_lock(void) { write_lock_bh(&ring_mgmt_lock); }
+inline void ring_write_unlock(void) { write_unlock_bh(&ring_mgmt_lock); }
+/* use ring_read_lock/ring_read_unlock in process context (a bottom half may use write_lock) */
+inline void ring_read_lock(void) { read_lock_bh(&ring_mgmt_lock); }
+inline void ring_read_unlock(void) { read_unlock_bh(&ring_mgmt_lock); }
+/* use ring_read_lock_inbh/ring_read_unlock_inbh in bottom half contex */
+inline void ring_read_lock_inbh(void) { read_lock(&ring_mgmt_lock); }
+inline void ring_read_unlock_inbh(void) { read_unlock(&ring_mgmt_lock); }
+
+#else
+
+static atomic_t num_ring_readers, ring_stop;
+
+/* Do NOT call schedule() as this might cause crash when exiting */
+
+inline void init_ring_readers(void) {
+ atomic_set(&num_ring_readers, 0);
+ atomic_set(&ring_stop, 0);
+}
+
+inline void ring_write_lock(void) {
+ atomic_set(&ring_stop, 1);
+
+ while(atomic_read(&num_ring_readers) > 0) { /* schedule() */; }
+}
+
+inline void ring_write_unlock(void) {
+ atomic_set(&ring_stop, 0);
+}
+
+inline void ring_read_lock(void) {
+ while(atomic_read(&ring_stop) == 1) { /* schedule() */; }
+ atomic_inc(&num_ring_readers);
+}
+
+inline void ring_read_unlock(void) {
+ atomic_dec(&num_ring_readers);
+}
+
+#endif
+
+/* ********************************** */
/*
Caveat
@@ -204,16 +280,17 @@
/* Forward */
static struct proto_ops ring_ops;
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,11))
+#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,
- u_int8_t channel_id,
- u_int8_t num_rx_channels);
+ u_int32_t channel_id, u_int32_t num_rx_channels);
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);
+static int remove_from_cluster(struct sock *sock, struct pf_ring_socket *pfr);
+static int ring_map_dna_device(struct pf_ring_socket *pfr,
+ dna_device_mapping * mapping);
/* Extern */
extern
@@ -230,6 +307,8 @@
static unsigned int min_num_slots = 4096;
static unsigned int enable_tx_capture = 1;
static unsigned int enable_ip_defrag = 0;
+static unsigned int quick_mode = 0;
+static unsigned int enable_debug = 0;
static unsigned int transparent_mode = standard_linux_path;
static u_int32_t ring_id_serial = 0;
@@ -239,44 +318,64 @@
#endif
#endif
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)) || defined(REDHAT_PATCHED_KERNEL)
+#if(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)) || defined(REDHAT_PATCHED_KERNEL)
module_param(min_num_slots, uint, 0644);
module_param(transparent_mode, uint, 0644);
+module_param(enable_debug, uint, 0644);
module_param(enable_tx_capture, uint, 0644);
module_param(enable_ip_defrag, uint, 0644);
+module_param(quick_mode, uint, 0644);
#else
MODULE_PARM(min_num_slots, "i");
MODULE_PARM(transparent_mode, "i");
+MODULE_PARM(enable_debug, "i");
MODULE_PARM(enable_tx_capture, "i");
MODULE_PARM(enable_ip_defrag, "i");
+MODULE_PARM(quick_mode, "i");
#endif
MODULE_PARM_DESC(min_num_slots, "Min number of ring slots");
MODULE_PARM_DESC(transparent_mode,
"0=standard Linux, 1=direct2pfring+transparent, 2=direct2pfring+non transparent"
"For 1 and 2 you need to use a PF_RING aware driver");
+MODULE_PARM_DESC(enable_debug, "Set to 1 to enable PF_RING debug tracing into the syslog");
MODULE_PARM_DESC(enable_tx_capture, "Set to 1 to capture outgoing packets");
MODULE_PARM_DESC(enable_ip_defrag,
"Set to 1 to enable IP defragmentation"
"(only rx traffic is defragmentead)");
+MODULE_PARM_DESC(quick_mode,
+ "Set to 1 to run at full speed but with up"
+ "to one socket per interface");
/* ********************************** */
#define MIN_QUEUED_PKTS 64
#define MAX_QUEUE_LOOPS 64
-#define ring_sk_datatype(__sk) ((struct ring_opt *)__sk)
+#define ring_sk_datatype(__sk) ((struct pf_ring_socket *)__sk)
#define ring_sk(__sk) ((__sk)->sk_protinfo)
#define _rdtsc() ({ uint64_t x; asm volatile("rdtsc" : "=A" (x)); x; })
/* ***************** Legacy code ************************ */
+u_int get_num_rx_queues(struct net_device *dev) {
+#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
+ return(1);
+#else
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) && defined(CONFIG_RPS)
+ return(dev->real_num_rx_queues);
+#else
+ return(dev->real_num_tx_queues);
+#endif
+#endif
+}
+
#if defined(RHEL_MAJOR) && (RHEL_MAJOR == 5) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18))
/* Redhat backports these functions to 2.6.18 so do nothing */
#else
-#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
+#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23))
static inline void skb_reset_network_header(struct sk_buff *skb) {
/* skb->network_header = skb->data - skb->head; */
}
@@ -290,21 +389,16 @@
/* skb->network_header += offset; */
}
-static inline void skb_copy_to_linear_data(struct sk_buff *skb,
- const void *from,
- const unsigned int len) {
- memcpy(skb->data, from, len);
-}
#endif /* KERNEL_VERSION */
#endif /* RH_MAJOR */
-#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16))
+#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)) || (defined(RHEL_MAJOR) && (RHEL_MAJOR == 5) && (RHEL_MINOR < 2))
static inline struct iphdr *ip_hdr(const struct sk_buff *skb)
{
return(struct iphdr *)skb->nh.iph;
}
-#ifndef REDHAT_PATCHED_KERNEL
+#if(!defined(REDHAT_PATCHED_KERNEL)) || ((RHEL_MAJOR == 5) && (RHEL_MINOR < 2))
static inline void skb_set_network_header(struct sk_buff *skb, const int offset)
{
skb->nh.iph = (struct iphdr *)skb->data + offset;
@@ -324,11 +418,11 @@
/* ************************************************** */
-static inline char* get_slot(struct ring_opt *pfr, u_int32_t off) { return(&(pfr->ring_slots[off])); }
+static inline char* get_slot(struct pf_ring_socket *pfr, u_int32_t off) { return(&(pfr->ring_slots[off])); }
/* ********************************** */
-static inline int get_next_slot_offset(struct ring_opt *pfr, u_int32_t off, u_int32_t *real_off)
+static inline int get_next_slot_offset(struct pf_ring_socket *pfr, u_int32_t off, u_int32_t *real_off)
{
struct pfring_pkthdr *hdr;
u_int32_t real_slot_size;
@@ -336,9 +430,13 @@
// smp_rmb();
hdr = (struct pfring_pkthdr*)get_slot(pfr, off);
- real_slot_size = pfr->slot_header_len + hdr->extended_hdr.parsed_header_len + hdr->caplen;
- if((off + real_slot_size + pfr->slots_info->slot_len) > (pfr->slots_info->tot_mem - sizeof(FlowSlotInfo))){
+ real_slot_size = pfr->slot_header_len + hdr->caplen;
+
+ if(!quick_mode)
+ real_slot_size += hdr->extended_hdr.parsed_header_len;
+
+ if((off + real_slot_size + pfr->slots_info->slot_len) > (pfr->slots_info->tot_mem - sizeof(FlowSlotInfo))) {
*real_off = pfr->slots_info->tot_mem - sizeof(FlowSlotInfo) - off;
return 0;
}
@@ -349,7 +447,7 @@
/* ********************************** */
-static inline u_int32_t num_queued_pkts(struct ring_opt *pfr)
+static inline u_int32_t num_queued_pkts(struct pf_ring_socket *pfr)
{
// smp_rmb();
@@ -362,20 +460,20 @@
return(((u_int32_t) - 1) + tot_insert - tot_read);
}
-#if defined(RING_DEBUG)
- printk("[PF_RING] -> [tot_insert=%d][tot_read=%d]\n",
- tot_insert, tot_read);
-#endif
+ if(enable_debug) {
+ printk("[PF_RING] -> [tot_insert=%d][tot_read=%d]\n",
+ tot_insert, tot_read);
+ }
} else
return(0);
}
/* ************************************* */
-inline u_int get_num_ring_free_slots(struct ring_opt * pfr)
+inline u_int get_num_ring_free_slots(struct pf_ring_socket * pfr)
{
u_int32_t nqpkts = num_queued_pkts(pfr);
-
+
if(nqpkts < (pfr->slots_info->min_num_slots))
return(pfr->slots_info->min_num_slots - nqpkts);
else
@@ -384,7 +482,7 @@
/* ********************************** */
-static inline int check_and_init_free_slot(struct ring_opt *pfr, int off)
+static inline int check_and_init_free_slot(struct pf_ring_socket *pfr, int off)
{
// smp_rmb();
@@ -393,20 +491,31 @@
Both insert and remove offset are set on the same slot.
We need to find out whether the memory is full or empty
*/
-
+
if(num_queued_pkts(pfr) >= min_num_slots)
return(0); /* Memory is full */
} else {
/* There are packets in the ring. We have to check whether we have enough to accommodate a new packet */
if(pfr->slots_info->insert_off < pfr->slots_info->remove_off) {
- if((pfr->slots_info->remove_off - pfr->slots_info->insert_off) < pfr->slots_info->slot_len)
+
+#if 1 /* Zero-copy recv: this prevents from overwriting packets while apps are processing them */
+ if((pfr->slots_info->remove_off - pfr->slots_info->insert_off) < (2 * pfr->slots_info->slot_len))
+#else
+ if((pfr->slots_info->remove_off - pfr->slots_info->insert_off) < pfr->slots_info->slot_len )
+#endif
return(0);
} else {
/* We have enough room for the incoming packet as after we insert a packet, the insert_off
offset is wrapped to the beginning in case the space remaining is less than slot_len
(i.e. the memory needed to accommodate a packet)
*/
+
+#if 1 /* Zero-copy recv: this prevents from overwriting packets while apps are processing them */
+ if ((pfr->slots_info->tot_mem - sizeof(FlowSlotInfo) - pfr->slots_info->insert_off) < (2 * pfr->slots_info->slot_len) &&
+ pfr->slots_info->remove_off == 0)
+ return(0);
+#endif
}
}
@@ -421,16 +530,22 @@
static struct sk_buff *ring_gather_frags(struct sk_buff *skb)
{
#if(LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23))
- skb = ip_defrag(skb, IP_DEFRAG_RING);
+ skb
+#else
+ int status
+#endif
+ = ip_defrag(skb, IP_DEFRAG_RING);
- if(skb)
- ip_send_check(ip_hdr(skb));
+ if(
+#if(LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23))
+ skb == NULL
#else
- if(ip_defrag(skb, IP_DEFRAG_RING))
+ status
+#endif
+ )
skb = NULL;
else
ip_send_check(ip_hdr(skb));
-#endif
return(skb);
}
@@ -439,15 +554,14 @@
static void ring_sock_destruct(struct sock *sk)
{
- struct ring_opt *pfr;
+ struct pf_ring_socket *pfr;
skb_queue_purge(&sk->sk_receive_queue);
if(!sock_flag(sk, SOCK_DEAD)) {
-#if defined(RING_DEBUG)
- printk("[PF_RING] Attempt to release alive ring socket: %p\n",
- sk);
-#endif
+ if(enable_debug) {
+ printk("[PF_RING] Attempt to release alive ring socket: %p\n", sk);
+ }
return;
}
@@ -459,42 +573,37 @@
/* ********************************** */
-static void ring_proc_add(struct ring_opt *pfr)
+static void ring_proc_add(struct pf_ring_socket *pfr)
{
- int debug = 0;
+ if((ring_proc_dir != NULL)
+ && (pfr->sock_proc_name[0] == '\0')) {
+ snprintf(pfr->sock_proc_name, sizeof(pfr->sock_proc_name),
+ "%d-%s.%d", pfr->ring_pid,
+ pfr->ring_netdev->dev->name, pfr->ring_id);
- if(ring_proc_dir != NULL) {
- char name[64];
-
- snprintf(name, sizeof(name), "%d-%s.%d", pfr->ring_pid,
- pfr->ring_netdev->name, pfr->ring_id);
-
- create_proc_read_entry(name, 0 /* read-only */,
+ create_proc_read_entry(pfr->sock_proc_name, 0 /* read-only */,
ring_proc_dir,
ring_proc_get_info, pfr);
- if(debug) printk("[PF_RING] Added /proc/net/pf_ring/%s\n", name);
+ printk("[PF_RING] Added /proc/net/pf_ring/%s\n",
+ pfr->sock_proc_name);
}
}
/* ********************************** */
-static void ring_proc_remove(struct ring_opt *pfr)
+static void ring_proc_remove(struct pf_ring_socket *pfr)
{
- int debug = 0;
-
- if(ring_proc_dir != NULL) {
- char name[64];
-
- snprintf(name, sizeof(name), "%d-%s.%d",
- pfr->ring_pid, pfr->ring_netdev->name,
- pfr->ring_id);
+ if((ring_proc_dir != NULL)
+ && (pfr->sock_proc_name[0] != '\0')) {
+ printk("[PF_RING] Removing /proc/net/pf_ring/%s\n", pfr->sock_proc_name);
- printk("[PF_RING] Removing /proc/net/pf_ring/%s\n", name);
+ remove_proc_entry(pfr->sock_proc_name, ring_proc_dir);
- remove_proc_entry(name, ring_proc_dir);
+ if(enable_debug)
+ printk("[PF_RING] Removed /proc/net/pf_ring/%s\n", pfr->sock_proc_name);
- if(debug) printk("[PF_RING] Removed /proc/net/pf_ring/%s\n", name);
+ pfr->sock_proc_name[0] = '\0';
}
}
@@ -508,10 +617,30 @@
if(data != NULL) {
ring_device_element *dev_ptr = (ring_device_element*)data;
struct net_device *dev = dev_ptr->dev;
- char dev_buf[16] = { 0 };
+ char dev_buf[16] = { 0 }, *dev_family = "???";
+
+ if(dev_ptr->is_dna_device) {
+ switch(dev_ptr->dna_device_model) {
+ case intel_e1000e:
+ dev_family = "Intel e1000e"; break;
+ case intel_igb:
+ dev_family = "Intel igb"; break;
+ break;
+ case intel_ixgbe:
+ dev_family = "Intel ixgbe"; break;
+ break;
+ }
+ } else {
+ switch(dev_ptr->device_type) {
+ case standard_nic_family: dev_family = "Standard NIC"; break;
+ case intel_82599_family: dev_family = "Intel 82599"; break;
+ case silicom_redirector_family: dev_family = "Silicom Redirector"; break;
+ }
+ }
rlen = sprintf(buf, "Name: %s\n", dev->name);
rlen += sprintf(buf+rlen, "Index: %d\n", dev->ifindex);
+ rlen += sprintf(buf+rlen, "Polling Mode: %s\n", dev_ptr->is_dna_device ? "DNA" : "NAPI/TNAPI");
switch(dev->type) {
case 1: strcpy(dev_buf, "Ethernet"); break;
@@ -520,47 +649,87 @@
}
rlen += sprintf(buf+rlen, "Type: %s\n", dev_buf);
+ rlen += sprintf(buf+rlen, "Family: %s\n", dev_family);
+
+ if(!dev_ptr->is_dna_device) {
+ if(dev->ifindex < MAX_NUM_IFIDX) {
+ rlen += sprintf(buf+rlen, "# bound sockets: %d\n",
+ num_rings_per_device[dev->ifindex]);
+ }
+ }
+
#if(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31))
rlen += sprintf(buf+rlen, "Max # TX Queues: %d\n", dev->num_tx_queues);
- rlen += sprintf(buf+rlen, "# Used TX Queues: %d\n", dev->real_num_tx_queues);
#endif
+
+ rlen += sprintf(buf+rlen, "# Used RX Queues: %d\n",
+ dev_ptr->is_dna_device ? dev_ptr->num_dna_rx_queues : get_num_rx_queues(dev));
}
return rlen;
}
-/* ************************************* */
+/* **************** 82599 ****************** */
-int handle_hw_filtering_rule(struct net_device *dev, hw_filtering_rule *rule,
- u_int8_t add_rule) {
+static int i82599_generic_handler(struct pf_ring_socket *pfr,
+ hw_filtering_rule *rule, hw_filtering_rule_command request) {
#if(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31))
- int debug = 0;
- struct ethtool_eeprom eeprom; /* Used to to the magic [MAGIC_HW_FILTERING_RULE_ELEMENT] */
- hw_filtering_rule_element element;
+ struct net_device *dev = pfr->ring_netdev->dev;
+ struct ethtool_eeprom eeprom; /* Used to to the magic [MAGIC_HW_FILTERING_RULE_REQUEST] */
if(dev == NULL) return(-1);
if((dev->ethtool_ops == NULL) || (dev->ethtool_ops->set_eeprom == NULL)) return(-1);
- if(debug) printk("[PF_RING] hw_filtering_rule[%s][add=%d][id=%d][%p]\n",
- dev->name, add_rule ? 1 : 0, rule->rule_id,
- dev->ethtool_ops->set_eeprom);
-
- memset(&element, 0, sizeof(element));
- eeprom.len = 0, eeprom.magic = MAGIC_HW_FILTERING_RULE_ELEMENT;
-
- element.command = RULE_COMMAND;
- element.add_rule = add_rule;
- memcpy(&element.rule, rule, sizeof(hw_filtering_rule));
+ if(enable_debug) printk("[PF_RING] hw_filtering_rule[%s][request=%d][%p]\n",
+ dev->name, request, dev->ethtool_ops->set_eeprom);
- return(dev->ethtool_ops->set_eeprom(dev, &eeprom, (u8*)&element));
+ eeprom.len = 1 /* add/remove (no check) */,
+ eeprom.magic = MAGIC_HW_FILTERING_RULE_REQUEST, eeprom.offset = request;
+
+ return(dev->ethtool_ops->set_eeprom(dev, &eeprom, (u8*)rule));
#else
return(-1);
#endif
}
-/* ********************************** */
+/* ************************************* */
+
+static int handle_hw_filtering_rule(struct pf_ring_socket *pfr,
+ hw_filtering_rule *rule,
+ hw_filtering_rule_command command) {
+
+ printk("[PF_RING] --> handle_hw_filtering_rule(command=%d)\n", command);
+
+ switch(rule->rule_family_type) {
+ case intel_82599_five_tuple_rule:
+ if(pfr->ring_netdev->hw_filters.filter_handlers.five_tuple_handler == NULL)
+ return(-EINVAL);
+ else
+ return(i82599_generic_handler(pfr, rule, command));
+ break;
+
+ case intel_82599_perfect_filter_rule:
+ if(pfr->ring_netdev->hw_filters.filter_handlers.perfect_filter_handler == NULL)
+ return(-EINVAL);
+ else
+ return(i82599_generic_handler(pfr, rule, command));
+ break;
+
+ case silicom_redirector_rule:
+ if(pfr->ring_netdev->hw_filters.filter_handlers.redirector_rule_handler == NULL)
+ return(-EINVAL);
+ else
+ return(pfr->ring_netdev->hw_filters.filter_handlers.redirector_rule_handler(pfr, rule, command));
+ break;
+ }
+
+ return(-EINVAL);
+}
+/* ***************************************** */
+
+#ifdef ENABLE_PROC_WRITE_RULE
#if(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31))
static int ring_proc_dev_rule_read(char *buf, char **start, off_t offset,
int len, int *unused, void *data)
@@ -572,68 +741,68 @@
struct net_device *dev = dev_ptr->dev;
rlen = sprintf(buf, "Name: %s\n", dev->name);
- rlen += sprintf(buf+rlen, "# Filters: %d\n", dev_ptr->num_hw_filters);
+ rlen += sprintf(buf+rlen, "# Filters: %d\n", dev_ptr->hw_filters.num_filters);
rlen += sprintf(buf+rlen, "\nFiltering Rules:\n"
- "[perfect rule] +|-(rule_id,queue_id,vlan,tcp|udp|any,src_ip/mask,src_port,dst_ip/mask,dst_port)\n"
+ "[perfect rule] +|-(rule_id,queue_id,vlan,tcp|udp,src_ip/mask,src_port,dst_ip/mask,dst_port)\n"
"Example:\t+(1,-1,0,tcp,192.168.0.10/32,25,10.6.0.0/16,0) (queue_id = -1 => drop)\n\n"
- "[5 tuple rule] +|-(rule_id,queue_id,tcp|udp|any,src_ip,src_port,dst_ip,dst_port)\n"
+ "[5 tuple rule] +|-(rule_id,queue_id,tcp|udp,src_ip,src_port,dst_ip,dst_port)\n"
"Example:\t+(1,-1,tcp,192.168.0.10,25,0.0.0.0,0)\n\n"
"Note:\n\t- queue_id = -1 => drop\n\t- 0 = ignore value\n");
}
return rlen;
}
+#endif
/* ********************************** */
-static void init_five_tuple_filter_hw_rule(u_int8_t queue_id, u_int16_t rule_id,
- u_int8_t proto,
- u_int32_t s_addr, u_int32_t d_addr,
- u_int16_t s_port, u_int16_t d_port,
- hw_filtering_rule *rule) {
+#ifdef ENABLE_PROC_WRITE_RULE
+static void init_intel_82599_five_tuple_filter_hw_rule(u_int8_t queue_id, u_int8_t proto,
+ u_int32_t s_addr, u_int32_t d_addr,
+ u_int16_t s_port, u_int16_t d_port,
+ intel_82599_five_tuple_filter_hw_rule *rule) {
- /* printk("init_five_tuple_filter_hw_rule()\n"); */
+ /* printk("init_intel_82599_five_tuple_filter_hw_rule()\n"); */
- memset(rule, 0, sizeof(hw_filtering_rule));
+ memset(rule, 0, sizeof(intel_82599_five_tuple_filter_hw_rule));
- rule->rule_type = five_tuple_rule, rule->rule_id = rule_id, rule->queue_id = queue_id;
- rule->rule.five_tuple_rule.proto = proto;
- rule->rule.five_tuple_rule.s_addr = s_addr, rule->rule.five_tuple_rule.d_addr = d_addr;
- rule->rule.five_tuple_rule.s_port = s_port, rule->rule.five_tuple_rule.d_port = d_port;
+ rule->queue_id = queue_id, rule->proto = proto;
+ rule->s_addr = s_addr, rule->d_addr = d_addr;
+ rule->s_port = s_port, rule->d_port = d_port;
}
/* ********************************** */
-static void init_perfect_filter_hw_rule(u_int8_t queue_id, u_int16_t rule_id,
- u_int8_t proto,
- u_int16_t vlan,
- u_int32_t s_addr, u_int8_t s_mask,
- u_int32_t d_addr, u_int8_t d_mask,
- u_int16_t s_port, u_int16_t d_port,
- hw_filtering_rule *rule) {
+static void init_intel_82599_perfect_filter_hw_rule(u_int8_t queue_id,
+ u_int8_t proto, u_int16_t vlan,
+ u_int32_t s_addr, u_int8_t s_mask,
+ u_int32_t d_addr, u_int8_t d_mask,
+ u_int16_t s_port, u_int16_t d_port,
+ intel_82599_perfect_filter_hw_rule *rule) {
u_int32_t netmask;
- /* printk("init_perfect_filter_hw_rule()\n"); */
+ /* printk("init_intel_82599_perfect_filter_hw_rule()\n"); */
- memset(rule, 0, sizeof(hw_filtering_rule));
+ memset(rule, 0, sizeof(intel_82599_perfect_filter_hw_rule));
- rule->rule_type = perfect_filter_rule, rule->rule_id = rule_id, rule->queue_id = queue_id;
+ rule->queue_id = queue_id, rule->vlan_id = vlan, rule->proto = proto;
- rule->rule.perfect_rule.vlan_id = vlan;
- rule->rule.perfect_rule.proto = proto;
- rule->rule.perfect_rule.s_addr = s_addr;
+ rule->s_addr = s_addr;
if(s_mask == 32) netmask = 0xFFFFFFFF; else netmask = ~(0xFFFFFFFF >> s_mask);
- rule->rule.perfect_rule.s_addr &= netmask;
+ rule->s_addr &= netmask;
- rule->rule.perfect_rule.d_addr = d_addr;
+ rule->d_addr = d_addr;
if(d_mask == 32) netmask = 0xFFFFFFFF; else netmask = ~(0xFFFFFFFF >> d_mask);
- rule->rule.perfect_rule.d_addr &= netmask;
+ rule->d_addr &= netmask;
- rule->rule.perfect_rule.s_port = s_port, rule->rule.perfect_rule.d_port = d_port;
+ rule->s_port = s_port, rule->d_port = d_port;
}
+#endif /* ENABLE_PROC_WRITE_RULE */
+
/* ********************************** */
+#ifdef ENABLE_PROC_WRITE_RULE
static int ring_proc_dev_rule_write(struct file *file,
const char __user *buffer,
unsigned long count, void *data)
@@ -643,7 +812,7 @@
int num, queue_id, vlan, rc, rule_id, protocol;
int s_a, s_b, s_c, s_d, s_mask, s_port;
int d_a, d_b, d_c, d_d, d_mask, d_port;
- hw_filtering_rule rule;
+ hw_filtering_rule_request rule;
u_int8_t found = 0;
int debug = 0;
@@ -653,7 +822,7 @@
if(copy_from_user(buf, buffer, count)) return(-EFAULT);
buf[sizeof(buf)-1] = '\0', buf[count] = '\0';
- if(debug) printk("[PF_RING] ring_proc_dev_rule_write(%s)\n", buf);
+ if(enable_debug) printk("[PF_RING] ring_proc_dev_rule_write(%s)\n", buf);
num = sscanf(buf, "%c(%d,%d,%d,%c%c%c,%d.%d.%d.%d/%d,%d,%d.%d.%d.%d/%d,%d)",
&add, &rule_id, &queue_id, &vlan,
@@ -661,21 +830,21 @@
&s_a, &s_b, &s_c, &s_d, &s_mask, &s_port,
&d_a, &d_b, &d_c, &d_d, &d_mask, &d_port);
- if(debug)
+ if(enable_debug)
printk("[PF_RING] ring_proc_dev_rule_write(%s): num=%d (1)\n", buf, num);
if(num == 19) {
if(proto[0] == 't')
protocol = 6; /* TCP */
- else if(proto[0] == 'u')
+ else /* if(proto[0] == 'u') */
protocol = 17; /* UDP */
- else
- protocol = 0; /* any */
- init_perfect_filter_hw_rule(queue_id, rule_id, protocol, vlan,
- ((s_a & 0xff) << 24) + ((s_b & 0xff) << 16) + ((s_c & 0xff) << 8) + (s_d & 0xff), s_mask,
- ((d_a & 0xff) << 24) + ((d_b & 0xff) << 16) + ((d_c & 0xff) << 8) + (d_d & 0xff), d_mask,
- s_port, d_port, &rule);
+ rule.rule.rule_id = rule_id;
+ init_intel_82599_perfect_filter_hw_rule(queue_id, protocol, vlan,
+ ((s_a & 0xff) << 24) + ((s_b & 0xff) << 16) + ((s_c & 0xff) << 8) + (s_d & 0xff), s_mask,
+ ((d_a & 0xff) << 24) + ((d_b & 0xff) << 16) + ((d_c & 0xff) << 8) + (d_d & 0xff), d_mask,
+ s_port, d_port, &rule.rule.rule_family.perfect_rule);
+ rule.rule.rule_family_type = intel_82599_perfect_filter_rule;
found = 1;
}
@@ -686,7 +855,7 @@
&s_a, &s_b, &s_c, &s_d, &s_port,
&d_a, &d_b, &d_c, &d_d, &d_port);
- if(debug)
+ if(enable_debug)
printk("[PF_RING] ring_proc_dev_rule_write(%s): num=%d (2)\n", buf, num);
if(num == 16) {
@@ -697,10 +866,12 @@
else
protocol = 0; /* any */
- init_five_tuple_filter_hw_rule(queue_id, rule_id, protocol,
- ((s_a & 0xff) << 24) + ((s_b & 0xff) << 16) + ((s_c & 0xff) << 8) + (s_d & 0xff),
- ((d_a & 0xff) << 24) + ((d_b & 0xff) << 16) + ((d_c & 0xff) << 8) + (d_d & 0xff),
- s_port, d_port, &rule);
+ rule.rule.rule_id = rule_id;
+ init_intel_82599_five_tuple_filter_hw_rule(queue_id, protocol,
+ ((s_a & 0xff) << 24) + ((s_b & 0xff) << 16) + ((s_c & 0xff) << 8) + (s_d & 0xff),
+ ((d_a & 0xff) << 24) + ((d_b & 0xff) << 16) + ((d_c & 0xff) << 8) + (d_d & 0xff),
+ s_port, d_port, &rule.rule.rule_family.five_tuple_rule);
+ rule.rule.rule_family_type = intel_82599_five_tuple_rule;
found = 1;
}
}
@@ -708,16 +879,19 @@
if(!found)
return(-1);
- rc = handle_hw_filtering_rule(dev_ptr->dev, &rule, (add == '+') ? 1 : 0);
+ rule.command = (add == '+') ? add_hw_rule : remove_hw_rule;
+ rc = handle_hw_filtering_rule(dev_ptr->dev, &rule);
if(rc != -1) {
/* Rule programmed successfully */
if(add == '+')
- dev_ptr->num_hw_filters++;
+ dev_ptr->hw_filters.num_filters++, pfr->num_hw_filtering_rules++;
else {
- if(dev_ptr->num_hw_filters > 0)
- dev_ptr->num_hw_filters--;
+ if(dev_ptr->hw_filters.num_filters > 0)
+ dev_ptr->hw_filters.num_filters--;
+
+ pfr->num_hw_filtering_rules--;
}
}
@@ -725,13 +899,27 @@
}
#endif
+#endif
+
+/* ********************************** */
+
+static char* direction2string(packet_direction d) {
+ switch(d) {
+ case rx_and_tx_direction: return("RX+TX");
+ case rx_only_direction: return("RX only");
+ case tx_only_direction: return("TX only");
+ }
+
+ return("???");
+}
+
/* ********************************** */
static int ring_proc_get_info(char *buf, char **start, off_t offset,
int len, int *unused, void *data)
{
int rlen = 0;
- struct ring_opt *pfr;
+ struct pf_ring_socket *pfr;
FlowSlotInfo *fsi;
if(data == NULL) {
@@ -741,42 +929,51 @@
rlen += sprintf(buf + rlen, "Slot version : %d\n", RING_FLOWSLOT_VERSION);
rlen += sprintf(buf + rlen, "Capture TX : %s\n", enable_tx_capture ? "Yes [RX+TX]" : "No [RX only]");
rlen += sprintf(buf + rlen, "IP Defragment : %s\n", enable_ip_defrag ? "Yes" : "No");
- rlen += sprintf(buf + rlen, "Transparent mode : %s\n", (transparent_mode == standard_linux_path ? "Yes (mode 0)" : (transparent_mode == driver2pf_ring_transparent ? "Yes (mode 1)" : "No (mode 2)")));
+ rlen += sprintf(buf + rlen, "Socket Mode : %s\n", quick_mode ? "Quick" : "Standard");
+ rlen += sprintf(buf + rlen, "Transparent mode : %s\n",
+ (transparent_mode == standard_linux_path ? "Yes (mode 0)" :
+ (transparent_mode == driver2pf_ring_transparent ? "Yes (mode 1)" : "No (mode 2)")));
rlen += sprintf(buf + rlen, "Total rings : %d\n", ring_table_size);
rlen += sprintf(buf + rlen, "Total plugins : %d\n", plugin_registration_size);
} else {
/* detailed statistics about a PF_RING */
- pfr = (struct ring_opt *)data;
+ pfr = (struct pf_ring_socket *)data;
if(data) {
fsi = pfr->slots_info;
if(fsi) {
- rlen = sprintf(buf, "Bound Device : %s\n", pfr->ring_netdev->name);
- rlen += sprintf(buf + rlen, "Slot Version : %d [%s]\n", fsi->version, RING_VERSION);
- rlen += sprintf(buf + rlen, "Active : %d\n", pfr->ring_active);
- rlen += sprintf(buf + rlen, "Sampling Rate : %d\n", pfr->sample_rate);
- rlen += sprintf(buf + rlen, "Appl. Name : %s\n", pfr->appl_name ? pfr->appl_name : "<unknown>");
- rlen += sprintf(buf + rlen, "IP Defragment : %s\n", enable_ip_defrag ? "Yes" : "No");
- rlen += sprintf(buf + rlen, "BPF Filtering : %s\n", pfr->bpfFilter ? "Enabled" : "Disabled");
- rlen += sprintf(buf + rlen, "# Filt. Rules : %d\n", pfr->num_filtering_rules);
- rlen += sprintf(buf + rlen, "Cluster Id : %d\n", pfr->cluster_id);
- rlen += sprintf(buf + rlen, "Channel Id : %d\n", pfr->channel_id);
- rlen += sprintf(buf + rlen, "Min Num Slots : %d\n", fsi->min_num_slots);
- rlen += sprintf(buf + rlen, "Bucket Len : %d\n", fsi->data_len);
- rlen += sprintf(buf + rlen, "Slot Len : %d [bucket+header]\n", fsi->slot_len);
- rlen += sprintf(buf + rlen, "Tot Memory : %d\n", fsi->tot_mem);
- rlen += sprintf(buf + rlen, "Tot Packets : %lu\n", (unsigned long)fsi->tot_pkts);
- rlen += sprintf(buf + rlen, "Tot Pkt Lost : %lu\n", (unsigned long)fsi->tot_lost);
- rlen += sprintf(buf + rlen, "Tot Insert : %lu\n", (unsigned long)fsi->tot_insert);
- rlen += sprintf(buf + rlen, "Tot Read : %lu\n", (unsigned long)fsi->tot_read);
- rlen += sprintf(buf + rlen, "Insert Offset : %lu\n", (unsigned long)fsi->insert_off);
- rlen += sprintf(buf + rlen, "Remove Offset : %lu\n", (unsigned long)fsi->remove_off);
- rlen += sprintf(buf + rlen, "Tot Fwd Ok : %lu\n", (unsigned long)fsi->tot_fwd_ok);
- rlen += sprintf(buf + rlen, "Tot Fwd Errors : %lu\n", (unsigned long)fsi->tot_fwd_notok);
- rlen += sprintf(buf + rlen, "Num Free Slots : %u\n", get_num_ring_free_slots(pfr));
- } else
- rlen = sprintf(buf, "WARNING fsi == NULL\n");
+ rlen = sprintf(buf, "Bound Device : %s\n", pfr->ring_netdev->dev->name);
+ rlen += sprintf(buf + rlen, "Slot Version : %d [%s]\n", fsi->version, RING_VERSION);
+ rlen += sprintf(buf + rlen, "Active : %d\n", pfr->ring_active);
+ rlen += sprintf(buf + rlen, "Breed : %s\n", (pfr->dna_device_entry != NULL) ? "DNA" : "Non-DNA");
+ rlen += sprintf(buf + rlen, "Sampling Rate : %d\n", pfr->sample_rate);
+ rlen += sprintf(buf + rlen, "Capture Direction : %s\n", direction2string(pfr->direction));
+ rlen += sprintf(buf + rlen, "Appl. Name : %s\n", pfr->appl_name ? pfr->appl_name : "<unknown>");
+ rlen += sprintf(buf + rlen, "IP Defragment : %s\n", enable_ip_defrag ? "Yes" : "No");
+ rlen += sprintf(buf + rlen, "BPF Filtering : %s\n", pfr->bpfFilter ? "Enabled" : "Disabled");
+ rlen += sprintf(buf + rlen, "# Sw Filt. Rules : %d\n", pfr->num_sw_filtering_rules);
+ rlen += sprintf(buf + rlen, "# Hw Filt. Rules : %d\n", pfr->num_hw_filtering_rules);
+ rlen += sprintf(buf + rlen, "Cluster Id : %d\n", pfr->cluster_id);
+ rlen += sprintf(buf + rlen, "Channel Id : %d\n", pfr->channel_id);
+ rlen += sprintf(buf + rlen, "Min Num Slots : %d\n", fsi->min_num_slots);
+ rlen += sprintf(buf + rlen, "Poll Pkt Watermark : %d\n", pfr->poll_num_pkts_watermark);
+ rlen += sprintf(buf + rlen, "Bucket Len : %d\n", fsi->data_len);
+ rlen += sprintf(buf + rlen, "Slot Len : %d [bucket+header]\n", fsi->slot_len);
+ rlen += sprintf(buf + rlen, "Tot Memory : %d\n", fsi->tot_mem);
+ rlen += sprintf(buf + rlen, "Num Poll Calls : %u\n", pfr->num_poll_calls);
+ rlen += sprintf(buf + rlen, "Tot Packets : %lu\n", (unsigned long)fsi->tot_pkts);
+ rlen += sprintf(buf + rlen, "Tot Pkt Lost : %lu\n", (unsigned long)fsi->tot_lost);
+ rlen += sprintf(buf + rlen, "Tot Insert : %lu\n", (unsigned long)fsi->tot_insert);
+ rlen += sprintf(buf + rlen, "Tot Read : %lu\n", (unsigned long)fsi->tot_read);
+ rlen += sprintf(buf + rlen, "Insert Offset : %lu\n", (unsigned long)fsi->insert_off);
+ rlen += sprintf(buf + rlen, "Remove Offset : %lu\n", (unsigned long)fsi->remove_off);
+ rlen += sprintf(buf + rlen, "Tot Fwd Ok : %lu\n", (unsigned long)fsi->tot_fwd_ok);
+ rlen += sprintf(buf + rlen, "Tot Fwd Errors : %lu\n", (unsigned long)fsi->tot_fwd_notok);
+ rlen += sprintf(buf + rlen, "Num Free Slots : %u\n", get_num_ring_free_slots(pfr));
+ } else {
+ rlen = sprintf(buf, "WARNING ring not active (fsi == NULL)\n");
+ }
} else
rlen = sprintf(buf, "WARNING data == NULL\n");
}
@@ -882,16 +1079,15 @@
*/
static int ring_alloc_mem(struct sock *sk)
{
- u_int the_slot_len, num_pages;
+ u_int the_slot_len;
u_int32_t tot_mem;
- struct ring_opt *pfr = ring_sk(sk);
+ struct pf_ring_socket *pfr = ring_sk(sk);
/* Check if the memory has been already allocated */
if(pfr->ring_memory != NULL) return(0);
-#if defined(RING_DEBUG)
- printk("[PF_RING] ring_alloc_mem(bucket_len=%d)\n", pfr->bucket_len);
-#endif
+ if(enable_debug)
+ printk("[PF_RING] ring_alloc_mem(bucket_len=%d)\n", pfr->bucket_len);
/* **********************************************
@@ -911,23 +1107,34 @@
*
* ********************************************** */
- pfr->slot_header_len = sizeof(struct pfring_pkthdr);
+ if(quick_mode)
+ pfr->slot_header_len = sizeof(struct timeval) + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(u_int64_t) /* ts+caplen+len+timestamp_ns */;
+ else
+ pfr->slot_header_len = sizeof(struct pfring_pkthdr);
+
the_slot_len = pfr->slot_header_len + pfr->bucket_len;
tot_mem = PAGE_ALIGN(sizeof(FlowSlotInfo) + min_num_slots * the_slot_len);
/* Alignment necessary on ARM platforms */
- num_pages = tot_mem / PAGE_SIZE;
- num_pages += (num_pages + (SHMLBA-1)) % SHMLBA;
+ tot_mem += SHMLBA - (tot_mem % SHMLBA);
+
+ /* rounding size to the next power of 2 (needed by vPFRing) */
+ tot_mem--;
+ tot_mem |= tot_mem >> 1;
+ tot_mem |= tot_mem >> 2;
+ tot_mem |= tot_mem >> 4;
+ tot_mem |= tot_mem >> 8;
+ tot_mem |= tot_mem >> 16;
+ tot_mem++;
- pfr->ring_memory = vmalloc_user(num_pages*PAGE_SIZE);
+ /* Memory is already zeroed */
+ pfr->ring_memory = vmalloc_user(tot_mem);
if(pfr->ring_memory != NULL) {
-#if defined(RING_DEBUG)
- printk("[PF_RING] successfully allocated %lu bytes at 0x%08lx\n",
- (unsigned long)tot_mem, (unsigned long)pfr->ring_memory);
-#endif
- memset(pfr->ring_memory, 0, tot_mem);
+ if(enable_debug)
+ printk("[PF_RING] successfully allocated %lu bytes at 0x%08lx\n",
+ (unsigned long)tot_mem, (unsigned long)pfr->ring_memory);
} else {
printk("[PF_RING] ERROR: not enough memory for ring\n");
return(-1);
@@ -943,14 +1150,14 @@
pfr->slots_info->tot_mem = tot_mem;
pfr->slots_info->sample_rate = 1;
-#if defined(RING_DEBUG)
- printk("[PF_RING] allocated %d slots [slot_len=%d][tot_mem=%u]\n",
- pfr->slots_info->min_num_slots, pfr->slots_info->slot_len,
- pfr->slots_info->tot_mem);
-#endif
+ if(enable_debug)
+ printk("[PF_RING] allocated %d slots [slot_len=%d][tot_mem=%u]\n",
+ pfr->slots_info->min_num_slots, pfr->slots_info->slot_len,
+ pfr->slots_info->tot_mem);
pfr->insert_page_id = 1, pfr->insert_slot_id = 0;
- pfr->rules_default_accept_policy = 1, pfr->num_filtering_rules = 0;
+ pfr->sw_filtering_rules_default_accept_policy = 1;
+ pfr->num_sw_filtering_rules = pfr->num_hw_filtering_rules = 0;
return(0);
}
@@ -966,18 +1173,17 @@
static inline void ring_insert(struct sock *sk)
{
struct ring_element *next;
- struct ring_opt *pfr;
+ struct pf_ring_socket *pfr;
-#if defined(RING_DEBUG)
- printk("[PF_RING] ring_insert()\n");
-#endif
+ if(enable_debug)
+ printk("[PF_RING] ring_insert()\n");
next = kmalloc(sizeof(struct ring_element), GFP_ATOMIC);
if(next != NULL) {
next->sk = sk;
- write_lock_bh(&ring_mgmt_lock);
+ ring_write_lock();
list_add(&next->list, &ring_table);
- write_unlock_bh(&ring_mgmt_lock);
+ ring_write_unlock();
} else {
if(net_ratelimit())
printk("[PF_RING] net_ratelimit() failure\n");
@@ -985,14 +1191,12 @@
ring_table_size++;
- pfr = (struct ring_opt *)ring_sk(sk);
+ pfr = (struct pf_ring_socket *)ring_sk(sk);
pfr->ring_pid = current->pid;
}
/* ********************************** */
-// #define RING_DEBUG 1
-
/*
* ring_remove()
*
@@ -1007,81 +1211,90 @@
{
struct list_head *ptr, *tmp_ptr;
struct ring_element *entry, *to_delete = NULL;
- struct ring_opt *pfr_to_delete = ring_sk(sk);
+ struct pf_ring_socket *pfr_to_delete = ring_sk(sk);
+ u_int8_t master_found = 0, socket_found = 0;
-#if defined(RING_DEBUG)
- printk("[PF_RING] ring_remove()\n");
-#endif
+ if(enable_debug)
+ printk("[PF_RING] ring_remove()\n");
list_for_each_safe(ptr, tmp_ptr, &ring_table) {
- struct ring_opt *pfr;
+ struct pf_ring_socket *pfr;
entry = list_entry(ptr, struct ring_element, list);
pfr = ring_sk(entry->sk);
if(pfr->master_ring == pfr_to_delete) {
-#if defined(RING_DEBUG)
- printk("[PF_RING] Removing master ring\n");
-#endif
- pfr->master_ring = NULL;
+ if(enable_debug)
+ printk("[PF_RING] Removing master ring\n");
+
+ pfr->master_ring = NULL, master_found = 1;
} else if(entry->sk == sk) {
-#if defined(RING_DEBUG)
- printk("[PF_RING] Found socket to remove\n");
-#endif
+ if(enable_debug)
+ printk("[PF_RING] Found socket to remove\n");
+
list_del(ptr);
to_delete = entry;
- ring_table_size--;
+ ring_table_size--, socket_found = 1;
}
+
+ if(master_found && socket_found) break;
}
if(to_delete) kfree(to_delete);
-#if defined(RING_DEBUG)
- printk("[PF_RING] leaving ring_remove()\n");
-#endif
+ if(enable_debug)
+ printk("[PF_RING] leaving ring_remove()\n");
}
-// #undef RING_DEBUG
-
/* ******************************************************* */
-static int parse_pkt(struct sk_buff *skb,
- u_int16_t skb_displ, struct pfring_pkthdr *hdr)
+static int parse_raw_pkt(char *data, u_int data_len,
+ struct pfring_pkthdr *hdr, u_int8_t reset_all)
{
- struct ethhdr *eh = (struct ethhdr *)(skb->data - skb_displ);
+ struct ethhdr *eh = (struct ethhdr *)data;
u_int16_t displ, ip_len;
- memset(&hdr->extended_hdr.parsed_pkt, 0, sizeof(struct pkt_parsing_info));
- hdr->extended_hdr.parsed_header_len = 9;
+ if(reset_all)
+ memset(&hdr->extended_hdr.parsed_pkt, 0, sizeof(hdr->extended_hdr.parsed_pkt));
+ else
+ memset(&hdr->extended_hdr.parsed_pkt, 0, sizeof(hdr->extended_hdr.parsed_pkt)-sizeof(packet_user_detail) /* Preserve user data */);
+
+ if(data_len < sizeof(struct ethhdr)) return(0);
- /* MAC adderess */
+ /* MAC address */
memcpy(&hdr->extended_hdr.parsed_pkt.dmac, eh->h_dest, sizeof(eh->h_dest));
memcpy(&hdr->extended_hdr.parsed_pkt.smac, eh->h_source, sizeof(eh->h_source));
hdr->extended_hdr.parsed_pkt.eth_type = ntohs(eh->h_proto);
- hdr->extended_hdr.parsed_pkt.pkt_detail.offset.eth_offset = -skb_displ;
+ hdr->extended_hdr.parsed_pkt.offset.eth_offset = 0;
+
+ if(hdr->extended_hdr.parsed_pkt.eth_type == 0x8100 /* 802.1q (VLAN) */) {
+ hdr->extended_hdr.parsed_pkt.offset.vlan_offset =
+ hdr->extended_hdr.parsed_pkt.offset.eth_offset + sizeof(struct ethhdr);
- if(hdr->extended_hdr.parsed_pkt.eth_type == 0x8100 /* 802.1q (VLAN) */ ) {
- hdr->extended_hdr.parsed_pkt.pkt_detail.offset.vlan_offset =
- hdr->extended_hdr.parsed_pkt.pkt_detail.offset.eth_offset + sizeof(struct ethhdr);
hdr->extended_hdr.parsed_pkt.vlan_id =
- (skb->data[hdr->extended_hdr.parsed_pkt.pkt_detail.offset.vlan_offset] & 15) * 256 +
- skb->data[hdr->extended_hdr.parsed_pkt.pkt_detail.offset.vlan_offset + 1];
+ (data[hdr->extended_hdr.parsed_pkt.offset.vlan_offset] & 15) * 256 +
+ data[hdr->extended_hdr.parsed_pkt.offset.vlan_offset + 1];
hdr->extended_hdr.parsed_pkt.eth_type =
- (skb->data[hdr->extended_hdr.parsed_pkt.pkt_detail.offset.vlan_offset + 2]) * 256 +
- skb->data[hdr->extended_hdr.parsed_pkt.pkt_detail.offset.vlan_offset + 3];
+ (data[hdr->extended_hdr.parsed_pkt.offset.vlan_offset + 2]) * 256 +
+ data[hdr->extended_hdr.parsed_pkt.offset.vlan_offset + 3];
displ = 4;
} else {
displ = 0;
hdr->extended_hdr.parsed_pkt.vlan_id = 0; /* Any VLAN */
}
+ if(unlikely(enable_debug))
+ printk("[PF_RING] [eth_type=%04X]\n", hdr->extended_hdr.parsed_pkt.eth_type);
+
if(hdr->extended_hdr.parsed_pkt.eth_type == 0x0800 /* IPv4 */ ) {
struct iphdr *ip;
- hdr->extended_hdr.parsed_pkt.pkt_detail.offset.l3_offset = hdr->extended_hdr.parsed_pkt.pkt_detail.offset.eth_offset + displ + sizeof(struct ethhdr);
+ hdr->extended_hdr.parsed_pkt.offset.l3_offset = hdr->extended_hdr.parsed_pkt.offset.eth_offset + displ + sizeof(struct ethhdr);
+
+ if(data_len < hdr->extended_hdr.parsed_pkt.offset.l3_offset + sizeof(struct iphdr)) return(0);
- ip = (struct iphdr *)(skb->data + hdr->extended_hdr.parsed_pkt.pkt_detail.offset.l3_offset);
+ ip = (struct iphdr *)(&data[hdr->extended_hdr.parsed_pkt.offset.l3_offset]);
hdr->extended_hdr.parsed_pkt.ipv4_src = ntohl(ip->saddr);
hdr->extended_hdr.parsed_pkt.ipv4_dst = ntohl(ip->daddr);
@@ -1089,14 +1302,17 @@
hdr->extended_hdr.parsed_pkt.ipv4_tos = ip->tos;
hdr->extended_hdr.parsed_pkt.ip_version = 4;
ip_len = ip->ihl*4;
- } else if (hdr->extended_hdr.parsed_pkt.eth_type == 0x86DD /* IPv6 */) {
+ } else if(hdr->extended_hdr.parsed_pkt.eth_type == 0x86DD /* IPv6 */) {
struct ipv6hdr *ipv6;
hdr->extended_hdr.parsed_pkt.ip_version = 6;
ip_len = 40;
- hdr->extended_hdr.parsed_pkt.pkt_detail.offset.l3_offset = hdr->extended_hdr.parsed_pkt.pkt_detail.offset.eth_offset+displ+sizeof(struct ethhdr);
- ipv6 = (struct ipv6hdr*)(skb->data+hdr->extended_hdr.parsed_pkt.pkt_detail.offset.l3_offset);
+ hdr->extended_hdr.parsed_pkt.offset.l3_offset = hdr->extended_hdr.parsed_pkt.offset.eth_offset+displ+sizeof(struct ethhdr);
+
+ if(data_len < hdr->extended_hdr.parsed_pkt.offset.l3_offset + sizeof(struct ipv6hdr)) return(0);
+
+ ipv6 = (struct ipv6hdr*)(&data[hdr->extended_hdr.parsed_pkt.offset.l3_offset]);
/* Values of IPv6 addresses are stored as network byte order */
hdr->extended_hdr.parsed_pkt.ipv6_src = ipv6->saddr;
@@ -1118,56 +1334,92 @@
upper-layer header
*/
- while(hdr->extended_hdr.parsed_pkt.l3_proto == NEXTHDR_HOP ||
- hdr->extended_hdr.parsed_pkt.l3_proto == NEXTHDR_DEST ||
- hdr->extended_hdr.parsed_pkt.l3_proto == NEXTHDR_ROUTING ||
- hdr->extended_hdr.parsed_pkt.l3_proto == NEXTHDR_AUTH ||
- hdr->extended_hdr.parsed_pkt.l3_proto == NEXTHDR_ESP ||
- hdr->extended_hdr.parsed_pkt.l3_proto == NEXTHDR_FRAGMENT)
- {
+ while(hdr->extended_hdr.parsed_pkt.l3_proto == NEXTHDR_HOP ||
+ hdr->extended_hdr.parsed_pkt.l3_proto == NEXTHDR_DEST ||
+ hdr->extended_hdr.parsed_pkt.l3_proto == NEXTHDR_ROUTING ||
+ hdr->extended_hdr.parsed_pkt.l3_proto == NEXTHDR_AUTH ||
+ hdr->extended_hdr.parsed_pkt.l3_proto == NEXTHDR_ESP ||
+ hdr->extended_hdr.parsed_pkt.l3_proto == NEXTHDR_FRAGMENT) {
struct ipv6_opt_hdr *ipv6_opt;
- ipv6_opt = (struct ipv6_opt_hdr *)(skb->data+hdr->extended_hdr.parsed_pkt.pkt_detail.offset.l3_offset+ip_len);
+ ipv6_opt = (struct ipv6_opt_hdr *)(&data[hdr->extended_hdr.parsed_pkt.offset.l3_offset+ip_len]);
ip_len += 8;
- if (hdr->extended_hdr.parsed_pkt.l3_proto == NEXTHDR_AUTH)
+ if(hdr->extended_hdr.parsed_pkt.l3_proto == NEXTHDR_AUTH)
/*
RFC4302 2.2. Payload Length: This 8-bit field specifies the
length of AH in 32-bit words (4-byte units), minus "2".
*/
ip_len += ipv6_opt->hdrlen * 4;
- else if (hdr->extended_hdr.parsed_pkt.l3_proto != NEXTHDR_FRAGMENT)
+ else if(hdr->extended_hdr.parsed_pkt.l3_proto != NEXTHDR_FRAGMENT)
ip_len += ipv6_opt->hdrlen;
hdr->extended_hdr.parsed_pkt.l3_proto = ipv6_opt->nexthdr;
}
} else {
+ hdr->extended_hdr.parsed_pkt.l3_proto = 0;
return(0); /* No IP */
}
+ if(unlikely(enable_debug))
+ printk("[PF_RING] [l3_proto=%d]\n", hdr->extended_hdr.parsed_pkt.l3_proto);
+
if((hdr->extended_hdr.parsed_pkt.l3_proto == IPPROTO_TCP) || (hdr->extended_hdr.parsed_pkt.l3_proto == IPPROTO_UDP)) {
- hdr->extended_hdr.parsed_pkt.pkt_detail.offset.l4_offset = hdr->extended_hdr.parsed_pkt.pkt_detail.offset.l3_offset+ip_len;
+ hdr->extended_hdr.parsed_pkt.offset.l4_offset = hdr->extended_hdr.parsed_pkt.offset.l3_offset+ip_len;
if(hdr->extended_hdr.parsed_pkt.l3_proto == IPPROTO_TCP) {
- struct tcphdr *tcp =
- (struct tcphdr *)(skb->data+hdr->extended_hdr.parsed_pkt.pkt_detail.offset.l4_offset);
+ struct tcphdr *tcp;
+
+ if(data_len < hdr->extended_hdr.parsed_pkt.offset.l4_offset + sizeof(struct tcphdr)) return(0);
+
+ tcp = (struct tcphdr *)(&data[hdr->extended_hdr.parsed_pkt.offset.l4_offset]);
+
hdr->extended_hdr.parsed_pkt.l4_src_port = ntohs(tcp->source), hdr->extended_hdr.parsed_pkt.l4_dst_port = ntohs(tcp->dest);
- hdr->extended_hdr.parsed_pkt.pkt_detail.offset.payload_offset = hdr->extended_hdr.parsed_pkt.pkt_detail.offset.l4_offset + (tcp->doff * 4);
+ hdr->extended_hdr.parsed_pkt.offset.payload_offset = hdr->extended_hdr.parsed_pkt.offset.l4_offset + (tcp->doff * 4);
hdr->extended_hdr.parsed_pkt.tcp.seq_num = ntohl(tcp->seq), hdr->extended_hdr.parsed_pkt.tcp.ack_num = ntohl(tcp->ack_seq);
- hdr->extended_hdr.parsed_pkt.tcp.flags =
- (tcp->fin * TH_FIN_MULTIPLIER) + (tcp->syn * TH_SYN_MULTIPLIER) +
+ hdr->extended_hdr.parsed_pkt.tcp.flags = (tcp->fin * TH_FIN_MULTIPLIER) + (tcp->syn * TH_SYN_MULTIPLIER) +
(tcp->rst * TH_RST_MULTIPLIER) + (tcp->psh * TH_PUSH_MULTIPLIER) +
(tcp->ack * TH_ACK_MULTIPLIER) + (tcp->urg * TH_URG_MULTIPLIER);
} else if(hdr->extended_hdr.parsed_pkt.l3_proto == IPPROTO_UDP) {
- struct udphdr *udp = (struct udphdr *)(skb->data + hdr->extended_hdr.parsed_pkt.pkt_detail.offset.l4_offset);
+ struct udphdr *udp;
+
+ if(data_len < hdr->extended_hdr.parsed_pkt.offset.l4_offset + sizeof(struct udphdr)) return(0);
+
+ udp = (struct udphdr *)(&data[hdr->extended_hdr.parsed_pkt.offset.l4_offset]);
+
hdr->extended_hdr.parsed_pkt.l4_src_port = ntohs(udp->source), hdr->extended_hdr.parsed_pkt.l4_dst_port = ntohs(udp->dest);
- hdr->extended_hdr.parsed_pkt.pkt_detail.offset.payload_offset = hdr->extended_hdr.parsed_pkt.pkt_detail.offset.l4_offset + sizeof(struct udphdr);
+ hdr->extended_hdr.parsed_pkt.offset.payload_offset = hdr->extended_hdr.parsed_pkt.offset.l4_offset + sizeof(struct udphdr);
} else
- hdr->extended_hdr.parsed_pkt.pkt_detail.offset.payload_offset = hdr->extended_hdr.parsed_pkt.pkt_detail.offset.l4_offset;
+ hdr->extended_hdr.parsed_pkt.offset.payload_offset = hdr->extended_hdr.parsed_pkt.offset.l4_offset;
+
+ if(unlikely(enable_debug))
+ printk("[PF_RING] [l4_offset=%d][l4_src_port/l4_dst_port=%d/%d]\n",
+ hdr->extended_hdr.parsed_pkt.offset.l4_offset,
+ hdr->extended_hdr.parsed_pkt.l4_src_port,
+ hdr->extended_hdr.parsed_pkt.l4_dst_port);
} else
hdr->extended_hdr.parsed_pkt.l4_src_port = hdr->extended_hdr.parsed_pkt.l4_dst_port = 0;
- hdr->extended_hdr.parsed_pkt.pkt_detail.offset.eth_offset = skb_displ;
+ return(1); /* IP */
+}
+
+/* ********************************** */
+
+static int parse_pkt(struct sk_buff *skb,
+ u_int16_t skb_displ,
+ struct pfring_pkthdr *hdr,
+ u_int8_t reset_all)
+{
+ char pkt_header[78] = { 0 };
+ int rc, len = sizeof(pkt_header);
+
+ if(len > (skb->len + skb_displ))
+ len = skb->len + skb_displ;
- return(1); /* IP */
+ skb_copy_bits(skb, -skb_displ, pkt_header, len);
+
+ rc = parse_raw_pkt(pkt_header, len, hdr, reset_all);
+ hdr->extended_hdr.parsed_pkt.offset.eth_offset = -skb_displ;
+
+ return(rc);
}
/* ********************************** */
@@ -1199,7 +1451,7 @@
/* ********************************** */
-static int hash_bucket_match(filtering_hash_bucket * hash_bucket,
+static int hash_bucket_match(sw_filtering_hash_bucket * hash_bucket,
struct pfring_pkthdr *hdr,
u_char mask_src, u_char mask_dst)
{
@@ -1247,20 +1499,20 @@
&& (hash_bucket->rule.port_peer_a == (mask_dst ? 0 : hdr->extended_hdr.parsed_pkt.l4_dst_port))
&& (hash_bucket->rule.port_peer_b == (mask_src ? 0 : hdr->extended_hdr.parsed_pkt.l4_src_port)))))
{
- if (hdr->extended_hdr.parsed_pkt.ip_version == 6) {
- if (((memcmp(&hash_bucket->rule.host6_peer_a,
- (mask_src ? &ip_zero.v6 : &hdr->extended_hdr.parsed_pkt.ipv6_src),
- sizeof(ip_addr) == 0))
- && (memcmp(&hash_bucket->rule.host6_peer_b,
- (mask_dst ? &ip_zero.v6 : &hdr->extended_hdr.parsed_pkt.ipv6_dst),
- sizeof(ip_addr) == 0)))
- ||
- ((memcmp(&hash_bucket->rule.host6_peer_a,
- (mask_src ? &ip_zero.v6 : &hdr->extended_hdr.parsed_pkt.ipv6_dst),
- sizeof(ip_addr) == 0))
- && (memcmp(&hash_bucket->rule.host6_peer_b,
- (mask_dst ? &ip_zero.v6 : &hdr->extended_hdr.parsed_pkt.ipv6_src),
- sizeof(ip_addr) == 0)))) {
+ if(hdr->extended_hdr.parsed_pkt.ip_version == 6) {
+ if(((memcmp(&hash_bucket->rule.host6_peer_a,
+ (mask_src ? &ip_zero.v6 : &hdr->extended_hdr.parsed_pkt.ipv6_src),
+ sizeof(ip_addr) == 0))
+ && (memcmp(&hash_bucket->rule.host6_peer_b,
+ (mask_dst ? &ip_zero.v6 : &hdr->extended_hdr.parsed_pkt.ipv6_dst),
+ sizeof(ip_addr) == 0)))
+ ||
+ ((memcmp(&hash_bucket->rule.host6_peer_a,
+ (mask_src ? &ip_zero.v6 : &hdr->extended_hdr.parsed_pkt.ipv6_dst),
+ sizeof(ip_addr) == 0))
+ && (memcmp(&hash_bucket->rule.host6_peer_b,
+ (mask_dst ? &ip_zero.v6 : &hdr->extended_hdr.parsed_pkt.ipv6_src),
+ sizeof(ip_addr) == 0)))) {
return(1);
} else {
return(0);
@@ -1275,12 +1527,10 @@
/* ********************************** */
-inline int hash_bucket_match_rule(filtering_hash_bucket * hash_bucket,
+inline int hash_bucket_match_rule(sw_filtering_hash_bucket * hash_bucket,
hash_filtering_rule * rule)
{
- int debug = 0;
-
- if(debug)
+ if(enable_debug)
printk("[PF_RING] (%u,%d,%d.%d.%d.%d:%u,%d.%d.%d.%d:%u) "
"(%u,%d,%d.%d.%d.%d:%u,%d.%d.%d.%d:%u)\n",
hash_bucket->rule.vlan_id, hash_bucket->rule.proto,
@@ -1326,9 +1576,7 @@
inline int hash_filtering_rule_match(hash_filtering_rule * a,
hash_filtering_rule * b)
{
- int debug = 0;
-
- if(debug)
+ if(enable_debug)
printk("[PF_RING] (%u,%d,%d.%d.%d.%d:%u,%d.%d.%d.%d:%u) "
"(%u,%d,%d.%d.%d.%d:%u,%d.%d.%d.%d:%u)\n",
a->vlan_id, a->proto,
@@ -1371,20 +1619,19 @@
/* ********************************** */
/* 0 = no match, 1 = match */
-static int match_filtering_rule(struct ring_opt *the_ring,
- filtering_rule_element * rule,
+static int match_filtering_rule(struct pf_ring_socket *pfr,
+ sw_filtering_rule_element * rule,
struct pfring_pkthdr *hdr,
struct sk_buff *skb,
int displ,
struct parse_buffer *parse_memory_buffer[],
- u_int8_t * free_parse_mem,
- u_int * last_matched_plugin,
- rule_action_behaviour * behaviour)
+ u_int8_t *free_parse_mem,
+ u_int *last_matched_plugin,
+ rule_action_behaviour *behaviour)
{
- int debug = 0;
u_int8_t empty_mac[ETH_ALEN] = { 0 }; /* NULL MAC address */
- if(debug) printk("[PF_RING] match_filtering_rule()\n");
+ if(enable_debug) printk("[PF_RING] match_filtering_rule()\n");
*behaviour = forward_packet_and_stop_rule_evaluation; /* Default */
@@ -1421,12 +1668,13 @@
return(0);
}
- if((rule->rule.core_fields.port_high > 0)
- && (!((hdr->extended_hdr.parsed_pkt.l4_src_port >= rule->rule.core_fields.port_low)
- && (hdr->extended_hdr.parsed_pkt.l4_src_port <= rule->rule.core_fields.port_high)))
- && (!((hdr->extended_hdr.parsed_pkt.l4_dst_port >= rule->rule.core_fields.port_low)
- && (hdr->extended_hdr.parsed_pkt.l4_dst_port <= rule->rule.core_fields.port_high))))
- return(0);
+ if(rule->rule.core_fields.port_high > 0) {
+ if(((hdr->extended_hdr.parsed_pkt.l4_src_port < rule->rule.core_fields.port_low)
+ || (hdr->extended_hdr.parsed_pkt.l4_src_port > rule->rule.core_fields.port_high))
+ && ((hdr->extended_hdr.parsed_pkt.l4_dst_port < rule->rule.core_fields.port_low)
+ || (hdr->extended_hdr.parsed_pkt.l4_dst_port > rule->rule.core_fields.port_high)))
+ return(0);
+ }
if(rule->rule.balance_pool > 0) {
u_int32_t balance_hash =
@@ -1437,25 +1685,23 @@
#ifdef CONFIG_TEXTSEARCH
if(rule->pattern[0] != NULL) {
- if(debug)
+ if(enable_debug)
printk("[PF_RING] pattern\n");
- if((hdr->extended_hdr.parsed_pkt.pkt_detail.offset.payload_offset > 0)
- && (hdr->caplen > hdr->extended_hdr.parsed_pkt.pkt_detail.offset.payload_offset)) {
- char *payload = (char *)&(skb->data[hdr->extended_hdr.parsed_pkt.pkt_detail.offset.
- payload_offset /* -displ */ ]);
+ if((hdr->extended_hdr.parsed_pkt.offset.payload_offset > 0)
+ && (hdr->caplen > hdr->extended_hdr.parsed_pkt.offset.payload_offset)) {
+ char *payload = (char *)&(skb->data[hdr->extended_hdr.parsed_pkt.offset.payload_offset /* -displ */ ]);
int rc = 0, payload_len =
- hdr->caplen - hdr->extended_hdr.parsed_pkt.pkt_detail.offset.payload_offset - displ;
+ hdr->caplen - hdr->extended_hdr.parsed_pkt.offset.payload_offset - displ;
if(payload_len > 0) {
int i;
struct ts_state state;
- if(debug) {
+ if(enable_debug) {
printk("[PF_RING] Trying to match pattern [caplen=%d][len=%d][displ=%d][payload_offset=%d][",
hdr->caplen, payload_len, displ,
- hdr->extended_hdr.parsed_pkt.pkt_detail.offset.
- payload_offset);
+ hdr->extended_hdr.parsed_pkt.offset.payload_offset);
for(i = 0; i < payload_len; i++)
printk("[%d/%c]", i, payload[i] & 0xFF);
@@ -1464,11 +1710,11 @@
payload[payload_len] = '\0';
- if(debug)
+ if(enable_debug)
printk("[PF_RING] Attempt to match [%s]\n", payload);
for(i = 0; (i < MAX_NUM_PATTERN) && (rule->pattern[i] != NULL); i++) {
- if(debug)
+ if(enable_debug)
printk("[PF_RING] Attempt to match pattern %d\n", i);
rc = (textsearch_find_continuous
(rule->pattern[i], &state,
@@ -1477,7 +1723,7 @@
break;
}
- if(debug)
+ if(enable_debug)
printk("[PF_RING] Match returned: %d [payload_len=%d][%s]\n",
rc, payload_len, payload);
@@ -1490,15 +1736,15 @@
}
#endif
+ /* Step 1 - Filter (optional) */
if((rule->rule.extended_fields.filter_plugin_id > 0)
&& (rule->rule.extended_fields.filter_plugin_id < MAX_PLUGIN_ID)
&& (plugin_registration[rule->rule.extended_fields.filter_plugin_id] != NULL)
- && (plugin_registration[rule->rule.extended_fields.filter_plugin_id]->
- pfring_plugin_filter_skb != NULL)
+ && (plugin_registration[rule->rule.extended_fields.filter_plugin_id]->pfring_plugin_filter_skb != NULL)
) {
int rc;
- if(debug)
+ if(enable_debug)
printk("[PF_RING] rule->plugin_id [rule_id=%d]"
"[filter_plugin_id=%d][plugin_action=%d][ptr=%p]\n",
rule->rule.rule_id,
@@ -1506,50 +1752,48 @@
rule->rule.plugin_action.plugin_id,
plugin_registration[rule->rule.plugin_action.plugin_id]);
- rc = plugin_registration[rule->rule.extended_fields.
- filter_plugin_id]->pfring_plugin_filter_skb
- (the_ring, rule, hdr, skb,
- &parse_memory_buffer[rule->rule.extended_fields.filter_plugin_id]);
+ rc = plugin_registration[rule->rule.extended_fields.filter_plugin_id]->pfring_plugin_filter_skb
+ (pfr, rule, hdr, skb, displ, &parse_memory_buffer[rule->rule.extended_fields.filter_plugin_id]);
- if(parse_memory_buffer
- [rule->rule.extended_fields.filter_plugin_id])
+ if(parse_memory_buffer[rule->rule.extended_fields.filter_plugin_id])
*free_parse_mem = 1;
if(rc <= 0) {
- return(0); /* No match */
+ return(0); /* No match */
} else {
- *last_matched_plugin =
- rule->rule.extended_fields.filter_plugin_id;
+ *last_matched_plugin = rule->rule.extended_fields.filter_plugin_id;
hdr->extended_hdr.parsed_pkt.last_matched_plugin_id =
rule->rule.extended_fields.filter_plugin_id;
- if(debug)
- printk
- ("[PF_RING] [last_matched_plugin = %d][buffer=%p][len=%d]\n",
- *last_matched_plugin,
- parse_memory_buffer[rule->rule.extended_fields.filter_plugin_id],
- parse_memory_buffer[rule->rule.extended_fields.filter_plugin_id] ?
- parse_memory_buffer[rule->rule.extended_fields.filter_plugin_id]->mem_len : 0);
+ if(enable_debug)
+ printk("[PF_RING] [last_matched_plugin = %d][buffer=%p][len=%d]\n",
+ *last_matched_plugin,
+ parse_memory_buffer[rule->rule.extended_fields.filter_plugin_id],
+ parse_memory_buffer[rule->rule.extended_fields.filter_plugin_id] ?
+ parse_memory_buffer[rule->rule.extended_fields.filter_plugin_id]->mem_len : 0);
}
}
+ /* Step 2 - Handle skb */
/* Action to be performed in case of match */
if((rule->rule.plugin_action.plugin_id != NO_PLUGIN_ID)
&& (rule->rule.plugin_action.plugin_id < MAX_PLUGIN_ID)
&& (plugin_registration[rule->rule.plugin_action.plugin_id] != NULL)
&& (plugin_registration[rule->rule.plugin_action.plugin_id]->pfring_plugin_handle_skb != NULL)
) {
- if(debug)
- printk
- ("[PF_RING] Calling pfring_plugin_handle_skb(pluginId=%d)\n",
- rule->rule.plugin_action.plugin_id);
-
- plugin_registration[rule->rule.plugin_action.plugin_id]
- ->pfring_plugin_handle_skb(the_ring, rule, NULL, hdr, skb,
- rule->rule.extended_fields.
- filter_plugin_id,
+ int rc;
+
+ if(enable_debug)
+ printk("[PF_RING] Calling pfring_plugin_handle_skb(pluginId=%d)\n",
+ rule->rule.plugin_action.plugin_id);
+
+ rc = plugin_registration[rule->rule.plugin_action.plugin_id]
+ ->pfring_plugin_handle_skb(pfr, rule, NULL, hdr, skb, displ,
+ rule->rule.extended_fields.filter_plugin_id,
&parse_memory_buffer[rule->rule.extended_fields.filter_plugin_id],
behaviour);
+ if(rc <= 0)
+ return(0); /* No match */
if(*last_matched_plugin == 0)
*last_matched_plugin = rule->rule.plugin_action.plugin_id;
@@ -1557,21 +1801,22 @@
if(parse_memory_buffer[rule->rule.plugin_action.plugin_id])
*free_parse_mem = 1;
} else {
- if(debug)
+ if(enable_debug)
printk("[PF_RING] Skipping pfring_plugin_handle_skb(plugin_action=%d)\n",
rule->rule.plugin_action.plugin_id);
*behaviour = rule->rule.rule_action;
- if(debug)
+ if(enable_debug)
printk("[PF_RING] Rule %d behaviour: %d\n",
rule->rule.rule_id, rule->rule.rule_action);
}
- if(debug) {
+ if(enable_debug) {
printk("[PF_RING] MATCH: match_filtering_rule(vlan=%u, proto=%u, sip=%u, sport=%u, dip=%u, dport=%u)\n",
hdr->extended_hdr.parsed_pkt.vlan_id, hdr->extended_hdr.parsed_pkt.l3_proto,
hdr->extended_hdr.parsed_pkt.ipv4_src, hdr->extended_hdr.parsed_pkt.l4_src_port,
hdr->extended_hdr.parsed_pkt.ipv4_dst, hdr->extended_hdr.parsed_pkt.l4_dst_port);
+
printk("[PF_RING] [rule(vlan=%u, proto=%u, ip=%u-%u, port=%u-%u)(behaviour=%d)]\n",
rule->rule.core_fields.vlan_id,
rule->rule.core_fields.proto,
@@ -1591,18 +1836,27 @@
/*
Generic function for copying either a skb or a raw
memory block to the ring buffer
+
+ Return:
+ - 0 = packet was not copied (e.g. slot was full)
+ - 1 = the packet was copied (i.e. there was room for it)
*/
-inline void copy_data_to_ring(struct sk_buff *skb,
- struct ring_opt *pfr,
- struct pfring_pkthdr *hdr,
- int displ, int offset, void *plugin_mem,
- void *raw_data, uint raw_data_len) {
+inline int copy_data_to_ring(struct sk_buff *skb,
+ struct pf_ring_socket *pfr,
+ struct pfring_pkthdr *hdr,
+ int displ, int offset, void *plugin_mem,
+ void *raw_data, uint raw_data_len) {
char *ring_bucket;
u_int32_t off, taken;
+ u_short do_lock = ((!quick_mode) || (pfr->num_channels_per_ring > 0)) ? 1 : 0;
+
+ /* printk("[PF_RING] ==> copy_data_to_ring()\n"); */
- if(pfr->ring_slots == NULL) return;
+ if(pfr->ring_slots == NULL) return(0);
- write_lock_bh(&pfr->ring_index_lock);
+ /* We need to lock as two ksoftirqd might put data onto the same ring */
+
+ if(do_lock) write_lock(&pfr->ring_index_lock);
// smp_rmb();
off = pfr->slots_info->insert_off;
@@ -1611,12 +1865,13 @@
if(!check_and_init_free_slot(pfr, off)) /* Full */ {
/* No room left */
pfr->slots_info->tot_lost++;
-#if defined(RING_DEBUG)
- printk("[PF_RING] ==> slot(off=%d) is full [insert_off=%u][remove_off=%u][slot_len=%u][num_queued_pkts=%u]\n",
- off, pfr->slots_info->insert_off, pfr->slots_info->remove_off, pfr->slots_info->slot_len, num_queued_pkts(pfr));
-#endif
- write_unlock_bh(&pfr->ring_index_lock);
- return;
+
+ if(enable_debug)
+ printk("[PF_RING] ==> slot(off=%d) is full [insert_off=%u][remove_off=%u][slot_len=%u][num_queued_pkts=%u]\n",
+ off, pfr->slots_info->insert_off, pfr->slots_info->remove_off, pfr->slots_info->slot_len, num_queued_pkts(pfr));
+
+ if(do_lock) write_unlock(&pfr->ring_index_lock);
+ return(0);
}
ring_bucket = get_slot(pfr, off);
@@ -1624,16 +1879,17 @@
if(skb != NULL) {
/* skb copy mode */
- if((plugin_mem != NULL) && (offset > 0)) {
- memcpy(&ring_bucket[pfr->slot_header_len], plugin_mem, offset);
+ if(!quick_mode) {
+ if((plugin_mem != NULL) && (offset > 0))
+ memcpy(&ring_bucket[pfr->slot_header_len], plugin_mem, offset);
}
if(hdr->caplen > 0) {
-#if defined(RING_DEBUG)
- printk("[PF_RING] --> [caplen=%d][len=%d][displ=%d][extended_hdr.parsed_header_len=%d][bucket_len=%d][sizeof=%d]\n",
- hdr->caplen, hdr->len, displ, hdr->extended_hdr.parsed_header_len, pfr->bucket_len,
- pfr->slot_header_len);
-#endif
+ if(enable_debug)
+ printk("[PF_RING] --> [caplen=%d][len=%d][displ=%d][extended_hdr.parsed_header_len=%d][bucket_len=%d][sizeof=%d]\n",
+ hdr->caplen, hdr->len, displ, hdr->extended_hdr.parsed_header_len, pfr->bucket_len,
+ pfr->slot_header_len);
+
skb_copy_bits(skb, -displ, &ring_bucket[pfr->slot_header_len + offset], hdr->caplen);
} else {
if(hdr->extended_hdr.parsed_header_len >= pfr->bucket_len) {
@@ -1648,7 +1904,7 @@
}
} else {
/* Raw data copy mode */
- raw_data_len = min(raw_data_len, pfr->bucket_len); /* Avoid overruns */
+ raw_data_len = min_val(raw_data_len, pfr->bucket_len); /* Avoid overruns */
memcpy(&ring_bucket[pfr->slot_header_len], raw_data, raw_data_len); /* Copy raw data if present */
hdr->len = hdr->caplen = raw_data_len, hdr->extended_hdr.if_index = FAKE_PACKET;
/* printk("[PF_RING] Copied raw data at slot with offset %d [len=%d]\n", off, raw_data_len); */
@@ -1658,81 +1914,115 @@
pfr->slots_info->insert_off = get_next_slot_offset(pfr, off, &taken);
-#if defined(RING_DEBUG)
- printk("[PF_RING] ==> insert_off=%d\n", pfr->slots_info->insert_off);
-#endif
+ if(enable_debug)
+ printk("[PF_RING] ==> insert_off=%d\n", pfr->slots_info->insert_off);
/*
NOTE: smp_* barriers are _compiler_ barriers on UP, mandatory barriers on SMP
a consumer _must_ see the new value of tot_insert only after the buffer update completes
*/
- smp_wmb();
+ smp_mb();
+ //wmb();
+
pfr->slots_info->tot_insert++;
- write_unlock_bh(&pfr->ring_index_lock);
+ if(do_lock) write_unlock(&pfr->ring_index_lock);
- if(waitqueue_active(&pfr->ring_slots_waitqueue))
+ if(num_queued_pkts(pfr) >= pfr->poll_num_pkts_watermark)
wake_up_interruptible(&pfr->ring_slots_waitqueue);
+
+#ifdef VPFRING_SUPPORT
+ if (pfr->vpfring_host_eventfd_ctx && !(pfr->slots_info->vpfring_guest_flags & VPFRING_GUEST_NO_INTERRUPT))
+ eventfd_signal(pfr->vpfring_host_eventfd_ctx, 1);
+#endif //VPFRING_SUPPORT
+
+ return(1);
}
/* ********************************** */
-static void copy_raw_data_to_ring(struct ring_opt *pfr,
- struct pfring_pkthdr *dummy_hdr,
- void *raw_data, uint raw_data_len) {
- copy_data_to_ring(NULL, pfr, dummy_hdr, 0, 0, NULL, raw_data, raw_data_len);
+inline int copy_raw_data_to_ring(struct pf_ring_socket *pfr,
+ struct pfring_pkthdr *dummy_hdr,
+ void *raw_data, uint raw_data_len) {
+ return(copy_data_to_ring(NULL, pfr, dummy_hdr, 0, 0, NULL, raw_data, raw_data_len));
}
/* ********************************** */
-static void add_pkt_to_ring(struct sk_buff *skb,
- struct ring_opt *_pfr,
- struct pfring_pkthdr *hdr,
- int displ, u_int8_t channel_id,
- int offset, void *plugin_mem)
+inline int add_pkt_to_ring(struct sk_buff *skb,
+ struct pf_ring_socket *_pfr,
+ struct pfring_pkthdr *hdr,
+ int displ, u_int32_t channel_id,
+ int offset, void *plugin_mem)
{
- struct ring_opt *pfr = (_pfr->master_ring != NULL) ? _pfr->master_ring : _pfr;
- int32_t the_bit = 1 << channel_id;
+ struct pf_ring_socket *pfr = (_pfr->master_ring != NULL) ? _pfr->master_ring : _pfr;
+ u_int32_t the_bit = 1 << channel_id;
-#if defined(RING_DEBUG)
- printk("[PF_RING] --> add_pkt_to_ring(len=%d) [pfr->channel_id=%d][channel_id=%d]\n",
- hdr->len, pfr->channel_id, channel_id);
-#endif
+ if(enable_debug)
+ printk("[PF_RING] --> add_pkt_to_ring(len=%d) [pfr->channel_id=%d][channel_id=%d]\n",
+ hdr->len, pfr->channel_id, channel_id);
if((!pfr->ring_active) || (!skb))
- return;
+ return(0);
if((pfr->channel_id != RING_ANY_CHANNEL)
&& (channel_id != RING_ANY_CHANNEL)
&& ((pfr->channel_id & the_bit) != the_bit))
- return; /* Wrong channel */
+ return(0); /* Wrong channel */
- hdr->caplen = min(pfr->bucket_len - offset, hdr->caplen);
+ hdr->caplen = min_val(pfr->bucket_len - offset, hdr->caplen);
if(pfr->kernel_consumer_plugin_id
&& plugin_registration[pfr->kernel_consumer_plugin_id]->pfring_packet_reader) {
- write_lock_bh(&pfr->ring_index_lock); /* Serialize */
+ write_lock(&pfr->ring_index_lock); /* Serialize */
plugin_registration[pfr->kernel_consumer_plugin_id]->pfring_packet_reader(pfr, skb, channel_id, hdr, displ);
pfr->slots_info->tot_pkts++;
- write_unlock_bh(&pfr->ring_index_lock);
- return;
+ write_unlock(&pfr->ring_index_lock);
+ return(0);
}
- copy_data_to_ring(skb, pfr, hdr, displ, offset, plugin_mem, NULL, 0);
+ return(copy_data_to_ring(skb, pfr, hdr, displ, offset, plugin_mem, NULL, 0));
}
/* ********************************** */
-static int add_hdr_to_ring(struct ring_opt *pfr, struct pfring_pkthdr *hdr)
+static int add_packet_to_ring(struct pf_ring_socket *pfr, struct pfring_pkthdr *hdr,
+ struct sk_buff *skb,
+ int displ, u_int8_t parse_pkt_first)
{
- read_lock_bh(&ring_mgmt_lock);
- add_pkt_to_ring(NULL, pfr, hdr, 0, 0, 0, NULL);
- read_unlock_bh(&ring_mgmt_lock);
+ if(parse_pkt_first)
+ parse_pkt(skb, displ, hdr, 0 /* Do not reset user-specified fields */);
+
+ ring_read_lock();
+ add_pkt_to_ring(skb, pfr, hdr, 0, RING_ANY_CHANNEL, displ, NULL);
+ ring_read_unlock();
+ return(0);
+}
+
+/* ********************************** */
+
+static int add_raw_packet_to_ring(struct pf_ring_socket *pfr, struct pfring_pkthdr *hdr,
+ char *data, u_int data_len,
+ u_int8_t parse_pkt_first)
+{
+ if(parse_pkt_first)
+ parse_raw_pkt(data, data_len, hdr, 0 /* Do not reset user-specified fields */);
+
+ ring_read_lock();
+ copy_raw_data_to_ring(pfr, hdr, data, data_len);
+ ring_read_unlock();
return(0);
}
/* ********************************** */
+static int add_hdr_to_ring(struct pf_ring_socket *pfr, struct pfring_pkthdr *hdr)
+{
+ return(add_packet_to_ring(pfr, hdr, NULL, 0, 0));
+}
+
+/* ********************************** */
+
/* Free filtering placeholders */
static void free_parse_memory(struct parse_buffer *parse_memory_buffer[])
{
@@ -1751,13 +2041,12 @@
/* ********************************** */
static int reflect_packet(struct sk_buff *skb,
- struct ring_opt *pfr,
+ struct pf_ring_socket *pfr,
struct net_device *reflector_dev,
- int displ)
+ int displ,
+ rule_action_behaviour behaviour)
{
- int debug = 0;
-
- if(debug)
+ if(enable_debug)
printk("[PF_RING] reflect_packet called\n");
if((reflector_dev != NULL)
@@ -1774,6 +2063,15 @@
atomic_inc(&skb->users);
if(displ > 0) skb->data -= displ, skb->len += displ;
+ if(behaviour == bounce_packet_and_stop_rule_evaluation) {
+ char dst_mac[6];
+
+ /* Swap mac addresses */
+ memcpy(dst_mac, skb->data, 6);
+ memcpy(skb->data, &skb->data[6], 6);
+ memcpy(&skb->data[6], dst_mac, 6);
+ }
+
/*
NOTE
dev_queue_xmit() must be called with interrupts enabled
@@ -1795,6 +2093,7 @@
atomic_dec(&skb->users);
}
+ /* yield(); */
return(ret == NETDEV_TX_OK ? 0 : -ENETDOWN);
} else
pfr->slots_info->tot_fwd_notok++;
@@ -1804,296 +2103,387 @@
/* ********************************** */
-static int add_skb_to_ring(struct sk_buff *skb,
- struct ring_opt *pfr,
- struct pfring_pkthdr *hdr,
- int is_ip_pkt, int displ,
- u_int8_t channel_id,
- u_int8_t num_rx_channels)
-{
- int fwd_pkt = 0;
- struct list_head *ptr, *tmp_ptr;
- u_int8_t free_parse_mem = 0;
- u_int last_matched_plugin = 0, debug = 0;
- u_char hash_found = 0;
- struct parse_buffer *parse_memory_buffer[MAX_PLUGIN_ID] = { NULL };
+int check_perfect_rules(struct sk_buff *skb,
+ struct pf_ring_socket *pfr,
+ struct pfring_pkthdr *hdr,
+ int *fwd_pkt,
+ u_int8_t *free_parse_mem,
+ struct parse_buffer *parse_memory_buffer[MAX_PLUGIN_ID],
+ int displ, u_int *last_matched_plugin)
+{
+ u_int hash_idx;
+ sw_filtering_hash_bucket *hash_bucket;
+ u_int8_t hash_found = 0;
+
+ hash_idx = hash_pkt_header(hdr, 0, 0) % DEFAULT_RING_HASH_SIZE;
+ hash_bucket = pfr->sw_filtering_hash[hash_idx];
+
+ while(hash_bucket != NULL) {
+ if(hash_bucket_match(hash_bucket, hdr, 0, 0)) {
+ hash_found = 1;
+ break;
+ } else
+ hash_bucket = hash_bucket->next;
+ } /* while */
- /* This is a memory holder for storing parsed packet information
- that will then be freed when the packet has been handled
- */
+ if(hash_found) {
+ rule_action_behaviour behaviour = forward_packet_and_stop_rule_evaluation;
-#if defined(RING_DEBUG)
- printk("[PF_RING] --> add_skb_to_ring(len=%d) [channel_id=%d/%d][active=%d][%s]\n",
- hdr->len, channel_id, num_rx_channels,
- pfr->ring_active, pfr->ring_netdev->name);
-#endif
+ if((hash_bucket->rule.plugin_action.plugin_id != NO_PLUGIN_ID)
+ && (hash_bucket->rule.plugin_action.plugin_id < MAX_PLUGIN_ID)
+ && (plugin_registration[hash_bucket->rule.plugin_action.plugin_id] != NULL)
+ && (plugin_registration[hash_bucket->rule.plugin_action.plugin_id]->
+ pfring_plugin_handle_skb != NULL)
+ ) {
+ plugin_registration[hash_bucket->rule.plugin_action.plugin_id]
+ ->pfring_plugin_handle_skb(pfr, NULL, hash_bucket, hdr, skb, displ, 0, /* no plugin */
+ &parse_memory_buffer[hash_bucket->rule.plugin_action.plugin_id],
+ &behaviour);
+
+ if(parse_memory_buffer[hash_bucket->rule.plugin_action.plugin_id])
+ *free_parse_mem = 1;
+ *last_matched_plugin = hash_bucket->rule.plugin_action.plugin_id;
+ hdr->extended_hdr.parsed_pkt.last_matched_plugin_id = hash_bucket->rule.plugin_action.plugin_id;
+ } else
+ behaviour = hash_bucket->rule.rule_action;
- if((!pfring_enabled) || ((!pfr->ring_active) && (pfr->master_ring == NULL)))
- return(-1);
+ switch(behaviour) {
+ case forward_packet_and_stop_rule_evaluation:
+ *fwd_pkt = 1;
+ break;
+ case dont_forward_packet_and_stop_rule_evaluation:
+ *fwd_pkt = 0;
+ break;
+ case execute_action_and_stop_rule_evaluation:
+ *fwd_pkt = 0;
+ break;
+ case execute_action_and_continue_rule_evaluation:
+ *fwd_pkt = 0;
+ hash_found = 0; /* This way we also evaluate the list of rules */
+ break;
+ case forward_packet_add_rule_and_stop_rule_evaluation:
+ *fwd_pkt = 1;
+ break;
+ case reflect_packet_and_stop_rule_evaluation:
+ case bounce_packet_and_stop_rule_evaluation:
+ *fwd_pkt = 0;
+ reflect_packet(skb, pfr, hash_bucket->rule.internals.reflector_dev, displ, behaviour);
+ break;
+ case reflect_packet_and_continue_rule_evaluation:
+ case bounce_packet_and_continue_rule_evaluation:
+ *fwd_pkt = 0;
+ reflect_packet(skb, pfr, hash_bucket->rule.internals.reflector_dev, displ, behaviour);
+ hash_found = 0; /* This way we also evaluate the list of rules */
+ break;
+ }
+ } else {
+ /* printk("[PF_RING] Packet not found\n"); */
+ }
- pfr->num_rx_channels = num_rx_channels; /* Constantly updated */
- hdr->extended_hdr.parsed_pkt.last_matched_rule_id = (u_int16_t)-1;
+ return(hash_found);
+}
- atomic_set(&pfr->num_ring_users, 1);
+/* ********************************** */
- /* [1] BPF Filtering (from af_packet.c) */
- if(pfr->bpfFilter != NULL) {
- unsigned res = 1, len;
+int check_wildcard_rules(struct sk_buff *skb,
+ struct pf_ring_socket *pfr,
+ struct pfring_pkthdr *hdr,
+ int *fwd_pkt,
+ u_int8_t *free_parse_mem,
+ struct parse_buffer *parse_memory_buffer[MAX_PLUGIN_ID],
+ int displ, u_int *last_matched_plugin)
+{
+ struct list_head *ptr, *tmp_ptr;
- len = skb->len - skb->data_len;
+ if(enable_debug)
+ printk("[PF_RING] Entered check_wildcard_rules()\n");
- skb->data -= displ;
- res = sk_run_filter(skb, pfr->bpfFilter->insns,
- pfr->bpfFilter->len);
- skb->data += displ;
+ list_for_each_safe(ptr, tmp_ptr, &pfr->sw_filtering_rules) {
+ sw_filtering_rule_element *entry;
+ rule_action_behaviour behaviour = forward_packet_and_stop_rule_evaluation;
- if(res == 0) {
- /* Filter failed */
-#if defined(RING_DEBUG)
- printk("[PF_RING] add_skb_to_ring(skb): Filter failed [len=%d][tot=%llu]"
- "[insert_off=%d][pkt_type=%d][cloned=%d]\n",
- (int)skb->len, pfr->slots_info->tot_pkts,
- pfr->slots_info->insert_off, skb->pkt_type,
- skb->cloned);
-#endif
- atomic_set(&pfr->num_ring_users, 0);
- return(-1);
- }
- }
+ entry = list_entry(ptr, sw_filtering_rule_element, list);
-#if defined(RING_DEBUG)
- printk("[PF_RING] add_skb_to_ring: [%s][displ=%d][len=%d][caplen=%d]"
- "[is_ip_pkt=%d][%d -> %d][%p/%p]\n",
- (skb->dev->name == NULL) ? skb->dev->name : "<NULL>",
- displ, hdr->len, hdr->caplen,
- is_ip_pkt, hdr->extended_hdr.parsed_pkt.l4_src_port,
- hdr->extended_hdr.parsed_pkt.l4_dst_port, skb->dev,
- pfr->ring_netdev);
-#endif
-
- /* ************************************* */
-
-#if defined(RING_DEBUG)
- printk("[PF_RING] add_skb_to_ring(skb) [len=%d][tot=%llu][insert_off=%d]"
- "[pkt_type=%d][cloned=%d]\n",
- (int)skb->len, pfr->slots_info->tot_pkts,
- pfr->slots_info->insert_off, skb->pkt_type, skb->cloned);
-#endif
+ if(match_filtering_rule(pfr, entry, hdr, skb, displ,
+ parse_memory_buffer, free_parse_mem,
+ last_matched_plugin, &behaviour)) {
+ if(enable_debug)
+ printk("[PF_RING] behaviour=%d\n", behaviour);
- /* Extensions */
- fwd_pkt = pfr->rules_default_accept_policy;
- /* printk("[PF_RING] rules_default_accept_policy: [fwd_pkt=%d]\n", fwd_pkt); */
+ hdr->extended_hdr.parsed_pkt.last_matched_rule_id = entry->rule.rule_id;
- /* ************************** */
+ if(behaviour == forward_packet_and_stop_rule_evaluation) {
+ *fwd_pkt = 1;
+ break;
+ } else if(behaviour == forward_packet_add_rule_and_stop_rule_evaluation) {
+ sw_filtering_hash_bucket *hash_bucket;
- /* [2] Filter packet according to rules */
- if(debug)
- printk("[PF_RING] About to evaluate packet [len=%d][tot=%llu][insert_off=%d]"
- "[pkt_type=%d][cloned=%d]\n", (int)skb->len,
- pfr->slots_info->tot_pkts, pfr->slots_info->insert_off,
- skb->pkt_type, skb->cloned);
+ *fwd_pkt = 1;
+ hash_bucket = (sw_filtering_hash_bucket *)kcalloc(1, sizeof(sw_filtering_hash_bucket),
+ GFP_ATOMIC);
+
+ if(hash_bucket) {
+ int rc = 0;
+
+ if(*last_matched_plugin
+ && plugin_registration[*last_matched_plugin] != NULL
+ && plugin_registration[*last_matched_plugin]->pfring_plugin_add_rule != NULL
+ && (plugin_registration[*last_matched_plugin]->pfring_plugin_add_rule(entry, hdr, hash_bucket) == 0) ) {
+ if(enable_debug) {
+ printk("pfring_plugin_add_rule(entry, hdr, hash_bucket) done!\n");
+ }
+ } else {
+ hash_bucket->rule.vlan_id = hdr->extended_hdr.parsed_pkt.vlan_id;
+ hash_bucket->rule.proto = hdr->extended_hdr.parsed_pkt.l3_proto;
+ hash_bucket->rule.host4_peer_a = hdr->extended_hdr.parsed_pkt.ipv4_src;
+ hash_bucket->rule.host4_peer_b = hdr->extended_hdr.parsed_pkt.ipv4_dst;
+ hash_bucket->rule.port_peer_a = hdr->extended_hdr.parsed_pkt.l4_src_port;
+ hash_bucket->rule.port_peer_b = hdr->extended_hdr.parsed_pkt.l4_dst_port;
+ hash_bucket->rule.rule_action = forward_packet_and_stop_rule_evaluation;
+ hash_bucket->rule.reflector_device_name[0] = '\0';
+ hash_bucket->rule.internals.jiffies_last_match = jiffies; /* Avoid immediate rule purging */
+ hash_bucket->rule.internals.reflector_dev = NULL;
+ hash_bucket->rule.plugin_action.plugin_id = NO_PLUGIN_ID;
+ }
- /* [2.1] Search the hash */
- if(pfr->filtering_hash != NULL) {
- u_int hash_idx;
- filtering_hash_bucket *hash_bucket;
-
- hash_idx = hash_pkt_header(hdr, 0, 0) % DEFAULT_RING_HASH_SIZE;
- hash_bucket = pfr->filtering_hash[hash_idx];
-
- while(hash_bucket != NULL) {
- if(hash_bucket_match(hash_bucket, hdr, 0, 0)) {
- hash_found = 1;
- break;
- } else
- hash_bucket = hash_bucket->next;
- } /* while */
+ write_lock(&pfr->ring_rules_lock);
+ rc = pfr->handle_hash_rule(pfr, hash_bucket, 1 /* add_rule_from_plugin */);
- if(hash_found) {
- rule_action_behaviour behaviour = forward_packet_and_stop_rule_evaluation;
+ if((rc != 0) && (rc != -EEXIST)) {
+ write_unlock(&pfr->ring_rules_lock);
+ kfree(hash_bucket);
+ return(-1);
+ } else {
+ if(rc != -EEXIST) /* Rule already existing */
+ pfr->num_sw_filtering_rules++;
- if((hash_bucket->rule.plugin_action.plugin_id != NO_PLUGIN_ID)
- && (hash_bucket->rule.plugin_action.plugin_id < MAX_PLUGIN_ID)
- && (plugin_registration[hash_bucket->rule.plugin_action.plugin_id] != NULL)
- && (plugin_registration[hash_bucket->rule.plugin_action.plugin_id]->
- pfring_plugin_handle_skb != NULL)
- ) {
- plugin_registration[hash_bucket->rule.plugin_action.plugin_id]
- ->pfring_plugin_handle_skb(pfr, NULL, hash_bucket, hdr, skb, 0, /* no plugin */
- &parse_memory_buffer
- [hash_bucket->rule.plugin_action.plugin_id],
- &behaviour);
-
- if(parse_memory_buffer[hash_bucket->rule.plugin_action.plugin_id])
- free_parse_mem = 1;
- last_matched_plugin = hash_bucket->rule.plugin_action.plugin_id;
- hdr->extended_hdr.parsed_pkt.last_matched_plugin_id = hash_bucket->rule.plugin_action.plugin_id;
- } else
- behaviour = hash_bucket->rule.rule_action;
+ write_unlock(&pfr->ring_rules_lock);
- switch (behaviour) {
- case forward_packet_and_stop_rule_evaluation:
- fwd_pkt = 1;
+ if(enable_debug)
+ printk("[PF_RING] Added rule: [%d.%d.%d.%d:%d <-> %d.%d.%d.%d:%d][tot_rules=%d]\n",
+ ((hash_bucket->rule.host4_peer_a >> 24) & 0xff), ((hash_bucket->rule.host4_peer_a >> 16) & 0xff),
+ ((hash_bucket->rule.host4_peer_a >> 8) & 0xff), ((hash_bucket->rule.host4_peer_a >> 0) & 0xff),
+ hash_bucket->rule.port_peer_a, ((hash_bucket->rule.host4_peer_b >> 24) & 0xff),
+ ((hash_bucket->rule.host4_peer_b >> 16) & 0xff), ((hash_bucket->rule.host4_peer_b >> 8) & 0xff),
+ ((hash_bucket->rule.host4_peer_b >> 0) & 0xff), hash_bucket->rule.port_peer_b, pfr->num_sw_filtering_rules);
+ }
+ }
break;
- case dont_forward_packet_and_stop_rule_evaluation:
- fwd_pkt = 0;
+ } else if(behaviour == dont_forward_packet_and_stop_rule_evaluation) {
+ *fwd_pkt = 0;
break;
- case execute_action_and_continue_rule_evaluation:
- hash_found = 0; /* This way we also evaluate the list of rules */
+ }
+
+ if(entry->rule.rule_action == forward_packet_and_stop_rule_evaluation) {
+ *fwd_pkt = 1;
break;
- case forward_packet_add_rule_and_stop_rule_evaluation:
- fwd_pkt = 1;
+ } else if(entry->rule.rule_action == dont_forward_packet_and_stop_rule_evaluation) {
+ *fwd_pkt = 0;
break;
- case reflect_packet_and_stop_rule_evaluation:
- fwd_pkt = 0;
- reflect_packet(skb, pfr, hash_bucket->rule.internals.reflector_dev, displ);
+ } else if(entry->rule.rule_action == execute_action_and_stop_rule_evaluation) {
+ printk("[PF_RING] *** execute_action_and_stop_rule_evaluation\n");
break;
- case reflect_packet_and_continue_rule_evaluation:
- fwd_pkt = 0;
- reflect_packet(skb, pfr, hash_bucket->rule.internals.reflector_dev, displ);
- hash_found = 0; /* This way we also evaluate the list of rules */
+ } else if(entry->rule.rule_action == execute_action_and_continue_rule_evaluation) {
+ /* The action has already been performed inside match_filtering_rule()
+ hence instead of stopping rule evaluation, the next rule
+ will be evaluated */
+ } else if((entry->rule.rule_action == reflect_packet_and_stop_rule_evaluation)
+ || (entry->rule.rule_action == bounce_packet_and_stop_rule_evaluation)) {
+ *fwd_pkt = 0;
+ reflect_packet(skb, pfr, entry->rule.internals.reflector_dev, displ, entry->rule.rule_action);
break;
+ } else if((entry->rule.rule_action == reflect_packet_and_continue_rule_evaluation)
+ || (entry->rule.rule_action == bounce_packet_and_continue_rule_evaluation)) {
+ *fwd_pkt = 1;
+ reflect_packet(skb, pfr, entry->rule.internals.reflector_dev, displ, entry->rule.rule_action);
}
- } else {
- /* printk("[PF_RING] Packet not found\n"); */
+ }
+ } /* for */
+
+ return(0);
+}
+
+/* ********************************** */
+
+/*
+ This code has been partially copied from af_packet.c
+
+ Return code
+ 1: pass the filter
+ 0: this packet has to be dropped
+ */
+int bpf_filter_skb(struct sk_buff *skb,
+ struct pf_ring_socket *pfr,
+ int displ) {
+ if(pfr->bpfFilter != NULL) {
+ unsigned res = 1, len;
+ u8 *skb_head = skb->data;
+ int skb_len = skb->len;
+
+ len = skb->len - skb->data_len;
+
+ if(displ > 0) {
+ /*
+ Move off the offset (we modify the packet for the sake of filtering)
+ thus we need to restore it later on
+
+ NOTE: displ = 0 | skb_network_offset(skb)
+ */
+ skb_push(skb, displ);
+ }
+
+ rcu_read_lock_bh();
+ res = sk_run_filter(skb, pfr->bpfFilter->insns
+#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38))
+ , skb->len
+#endif
+ );
+ rcu_read_unlock_bh();
+
+ /* Restore */
+ if(displ > 0)
+ skb->data = skb_head, skb->len = skb_len;
+
+ if(res == 0) {
+ /* Filter failed */
+ if(enable_debug)
+ printk("[PF_RING] add_skb_to_ring(skb): Filter failed [len=%d][tot=%llu]"
+ "[insert_off=%d][pkt_type=%d][cloned=%d]\n",
+ (int)skb->len, pfr->slots_info->tot_pkts,
+ pfr->slots_info->insert_off, skb->pkt_type,
+ skb->cloned);
+
+ return(0);
}
}
- /* [2.2] Search rules list */
- if((!hash_found) && (pfr->num_filtering_rules > 0)) {
- list_for_each_safe(ptr, tmp_ptr, &pfr->rules) {
- filtering_rule_element *entry;
- rule_action_behaviour behaviour =
- forward_packet_and_stop_rule_evaluation;
-
- entry = list_entry(ptr, filtering_rule_element, list);
-
- if(match_filtering_rule(pfr, entry, hdr, skb, displ,
- parse_memory_buffer,
- &free_parse_mem,
- &last_matched_plugin,
- &behaviour)) {
- if(debug)
- printk("[PF_RING] behaviour=%d\n", behaviour);
+ return(1);
+}
- hdr->extended_hdr.parsed_pkt.last_matched_rule_id = entry->rule.rule_id;
+/* ********************************** */
- if(behaviour == forward_packet_and_stop_rule_evaluation) {
- fwd_pkt = 1;
- break;
- } else if(behaviour == forward_packet_add_rule_and_stop_rule_evaluation) {
- filtering_hash_bucket *hash_bucket;
+/*
+ * add_skb_to_ring()
+ *
+ * Add the specified skb to the ring so that userland apps/plugins
+ * can use the packet.
+ *
+ * Return code:
+ * 0 packet successully processed but no room in the ring
+ * 1 packet successully processed and available room in the ring
+ * -1 processing error (e.g. the packet has been discarded by
+ * filter, ring not active...)
+ *
+ */
+static int add_skb_to_ring(struct sk_buff *skb,
+ struct pf_ring_socket *pfr,
+ struct pfring_pkthdr *hdr,
+ int is_ip_pkt, int displ,
+ u_int8_t channel_id,
+ u_int8_t num_rx_channels)
+{
+ int fwd_pkt = 0, rc = 0;
+ struct parse_buffer *parse_memory_buffer[MAX_PLUGIN_ID] = { NULL };
+ u_int8_t free_parse_mem = 0;
+ u_int last_matched_plugin = 0;
+ u_int8_t hash_found = 0;
- fwd_pkt = 1;
+ if(pfr && pfr->rehash_rss && skb->dev)
+ channel_id = hash_pkt_header(hdr, 0, 0) % get_num_rx_queues(skb->dev);
- hash_bucket = (filtering_hash_bucket *)kcalloc(1, sizeof(filtering_hash_bucket),
- GFP_KERNEL);
+ /* This is a memory holder for storing parsed packet information
+ that will then be freed when the packet has been handled
+ */
- if(hash_bucket) {
- int rc = 0;
-
- if(last_matched_plugin
- && plugin_registration[last_matched_plugin] != NULL
- && plugin_registration[last_matched_plugin]->pfring_plugin_add_rule != NULL
- && (plugin_registration[last_matched_plugin]->pfring_plugin_add_rule(entry, hdr, hash_bucket) == 0) ) {
- if(debug) {
- printk("pfring_plugin_add_rule(entry, hdr, hash_bucket) done!\n");
- }
- } else {
- hash_bucket->rule.vlan_id = hdr->extended_hdr.parsed_pkt.vlan_id;
- hash_bucket->rule.proto = hdr->extended_hdr.parsed_pkt.l3_proto;
- hash_bucket->rule.host4_peer_a = hdr->extended_hdr.parsed_pkt.ipv4_src;
- hash_bucket->rule.host4_peer_b = hdr->extended_hdr.parsed_pkt.ipv4_dst;
- hash_bucket->rule.port_peer_a = hdr->extended_hdr.parsed_pkt.l4_src_port;
- hash_bucket->rule.port_peer_b = hdr->extended_hdr.parsed_pkt.l4_dst_port;
- hash_bucket->rule.rule_action = forward_packet_and_stop_rule_evaluation;
- hash_bucket->rule.reflector_device_name[0] = '\0';
- hash_bucket->rule.internals.jiffies_last_match = jiffies;/* Avoid immediate rule purging */
- hash_bucket->rule.internals.reflector_dev = NULL;
- hash_bucket->rule.plugin_action.plugin_id = NO_PLUGIN_ID;
- }
+ if(enable_debug)
+ printk("[PF_RING] --> add_skb_to_ring(len=%d) [channel_id=%d/%d][active=%d][%s]\n",
+ hdr->len, channel_id, num_rx_channels,
+ pfr->ring_active, pfr->ring_netdev->dev->name);
- write_lock(&pfr->ring_rules_lock);
- rc = pfr->handle_hash_rule(pfr, hash_bucket, 1 /* add_rule_from_plugin */);
+ if((!pfring_enabled) || ((!pfr->ring_active) && (pfr->master_ring == NULL)))
+ return(-1);
- if((rc != 0) && (rc != -EEXIST)) {
- write_unlock(&pfr->ring_rules_lock);
- kfree(hash_bucket);
- return(-1);
- } else {
- if(rc != -EEXIST) /* Rule already existing */
- pfr->num_filtering_rules++;
-
- write_unlock(&pfr->ring_rules_lock);
-
- if(debug)
- printk("[PF_RING] Added rule: [%d.%d.%d.%d:%d <-> %d.%d.%d.%d:%d][tot_rules=%d]\n",
- ((hash_bucket->rule.host4_peer_a >> 24) & 0xff), ((hash_bucket->rule.host4_peer_a >> 16) & 0xff),
- ((hash_bucket->rule.host4_peer_a >> 8) & 0xff), ((hash_bucket->rule.host4_peer_a >> 0) & 0xff),
- hash_bucket->rule.port_peer_a, ((hash_bucket->rule.host4_peer_b >> 24) & 0xff),
- ((hash_bucket->rule.host4_peer_b >> 16) & 0xff), ((hash_bucket->rule.host4_peer_b >> 8) & 0xff),
- ((hash_bucket->rule.host4_peer_b >> 0) & 0xff), hash_bucket->rule.port_peer_b, pfr->num_filtering_rules);
- }
- }
- break;
- } else if(behaviour == dont_forward_packet_and_stop_rule_evaluation) {
- fwd_pkt = 0;
- break;
- }
+ pfr->num_rx_channels = num_rx_channels; /* Constantly updated */
+ hdr->extended_hdr.parsed_pkt.last_matched_rule_id = (u_int16_t)-1;
- if(entry->rule.rule_action == forward_packet_and_stop_rule_evaluation) {
- fwd_pkt = 1;
- break;
- } else if(entry->rule.rule_action == dont_forward_packet_and_stop_rule_evaluation) {
- fwd_pkt = 0;
- break;
- } else if(entry->rule.rule_action == execute_action_and_continue_rule_evaluation) {
- /* The action has already been performed inside match_filtering_rule()
- hence instead of stopping rule evaluation, the next rule
- will be evaluated */
- } else if(entry->rule.rule_action == reflect_packet_and_stop_rule_evaluation) {
- fwd_pkt = 0;
- reflect_packet(skb, pfr, entry->rule.internals.reflector_dev, displ);
- break;
- } else if(entry->rule.rule_action == reflect_packet_and_continue_rule_evaluation) {
- fwd_pkt = 0;
- reflect_packet(skb, pfr, entry->rule.internals.reflector_dev, displ);
- }
- }
- } /* for */
+ atomic_set(&pfr->num_ring_users, 1);
+
+ /* [1] BPF Filtering */
+ if(pfr->bpfFilter != NULL) {
+ if(bpf_filter_skb(skb, pfr, displ) == 0) {
+ atomic_set(&pfr->num_ring_users, 0);
+ return(-1);
+ }
+ }
+
+ if(enable_debug) {
+ printk("[PF_RING] add_skb_to_ring: [%s][displ=%d][len=%d][caplen=%d]"
+ "[is_ip_pkt=%d][%d -> %d][%p/%p]\n",
+ (skb->dev->name != NULL) ? skb->dev->name : "<NULL>",
+ displ, hdr->len, hdr->caplen,
+ is_ip_pkt, hdr->extended_hdr.parsed_pkt.l4_src_port,
+ hdr->extended_hdr.parsed_pkt.l4_dst_port, skb->dev,
+ pfr->ring_netdev);
+ }
+
+ /* Extensions */
+ fwd_pkt = pfr->sw_filtering_rules_default_accept_policy;
+ /* printk("[PF_RING] rules_default_accept_policy: [fwd_pkt=%d]\n", fwd_pkt); */
+
+ /* ************************** */
+
+ /* [2] Filter packet according to rules */
+
+ /* [2.1] Search the hash */
+ if(pfr->sw_filtering_hash != NULL)
+ hash_found = check_perfect_rules(skb, pfr, hdr, &fwd_pkt, &free_parse_mem,
+ parse_memory_buffer, displ, &last_matched_plugin);
+
+ if(enable_debug)
+ printk("[PF_RING] check_perfect_rules() returned %d\n", hash_found);
+
+ /* [2.2] Search rules list */
+ if((!hash_found) && (pfr->num_sw_filtering_rules > 0)) {
+ if(check_wildcard_rules(skb, pfr, hdr, &fwd_pkt, &free_parse_mem,
+ parse_memory_buffer, displ, &last_matched_plugin) != 0)
+ fwd_pkt = 0;
+
+ if(enable_debug)
+ printk("[PF_RING] check_wildcard_rules() completed: fwd_pkt=%d\n", fwd_pkt);
}
if(fwd_pkt) {
/* We accept the packet: it needs to be queued */
- if(debug)
+ if(enable_debug)
printk("[PF_RING] Forwarding packet to userland\n");
/* [3] Packet sampling */
if(pfr->sample_rate > 1) {
- write_lock_bh(&pfr->ring_index_lock);
+ write_lock(&pfr->ring_index_lock);
pfr->slots_info->tot_pkts++;
- if(pfr->pktToSample == 0) {
+ if(pfr->pktToSample <= 1) {
pfr->pktToSample = pfr->sample_rate;
} else {
pfr->pktToSample--;
-#if defined(RING_DEBUG)
- printk("[PF_RING] add_skb_to_ring(skb): sampled packet [len=%d]"
- "[tot=%llu][insert_off=%d][pkt_type=%d][cloned=%d]\n",
- (int)skb->len, pfr->slots_info->tot_pkts,
- pfr->slots_info->insert_off, skb->pkt_type,
- skb->cloned);
-#endif
+ if(enable_debug)
+ printk("[PF_RING] add_skb_to_ring(skb): sampled packet [len=%d]"
+ "[tot=%llu][insert_off=%d][pkt_type=%d][cloned=%d]\n",
+ (int)skb->len, pfr->slots_info->tot_pkts,
+ pfr->slots_info->insert_off, skb->pkt_type,
+ skb->cloned);
+
+ write_unlock(&pfr->ring_index_lock);
- write_unlock_bh(&pfr->ring_index_lock);
if(free_parse_mem)
free_parse_memory(parse_memory_buffer);
+
atomic_set(&pfr->num_ring_users, 0);
return(-1);
}
- write_unlock_bh(&pfr->ring_index_lock);
+ write_unlock(&pfr->ring_index_lock);
}
if(hdr->caplen > 0) {
@@ -2103,14 +2493,13 @@
if((last_matched_plugin > 0)
&& (parse_memory_buffer[last_matched_plugin] != NULL)) {
- offset = hdr->extended_hdr.parsed_header_len =
- parse_memory_buffer[last_matched_plugin]->mem_len;
+ offset = hdr->extended_hdr.parsed_header_len = parse_memory_buffer[last_matched_plugin]->mem_len;
hdr->extended_hdr.parsed_pkt.last_matched_plugin_id = last_matched_plugin;
-#if defined(RING_DEBUG)
- printk("[PF_RING] --> [last_matched_plugin = %d][extended_hdr.parsed_header_len=%d]\n",
- last_matched_plugin, hdr->extended_hdr.parsed_header_len);
-#endif
+
+ if(enable_debug)
+ printk("[PF_RING] --> [last_matched_plugin = %d][extended_hdr.parsed_header_len=%d]\n",
+ last_matched_plugin, hdr->extended_hdr.parsed_header_len);
if(offset > pfr->bucket_len)
offset = hdr->extended_hdr.parsed_header_len = pfr->bucket_len;
@@ -2119,20 +2508,20 @@
} else
offset = 0, hdr->extended_hdr.parsed_header_len = 0, mem = NULL;
- add_pkt_to_ring(skb, pfr, hdr, displ, channel_id, offset, mem);
+ rc = add_pkt_to_ring(skb, pfr, hdr, displ, channel_id, offset, mem);
}
}
-#if defined(RING_DEBUG)
- printk("[PF_RING] [pfr->slots_info->insert_off=%d]\n",
- pfr->slots_info->insert_off);
-#endif
+ if(enable_debug)
+ printk("[PF_RING] [pfr->slots_info->insert_off=%d]\n",
+ pfr->slots_info->insert_off);
if(free_parse_mem)
free_parse_memory(parse_memory_buffer);
+
atomic_set(&pfr->num_ring_users, 0);
- return(0);
+ return(rc);
}
/* ********************************** */
@@ -2159,28 +2548,29 @@
if(reg == NULL)
return(-1);
-#ifdef RING_DEBUG
- printk("[PF_RING] --> register_plugin(%d)\n", reg->plugin_id);
-#endif
+ if(enable_debug)
+ printk("[PF_RING] --> register_plugin(%d)\n", reg->plugin_id);
if((reg->plugin_id >= MAX_PLUGIN_ID) || (reg->plugin_id == 0))
return(-EINVAL);
if(plugin_registration[reg->plugin_id] != NULL)
return(-EINVAL); /* plugin already registered */
- else {
- plugin_registration[reg->plugin_id] = reg;
- plugin_registration_size++;
-
- max_registered_plugin_id =
- max(max_registered_plugin_id, reg->plugin_id);
- printk("[PF_RING] registered plugin [id=%d][max=%d][%p]\n",
- reg->plugin_id, max_registered_plugin_id,
- plugin_registration[reg->plugin_id]);
- try_module_get(THIS_MODULE); /* Increment usage count */
- return(0);
- }
+ if(reg->pfring_plugin_register == NULL)
+ printk("[PF_RING] WARNING: plugin %d does not implement handle pfring_plugin_register: please fix it\n",
+ reg->plugin_id);
+
+ plugin_registration[reg->plugin_id] = reg;
+ plugin_registration_size++;
+
+ max_registered_plugin_id = max_val(max_registered_plugin_id, reg->plugin_id);
+
+ printk("[PF_RING] registered plugin [id=%d][max=%d][%p]\n",
+ reg->plugin_id, max_registered_plugin_id,
+ plugin_registration[reg->plugin_id]);
+ try_module_get(THIS_MODULE); /* Increment usage count */
+ return(0);
}
/* ********************************** */
@@ -2200,32 +2590,27 @@
plugin_registration[pfring_plugin_id] = NULL;
plugin_registration_size--;
- read_lock_bh(&ring_mgmt_lock);
+ ring_read_lock();
list_for_each_safe(ring_ptr, ring_tmp_ptr, &ring_table) {
struct ring_element *entry =
list_entry(ring_ptr, struct ring_element, list);
- struct ring_opt *pfr = ring_sk(entry->sk);
+ struct pf_ring_socket *pfr = ring_sk(entry->sk);
- list_for_each_safe(ptr, tmp_ptr, &pfr->rules) {
- filtering_rule_element *rule;
+ list_for_each_safe(ptr, tmp_ptr, &pfr->sw_filtering_rules) {
+ sw_filtering_rule_element *rule;
- rule = list_entry(ptr, filtering_rule_element, list);
+ rule = list_entry(ptr, sw_filtering_rule_element, list);
if(rule->rule.plugin_action.plugin_id == pfring_plugin_id) {
if(plugin_registration[pfring_plugin_id]
&& plugin_registration[pfring_plugin_id]->pfring_plugin_free_ring_mem) {
/* Custom free function */
- plugin_registration
- [pfring_plugin_id]->
- pfring_plugin_free_ring_mem
- (rule);
+ plugin_registration[pfring_plugin_id]->pfring_plugin_free_ring_mem(rule);
} else {
if(rule->plugin_data_ptr !=
NULL) {
- kfree(rule->
- plugin_data_ptr);
- rule->plugin_data_ptr =
- NULL;
+ kfree(rule->plugin_data_ptr);
+ rule->plugin_data_ptr = NULL;
}
}
@@ -2233,7 +2618,7 @@
}
}
}
- read_unlock_bh(&ring_mgmt_lock);
+ ring_read_unlock();
for(i = MAX_PLUGIN_ID - 1; i > 0; i--) {
if(plugin_registration[i] != NULL) {
@@ -2268,31 +2653,206 @@
/* ********************************** */
+static struct sk_buff* defrag_skb(struct sk_buff *skb,
+ u_int16_t displ,
+ struct pfring_pkthdr *hdr,
+ int *defragmented_skb) {
+ struct sk_buff *cloned = NULL;
+ struct iphdr *iphdr = NULL;
+ struct sk_buff *skk = NULL;
+
+ skb_set_network_header(skb, hdr->extended_hdr.parsed_pkt.offset.l3_offset - displ);
+ skb_reset_transport_header(skb);
+
+ iphdr = ip_hdr(skb);
+
+ if(iphdr && (iphdr->version == 4)) {
+ if(unlikely(enable_debug))
+ printk("[PF_RING] [version=%d] %X -> %X\n",
+ iphdr->version, iphdr->saddr, iphdr->daddr);
+
+ if(iphdr->frag_off & htons(IP_MF | IP_OFFSET)) {
+ if((cloned = skb_clone(skb, GFP_ATOMIC)) != NULL) {
+ int vlan_offset = 0;
+
+ if (displ && (hdr->extended_hdr.parsed_pkt.offset.l3_offset - displ) /*VLAN*/){
+ vlan_offset = 4;
+ skb_pull(cloned, vlan_offset);
+ displ += vlan_offset;
+ }
+
+ skb_set_network_header(cloned, hdr->extended_hdr.parsed_pkt.offset.l3_offset - displ);
+ skb_reset_transport_header(cloned);
+ iphdr = ip_hdr(cloned);
+
+ if(unlikely(enable_debug)) {
+ int ihl, end;
+ int offset = ntohs(iphdr->frag_off);
+ offset &= IP_OFFSET;
+ offset <<= 3;
+ ihl = iphdr->ihl * 4;
+ end = offset + cloned->len - ihl;
+
+ printk("[PF_RING] There is a fragment to handle [proto=%d][frag_off=%u]"
+ "[ip_id=%u][ip_hdr_len=%d][end=%d][network_header=%d][displ=%d]\n",
+ iphdr->protocol, offset,
+ ntohs(iphdr->id),
+ ihl, end,
+ hdr->extended_hdr.parsed_pkt.offset.l3_offset - displ, displ);
+ }
+ skk = ring_gather_frags(cloned);
+
+ if(skk != NULL) {
+ if(unlikely(enable_debug)) {
+ unsigned char *c;
+ printk("[PF_RING] IP reasm on new skb [skb_len=%d]"
+ "[head_len=%d][nr_frags=%d][frag_list=%p]\n",
+ (int)skk->len,
+ skb_headlen(skk),
+ skb_shinfo(skk)->nr_frags,
+ skb_shinfo(skk)->frag_list);
+ c = skb_network_header(skk);
+ printk("[PF_RING] IP header "
+ "%X %X %X %X %X %X %X %X %X %X %X %X %X %X %X %X %X %X %X %X\n",
+ c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7], c[8], c[9],
+ c[10], c[11], c[12], c[13], c[14], c[15], c[16], c[17], c[18], c[19]);
+ c -= displ;
+ printk("[PF_RING] L2 header "
+ "%X %X %X %X %X %X %X %X %X %X %X %X %X %X %X %X %X %X\n",
+ c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7], c[8], c[9],
+ c[10], c[11], c[12], c[13], c[14], c[15], c[16], c[17]);
+ }
+
+ if (vlan_offset > 0){
+ skb_push(skk, vlan_offset);
+ displ -= vlan_offset;
+ }
+
+ skb = skk;
+ *defragmented_skb = 1;
+ hdr->len = hdr->caplen = skb->len + displ;
+ parse_pkt(skb, displ, hdr, 1);
+ } else {
+ //printk("[PF_RING] Fragment queued \n");
+ return(NULL); /* mask rcvd fragments */
+ }
+ }
+ } else {
+ if(unlikely(enable_debug))
+ printk("[PF_RING] Do not seems to be a fragmented ip_pkt[iphdr=%p]\n",
+ iphdr);
+ }
+ } else if(iphdr && iphdr->version == 6) {
+ /* Re-assembling fragmented IPv6 packets has not been
+ implemented. Probability of observing fragmented IPv6
+ packets is extremely low. */
+ if(unlikely(enable_debug))
+ printk("[PF_RING] Re-assembling fragmented IPv6 packet hs not been implemented\n");
+ }
+
+ return(skb);
+}
+
+/* ********************************** */
+
+static inline void set_skb_time(struct sk_buff *skb, struct pfring_pkthdr *hdr) {
+ /* 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); /* If timestamp is missing add it */
+ hdr->ts.tv_sec = skb->stamp.tv_sec, hdr->ts.tv_usec = skb->stamp.tv_usec;
+ hdr->extended_hdr.timestamp_ns = 0; /* No nsec for old kernels */
+#elif(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22))
+ if(skb->tstamp.off_sec == 0)
+ __net_timestamp(skb); /* If timestamp is missing add it */
+ hdr->ts.tv_sec = skb->tstamp.off_sec, hdr->ts.tv_usec = skb->tstamp.off_usec;
+ hdr->extended_hdr.timestamp_ns = 0; /* No nsec for old kernels */
+#else /* 2.6.22 and above */
+ if(skb->tstamp.tv64 == 0)
+ __net_timestamp(skb); /* If timestamp is missing add it */
+
+ hdr->ts = ktime_to_timeval(skb->tstamp);
+
+#if(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30))
+ {
+ /* Use hardware timestamps when present. If not, just use software timestamps */
+ hdr->extended_hdr.timestamp_ns = ktime_to_ns(skb_hwtstamps(skb)->hwtstamp);
+
+ if(enable_debug)
+ printk("[PF_RING] hwts=%llu/dev=%s\n",
+ hdr->extended_hdr.timestamp_ns,
+ skb->dev ? skb->dev->name : "???");
+ }
+#endif
+ if(hdr->extended_hdr.timestamp_ns == 0)
+ hdr->extended_hdr.timestamp_ns = ktime_to_ns(skb->tstamp);
+#endif
+}
+
+/* ********************************** */
+
+/*
+ PF_RING main entry point
+
+ Return code
+ 0 - Packet not handled
+ 1 - Packet handled successfully
+ 2 - Packet handled successfully but unable to copy it into
+ the ring due to lack of available space
+*/
+
static int skb_ring_handler(struct sk_buff *skb,
u_char recv_packet,
u_char real_skb /* 1=real skb, 0=faked skb */ ,
- u_int8_t channel_id,
- u_int8_t num_rx_channels)
+ u_int32_t channel_id,
+ u_int32_t num_rx_channels)
{
struct sock *skElement;
- int rc = 0, is_ip_pkt;
+ int rc = 0, is_ip_pkt = 0, room_available = 0;
struct list_head *ptr;
struct pfring_pkthdr hdr;
int displ;
+ int defragmented_skb = 0;
struct sk_buff *skk = NULL;
struct sk_buff *orig_skb = skb;
+ /* Check if there's at least one PF_RING ring defined that
+ could receive the packet: if none just stop here */
+
+ if(ring_table_size == 0)
+ return(rc);
+
+ 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;
+
+ if(enable_debug) {
+ if(skb->dev && (skb->dev->ifindex < MAX_NUM_IFIDX))
+ printk("[PF_RING] --> skb_ring_handler(%s): %d rings [num_any_rings=%d]\n",
+ skb->dev->name, num_rings_per_device[skb->dev->ifindex], num_any_rings);
+ }
+
+ if((num_any_rings == 0)
+ && (skb->dev
+ && (skb->dev->ifindex < MAX_NUM_IFIDX)
+ && (num_rings_per_device[skb->dev->ifindex] == 0)))
+ return(rc);
+
#ifdef PROFILING
uint64_t rdt = _rdtsc(), rdt1, rdt2;
#endif
#if(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30))
- channel_id = skb_get_rx_queue(skb);
+ if (channel_id == UNKNOWN_RX_CHANNEL)
+ channel_id = skb_get_rx_queue(skb);
#endif
-#if defined(RING_DEBUG)
- // printk("[PF_RING] --> skb_ring_handler() [channel_id=%d/%d]\n", channel_id, num_rx_channels);
-#endif
+ if(channel_id > MAX_NUM_RX_CHANNELS) channel_id = 0 /* MAX_NUM_RX_CHANNELS */;
if((!skb) /* Invalid skb */ ||((!enable_tx_capture) && (!recv_packet))) {
/*
@@ -2302,264 +2862,194 @@
*/
return(0);
}
-#if defined(RING_DEBUG)
- if(0) {
+
+ if(enable_debug) {
struct timeval tv;
skb_get_timestamp(skb, &tv);
printk("[PF_RING] skb_ring_handler() [skb=%p][%u.%u][len=%d][dev=%s][csum=%u]\n",
skb, (unsigned int)tv.tv_sec, (unsigned int)tv.tv_usec,
- skb->len,
- skb->dev == NULL ? "<NULL>" : skb->dev->name,
+ skb->len, skb->dev == NULL ? "<NULL>" : skb->dev->name,
skb->csum);
}
-#endif
-
-#if defined (RING_DEBUG)
- /* printk("[PF_RING] channel_id=%d\n", channel_id); */
-#endif
#ifdef PROFILING
rdt1 = _rdtsc();
#endif
- 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;
-
- is_ip_pkt = parse_pkt(skb, displ, &hdr);
+ memset(&hdr, 0, sizeof(hdr));
- /* (de)Fragmentation <fusco@ntop.org> */
- if(enable_ip_defrag
- && real_skb
- && is_ip_pkt
- && recv_packet
- && (ring_table_size > 0)) {
- struct sk_buff *cloned = NULL;
- struct iphdr *iphdr = NULL;
-
- skb_reset_network_header(skb);
- skb_reset_transport_header(skb);
- skb_set_network_header(skb, ETH_HLEN - displ);
-
- iphdr = ip_hdr(skb);
-
- if(iphdr && (iphdr->version == 4)) {
-#if defined (RING_DEBUG)
- printk("[PF_RING] [version=%d] %X -> %X\n",
- iphdr->version, iphdr->saddr, iphdr->daddr);
-#endif
- if(iphdr->frag_off & htons(IP_MF | IP_OFFSET)) {
- if((cloned = skb_clone(skb, GFP_ATOMIC)) != NULL) {
-#if defined (RING_DEBUG)
- int offset = ntohs(iphdr->frag_off);
- offset &= IP_OFFSET;
- offset <<= 3;
-
- printk
- ("[PF_RING] There is a fragment to handle [proto=%d][frag_off=%u]"
- "[ip_id=%u][network_header=%d][displ=%d]\n",
- iphdr->protocol, offset,
- ntohs(iphdr->id),
- hdr.extended_hdr.parsed_pkt.pkt_detail.offset.
- l3_offset - displ, displ);
-#endif
- skk = ring_gather_frags(cloned);
-
- if(skk != NULL) {
-#if defined (RING_DEBUG)
- printk
- ("[PF_RING] IP reasm on new skb [skb_len=%d]"
- "[head_len=%d][nr_frags=%d][frag_list=%p]\n",
- (int)skk->len,
- skb_headlen(skk),
- skb_shinfo(skk)->nr_frags,
- skb_shinfo(skk)->frag_list);
-#endif
- skb = skk;
- parse_pkt(skb, displ, &hdr);
- hdr.len = hdr.caplen = skb->len + displ;
- } else {
- //printk("[PF_RING] Fragment queued \n");
- return(0); /* mask rcvd fragments */
- }
- }
- } else {
-#if defined (RING_DEBUG)
- printk("[PF_RING] Do not seems to be a fragmented ip_pkt[iphdr=%p]\n",
- iphdr);
-#endif
- }
- } else if(iphdr && iphdr->version == 6)
- {
- /* Re-assembling fragmented IPv6 packets has not been
- implemented. Probability of observing fragmented IPv6
- packets is extremely low. */
-#if defined (RING_DEBUG)
- printk("[PF_RING] Re-assembling fragmented IPv6 packet hs not been implemented\n");
-#endif
- }
- }
-
- /* 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;
-#elif(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22))
- 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;
-#else /* 2.6.22 and above */
- if(skb->tstamp.tv64 == 0)
- __net_timestamp(skb);
- hdr.ts = ktime_to_timeval(skb->tstamp);
-#endif
+ set_skb_time(skb, &hdr);
hdr.len = hdr.caplen = skb->len + displ;
- if(skb->dev)
- hdr.extended_hdr.if_index = skb->dev->ifindex;
- else
- hdr.extended_hdr.if_index = -1;
+ if(quick_mode) {
+ struct pf_ring_socket *pfr = device_rings[skb->dev->ifindex][channel_id];
- /* Avoid the ring to be manipulated while playing with it */
- read_lock_bh(&ring_mgmt_lock);
+ hdr.extended_hdr.parsed_header_len = 0;
- /* [1] Check unclustered sockets */
- list_for_each(ptr, &ring_table) {
- struct ring_opt *pfr;
- struct ring_element *entry;
-
- entry = list_entry(ptr, struct ring_element, list);
-
- skElement = entry->sk;
- pfr = ring_sk(skElement);
+ if(pfr && pfr->rehash_rss && skb->dev) {
+ parse_pkt(skb, displ, &hdr, 1);
+ channel_id = hash_pkt_header(&hdr, 0, 0) % get_num_rx_queues(skb->dev);
+ }
-#if defined (RING_DEBUG)
- if(0)
- printk("[PF_RING] Scanning ring [%s][cluster=%d]\n",
- pfr->ring_netdev->name, pfr->cluster_id);
-#endif
+ if(enable_debug) printk("[PF_RING] Expecting channel %d [%p]\n", channel_id, pfr);
if((pfr != NULL)
- && (pfr->ring_netdev != &none_dev) /* Not a dummy socket bound to "none" */
- && (pfr->cluster_id == 0 /* No cluster */ )
- && (pfr->ring_slots != NULL)
&& is_valid_skb_direction(pfr->direction, recv_packet)
- && ((pfr->ring_netdev == skb->dev)
- || (pfr->ring_netdev == &any_dev) /* Socket bound to 'any' */
- || ((skb->dev->flags & IFF_SLAVE) && (pfr->ring_netdev == skb->dev->master)))) {
- /* We've found the ring where the packet can be stored */
- int old_caplen = hdr.caplen; /* Keep old lenght */
- hdr.caplen = min(hdr.caplen, pfr->bucket_len);
- add_skb_to_ring(skb, pfr, &hdr, is_ip_pkt, displ, channel_id, num_rx_channels);
- hdr.caplen = old_caplen;
- rc = 1; /* Ring found: we've done our job */
+ ) {
+ /* printk("==>>> [%d][%d]\n", skb->dev->ifindex, channel_id); */
+
+ rc = 1, hdr.len = skb->len, hdr.caplen = min_val(hdr.caplen, pfr->bucket_len);
+ room_available |= copy_data_to_ring(skb, pfr, &hdr, displ, 0, NULL, NULL, 0);
}
- }
+ } else {
- /* [2] Check socket clusters */
- list_for_each(ptr, &ring_cluster_list) {
- ring_cluster_element *cluster_ptr;
- struct ring_opt *pfr;
+ is_ip_pkt = parse_pkt(skb, displ, &hdr, 1);
- cluster_ptr = list_entry(ptr, ring_cluster_element, list);
+ if(enable_ip_defrag) {
+ if(real_skb
+ && is_ip_pkt
+ && recv_packet) {
+ skb = skk = defrag_skb(skb, displ, &hdr, &defragmented_skb);
- if(cluster_ptr->cluster.num_cluster_elements > 0) {
- u_int skb_hash = hash_pkt_cluster(cluster_ptr, &hdr);
- u_short num_iterations;
+ if(skb == NULL)
+ return(0);
+ }
+ }
- /*
- We try to add the packet to the right cluster
- element, but if we're working in round-robin and this
- element is full, we try to add this to the next available
- element. If none with at least a free slot can be found
- then we give up :-(
- */
+ if(skb->dev)
+ hdr.extended_hdr.if_index = skb->dev->ifindex;
+ else
+ hdr.extended_hdr.if_index = UNKNOWN_INTERFACE;
- for(num_iterations = 0;
- num_iterations < cluster_ptr->cluster.num_cluster_elements;
- num_iterations++) {
-
- skElement = cluster_ptr->cluster.sk[skb_hash];
-
- if(skElement != NULL) {
- pfr = ring_sk(skElement);
-
- if((pfr != NULL)
- && (pfr->ring_slots != NULL)
- && ((pfr->ring_netdev == skb->dev)
- || ((skb->dev->flags & IFF_SLAVE)
- && (pfr->ring_netdev == skb->dev->master)))
- && is_valid_skb_direction(pfr->direction, recv_packet)
- ) {
- if(check_and_init_free_slot(pfr, pfr->slots_info->insert_off) /* Not full */) {
- /* We've found the ring where the packet can be stored */
- add_skb_to_ring(skb, pfr, &hdr, is_ip_pkt, displ,
- channel_id, num_rx_channels);
- rc = 1; /* Ring found: we've done our job */
- break;
- }
- }
- }
+ /* Avoid the ring to be manipulated while playing with it */
+ ring_read_lock();
- if(cluster_ptr->cluster.hashing_mode != cluster_round_robin)
- break;
- else
- skb_hash = (skb_hash + 1) % cluster_ptr->cluster.num_cluster_elements;
+ /* [1] Check unclustered sockets */
+ list_for_each(ptr, &ring_table) {
+ struct pf_ring_socket *pfr;
+ struct ring_element *entry;
+
+ entry = list_entry(ptr, struct ring_element, list);
+
+ skElement = entry->sk;
+ pfr = ring_sk(skElement);
+
+ if((pfr != NULL)
+ && ((pfr->ring_netdev->dev == skb->dev)
+ || (pfr->ring_netdev == &any_device_element) /* Socket bound to 'any' */
+ || ((skb->dev->flags & IFF_SLAVE) && (pfr->ring_netdev->dev == skb->dev->master)))
+ && (pfr->ring_netdev != &none_device_element) /* Not a dummy socket bound to "none" */
+ && (pfr->cluster_id == 0 /* No cluster */ )
+ && (pfr->ring_slots != NULL)
+ && is_valid_skb_direction(pfr->direction, recv_packet)
+ ) {
+ /* We've found the ring where the packet can be stored */
+ int old_caplen = hdr.caplen; /* Keep old lenght */
+ hdr.caplen = min_val(hdr.caplen, pfr->bucket_len);
+ room_available |= add_skb_to_ring(skb, pfr, &hdr, is_ip_pkt,
+ displ, channel_id, num_rx_channels);
+ hdr.caplen = old_caplen;
+ rc = 1; /* Ring found: we've done our job */
}
}
- } /* Clustering */
- read_unlock_bh(&ring_mgmt_lock);
+ /* [2] Check socket clusters */
+ list_for_each(ptr, &ring_cluster_list) {
+ ring_cluster_element *cluster_ptr;
+ struct pf_ring_socket *pfr;
+
+ cluster_ptr = list_entry(ptr, ring_cluster_element, list);
+
+ if(cluster_ptr->cluster.num_cluster_elements > 0) {
+ u_int skb_hash = hash_pkt_cluster(cluster_ptr, &hdr);
+ u_short num_iterations;
+
+ /*
+ We try to add the packet to the right cluster
+ element, but if we're working in round-robin and this
+ element is full, we try to add this to the next available
+ element. If none with at least a free slot can be found
+ then we give up :-(
+ */
+
+ for(num_iterations = 0;
+ num_iterations < cluster_ptr->cluster.num_cluster_elements;
+ num_iterations++) {
+
+ skElement = cluster_ptr->cluster.sk[skb_hash];
+
+ if(skElement != NULL) {
+ pfr = ring_sk(skElement);
+
+ if((pfr != NULL)
+ && (pfr->ring_slots != NULL)
+ && ((pfr->ring_netdev->dev == skb->dev)
+ || ((skb->dev->flags & IFF_SLAVE)
+ && (pfr->ring_netdev->dev == skb->dev->master)))
+ && is_valid_skb_direction(pfr->direction, recv_packet)
+ ) {
+ if(check_and_init_free_slot(pfr, pfr->slots_info->insert_off) /* Not full */) {
+ /* We've found the ring where the packet can be stored */
+ room_available |= add_skb_to_ring(skb, pfr, &hdr, is_ip_pkt,
+ displ, channel_id, num_rx_channels);
+ rc = 1; /* Ring found: we've done our job */
+ break;
+ }
+ }
+ }
+
+ if(cluster_ptr->cluster.hashing_mode != cluster_round_robin)
+ break;
+ else
+ skb_hash = (skb_hash + 1) % cluster_ptr->cluster.num_cluster_elements;
+ }
+ }
+ } /* Clustering */
-#ifdef PROFILING
- rdt1 = _rdtsc() - rdt1;
-#endif
+ ring_read_unlock();
#ifdef PROFILING
- rdt2 = _rdtsc();
+ rdt1 = _rdtsc() - rdt1;
+ rdt2 = _rdtsc();
#endif
- /* Fragment handling */
- if(skk != NULL)
- kfree_skb(skk);
+ /* Fragment handling */
+ if(skk != NULL && defragmented_skb)
+ kfree_skb(skk);
+ }
if(rc == 1) {
- if(transparent_mode != driver2pf_ring_non_transparent) {
+ if(transparent_mode != driver2pf_ring_non_transparent /* 2 */)
rc = 0;
- } else {
+ else {
if(recv_packet && real_skb) {
-#if defined(RING_DEBUG)
- printk("[PF_RING] kfree_skb()\n");
-#endif
+ if(enable_debug)
+ printk("[PF_RING] kfree_skb()\n");
- kfree_skb(orig_skb);
+ kfree_skb(orig_skb); /* Free memory */
}
}
}
+
#ifdef PROFILING
rdt2 = _rdtsc() - rdt2;
rdt = _rdtsc() - rdt;
-#if defined(RING_DEBUG)
- printk
- ("[PF_RING] # 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
+ if(enable_debug)
+ printk("[PF_RING] # 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
//printk("[PF_RING] Returned %d\n", rc);
- return(rc); /* 0 = packet not handled */
+
+ if((rc == 1) && (room_available == 0))
+ rc = 2;
+
+ return(rc); /* 0 = packet not handled */
}
/* ********************************** */
@@ -2568,10 +3058,9 @@
static int buffer_ring_handler(struct net_device *dev, char *data, int len)
{
-#if defined(RING_DEBUG)
- printk("[PF_RING] buffer_ring_handler: [dev=%s][len=%d]\n",
- dev->name == NULL ? "<NULL>" : dev->name, len);
-#endif
+ if(enable_debug)
+ printk("[PF_RING] buffer_ring_handler: [dev=%s][len=%d]\n",
+ dev->name == NULL ? "<NULL>" : dev->name, len);
skb.dev = dev, skb.len = len, skb.data = data, skb.data_len = len;
@@ -2584,10 +3073,9 @@
skb.tstamp.tv64 = 0;
#endif
- return(skb_ring_handler
- (&skb, 1, 0 /* fake skb */ ,
- UNKNOWN_RX_CHANNEL,
- UNKNOWN_NUM_RX_CHANNELS));
+ return(skb_ring_handler(&skb, 1, 0 /* fake skb */ ,
+ UNKNOWN_RX_CHANNEL,
+ UNKNOWN_NUM_RX_CHANNELS));
}
/* ************************************* */
@@ -2596,17 +3084,32 @@
{
if(rule->internals.reflector_dev != NULL)
dev_put(rule->internals.reflector_dev); /* Release device */
+
+ if(rule->extended_fields.filter_plugin_id > 0) {
+ if(plugin_registration[rule->extended_fields.filter_plugin_id]->pfring_plugin_register)
+ plugin_registration[rule->extended_fields.filter_plugin_id]->pfring_plugin_register(0);
+ }
+
+ if(rule->plugin_action.plugin_id > 0) {
+ if(plugin_registration[rule->plugin_action.plugin_id]->pfring_plugin_register)
+ plugin_registration[rule->plugin_action.plugin_id]->pfring_plugin_register(0);
+ }
}
/* ************************************* */
-static void free_filtering_hash_bucket(filtering_hash_bucket * bucket)
+static void free_sw_filtering_hash_bucket(sw_filtering_hash_bucket * bucket)
{
if(bucket->plugin_data_ptr)
kfree(bucket->plugin_data_ptr);
if(bucket->rule.internals.reflector_dev != NULL)
dev_put(bucket->rule.internals.reflector_dev); /* Release device */
+
+ if(bucket->rule.plugin_action.plugin_id > 0) {
+ if(plugin_registration[bucket->rule.plugin_action.plugin_id]->pfring_plugin_register)
+ plugin_registration[bucket->rule.plugin_action.plugin_id]->pfring_plugin_register(0);
+ }
}
/*
@@ -2619,96 +3122,84 @@
/* ************************************* */
-static int handle_filtering_hash_bucket(struct ring_opt *pfr,
- filtering_hash_bucket * rule,
- u_char add_rule)
+static int handle_sw_filtering_hash_bucket(struct pf_ring_socket *pfr,
+ sw_filtering_hash_bucket * rule,
+ u_char add_rule)
{
u_int32_t hash_value = hash_pkt(rule->rule.vlan_id, rule->rule.proto,
- rule->rule.host_peer_a,
- rule->rule.host_peer_b,
- rule->rule.port_peer_a,
- rule->rule.port_peer_b) % DEFAULT_RING_HASH_SIZE;
- int rc = -1, debug = 0;
-
- if(debug)
- printk
- ("[PF_RING] handle_filtering_hash_bucket(vlan=%u, proto=%u, "
- "sip=%d.%d.%d.%d, sport=%u, dip=%d.%d.%d.%d, dport=%u, "
- "hash_value=%u, add_rule=%d) called\n", rule->rule.vlan_id,
- rule->rule.proto, ((rule->rule.host4_peer_a >> 24) & 0xff),
- ((rule->rule.host4_peer_a >> 16) & 0xff),
- ((rule->rule.host4_peer_a >> 8) & 0xff),
- ((rule->rule.host4_peer_a >> 0) & 0xff),
- rule->rule.port_peer_a,
- ((rule->rule.host4_peer_b >> 24) & 0xff),
- ((rule->rule.host4_peer_b >> 16) & 0xff),
- ((rule->rule.host4_peer_b >> 8) & 0xff),
- ((rule->rule.host4_peer_b >> 0) & 0xff),
- rule->rule.port_peer_b, hash_value, add_rule);
+ rule->rule.host_peer_a, rule->rule.host_peer_b,
+ rule->rule.port_peer_a, rule->rule.port_peer_b)
+ % DEFAULT_RING_HASH_SIZE;
+ int rc = -1;
+
+ if(enable_debug)
+ printk("[PF_RING] handle_sw_filtering_hash_bucket(vlan=%u, proto=%u, "
+ "sip=%d.%d.%d.%d, sport=%u, dip=%d.%d.%d.%d, dport=%u, "
+ "hash_value=%u, add_rule=%d) called\n", rule->rule.vlan_id,
+ rule->rule.proto, ((rule->rule.host4_peer_a >> 24) & 0xff),
+ ((rule->rule.host4_peer_a >> 16) & 0xff),
+ ((rule->rule.host4_peer_a >> 8) & 0xff),
+ ((rule->rule.host4_peer_a >> 0) & 0xff),
+ rule->rule.port_peer_a,
+ ((rule->rule.host4_peer_b >> 24) & 0xff),
+ ((rule->rule.host4_peer_b >> 16) & 0xff),
+ ((rule->rule.host4_peer_b >> 8) & 0xff),
+ ((rule->rule.host4_peer_b >> 0) & 0xff),
+ rule->rule.port_peer_b, hash_value, add_rule);
if(add_rule) {
- if(pfr->filtering_hash == NULL)
- pfr->filtering_hash = (filtering_hash_bucket **)
- kcalloc(DEFAULT_RING_HASH_SIZE,
- sizeof(filtering_hash_bucket *),
- GFP_ATOMIC);
- if(pfr->filtering_hash == NULL) {
+ if(pfr->sw_filtering_hash == NULL)
+ pfr->sw_filtering_hash = (sw_filtering_hash_bucket **)
+ kcalloc(DEFAULT_RING_HASH_SIZE, sizeof(sw_filtering_hash_bucket *), GFP_ATOMIC);
+ if(pfr->sw_filtering_hash == NULL) {
/* kfree(rule); */
- if(debug)
- printk
- ("[PF_RING] handle_filtering_hash_bucket() returned %d [0]\n",
- -EFAULT);
+ if(enable_debug)
+ printk("[PF_RING] handle_sw_filtering_hash_bucket() returned %d [0]\n", -EFAULT);
return(-EFAULT);
}
}
- if(debug)
- printk
- ("[PF_RING] handle_filtering_hash_bucket() allocated memory\n");
+ if(enable_debug)
+ printk("[PF_RING] handle_sw_filtering_hash_bucket() allocated memory\n");
- if(pfr->filtering_hash == NULL) {
+ if(pfr->sw_filtering_hash == NULL) {
/* We're trying to delete a hash rule from an empty hash */
return(-EFAULT);
}
- if(pfr->filtering_hash[hash_value] == NULL) {
+ if(pfr->sw_filtering_hash[hash_value] == NULL) {
if(add_rule)
- pfr->filtering_hash[hash_value] = rule, rule->next = NULL, rc = 0;
+ pfr->sw_filtering_hash[hash_value] = rule, rule->next = NULL, rc = 0;
else {
- if(debug)
- printk("[PF_RING] handle_filtering_hash_bucket() returned %d [1]\n", -1);
+ if(enable_debug)
+ printk("[PF_RING] handle_sw_filtering_hash_bucket() returned %d [1]\n", -1);
return(-1); /* Unable to find the specified rule */
}
} else {
- filtering_hash_bucket *prev = NULL, *bucket =
- pfr->filtering_hash[hash_value];
+ sw_filtering_hash_bucket *prev = NULL, *bucket = pfr->sw_filtering_hash[hash_value];
while(bucket != NULL) {
- if(hash_filtering_rule_match
- (&bucket->rule, &rule->rule)) {
+ if(hash_filtering_rule_match(&bucket->rule, &rule->rule)) {
if(add_rule) {
- if(debug)
+ if(enable_debug)
printk("[PF_RING] Duplicate found while adding rule: discarded\n");
/* kfree(rule); */
return(-EEXIST);
} else {
/* We've found the bucket to delete */
- if(debug)
- printk("[PF_RING] handle_filtering_hash_bucket()"
+ if(enable_debug)
+ printk("[PF_RING] handle_sw_filtering_hash_bucket()"
" found a bucket to delete: removing it\n");
if(prev == NULL)
- pfr->
- filtering_hash[hash_value] =
- bucket->next;
+ pfr->sw_filtering_hash[hash_value] = bucket->next;
else
prev->next = bucket->next;
- free_filtering_hash_bucket(bucket);
+ free_sw_filtering_hash_bucket(bucket);
kfree(bucket);
- if(debug)
- printk("[PF_RING] handle_filtering_hash_bucket() returned %d [2]\n",
- 0);
+ if(enable_debug)
+ printk("[PF_RING] handle_sw_filtering_hash_bucket() returned %d [2]\n", 0);
return(0);
}
} else {
@@ -2720,11 +3211,16 @@
if(add_rule) {
/* If the flow arrived until here, then this rule is unique */
- if(debug)
- printk("[PF_RING] handle_filtering_hash_bucket() "
+ if(enable_debug)
+ printk("[PF_RING] handle_sw_filtering_hash_bucket() "
"no duplicate rule found: adding the rule\n");
- rule->next = pfr->filtering_hash[hash_value];
- pfr->filtering_hash[hash_value] = rule;
+
+ if(rule->rule.plugin_action.plugin_id > 0) {
+ if(plugin_registration[rule->rule.plugin_action.plugin_id]->pfring_plugin_register)
+ plugin_registration[rule->rule.plugin_action.plugin_id]->pfring_plugin_register(0);
+ }
+ rule->next = pfr->sw_filtering_hash[hash_value];
+ pfr->sw_filtering_hash[hash_value] = rule;
rc = 0;
} else {
/* The rule we searched for has not been found */
@@ -2732,8 +3228,8 @@
}
}
- if(debug)
- printk("[PF_RING] handle_filtering_hash_bucket() returned %d [3]\n",
+ if(enable_debug)
+ printk("[PF_RING] handle_sw_filtering_hash_bucket() returned %d [3]\n",
rc);
return(rc);
@@ -2743,7 +3239,7 @@
static int packet_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16))
+#if(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16))
, struct net_device *orig_dev
#endif
)
@@ -2758,6 +3254,10 @@
} else
rc = 0;
+ /*
+ This packet has been received by Linux through its standard
+ mechanisms (no PF_RING transparent/TNAPI)
+ */
kfree_skb(skb);
return(rc);
}
@@ -2792,12 +3292,11 @@
)
{
struct sock *sk;
- struct ring_opt *pfr;
- int err;
+ struct pf_ring_socket *pfr;
+ int err = -ENOMEM;
-#if defined(RING_DEBUG)
- printk("[PF_RING] ring_create()\n");
-#endif
+ if(enable_debug)
+ printk("[PF_RING] ring_create()\n");
/* Are you root, superuser or so ? */
if(!capable(CAP_NET_ADMIN))
@@ -2809,8 +3308,6 @@
if(protocol != htons(ETH_P_ALL))
return -EPROTONOSUPPORT;
- err = -ENOMEM;
-
#if(LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,11))
sk = sk_alloc(PF_RING, GFP_KERNEL, 1, NULL);
#else
@@ -2832,7 +3329,6 @@
sk_set_owner(sk, THIS_MODULE);
#endif
- err = -ENOMEM;
ring_sk(sk) = ring_sk_datatype(kmalloc(sizeof(*pfr), GFP_KERNEL));
if(!(pfr = ring_sk(sk))) {
@@ -2845,40 +3341,145 @@
pfr->num_rx_channels = UNKNOWN_NUM_RX_CHANNELS;
pfr->channel_id = RING_ANY_CHANNEL;
pfr->bucket_len = DEFAULT_BUCKET_LEN;
- pfr->handle_hash_rule = handle_filtering_hash_bucket;
+ pfr->poll_num_pkts_watermark = DEFAULT_MIN_PKT_QUEUED;
+ pfr->handle_hash_rule = handle_sw_filtering_hash_bucket;
+ pfr->add_packet_to_ring = add_packet_to_ring;
+ pfr->add_raw_packet_to_ring = add_raw_packet_to_ring;
init_waitqueue_head(&pfr->ring_slots_waitqueue);
rwlock_init(&pfr->ring_index_lock);
rwlock_init(&pfr->ring_rules_lock);
atomic_set(&pfr->num_ring_users, 0);
- INIT_LIST_HEAD(&pfr->rules);
+ INIT_LIST_HEAD(&pfr->sw_filtering_rules);
+ INIT_LIST_HEAD(&pfr->hw_filtering_rules);
sk->sk_family = PF_RING;
sk->sk_destruct = ring_sock_destruct;
ring_insert(sk);
pfr->master_ring = NULL;
- pfr->ring_netdev = &none_dev; /* Unbound socket */
+ pfr->ring_netdev = &none_device_element; /* Unbound socket */
pfr->sample_rate = 1; /* No sampling */
- pfr->ring_pid = current->pid;
pfr->ring_id = ring_id_serial++;
ring_proc_add(pfr);
-#if defined(RING_DEBUG)
- printk("[PF_RING] ring_create(): created\n");
-#endif
+ if(enable_debug)
+ printk("[PF_RING] ring_create(): created\n");
return(0);
out:
return err;
}
+/* ************************************* */
+
+static int ring_proc_virtual_filtering_dev_get_info(char *buf, char **start, off_t offset,
+ int len, int *unused, void *data)
+{
+ int rlen = 0;
+
+ if(data != NULL) {
+ virtual_filtering_device_info *info = (virtual_filtering_device_info*)data;
+ char *dev_family = "???";
+
+ switch(info->device_type) {
+ case standard_nic_family: dev_family = "Standard NIC"; break;
+ case intel_82599_family: dev_family = "Intel 82599"; break;
+ case silicom_redirector_family: dev_family = "Silicom Redirector"; break;
+ }
+
+ rlen = sprintf(buf, "Name: %s\n", info->device_name);
+ rlen += sprintf(buf+rlen, "Family: %s\n", dev_family);
+ }
+
+ return rlen;
+}
+
+/* ************************************* */
+
+static virtual_filtering_device_element* add_virtual_filtering_device(struct sock *sock,
+ virtual_filtering_device_info *info)
+{
+ virtual_filtering_device_element *elem;
+ struct list_head *ptr, *tmp_ptr;
+
+ if(enable_debug)
+ printk("[PF_RING] --> add_virtual_filtering_device(%s)\n", info->device_name);
+
+ if(info == NULL)
+ return(NULL);
+
+ /* Check if the same entry is already present */
+ write_lock(&virtual_filtering_lock);
+ list_for_each_safe(ptr, tmp_ptr, &virtual_filtering_devices_list) {
+ virtual_filtering_device_element *filtering_ptr = list_entry(ptr, virtual_filtering_device_element, list);
+
+ if(strcmp(filtering_ptr->info.device_name, info->device_name) == 0) {
+ write_unlock(&virtual_filtering_lock);
+ return(NULL); /* Entry alredy present */
+ }
+ }
+
+ elem = kmalloc(sizeof(virtual_filtering_device_element), GFP_KERNEL);
+
+ if(elem == NULL)
+ return(NULL);
+ else {
+ memcpy(&elem->info, info, sizeof(virtual_filtering_device_info));
+ INIT_LIST_HEAD(&elem->list);
+ }
+
+ list_add(&elem->list, &virtual_filtering_devices_list); /* Add as first entry */
+ write_unlock(&virtual_filtering_lock);
+
+ /* Add /proc entry */
+ elem->info.proc_entry = proc_mkdir(elem->info.device_name, ring_proc_dev_dir);
+ create_proc_read_entry(PROC_INFO, 0 /* read-only */,
+ elem->info.proc_entry,
+ ring_proc_virtual_filtering_dev_get_info /* read */,
+ (void*)&elem->info);
+
+ return(elem);
+}
+
+/* ************************************* */
+
+static int remove_virtual_filtering_device(struct sock *sock, char *device_name)
+{
+ struct list_head *ptr, *tmp_ptr;
+
+ if(enable_debug)
+ printk("[PF_RING] --> remove_virtual_filtering_device(%s)\n", device_name);
+
+ write_lock(&virtual_filtering_lock);
+ list_for_each_safe(ptr, tmp_ptr, &virtual_filtering_devices_list) {
+ virtual_filtering_device_element *filtering_ptr;
+
+ filtering_ptr = list_entry(ptr, virtual_filtering_device_element, list);
+
+ if(strcmp(filtering_ptr->info.device_name, device_name) == 0) {
+ /* Remove /proc entry */
+ remove_proc_entry(PROC_INFO, filtering_ptr->info.proc_entry);
+ remove_proc_entry(filtering_ptr->info.device_name, ring_proc_dev_dir);
+
+ list_del(ptr);
+ write_unlock(&virtual_filtering_lock);
+ kfree(filtering_ptr);
+ return(0);
+ }
+ }
+
+ write_unlock(&virtual_filtering_lock);
+
+ return(-EINVAL); /* Not found */
+}
+
/* *********************************************** */
static int ring_release(struct socket *sock)
{
struct sock *sk = sock->sk;
- struct ring_opt *pfr = ring_sk(sk);
+ struct pf_ring_socket *pfr = ring_sk(sk);
struct list_head *ptr, *tmp_ptr;
void *ring_memory_ptr;
@@ -2898,21 +3499,48 @@
schedule();
}
-#if defined(RING_DEBUG)
- printk("[PF_RING] called ring_release(%s)\n", pfr->ring_netdev->name);
-#endif
+ if(enable_debug)
+ printk("[PF_RING] called ring_release(%s)\n", pfr->ring_netdev->dev->name);
if(pfr->kernel_consumer_options) kfree(pfr->kernel_consumer_options);
/*
The calls below must be placed outside the
- write_lock_bh...write_unlock_bh block.
+ write_lock...write_unlock block.
*/
sock_orphan(sk);
ring_proc_remove(pfr);
- write_lock_bh(&ring_mgmt_lock);
+ ring_write_lock();
+
+ if(pfr->ring_netdev->dev && pfr->ring_netdev == &any_device_element)
+ num_any_rings--;
+ else {
+ if(pfr->ring_netdev
+ && (pfr->ring_netdev->dev->ifindex < MAX_NUM_IFIDX)) {
+ if(num_rings_per_device[pfr->ring_netdev->dev->ifindex] > 0)
+ num_rings_per_device[pfr->ring_netdev->dev->ifindex]--;
+
+ if(quick_mode) {
+ int i;
+
+ for(i=0; i<MAX_NUM_RX_CHANNELS; i++) {
+ u_int32_t the_bit = 1 << i;
+
+ if((pfr->channel_id & the_bit) == the_bit) {
+ if(device_rings[pfr->ring_netdev->dev->ifindex][i] == pfr) {
+ /*
+ We must make sure that this is really us and not that by some chance
+ (e.g. bind failed) another ring
+ */
+ device_rings[pfr->ring_netdev->dev->ifindex][i] = NULL;
+ }
+ }
+ }
+ }
+ }
+ }
- if(pfr->ring_netdev != &none_dev) {
+ if(pfr->ring_netdev != &none_device_element) {
if(pfr->cluster_id != 0)
remove_from_cluster(sk, pfr);
}
@@ -2922,24 +3550,23 @@
sock->sk = NULL;
/* Free rules */
- if(pfr->ring_netdev != &none_dev) {
- list_for_each_safe(ptr, tmp_ptr, &pfr->rules) {
- filtering_rule_element *rule;
+ if(pfr->ring_netdev != &none_device_element) {
+ list_for_each_safe(ptr, tmp_ptr, &pfr->sw_filtering_rules) {
+ sw_filtering_rule_element *rule;
#ifdef CONFIG_TEXTSEARCH
int i;
#endif
- rule = list_entry(ptr, filtering_rule_element, list);
+ rule = list_entry(ptr, sw_filtering_rule_element, list);
if(plugin_registration[rule->rule.plugin_action.plugin_id]
&& plugin_registration[rule->rule.plugin_action.plugin_id]->pfring_plugin_free_ring_mem) {
/* Custom free function */
plugin_registration[rule->rule.plugin_action.plugin_id]->pfring_plugin_free_ring_mem(rule);
} else {
-#ifdef DEBUG
- printk("[PF_RING] --> default_free [rule->rule.plugin_action.plugin_id=%d]\n",
- rule->rule.plugin_action.plugin_id);
-#endif
+ if(enable_debug)
+ printk("[PF_RING] --> default_free [rule->rule.plugin_action.plugin_id=%d]\n",
+ rule->rule.plugin_action.plugin_id);
if(rule->plugin_data_ptr != NULL) {
kfree(rule->plugin_data_ptr);
rule->plugin_data_ptr = NULL;
@@ -2957,35 +3584,60 @@
}
/* Filtering hash rules */
- if(pfr->filtering_hash) {
+ if(pfr->sw_filtering_hash) {
int i;
for(i = 0; i < DEFAULT_RING_HASH_SIZE; i++) {
- if(pfr->filtering_hash[i] != NULL) {
- filtering_hash_bucket *scan =
- pfr->filtering_hash[i], *next;
+ if(pfr->sw_filtering_hash[i] != NULL) {
+ sw_filtering_hash_bucket *scan = pfr->sw_filtering_hash[i], *next;
while(scan != NULL) {
next = scan->next;
- free_filtering_hash_bucket(scan);
+ free_sw_filtering_hash_bucket(scan);
kfree(scan);
scan = next;
}
}
}
- kfree(pfr->filtering_hash);
+ kfree(pfr->sw_filtering_hash);
+ }
+
+ /* printk("[PF_RING] --> num_hw_filtering_rules=%d\n", pfr->num_hw_filtering_rules); */
+
+ /* Free Hw Filtering Rules */
+ if(pfr->num_hw_filtering_rules > 0) {
+ list_for_each_safe(ptr, tmp_ptr, &pfr->hw_filtering_rules) {
+ hw_filtering_rule_element *hw_rule = list_entry(ptr, hw_filtering_rule_element, list);
+
+ /* Remove hw rule */
+ handle_hw_filtering_rule(pfr, &hw_rule->rule, remove_hw_rule);
+
+ list_del(ptr);
+ kfree(hw_rule);
+ }
}
}
+ if(pfr->v_filtering_dev != NULL) {
+ remove_virtual_filtering_device(sk, pfr->v_filtering_dev->info.device_name);
+ pfr->v_filtering_dev = NULL;
+ /* pfr->v_filtering_dev has been freed by remove_virtual_filtering_device() */
+ }
+
/* Free the ring buffer later, vfree needs interrupts enabled */
ring_memory_ptr = pfr->ring_memory;
ring_sk(sk) = NULL;
skb_queue_purge(&sk->sk_write_queue);
sock_put(sk);
- write_unlock_bh(&ring_mgmt_lock);
+ ring_write_unlock();
+
+#ifdef VPFRING_SUPPORT
+ if (pfr->vpfring_host_eventfd_ctx)
+ eventfd_ctx_put(pfr->vpfring_host_eventfd_ctx);
+#endif //VPFRING_SUPPORT
if(pfr->appl_name != NULL)
kfree(pfr->appl_name);
@@ -2993,11 +3645,19 @@
if(ring_memory_ptr != NULL)
vfree(ring_memory_ptr);
+ if(pfr->dna_device_entry != NULL) {
+ dna_device_mapping mapping;
+
+ mapping.operation = remove_device_mapping;
+ snprintf(mapping.device_name, sizeof(mapping.device_name), "%s", pfr->dna_device_entry->dev.netdev->name);
+ mapping.channel_id = pfr->dna_device_entry->dev.channel_id;
+ ring_map_dna_device(pfr, &mapping);
+ }
+
kfree(pfr);
-#if defined(RING_DEBUG)
- printk("[PF_RING] ring_release: done\n");
-#endif
+ if(enable_debug)
+ printk("[PF_RING] ring_release: done\n");
return 0;
}
@@ -3007,17 +3667,35 @@
/*
* 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)
+static int packet_ring_bind(struct sock *sk, char *dev_name)
{
- struct ring_opt *pfr = ring_sk(sk);
+ struct pf_ring_socket *pfr = ring_sk(sk);
+ struct list_head *ptr, *tmp_ptr;
+ ring_device_element *dev = NULL;
- if((!dev) || (dev->type != ARPHRD_ETHER))
- return(-1);
+ if(dev_name == NULL)
+ return(-EINVAL);
-#if defined(RING_DEBUG)
- printk("[PF_RING] packet_ring_bind(%s, bucket_len=%d) called\n",
- dev->name, pfr->bucket_len);
-#endif
+ /* ************** */
+
+ list_for_each_safe(ptr, tmp_ptr, &ring_aware_device_list) {
+ ring_device_element *dev_ptr = list_entry(ptr, ring_device_element,
+ device_list);
+
+ if(strcmp(dev_ptr->dev->name, dev_name) == 0) {
+ dev = dev_ptr;
+ break;
+ }
+ }
+
+ if((dev == NULL) || (dev->dev->type != ARPHRD_ETHER))
+ return(-EINVAL);
+
+ /* printk("[PF_RING] DeviceId: %u\n", dev->dev->ifindex); */
+
+ if(enable_debug)
+ printk("[PF_RING] packet_ring_bind(%s, bucket_len=%d) called\n",
+ dev->dev->name, pfr->bucket_len);
/* Remove old binding (by default binding to none)
BEFORE binding to a new device
@@ -3027,9 +3705,9 @@
/*
IMPORTANT
Leave this statement here as last one. In fact when
- the ring_netdev != &none_dev the socket is ready to be used.
+ the ring_netdev != &none_device_element the socket is ready to be used.
*/
- pfr->ring_netdev = dev;
+ pfr->ring_netdev = dev, pfr->channel_id = RING_ANY_CHANNEL;
/* Time to rebind to a new device */
ring_proc_add(pfr);
@@ -3041,11 +3719,20 @@
the num of RX queues is updated with the real value
*/
#if(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31))
- pfr->num_rx_channels = pfr->ring_netdev->real_num_tx_queues;
+ pfr->num_rx_channels = pfr->ring_netdev->dev->real_num_tx_queues;
#else
pfr->num_rx_channels = 1;
#endif
+ if((dev == &any_device_element) && (!quick_mode)) {
+ num_any_rings++;
+ } else {
+ if(dev->dev->ifindex < MAX_NUM_IFIDX) {
+ num_rings_per_device[dev->dev->ifindex]++;
+ } else
+ printk("[PF_RING] INTERNAL ERROR: ifindex %d for %s is > than MAX_NUM_IFIDX\n",
+ dev->dev->ifindex, dev->dev->name);
+ }
return(0);
}
@@ -3056,14 +3743,12 @@
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("[PF_RING] ring_bind() called\n");
-#endif
+ if(enable_debug)
+ printk("[PF_RING] ring_bind() called\n");
/*
- * Check legality
+ * Check legality
*/
if(addr_len != sizeof(struct sockaddr))
return -EINVAL;
@@ -3075,10 +3760,10 @@
/* Safety check: add trailing zero if missing */
sa->sa_data[sizeof(sa->sa_data) - 1] = '\0';
-#if defined(RING_DEBUG)
- printk("[PF_RING] searching device %s\n", sa->sa_data);
-#endif
+ if(enable_debug)
+ printk("[PF_RING] searching device %s\n", sa->sa_data);
+#if 0
if(strcmp(sa->sa_data, "any") == 0)
dev = &any_dev;
else {
@@ -3087,19 +3772,20 @@
&init_net,
#endif
sa->sa_data)) == NULL) {
-#if defined(RING_DEBUG)
- printk("[PF_RING] search failed\n");
-#endif
+
+ if(enable_debug)
+ printk("[PF_RING] search failed\n");
return(-EINVAL);
}
}
+#endif
- return(packet_ring_bind(sk, dev));
+ return(packet_ring_bind(sk, sa->sa_data));
}
/* ************************************* */
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11))
+#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11))
/*
* rvmalloc / rvfree / kvirt_to_pa copied from usbvideo.c
*/
@@ -3126,18 +3812,16 @@
start = vma->vm_start;
-#if defined(RING_DEBUG)
- printk("[PF_RING] do_memory_mmap(mode=%d, size=%lu, ptr=%p)\n", mode, size, ptr);
-#endif
+ if(enable_debug)
+ printk("[PF_RING] do_memory_mmap(mode=%d, size=%lu, ptr=%p)\n", mode, size, ptr);
while(size > 0) {
int rc;
if(mode == 0) {
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11))
- // rc = vm_insert_page(vma, start, vmalloc_to_page(ptr));
+#if(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11))
rc = remap_vmalloc_range(vma, ptr, 0);
- break;
+ break; /* Do not iterate */
#else
rc = remap_pfn_range(vma, start, kvirt_to_pa((unsigned long)ptr), PAGE_SIZE, PAGE_SHARED);
#endif
@@ -3148,9 +3832,9 @@
}
if(rc) {
-#if defined(RING_DEBUG)
- printk("[PF_RING] remap_pfn_range() failed\n");
-#endif
+ if(enable_debug)
+ printk("[PF_RING] remap_pfn_range() failed\n");
+
return(-EAGAIN);
}
@@ -3172,13 +3856,13 @@
struct socket *sock, struct vm_area_struct *vma)
{
struct sock *sk = sock->sk;
- struct ring_opt *pfr = ring_sk(sk);
+ struct pf_ring_socket *pfr = ring_sk(sk);
int rc;
+ unsigned long mem_id = 0;
unsigned long size = (unsigned long)(vma->vm_end - vma->vm_start);
-#if defined(RING_DEBUG)
- printk("[PF_RING] ring_mmap() called\n");
-#endif
+ if(enable_debug)
+ printk("[PF_RING] ring_mmap() called\n");
if(ring_alloc_mem(sk) != 0) {
printk("[PF_RING] ring_mmap(): unable to allocate memory\n");
@@ -3186,81 +3870,88 @@
}
if(size % PAGE_SIZE) {
-#if defined(RING_DEBUG)
- printk("[PF_RING] ring_mmap() failed: len is not multiple of PAGE_SIZE\n");
-#endif
+ if(enable_debug)
+ printk("[PF_RING] ring_mmap() failed: len is not multiple of PAGE_SIZE\n");
+
return(-EINVAL);
}
-#if defined(RING_DEBUG)
- printk("[PF_RING] ring_mmap() called, size: %ld bytes [bucket_len=%d]\n",
- size, pfr->bucket_len);
-#endif
-
- if((pfr->dna_device == NULL) && (pfr->ring_memory == NULL)) {
-#if defined(RING_DEBUG)
- printk("[PF_RING] ring_mmap() failed: "
- "mapping area to an unbound socket\n");
-#endif
- return -EINVAL;
- }
+ if(enable_debug)
+ printk("[PF_RING] ring_mmap() called, size: %ld bytes [bucket_len=%d]\n",
+ size, pfr->bucket_len);
- if(pfr->dna_device == NULL) {
- /* if userspace tries to mmap beyond end of our buffer, fail */
- if(size > pfr->slots_info->tot_mem) {
-#if defined(RING_DEBUG)
- printk("[PF_RING] ring_mmap() failed: "
- "area too large [%ld > %d]\n",
- size, pfr->slots_info->tot_mem);
-#endif
- return(-EINVAL);
- }
-#if defined(RING_DEBUG)
- printk("[PF_RING] mmap [slot_len=%d]"
- "[tot_slots=%d] for ring on device %s\n",
- pfr->slots_info->slot_len, pfr->slots_info->min_num_slots,
- pfr->ring_netdev->name);
-#endif
+ /* using vm_pgoff as memory id */
+ mem_id = vma->vm_pgoff;
- if((rc = do_memory_mmap(vma, size, pfr->ring_memory, VM_LOCKED, 0)) < 0)
- return(rc);
- } else {
- int count = pfr->mmap_count;
- /* DNA Device */
- if(pfr->dna_device == NULL)
- return(-EAGAIN);
+ if( (mem_id == 0 && pfr->ring_memory == NULL) ||
+ (mem_id > 0 && pfr->dna_device == NULL)) {
- printk("[PF_RING] mmap count(%d)\n", count);
+ if(enable_debug)
+ printk("[PF_RING] ring_mmap() failed: "
+ "mapping area to an unbound socket\n");
- pfr->mmap_count++;
+ return -EINVAL;
+ }
- switch(count) {
+ switch(mem_id) {
+ /* RING */
case 0:
- if((rc = do_memory_mmap(vma, size,
- (void *)pfr->dna_device->packet_memory, VM_LOCKED, 1)) < 0)
- return(rc);
+
+ /* if userspace tries to mmap beyond end of our buffer, fail */
+ if(size > pfr->slots_info->tot_mem) {
+ if(enable_debug)
+ printk("[PF_RING] ring_mmap() failed: "
+ "area too large [%ld > %d]\n",
+ size, pfr->slots_info->tot_mem);
+ return(-EINVAL);
+ }
+
+ if(enable_debug)
+ printk("[PF_RING] mmap [slot_len=%d]"
+ "[tot_slots=%d] for ring on device %s\n",
+ pfr->slots_info->slot_len, pfr->slots_info->min_num_slots,
+ pfr->ring_netdev->dev->name);
+
+ if((rc = do_memory_mmap(vma, size, pfr->ring_memory, VM_LOCKED, 0)) < 0)
+ return(rc);
break;
+ /* DNA Device */
case 1:
- if((rc = do_memory_mmap(vma, size,
- (void *)pfr->dna_device->descr_packet_memory, VM_LOCKED, 1)) < 0)
+ /* DNA: RX packet memory */
+ if((rc = do_memory_mmap(vma, size, (void *)pfr->dna_device->rx_packet_memory, VM_LOCKED, 1)) < 0)
return(rc);
break;
case 2:
- if((rc = do_memory_mmap(vma, size,
- (void *)pfr->dna_device->phys_card_memory, (VM_RESERVED | VM_IO), 2)) < 0)
+ /* DNA: RX packet descriptors */
+ if((rc = do_memory_mmap(vma, size, (void *)pfr->dna_device->rx_descr_packet_memory, VM_LOCKED, 1)) < 0)
+ return(rc);
+ break;
+
+ case 3:
+ if((rc = do_memory_mmap(vma, size, (void *)pfr->dna_device->phys_card_memory, (VM_RESERVED | VM_IO), 2)) < 0)
+ return(rc);
+ break;
+
+ case 4:
+ /* DNA: TX packet memory */
+ if((rc = do_memory_mmap(vma, size, (void *)pfr->dna_device->tx_packet_memory, VM_LOCKED, 1)) < 0)
+ return(rc);
+ break;
+
+ case 5:
+ /* DNA: TX packet descriptors */
+ if((rc = do_memory_mmap(vma, size, (void *)pfr->dna_device->tx_descr_packet_memory, VM_LOCKED, 1)) < 0)
return(rc);
break;
default:
return(-EAGAIN);
- }
}
-#if defined(RING_DEBUG)
- printk("[PF_RING] ring_mmap succeeded\n");
-#endif
+ if(enable_debug)
+ printk("[PF_RING] ring_mmap succeeded\n");
return 0;
}
@@ -3270,23 +3961,21 @@
static int ring_recvmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *msg, size_t len, int flags)
{
- struct ring_opt *pfr = ring_sk(sock->sk);
+ struct pf_ring_socket *pfr = ring_sk(sock->sk);
u_int32_t queued_pkts, num_loops = 0;
-#if defined(RING_DEBUG)
- printk("[PF_RING] ring_recvmsg called\n");
-#endif
+ if(enable_debug)
+ printk("[PF_RING] ring_recvmsg called\n");
pfr->ring_active = 1;
while((queued_pkts = num_queued_pkts(pfr)) < MIN_QUEUED_PKTS) {
wait_event_interruptible(pfr->ring_slots_waitqueue, 1);
-#if defined(RING_DEBUG)
- printk("[PF_RING] -> ring_recvmsg "
- "[queued_pkts=%d][num_loops=%d]\n",
- queued_pkts, num_loops);
-#endif
+ if(enable_debug)
+ printk("[PF_RING] -> ring_recvmsg "
+ "[queued_pkts=%d][num_loops=%d]\n",
+ queued_pkts, num_loops);
if(queued_pkts > 0) {
if(num_loops++ > MAX_QUEUE_LOOPS)
@@ -3303,7 +3992,7 @@
static int ring_sendmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *msg, size_t len)
{
- struct ring_opt *pfr = ring_sk(sock->sk);
+ struct pf_ring_socket *pfr = ring_sk(sock->sk);
struct sockaddr_pkt *saddr=(struct sockaddr_pkt *)msg->msg_name;
struct sk_buff *skb;
__be16 proto=0;
@@ -3312,13 +4001,13 @@
/*
* Get and verify the address.
*/
- if (saddr)
+ if(saddr)
{
- if (saddr == NULL) proto = htons(ETH_P_ALL);
+ if(saddr == NULL) proto = htons(ETH_P_ALL);
- if (msg->msg_namelen < sizeof(struct sockaddr))
+ if(msg->msg_namelen < sizeof(struct sockaddr))
return(-EINVAL);
- if (msg->msg_namelen == sizeof(struct sockaddr_pkt))
+ if(msg->msg_namelen == sizeof(struct sockaddr_pkt))
proto = saddr->spkt_protocol;
}
else
@@ -3327,11 +4016,11 @@
/*
* Find the device first to size check it
*/
- if (pfr->ring_netdev == NULL)
+ if(pfr->ring_netdev->dev == NULL)
goto out_unlock;
err = -ENETDOWN;
- if (!(pfr->ring_netdev->flags & IFF_UP))
+ if(!(pfr->ring_netdev->dev->flags & IFF_UP))
goto out_unlock;
/*
@@ -3339,11 +4028,11 @@
* raw protocol and you must do your own fragmentation at this level.
*/
err = -EMSGSIZE;
- if (len > pfr->ring_netdev->mtu + pfr->ring_netdev->hard_header_len)
+ if(len > pfr->ring_netdev->dev->mtu + pfr->ring_netdev->dev->hard_header_len)
goto out_unlock;
err = -ENOBUFS;
- skb = sock_wmalloc(sock->sk, len + LL_RESERVED_SPACE(pfr->ring_netdev), 0, GFP_KERNEL);
+ skb = sock_wmalloc(sock->sk, len + LL_RESERVED_SPACE(pfr->ring_netdev->dev), 0, GFP_KERNEL);
/*
* If the write buffer is full, then tough. At this level the user gets to
@@ -3351,7 +4040,7 @@
* more flexible.
*/
- if (skb == NULL)
+ if(skb == NULL)
goto out_unlock;
/*
@@ -3362,32 +4051,37 @@
* hard header at transmission time by themselves. PPP is the
* notable one here. This should really be fixed at the driver level.
*/
- skb_reserve(skb, LL_RESERVED_SPACE(pfr->ring_netdev));
+ skb_reserve(skb, LL_RESERVED_SPACE(pfr->ring_netdev->dev));
skb_reset_network_header(skb);
/* Try to align data part correctly */
-#if(LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18))
- if (pfr->ring_netdev->header_ops) {
- skb->data -= pfr->ring_netdev->hard_header_len;
- skb->tail -= pfr->ring_netdev->hard_header_len;
- if (len < pfr->ring_netdev->hard_header_len)
+#if(LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23))
+ if(pfr->ring_netdev->dev->header_ops) {
+ skb->data -= pfr->ring_netdev->dev->hard_header_len;
+ skb->tail -= pfr->ring_netdev->dev->hard_header_len;
+ if(len < pfr->ring_netdev->dev->hard_header_len)
skb_reset_network_header(skb);
}
#else
- if (pfr->ring_netdev->hard_header) {
- skb->data -= pfr->ring_netdev->hard_header_len;
- skb->tail -= pfr->ring_netdev->hard_header_len;
- if (len < pfr->ring_netdev->hard_header_len)
+ if(pfr->ring_netdev->dev->hard_header) {
+ skb->data -= pfr->ring_netdev->dev->hard_header_len;
+ skb->tail -= pfr->ring_netdev->dev->hard_header_len;
+ if(len < pfr->ring_netdev->dev->hard_header_len) {
+#if(LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18))
+ skb_reset_network_header(skb);
+#else
skb->nh.raw = skb->data;
+#endif
+ }
}
#endif
/* Returns -EFAULT on error */
err = memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len);
skb->protocol = proto;
- skb->dev = pfr->ring_netdev;
+ skb->dev = pfr->ring_netdev->dev;
skb->priority = sock->sk->sk_priority;
- if (err)
+ if(err)
goto out_free;
/*
@@ -3395,15 +4089,16 @@
*/
dev_queue_xmit(skb);
- dev_put(pfr->ring_netdev);
+ dev_put(pfr->ring_netdev->dev);
return(len);
out_free:
kfree_skb(skb);
out_unlock:
- if (pfr->ring_netdev)
- dev_put(pfr->ring_netdev);
+ if(pfr->ring_netdev)
+ dev_put(pfr->ring_netdev->dev);
+
return err;
}
@@ -3412,72 +4107,75 @@
unsigned int ring_poll(struct file *file,
struct socket *sock, poll_table * wait)
{
- struct ring_opt *pfr = ring_sk(sock->sk);
+ struct pf_ring_socket *pfr = ring_sk(sock->sk);
int rc, mask = 0;
-#if defined(RING_DEBUG)
- printk("[PF_RING] -- poll called\n");
-#endif
+ if(enable_debug)
+ printk("[PF_RING] -- poll called\n");
+
+ pfr->num_poll_calls++;
if(pfr->dna_device == NULL) {
/* PF_RING mode (No DNA) */
-#if defined(RING_DEBUG)
- printk("[PF_RING] poll called (non DNA device)\n");
-#endif
+ if(enable_debug)
+ printk("[PF_RING] poll called (non DNA device)\n");
pfr->ring_active = 1;
// smp_rmb();
- if(pfr->slots_info->tot_read == pfr->slots_info->tot_insert) {
+ if(num_queued_pkts(pfr) < pfr->poll_num_pkts_watermark) {
poll_wait(file, &pfr->ring_slots_waitqueue, wait);
+ // smp_mb();
}
- if(num_queued_pkts(pfr) > 0)
+ if(num_queued_pkts(pfr) >= pfr->poll_num_pkts_watermark)
mask |= POLLIN | POLLRDNORM;
return(mask);
} else {
/* DNA mode */
+ /* enable_debug = 1; */
-#if defined(RING_DEBUG)
- printk("[PF_RING] poll called on DNA device [%d]\n",
- *pfr->dna_device->interrupt_received);
-#endif
+ if(enable_debug)
+ printk("[PF_RING] poll called on DNA device [%d]\n",
+ *pfr->dna_device->interrupt_received);
if(pfr->dna_device->wait_packet_function_ptr == NULL) {
-#if defined(RING_DEBUG)
- printk("[PF_RING] wait_packet_function_ptr is NULL: returning to caller\n");
-#endif
+ if(enable_debug)
+ printk("[PF_RING] wait_packet_function_ptr is NULL: returning to caller\n");
return(0);
}
rc = pfr->dna_device->wait_packet_function_ptr(pfr->dna_device->adapter_ptr, 1);
-#if defined(RING_DEBUG)
- printk("[PF_RING] wait_packet_function_ptr(1) returned %d\n", rc);
-#endif
+ if(enable_debug)
+ printk("[PF_RING] wait_packet_function_ptr(1) returned %d\n", rc);
if(rc == 0) {
+ if(enable_debug)
+ printk("[PF_RING] calling poll_wait()\n");
+
/* No packet arrived yet */
poll_wait(file, pfr->dna_device->packet_waitqueue, wait);
+
+ if(enable_debug)
+ printk("[PF_RING] poll_wait() just returned\n");
} else
rc = pfr->dna_device->wait_packet_function_ptr(pfr->dna_device->adapter_ptr, 0);
-#if defined(RING_DEBUG)
- printk("[PF_RING] wait_packet_function_ptr(0) returned %d\n", rc);
-#endif
+ if(enable_debug)
+ printk("[PF_RING] wait_packet_function_ptr(0) returned %d\n", rc);
//*pfr->dna_device->interrupt_received = rc;
if(rc == 0)
rc = *pfr->dna_device->interrupt_received;
-#if defined(RING_DEBUG)
- printk("[PF_RING] poll %s return [%d]\n",
- pfr->ring_netdev->name,
- *pfr->dna_device->interrupt_received);
-#endif
+ if(enable_debug)
+ printk("[PF_RING] poll %s return [%d]\n",
+ pfr->ring_netdev->dev->name,
+ *pfr->dna_device->interrupt_received);
if(rc) {
return(POLLIN | POLLRDNORM);
@@ -3529,13 +4227,12 @@
/* ************************************* */
-static int remove_from_cluster(struct sock *sock, struct ring_opt *pfr)
+static int remove_from_cluster(struct sock *sock, struct pf_ring_socket *pfr)
{
struct list_head *ptr, *tmp_ptr;
-#if defined(RING_DEBUG)
- printk("[PF_RING] --> remove_from_cluster(%d)\n", pfr->cluster_id);
-#endif
+ if(enable_debug)
+ printk("[PF_RING] --> remove_from_cluster(%d)\n", pfr->cluster_id);
if(pfr->cluster_id == 0 /* 0 = No Cluster */ )
return(0); /* Noting to do */
@@ -3546,8 +4243,7 @@
cluster_ptr = list_entry(ptr, ring_cluster_element, list);
if(cluster_ptr->cluster.cluster_id == pfr->cluster_id) {
- return(remove_from_cluster_list
- (&cluster_ptr->cluster, sock));
+ return(remove_from_cluster_list(&cluster_ptr->cluster, sock));
}
}
@@ -3556,26 +4252,23 @@
/* ************************************* */
-// #define RING_DEBUG 1
-
static int set_master_ring(struct sock *sock,
- struct ring_opt *pfr,
+ struct pf_ring_socket *pfr,
u_int32_t master_socket_id)
{
int rc = -1;
struct list_head *ptr;
-#if defined(RING_DEBUG)
- printk("[PF_RING] set_master_ring(%s=%d)\n",
- pfr->ring_netdev ? pfr->ring_netdev->name : "none",
- master_socket_id);
-#endif
+ if(enable_debug)
+ printk("[PF_RING] set_master_ring(%s=%d)\n",
+ pfr->ring_netdev->dev ? pfr->ring_netdev->dev->name : "none",
+ master_socket_id);
/* Avoid the ring to be manipulated while playing with it */
- read_lock_bh(&ring_mgmt_lock);
+ ring_read_lock();
list_for_each(ptr, &ring_table) {
- struct ring_opt *sk_pfr;
+ struct pf_ring_socket *sk_pfr;
struct ring_element *entry;
struct sock *skElement;
@@ -3587,48 +4280,42 @@
if((sk_pfr != NULL) && (sk_pfr->ring_id == master_socket_id)) {
pfr->master_ring = sk_pfr;
-#if defined(RING_DEBUG)
- printk("[PF_RING] Found set_master_ring(%s) -> %s\n",
- sk_pfr->ring_netdev ? sk_pfr->ring_netdev->name : "none",
- pfr->master_ring->ring_netdev->name);
-#endif
+ if(enable_debug)
+ printk("[PF_RING] Found set_master_ring(%s) -> %s\n",
+ sk_pfr->ring_netdev->dev ? sk_pfr->ring_netdev->dev->name : "none",
+ pfr->master_ring->ring_netdev->dev->name);
rc = 0;
break;
} else {
-#if defined(RING_DEBUG)
- printk("[PF_RING] Skipping socket(%s)=%d\n",
- sk_pfr->ring_netdev ? sk_pfr->ring_netdev->name : "none",
- sk_pfr->ring_id);
-#endif
+ if(enable_debug)
+ printk("[PF_RING] Skipping socket(%s)=%d\n",
+ sk_pfr->ring_netdev->dev ? sk_pfr->ring_netdev->dev->name : "none",
+ sk_pfr->ring_id);
}
}
- read_unlock_bh(&ring_mgmt_lock);
+ ring_read_unlock();
-#if defined(RING_DEBUG)
- printk("[PF_RING] set_master_ring(%s, socket_id=%d) = %d\n",
- pfr->ring_netdev ? pfr->ring_netdev->name : "none",
- master_socket_id, rc);
-#endif
+ if(enable_debug)
+ printk("[PF_RING] set_master_ring(%s, socket_id=%d) = %d\n",
+ pfr->ring_netdev->dev ? pfr->ring_netdev->dev->name : "none",
+ master_socket_id, rc);
return(rc);
}
-// #undef RING_DEBUG
-
/* ************************************* */
static int add_sock_to_cluster(struct sock *sock,
- struct ring_opt *pfr,
+ struct pf_ring_socket *pfr,
struct add_to_cluster *cluster)
{
struct list_head *ptr, *tmp_ptr;
ring_cluster_element *cluster_ptr;
-#ifdef RING_DEBUG
- printk("[PF_RING] --> add_sock_to_cluster(%d)\n", cluster->clusterId);
-#endif
+ if(enable_debug)
+ printk("[PF_RING] --> add_sock_to_cluster(%d)\n", cluster->clusterId);
if(cluster->clusterId == 0 /* 0 = No Cluster */ )
return(-EINVAL);
@@ -3665,21 +4352,52 @@
/* ************************************* */
-static int ring_map_dna_device(struct ring_opt *pfr,
- dna_device_mapping * mapping)
+static int ring_map_dna_device(struct pf_ring_socket *pfr,
+ dna_device_mapping *mapping)
{
- int debug = 1;
+ struct list_head *ptr, *tmp_ptr;
+ dna_device_list *entry;
+
+ if(enable_debug)
+ printk("[PF_RING] ring_map_dna_device(%s@%d): %s\n",
+ mapping->device_name,
+ mapping->channel_id,
+ (mapping->operation == remove_device_mapping) ? "remove" : "add");
if(mapping->operation == remove_device_mapping) {
+ /* Unlock driver */
+ u8 found = 0;
+
+ list_for_each_safe(ptr, tmp_ptr, &ring_dna_devices_list) {
+ entry = list_entry(ptr, dna_device_list, list);
+
+ if((!strcmp(entry->dev.netdev->name, mapping->device_name))
+ && (entry->dev.channel_id == mapping->channel_id)
+ && entry->in_use) {
+ if(entry->sock_a == pfr) entry->sock_a = NULL;
+ else if(entry->sock_b == pfr) entry->sock_b = NULL;
+ else if(entry->sock_c == pfr) entry->sock_c = NULL;
+ else {
+ printk("[PF_RING] ring_map_dna_device(%s, %u): something got wrong 1\n",
+ mapping->device_name, mapping->channel_id);
+ return(-1); /* Something got wrong */
+ }
+
+ entry->in_use--, found = 1;
+ break;
+ }
+ }
+
+ if(pfr->dna_device != NULL)
+ pfr->dna_device->usage_notification(pfr->dna_device->adapter_ptr, 0 /* unlock */);
+
pfr->dna_device = NULL;
- if(debug)
+ if(enable_debug)
printk("[PF_RING] ring_map_dna_device(%s): removed mapping\n",
mapping->device_name);
- return(0);
- } else {
- struct list_head *ptr, *tmp_ptr;
- dna_device_list *entry;
+ if(!found) return(-1); else return(0);
+ } else {
ring_proc_remove(pfr);
list_for_each_safe(ptr, tmp_ptr, &ring_dna_devices_list) {
@@ -3687,19 +4405,51 @@
if((!strcmp(entry->dev.netdev->name, mapping->device_name))
&& (entry->dev.channel_id == mapping->channel_id)) {
- pfr->dna_device = &entry->dev, pfr->ring_netdev = entry->dev.netdev;
- if(debug)
+ if(enable_debug)
+ printk("[PF_RING] ==>> %s@%d [in_use=%d][%p]\n",
+ entry->dev.netdev->name,
+ mapping->channel_id,
+ entry->in_use, entry);
+
+ if(entry->sock_a == NULL) entry->sock_a = pfr;
+ else if(entry->sock_b == NULL) entry->sock_b = pfr;
+ else if(entry->sock_c == NULL) entry->sock_c = pfr;
+ else {
+ printk("[PF_RING] ring_map_dna_device(%s, %u, %s): something got wrong (too many DNA devices open)\n",
+ mapping->device_name, mapping->channel_id, direction2string(pfr->direction));
+ return(-1); /* Something got wrong: too many mappings */
+ }
+
+ entry->in_use++, pfr->dna_device_entry = entry;
+
+ pfr->dna_device = &entry->dev, pfr->ring_netdev->dev = entry->dev.netdev /* Default */;
+
+ if(enable_debug)
printk("[PF_RING] ring_map_dna_device(%s, %u): added mapping\n",
mapping->device_name, mapping->channel_id);
+ /* Now let's set the read ring_netdev device */
+ list_for_each_safe(ptr, tmp_ptr, &ring_aware_device_list) {
+ ring_device_element *dev_ptr = list_entry(ptr, ring_device_element, device_list);
+
+ if(!strcmp(dev_ptr->dev->name, mapping->device_name)) {
+ if(enable_debug)
+ printk("[PF_RING] ==>> %s [%p]\n", dev_ptr->dev->name, dev_ptr);
+ pfr->ring_netdev = dev_ptr;
+ break;
+ }
+ }
+
+ /* Lock driver */
+ pfr->dna_device->usage_notification(pfr->dna_device->adapter_ptr, 1 /* lock */);
ring_proc_add(pfr);
return(0);
}
}
}
- printk("[PF_RING] ring_map_dna_device(%s, %u): mapping failed\n",
+ printk("[PF_RING] ring_map_dna_device(%s, %u): mapping failed\n",
mapping->device_name, mapping->channel_id);
return(-1);
@@ -3707,23 +4457,22 @@
/* ************************************* */
-static void purge_idle_hash_rules(struct ring_opt *pfr,
+static void purge_idle_hash_rules(struct pf_ring_socket *pfr,
uint16_t rule_inactivity)
{
- int i, num_purged_rules = 0, debug = 0;
+ int i, num_purged_rules = 0;
unsigned long expire_jiffies =
jiffies - msecs_to_jiffies(1000 * rule_inactivity);
- if(debug)
+ if(enable_debug)
printk("[PF_RING] purge_idle_hash_rules(rule_inactivity=%d)\n",
rule_inactivity);
/* Free filtering hash rules inactive for more than rule_inactivity seconds */
- if(pfr->filtering_hash != NULL) {
+ if(pfr->sw_filtering_hash != NULL) {
for(i = 0; i < DEFAULT_RING_HASH_SIZE; i++) {
- if(pfr->filtering_hash[i] != NULL) {
- filtering_hash_bucket *scan =
- pfr->filtering_hash[i], *next, *prev = NULL;
+ if(pfr->sw_filtering_hash[i] != NULL) {
+ sw_filtering_hash_bucket *scan = pfr->sw_filtering_hash[i], *next, *prev = NULL;
while(scan != NULL) {
next = scan->next;
@@ -3731,7 +4480,7 @@
if(scan->rule.internals.jiffies_last_match < expire_jiffies) {
/* Expired rule: free it */
- if(debug)
+ if(enable_debug)
printk ("[PF_RING] Purging hash rule "
/* "[last_match=%u][expire_jiffies=%u]" */
"[%d.%d.%d.%d:%d <-> %d.%d.%d.%d:%d][purged=%d][tot_rules=%d]\n",
@@ -3750,18 +4499,18 @@
((scan->rule.host4_peer_b >> 0) & 0xff),
scan->rule.port_peer_b,
num_purged_rules,
- pfr->num_filtering_rules);
+ pfr->num_sw_filtering_rules);
- free_filtering_hash_bucket
+ free_sw_filtering_hash_bucket
(scan);
kfree(scan);
if(prev == NULL)
- pfr->filtering_hash[i] = next;
+ pfr->sw_filtering_hash[i] = next;
else
prev->next = next;
- pfr->num_filtering_rules--,
+ pfr->num_sw_filtering_rules--,
num_purged_rules++;
} else
prev = scan;
@@ -3772,9 +4521,259 @@
}
}
- if(debug)
+ if(enable_debug)
printk("[PF_RING] Purged %d hash rules [tot_rules=%d]\n",
- num_purged_rules, pfr->num_filtering_rules);
+ num_purged_rules, pfr->num_sw_filtering_rules);
+}
+
+/* ************************************* */
+
+static int remove_sw_filtering_rule_element(struct pf_ring_socket *pfr, u_int16_t rule_id)
+{
+ int rule_found = 0;
+ struct list_head *ptr, *tmp_ptr;
+
+ write_lock(&pfr->ring_rules_lock);
+
+ list_for_each_safe(ptr, tmp_ptr, &pfr->sw_filtering_rules) {
+ sw_filtering_rule_element *entry;
+
+ entry = list_entry(ptr, sw_filtering_rule_element, list);
+
+ if(entry->rule.rule_id == rule_id) {
+#ifdef CONFIG_TEXTSEARCH
+ int i;
+
+ for(i = 0; (i < MAX_NUM_PATTERN) && (entry->pattern[i] != NULL); i++)
+ textsearch_destroy(entry->pattern[i]);
+#endif
+ list_del(ptr);
+ pfr->num_sw_filtering_rules--;
+
+ if(entry->plugin_data_ptr)
+ kfree(entry->plugin_data_ptr);
+ free_filtering_rule(&entry->rule);
+ kfree(entry);
+ if(enable_debug)
+ printk("[PF_RING] SO_REMOVE_FILTERING_RULE: rule %d has been removed\n", rule_id);
+ rule_found = 1;
+ break;
+ }
+ } /* for */
+
+ write_unlock(&pfr->ring_rules_lock);
+
+ return(rule_found);
+}
+
+/* ************************************* */
+
+static int add_sw_filtering_rule_element(struct pf_ring_socket *pfr, sw_filtering_rule_element *rule)
+{
+ struct list_head *ptr, *tmp_ptr;
+ int idx = 0;
+ sw_filtering_rule_element *entry;
+ struct list_head *prev = NULL;
+
+ /* Rule checks */
+ if(rule->rule.extended_fields.filter_plugin_id > 0) {
+ int ret = 0;
+
+ if(rule->rule.extended_fields.filter_plugin_id >= MAX_PLUGIN_ID)
+ ret = -EFAULT;
+ else if(plugin_registration[rule->rule.extended_fields.filter_plugin_id] == NULL)
+ ret = -EFAULT;
+
+ if(ret != 0) {
+ if(enable_debug)
+ printk("[PF_RING] Invalid filtering plugin [id=%d]\n",
+ rule->rule.extended_fields.filter_plugin_id);
+ kfree(rule);
+ return(ret);
+ }
+ }
+
+ if(rule->rule.plugin_action.plugin_id != NO_PLUGIN_ID) {
+ int ret = 0;
+
+ if(rule->rule.plugin_action.plugin_id >= MAX_PLUGIN_ID)
+ ret = -EFAULT;
+ else if(plugin_registration[rule->rule.plugin_action.plugin_id] == NULL)
+ ret = -EFAULT;
+
+ if(ret != 0) {
+ if(enable_debug)
+ printk("[PF_RING] Invalid action plugin [id=%d]\n",
+ rule->rule.plugin_action.plugin_id);
+ kfree(rule);
+ return(ret);
+ }
+ }
+
+ if(rule->rule.reflector_device_name[0] != '\0') {
+ if((pfr->ring_netdev->dev != NULL)
+ && (strcmp(rule->rule.reflector_device_name, pfr->ring_netdev->dev->name) == 0)) {
+ if(enable_debug)
+ printk("[PF_RING] You cannot use as reflection device the same device on which this ring is bound\n");
+ kfree(rule);
+ return(-EFAULT);
+ }
+
+ rule->rule.internals.reflector_dev = dev_get_by_name(
+#if(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24))
+ &init_net,
+#endif
+ rule->rule.reflector_device_name);
+
+ if(rule->rule.internals.reflector_dev == NULL) {
+ printk("[PF_RING] Unable to find device %s\n", rule->rule.reflector_device_name);
+ kfree(rule);
+ return(-EFAULT);
+ }
+ } else
+ rule->rule.internals.reflector_dev = NULL;
+
+ /* Compile pattern if present */
+ if(strlen(rule->rule.extended_fields.payload_pattern) > 0) {
+ char *pattern = rule->rule.extended_fields.payload_pattern;
+
+ printk("[PF_RING] About to compile pattern '%s'\n", pattern);
+
+ while(pattern && (idx < MAX_NUM_PATTERN)) {
+ char *pipe = strchr(pattern, '|');
+
+ if(pipe)
+ pipe[0] = '\0';
+
+#ifdef CONFIG_TEXTSEARCH
+ rule->pattern[idx] = textsearch_prepare("bm" /* Boyer-Moore */
+ /* "kmp" = Knuth-Morris-Pratt */
+ , pattern, strlen(pattern),
+ GFP_KERNEL,
+ TS_AUTOLOAD
+#ifdef TS_IGNORECASE
+ | TS_IGNORECASE
+#endif
+ );
+ if(rule->pattern[idx])
+ printk("[PF_RING] Compiled pattern '%s' [idx=%d]\n", pattern, idx);
+#endif
+ if(pipe)
+ pattern = &pipe[1], idx++;
+ else
+ break;
+ }
+ } else {
+#ifdef CONFIG_TEXTSEARCH
+ rule->pattern[0] = NULL;
+#endif
+ }
+
+ if(enable_debug)
+ printk("[PF_RING] SO_ADD_FILTERING_RULE: About to add rule %d\n",
+ rule->rule.rule_id);
+
+ /* Implement an ordered add */
+ list_for_each_safe(ptr, tmp_ptr, &pfr->sw_filtering_rules) {
+ entry = list_entry(ptr, sw_filtering_rule_element, list);
+
+ if(enable_debug)
+ printk("[PF_RING] SO_ADD_FILTERING_RULE: [current rule %d][rule to add %d]\n",
+ entry->rule.rule_id,
+ rule->rule.rule_id);
+
+ if(entry->rule.rule_id > rule->rule.rule_id) {
+ if(prev == NULL) {
+ list_add(&rule->list, &pfr->sw_filtering_rules); /* Add as first entry */
+ pfr->num_sw_filtering_rules++;
+ if(enable_debug)
+ printk("[PF_RING] SO_ADD_FILTERING_RULE: added rule %d as head rule\n",
+ rule->rule.rule_id);
+ } else {
+ list_add(&rule->list, prev);
+ pfr->num_sw_filtering_rules++;
+ if(enable_debug)
+ printk("[PF_RING] SO_ADD_FILTERING_RULE: added rule %d\n",
+ rule->rule.rule_id);
+ }
+
+ rule = NULL;
+ break;
+ } else
+ prev = ptr;
+ } /* for */
+
+ if(rule != NULL) {
+ if(prev == NULL) {
+ list_add(&rule->list, &pfr->sw_filtering_rules); /* Add as first entry */
+ pfr->num_sw_filtering_rules++;
+ if(enable_debug)
+ printk("[PF_RING] SO_ADD_FILTERING_RULE: added rule %d as first rule\n",
+ rule->rule.rule_id);
+ } else {
+ list_add_tail(&rule->list, &pfr->sw_filtering_rules); /* Add as first entry */
+ pfr->num_sw_filtering_rules++;
+ if(enable_debug)
+ printk("[PF_RING] SO_ADD_FILTERING_RULE: added rule %d as last rule\n",
+ rule->rule.rule_id);
+ }
+ }
+
+ if(rule->rule.extended_fields.filter_plugin_id > 0) {
+ if(plugin_registration[rule->rule.extended_fields.filter_plugin_id]->pfring_plugin_register)
+ plugin_registration[rule->rule.extended_fields.filter_plugin_id]->pfring_plugin_register(1);
+ }
+
+ if(rule->rule.plugin_action.plugin_id > 0) {
+ if(plugin_registration[rule->rule.plugin_action.plugin_id]->pfring_plugin_register)
+ plugin_registration[rule->rule.plugin_action.plugin_id]->pfring_plugin_register(1);
+ }
+
+ return(0);
+}
+
+/* ************************************* */
+
+static int add_sw_filtering_hash_bucket(struct pf_ring_socket *pfr, sw_filtering_hash_bucket *rule) {
+ int rc = 0;
+
+ if(rule->rule.reflector_device_name[0] != '\0') {
+ if((pfr->ring_netdev->dev != NULL)
+ && (strcmp(rule->rule.reflector_device_name, pfr->ring_netdev->dev->name) == 0)) {
+ if(enable_debug)
+ printk("[PF_RING] You cannot use as reflection device the same device on "
+ "which this ring is bound\n");
+ kfree(rule);
+ return(-EFAULT);
+ }
+
+ rule->rule.internals.reflector_dev = dev_get_by_name(
+#if(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24))
+ &init_net,
+#endif
+ rule->rule.reflector_device_name);
+
+ if(rule->rule.internals.reflector_dev == NULL) {
+ printk("[PF_RING] Unable to find device %s\n",
+ rule->rule.reflector_device_name);
+ kfree(rule);
+ return(-EFAULT);
+ }
+ } else
+ rule->rule.internals.reflector_dev = NULL;
+
+ write_lock(&pfr->ring_rules_lock);
+ rc = handle_sw_filtering_hash_bucket(pfr, rule, 1 /* add */);
+
+ if((rc != 0) && (rc != -EEXIST)) {
+ kfree(rule);
+ } else {
+ if(rc != -EEXIST)
+ pfr->num_sw_filtering_rules++;
+ }
+
+ write_unlock(&pfr->ring_rules_lock);
+ return(rc);
}
/* ************************************* */
@@ -3788,18 +4787,20 @@
#endif
int optlen)
{
- struct ring_opt *pfr = ring_sk(sock->sk);
+ struct pf_ring_socket *pfr = ring_sk(sock->sk);
int val, found, ret = 0 /* OK */;
u_int32_t ring_id;
- u_int debug = 0;
struct add_to_cluster cluster;
- int32_t channel_id;
+ u_int32_t channel_id;
char applName[32 + 1] = { 0 };
- struct list_head *prev = NULL;
- filtering_rule_element *entry, *rule;
u_int16_t rule_id, rule_inactivity;
packet_direction direction;
hw_filtering_rule hw_rule;
+ struct list_head *ptr, *tmp_ptr;
+#ifdef VPFRING_SUPPORT
+ struct vpfring_eventfd_info eventfd_i;
+ struct file *eventfp;
+#endif //VPFRING_SUPPORT
if(pfr == NULL)
return(-EINVAL);
@@ -3809,13 +4810,12 @@
found = 1;
- switch (optname) {
+ switch(optname) {
case SO_ATTACH_FILTER:
ret = -EINVAL;
-#if !defined(RING_DEBUG)
- printk("[PF_RING] BPF filter (%d)\n", 0);
-#endif
+ if(enable_debug)
+ printk("[PF_RING] BPF filter (%d)\n", 0);
if(optlen == sizeof(struct sock_fprog)) {
unsigned int fsize;
@@ -3824,9 +4824,9 @@
ret = -EFAULT;
-#if !defined(RING_DEBUG)
- printk("[PF_RING] BPF filter (%d)\n", 1);
-#endif
+ if(enable_debug)
+ printk("[PF_RING] BPF filter (%d)\n", 1);
+
/*
NOTE
@@ -3865,10 +4865,9 @@
write_unlock(&pfr->ring_rules_lock);
ret = 0;
-#if !defined(RING_DEBUG)
- printk("[PF_RING] BPF filter attached successfully [len=%d]\n",
- filter->len);
-#endif
+ if(enable_debug)
+ printk("[PF_RING] BPF filter attached successfully [len=%d]\n",
+ filter->len);
}
break;
@@ -3908,11 +4907,43 @@
if(copy_from_user(&channel_id, optval, sizeof(channel_id)))
return -EFAULT;
+ if(quick_mode) {
+ /*
+ We need to set the device_rings[] for all channels set
+ in channel_id
+ */
+ int i;
+
+ pfr->num_channels_per_ring = 0;
+
+ for(i=0; i<pfr->num_rx_channels; i++) {
+ u_int32_t the_bit = 1 << i;
+
+ if((channel_id & the_bit) == the_bit) {
+ if(device_rings[pfr->ring_netdev->dev->ifindex][i] != NULL)
+ return(-EINVAL); /* Socket already bound on this device */
+ }
+ }
+
+ /* Everything seems to work thus let's set the values */
+
+ for(i=0; i<pfr->num_rx_channels; i++) {
+ u_int32_t the_bit = 1 << i;
+
+ if((channel_id & the_bit) == the_bit) {
+ if(enable_debug) printk("[PF_RING] Setting channel %d\n", i);
+
+ device_rings[pfr->ring_netdev->dev->ifindex][i] = pfr;
+ pfr->num_channels_per_ring++;
+ }
+ }
+ }
+
pfr->channel_id = channel_id;
-#if defined(RING_DEBUG)
- printk("[PF_RING] [pfr->channel_id=%d][channel_id=%d]\n",
- pfr->channel_id, channel_id);
-#endif
+ if(enable_debug)
+ printk("[PF_RING] [pfr->channel_id=%d][channel_id=%d]\n",
+ pfr->channel_id, channel_id);
+
ret = 0;
break;
@@ -3943,10 +4974,10 @@
return -EFAULT;
pfr->direction = direction;
-#if defined(RING_DEBUG)
- printk("[PF_RING] [pfr->direction=%d][direction=%d]\n",
- pfr->direction, direction);
-#endif
+ if(enable_debug)
+ printk("[PF_RING] SO_SET_PACKET_DIRECTION [pfr->direction=%s][direction=%s]\n",
+ direction2string(pfr->direction), direction2string(direction));
+
ret = 0;
break;
@@ -3976,215 +5007,67 @@
return -EFAULT;
write_lock(&pfr->ring_rules_lock);
- pfr->rules_default_accept_policy = new_policy;
+ pfr->sw_filtering_rules_default_accept_policy = new_policy;
write_unlock(&pfr->ring_rules_lock);
- /*
- if(debug)
- printk("[PF_RING] SO_TOGGLE_FILTER_POLICY: default policy is %s\n",
- pfr->rules_default_accept_policy ? "accept" : "drop");
- */
- }
- break;
-
- case SO_ADD_FILTERING_RULE:
- if(debug)
- printk("[PF_RING] +++ SO_ADD_FILTERING_RULE(len=%d)(len=%u)\n",
- optlen, (unsigned int)sizeof(ip_addr));
-
- if(pfr->ring_netdev == &none_dev) return -EFAULT;
-
- if(optlen == sizeof(filtering_rule)) {
- struct list_head *ptr, *tmp_ptr;
- int idx = 0;
-
- if(debug)
- printk("[PF_RING] Allocating memory [filtering_rule]\n");
-
- rule =(filtering_rule_element *)
- kcalloc(1, sizeof(filtering_rule_element), GFP_KERNEL);
-
- if(rule == NULL)
- return -EFAULT;
-
- if(copy_from_user(&rule->rule, optval, optlen))
- return -EFAULT;
-
- INIT_LIST_HEAD(&rule->list);
-
- /* Rule checks */
- if(rule->rule.extended_fields.filter_plugin_id > 0) {
- int ret = 0;
-
- if(rule->rule.extended_fields.filter_plugin_id >= MAX_PLUGIN_ID)
- ret = -EFAULT;
- else if(plugin_registration[rule->rule.extended_fields.filter_plugin_id] == NULL)
- ret = -EFAULT;
-
- if(ret != 0) {
- if(debug)
- printk("[PF_RING] Invalid filtering plugin [id=%d]\n",
- rule->rule.extended_fields.filter_plugin_id);
- kfree(rule);
- return(ret);
- }
- }
-
- if(rule->rule.plugin_action.plugin_id != NO_PLUGIN_ID) {
- int ret = 0;
-
- if(rule->rule.plugin_action.plugin_id >= MAX_PLUGIN_ID)
- ret = -EFAULT;
- else if(plugin_registration[rule->rule.plugin_action.plugin_id] == NULL)
- ret = -EFAULT;
-
- if(ret != 0) {
- if(debug)
- printk("[PF_RING] Invalid action plugin [id=%d]\n",
- rule->rule.plugin_action.plugin_id);
- kfree(rule);
- return(ret);
- }
- }
-
- if(rule->rule.reflector_device_name[0] != '\0') {
- rule->rule.internals.reflector_dev =
- dev_get_by_name(
-#if(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24))
- &init_net,
-#endif
- rule->rule.reflector_device_name);
-
- if(rule->rule.internals.reflector_dev == NULL) {
- printk("[PF_RING] Unable to find device %s\n",
- rule->rule.reflector_device_name);
- kfree(rule);
- return(-EFAULT);
- }
- } else
- rule->rule.internals.reflector_dev = NULL;
-
- /* Compile pattern if present */
- if(strlen(rule->rule.extended_fields.payload_pattern) > 0) {
- char *pattern =
- rule->rule.extended_fields.payload_pattern;
+ /*
+ if(enable_debug)
+ printk("[PF_RING] SO_TOGGLE_FILTER_POLICY: default policy is %s\n",
+ pfr->sw_filtering_rules_default_accept_policy ? "accept" : "drop");
+ */
+ }
+ break;
- printk("[PF_RING] About to compile pattern '%s'\n",
- pattern);
+ case SO_ADD_FILTERING_RULE:
+ if(enable_debug)
+ printk("[PF_RING] +++ SO_ADD_FILTERING_RULE(len=%d)(len=%u)\n",
+ optlen, (unsigned int)sizeof(ip_addr));
- while(pattern && (idx < MAX_NUM_PATTERN)) {
- char *pipe = strchr(pattern, '|');
+ if(pfr->ring_netdev == &none_device_element)
+ return -EFAULT;
- if(pipe)
- pipe[0] = '\0';
+ if(optlen == sizeof(filtering_rule)) {
+ int ret;
+ sw_filtering_rule_element *rule;
+ struct list_head *ptr, *tmp_ptr;
-#ifdef CONFIG_TEXTSEARCH
- rule->pattern[idx] = textsearch_prepare("bm" /* Boyer-Moore */
- /* "kmp" = Knuth-Morris-Pratt */
- ,
- pattern,
- strlen
- (pattern),
- GFP_KERNEL,
- TS_AUTOLOAD
-#ifdef TS_IGNORECASE
- | TS_IGNORECASE
-#endif
- );
- if(rule->pattern[idx])
- printk("[PF_RING] Compiled pattern '%s' [idx=%d]\n", pattern, idx);
-#endif
- if(pipe)
- pattern = &pipe[1], idx++;
- else
- break;
- }
- } else {
-#ifdef CONFIG_TEXTSEARCH
- rule->pattern[0] = NULL;
-#endif
- }
+ if(enable_debug)
+ printk("[PF_RING] Allocating memory [filtering_rule]\n");
- write_lock(&pfr->ring_rules_lock);
- if(debug)
- printk("[PF_RING] SO_ADD_FILTERING_RULE: About to add rule %d\n",
- rule->rule.rule_id);
+ rule =(sw_filtering_rule_element *)
+ kcalloc(1, sizeof(sw_filtering_rule_element), GFP_KERNEL);
- /* Implement an ordered add */
- list_for_each_safe(ptr, tmp_ptr, &pfr->rules) {
- entry = list_entry(ptr, filtering_rule_element, list);
-
- if(debug)
- printk("[PF_RING] SO_ADD_FILTERING_RULE: [current rule %d][rule to add %d]\n",
- entry->rule.rule_id,
- rule->rule.rule_id);
+ if(rule == NULL)
+ return -EFAULT;
- if(entry->rule.rule_id == rule->rule.rule_id) {
-#ifdef CONFIG_TEXTSEARCH
- int i;
-#endif
+ if(copy_from_user(&rule->rule, optval, optlen))
+ return -EFAULT;
- memcpy(&entry->rule, &rule->rule, sizeof(filtering_rule));
+ INIT_LIST_HEAD(&rule->list);
-#ifdef CONFIG_TEXTSEARCH
- for(i = 0; (i < MAX_NUM_PATTERN) && (entry->pattern[i] != NULL); i++)
- textsearch_destroy(entry->pattern[i]);
- memcpy(entry->pattern, rule->pattern,
- sizeof(struct ts_config *) * MAX_NUM_PATTERN);
-#endif
- kfree(rule);
- rule = NULL;
-
- if(debug)
- printk("[PF_RING] SO_ADD_FILTERING_RULE: overwritten rule_id %d\n",
- entry->rule.rule_id);
- break;
- } else if(entry->rule.rule_id >rule->rule.rule_id) {
- if(prev == NULL) {
- list_add(&rule->list, &pfr->rules); /* Add as first entry */
- pfr->num_filtering_rules++;
- if(debug)
- printk("[PF_RING] SO_ADD_FILTERING_RULE: added rule %d as head rule\n",
- rule->rule.
- rule_id);
- } else {
- list_add(&rule->list, prev);
- pfr->num_filtering_rules++;
- if(debug)
- printk("[PF_RING] SO_ADD_FILTERING_RULE: added rule %d\n",
- rule->rule.
- rule_id);
- }
+ write_lock(&pfr->ring_rules_lock);
+ list_for_each_safe(ptr, tmp_ptr, &pfr->sw_filtering_rules) {
+ sw_filtering_rule_element *entry;
- rule = NULL;
- break;
- } else
- prev = ptr;
- } /* for */
+ entry = list_entry(ptr, sw_filtering_rule_element, list);
- if(rule != NULL) {
- if(prev == NULL) {
- list_add(&rule->list, &pfr->rules); /* Add as first entry */
- pfr->num_filtering_rules++;
- if(debug)
- printk("[PF_RING] SO_ADD_FILTERING_RULE: added rule %d as first rule\n",
- rule->rule.rule_id);
- } else {
- list_add_tail(&rule->list, &pfr->rules); /* Add as first entry */
- pfr->num_filtering_rules++;
- if(debug)
- printk("[PF_RING] SO_ADD_FILTERING_RULE: added rule %d as last rule\n",
- rule->rule.rule_id);
+ if(entry->rule.rule_id == rule_id) {
+ /* A rule with the same if exists */
+ write_unlock(&pfr->ring_rules_lock);
+ return(-EEXIST);
}
}
+ ret = add_sw_filtering_rule_element(pfr, rule);
write_unlock(&pfr->ring_rules_lock);
+
+ if(ret != 0) return(ret);
} else if(optlen == sizeof(hash_filtering_rule)) {
/* This is a hash rule */
- filtering_hash_bucket *rule =
- (filtering_hash_bucket *) kcalloc(1,
- sizeof(filtering_hash_bucket),
- GFP_KERNEL);
- int rc;
+ sw_filtering_hash_bucket *rule =
+ (sw_filtering_hash_bucket *) kcalloc(1,
+ sizeof(sw_filtering_hash_bucket),
+ GFP_KERNEL);
+ int ret;
if(rule == NULL)
return -EFAULT;
@@ -4192,35 +5075,9 @@
if(copy_from_user(&rule->rule, optval, optlen))
return -EFAULT;
- if(rule->rule.reflector_device_name[0] != '\0') {
- rule->rule.internals.reflector_dev =
- dev_get_by_name(
-#if(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24))
- &init_net,
-#endif
- rule->rule.reflector_device_name);
-
- if(rule->rule.internals.reflector_dev == NULL) {
- printk("[PF_RING] Unable to find device %s\n",
- rule->rule.reflector_device_name);
- kfree(rule);
- return(-EFAULT);
- }
- } else
- rule->rule.internals.reflector_dev = NULL;
-
- write_lock(&pfr->ring_rules_lock);
- rc = handle_filtering_hash_bucket(pfr, rule, 1 /* add */ );
+ ret = add_sw_filtering_hash_bucket(pfr, rule);
- if((rc != 0) && (rc != -EEXIST)) {
- write_unlock(&pfr->ring_rules_lock);
- kfree(rule);
- return(rc);
- } else {
- if(rc != -EEXIST)
- pfr->num_filtering_rules++;
- write_unlock(&pfr->ring_rules_lock);
- }
+ if(ret != 0) return(ret);
} else {
printk("[PF_RING] Bad rule length (%d): discarded\n", optlen);
return -EFAULT;
@@ -4228,66 +5085,34 @@
break;
case SO_REMOVE_FILTERING_RULE:
- if(pfr->ring_netdev == &none_dev) return -EFAULT;
+ if(pfr->ring_netdev == &none_device_element) return -EFAULT;
- if(optlen == sizeof(u_int16_t /* rule _id */ )) {
+ if(optlen == sizeof(u_int16_t /* rule_id */ )) {
/* This is a list rule */
- u_int8_t rule_found = 0;
- struct list_head *ptr, *tmp_ptr;
-
if(copy_from_user(&rule_id, optval, optlen))
return -EFAULT;
- write_lock(&pfr->ring_rules_lock);
-
- list_for_each_safe(ptr, tmp_ptr, &pfr->rules) {
- entry = list_entry(ptr, filtering_rule_element, list);
-
- if(entry->rule.rule_id == rule_id) {
-#ifdef CONFIG_TEXTSEARCH
- int i;
-
- for(i = 0; (i < MAX_NUM_PATTERN) && (entry->pattern[i] != NULL); i++)
- textsearch_destroy(entry->pattern[i]);
-#endif
- list_del(ptr);
- pfr->num_filtering_rules--;
-
- if(entry->plugin_data_ptr)
- kfree(entry->plugin_data_ptr);
- free_filtering_rule(&entry->rule);
- kfree(entry);
- if(debug)
- printk("[PF_RING] SO_REMOVE_FILTERING_RULE: rule %d has been removed\n",
- rule_id);
- rule_found = 1;
- break;
- }
- } /* for */
-
- write_unlock(&pfr->ring_rules_lock);
- if(!rule_found) {
- if(debug)
- printk("[PF_RING] SO_REMOVE_FILTERING_RULE: rule %d does not exist\n",
- rule_id);
+ if(remove_sw_filtering_rule_element(pfr, rule_id) == 0) {
+ if(enable_debug)
+ printk("[PF_RING] SO_REMOVE_FILTERING_RULE: rule %d does not exist\n", rule_id);
return -EFAULT; /* Rule not found */
}
} else if(optlen == sizeof(hash_filtering_rule)) {
/* This is a hash rule */
- filtering_hash_bucket rule;
+ sw_filtering_hash_bucket rule;
int rc;
if(copy_from_user(&rule.rule, optval, optlen))
return -EFAULT;
write_lock(&pfr->ring_rules_lock);
- rc = handle_filtering_hash_bucket(pfr, &rule, 0 /* delete */ );
+ rc = handle_sw_filtering_hash_bucket(pfr, &rule, 0 /* delete */ );
if(rc != 0) {
write_unlock(&pfr->ring_rules_lock);
return(rc);
} else {
- pfr->num_filtering_rules--;
+ pfr->num_sw_filtering_rules--;
write_unlock(&pfr->ring_rules_lock);
}
} else
@@ -4298,23 +5123,66 @@
if(optlen != sizeof(pfr->sample_rate))
return -EINVAL;
- if(copy_from_user
- (&pfr->sample_rate, optval, sizeof(pfr->sample_rate)))
+ if(copy_from_user(&pfr->sample_rate, optval, sizeof(pfr->sample_rate)))
return -EFAULT;
break;
case SO_ACTIVATE_RING:
- if(debug)
+ if(enable_debug)
printk("[PF_RING] * SO_ACTIVATE_RING *\n");
+
+ if(pfr->dna_device_entry != NULL) {
+ struct pf_ring_socket *other1 = NULL, *other2 = NULL;
+
+ /* This is a DNA ring */
+ other1=pfr->dna_device_entry->sock_b;
+ other2=pfr->dna_device_entry->sock_c;
+ if(pfr->dna_device_entry->sock_b == pfr)
+ other1 = pfr->dna_device_entry->sock_a;
+ else if(pfr->dna_device_entry->sock_c == pfr)
+ other2 = pfr->dna_device_entry->sock_a;
+
+ /* We need to check if the other socket is not using our direction */
+ if((other1 && other1->ring_active && (other1->direction == pfr->direction || other1->direction == rx_and_tx_direction)) ||
+ ((other1 = other2) && other2->ring_active && (other2->direction == pfr->direction || other2->direction == rx_and_tx_direction))){
+ printk("[PF_RING] Unable to activate two DNA sockets on the same interface %s (direction_a=%s, direction_b=%s)\n",
+ pfr->ring_netdev->dev->name,
+ direction2string(pfr->direction),
+ direction2string(other1->direction));
+
+ return -EFAULT; /* No way: we can't have two sockets that are doing the same thing with DNA */
+ }
+ }
+
found = 1, pfr->ring_active = 1;
break;
case SO_DEACTIVATE_RING:
- if(debug)
+ if(enable_debug)
printk("[PF_RING] * SO_DEACTIVATE_RING *\n");
found = 1, pfr->ring_active = 0;
break;
+ case SO_SET_POLL_WATERMARK:
+ if(optlen != sizeof(u_int16_t))
+ return -EINVAL;
+ else {
+ u_int16_t threshold = pfr->slots_info->min_num_slots/2;
+
+ if(copy_from_user(&pfr->poll_num_pkts_watermark, optval, optlen))
+ return -EFAULT;
+
+ if(pfr->poll_num_pkts_watermark > threshold)
+ pfr->poll_num_pkts_watermark = threshold;
+
+ if(pfr->poll_num_pkts_watermark == 0)
+ pfr->poll_num_pkts_watermark = 1;
+
+ if(enable_debug)
+ printk("[PF_RING] --> SO_SET_POLL_WATERMARK=%d\n", pfr->poll_num_pkts_watermark);
+ }
+ break;
+
case SO_RING_BUCKET_LEN:
if(optlen != sizeof(u_int32_t))
return -EINVAL;
@@ -4322,9 +5190,8 @@
if(copy_from_user(&pfr->bucket_len, optval, optlen))
return -EFAULT;
-#ifdef RING_DEBUG
- printk("[PF_RING] --> SO_RING_BUCKET_LEN=%d\n", pfr->bucket_len);
-#endif
+ if(enable_debug)
+ printk("[PF_RING] --> SO_RING_BUCKET_LEN=%d\n", pfr->bucket_len);
}
break;
@@ -4343,7 +5210,7 @@
case SO_SET_MASTER_RING:
/* Avoid using master sockets with bound rings */
- if(pfr->ring_netdev == &none_dev) return -EFAULT;
+ if(pfr->ring_netdev == &none_device_element) return -EFAULT;
if(optlen != sizeof(ring_id))
return -EINVAL;
@@ -4357,15 +5224,90 @@
break;
case SO_ADD_HW_FILTERING_RULE:
- case SO_DEL_HW_FILTERING_RULE:
- if(optlen != sizeof(hw_rule))
+ if(optlen != sizeof(hw_filtering_rule))
return -EINVAL;
if(copy_from_user(&hw_rule, optval, sizeof(hw_rule)))
return -EFAULT;
- ret = handle_hw_filtering_rule(pfr->ring_netdev, &hw_rule,
- (optname == SO_ADD_HW_FILTERING_RULE) ? 1 : 0);
+ /* Check if a rule with the same id exists */
+ list_for_each_safe(ptr, tmp_ptr, &pfr->hw_filtering_rules) {
+ hw_filtering_rule_element *rule = list_entry(ptr, hw_filtering_rule_element, list);
+
+ if(rule->rule.rule_id == hw_rule.rule_id) {
+ /* There's already a rule with the same id: failure */
+ return -EINVAL;
+ }
+ }
+
+ ret = handle_hw_filtering_rule(pfr, &hw_rule, add_hw_rule);
+
+ if(ret != -1) {
+ hw_filtering_rule_element *rule;
+
+ /* Add the hw rule to the socket hw rule list */
+ rule = kmalloc(sizeof(hw_filtering_rule_element), GFP_ATOMIC);
+ if(rule != NULL) {
+ INIT_LIST_HEAD(&rule->list);
+ memcpy(&rule->rule, &hw_rule, sizeof(hw_rule));
+ list_add(&rule->list, &pfr->hw_filtering_rules); /* Add as first entry */
+ pfr->num_hw_filtering_rules++;
+ } else
+ printk("[PF_RING] Out of memory\n");
+
+ /* Increase the number of device hw rules */
+ list_for_each_safe(ptr, tmp_ptr, &ring_aware_device_list) {
+ ring_device_element *dev_ptr = list_entry(ptr, ring_device_element, device_list);
+
+ if(dev_ptr->dev == pfr->ring_netdev->dev) {
+ dev_ptr->hw_filters.num_filters++;
+ break;
+ }
+ }
+ }
+ break;
+
+ case SO_DEL_HW_FILTERING_RULE:
+ if(optlen != sizeof(u_int16_t))
+ return -EINVAL;
+
+ if(copy_from_user(&rule_id, optval, sizeof(u_int16_t)))
+ return -EFAULT;
+
+ /* Check if the rule we want to remove exists */
+ found = 0;
+ list_for_each_safe(ptr, tmp_ptr, &pfr->hw_filtering_rules) {
+ hw_filtering_rule_element *rule = list_entry(ptr, hw_filtering_rule_element, list);
+
+ if(rule->rule.rule_id == rule_id) {
+ /* There's already a rule with the same id: good */
+ memcpy(&hw_rule, &rule->rule, sizeof(hw_filtering_rule));
+ list_del(ptr);
+ kfree(rule);
+ found = 1;
+ break;
+ }
+ }
+
+ if(!found) return -EINVAL;
+
+ ret = handle_hw_filtering_rule(pfr, &hw_rule, remove_hw_rule);
+
+ if(ret != -1) {
+ struct list_head *ptr, *tmp_ptr;
+
+ pfr->num_hw_filtering_rules--;
+
+ list_for_each_safe(ptr, tmp_ptr, &ring_aware_device_list) {
+ ring_device_element *dev_ptr = list_entry(ptr, ring_device_element, device_list);
+
+ if(dev_ptr->dev == pfr->ring_netdev->dev) {
+ if(dev_ptr->hw_filters.num_filters > 0)
+ dev_ptr->hw_filters.num_filters--;
+ break;
+ }
+ }
+ }
break;
case SO_SET_PACKET_CONSUMER_MODE:
@@ -4396,9 +5338,8 @@
/* Notify the consumer that we're ready to start */
if(pfr->kernel_consumer_plugin_id
&& (plugin_registration[pfr->kernel_consumer_plugin_id] == NULL)) {
-#ifdef RING_DEBUG
- printk("[PF_RING] Plugin %d is unknown\n", pfr->kernel_consumer_plugin_id);
-#endif
+ if(enable_debug)
+ printk("[PF_RING] Plugin %d is unknown\n", pfr->kernel_consumer_plugin_id);
pfr->kernel_consumer_plugin_id = 0;
if(pfr->kernel_consumer_options != NULL) {
@@ -4408,13 +5349,65 @@
return -EFAULT;
} else {
- if(plugin_registration[pfr->kernel_consumer_plugin_id]->pfring_packet_start && (!pfr->ring_active)) {
- plugin_registration[pfr->kernel_consumer_plugin_id]->pfring_packet_start(pfr, copy_raw_data_to_ring);
+ if(plugin_registration[pfr->kernel_consumer_plugin_id]->pfring_packet_start
+ && (!pfr->ring_active)) {
+ plugin_registration[pfr->kernel_consumer_plugin_id]->
+ pfring_packet_start(pfr, copy_raw_data_to_ring);
}
}
}
break;
+ case SO_SET_VIRTUAL_FILTERING_DEVICE:
+ {
+ virtual_filtering_device_info elem;
+
+ if(optlen != sizeof(elem))
+ return -EINVAL;
+
+ if(copy_from_user(&elem, optval, sizeof(elem)))
+ return -EFAULT;
+
+ if((pfr->v_filtering_dev = add_virtual_filtering_device(sock->sk, &elem)) == NULL)
+ return -EFAULT;
+ }
+ break;
+
+ case SO_REHASH_RSS_PACKET:
+ if(enable_debug)
+ printk("[PF_RING] * SO_REHASH_RSS_PACKET *\n");
+
+ found = 1, pfr->rehash_rss = 1;
+ break;
+
+#ifdef VPFRING_SUPPORT
+ case SO_SET_VPFRING_HOST_EVENTFD:
+ if(optlen != sizeof(eventfd_i))
+ return -EINVAL;
+
+ if(copy_from_user(&eventfd_i, optval, sizeof(eventfd_i)))
+ return -EFAULT;
+
+ if (IS_ERR(eventfp = eventfd_fget(eventfd_i.fd)))
+ return -EFAULT;
+
+ /* We don't need to check the id (we have only one event)
+ * eventfd_i.id == VPFRING_HOST_EVENT_RX_INT */
+
+ pfr->vpfring_host_eventfd_ctx = eventfd_ctx_fileget(eventfp);
+ break;
+
+ case SO_SET_VPFRING_GUEST_EVENTFD:
+ return -EINVAL; /* (unused) */
+ break;
+
+ case SO_SET_VPFRING_CLEAN_EVENTFDS:
+ if (pfr->vpfring_host_eventfd_ctx)
+ eventfd_ctx_put(pfr->vpfring_host_eventfd_ctx);
+ pfr->vpfring_host_eventfd_ctx = NULL;
+ break;
+#endif //VPFRING_SUPPORT
+
default:
found = 0;
break;
@@ -4430,10 +5423,11 @@
static int ring_getsockopt(struct socket *sock,
int level, int optname,
- char __user * optval, int __user * optlen)
+ char __user *optval,
+ int __user *optlen)
{
- int len, debug = 0;
- struct ring_opt *pfr = ring_sk(sock->sk);
+ int len;
+ struct pf_ring_socket *pfr = ring_sk(sock->sk);
if(pfr == NULL)
return(-EINVAL);
@@ -4444,9 +5438,8 @@
if(len < 0)
return -EINVAL;
-#ifdef RING_DEBUG
- printk("[PF_RING] --> getsockopt(%d)\n", optname);
-#endif
+ if(enable_debug)
+ printk("[PF_RING] --> getsockopt(%d)\n", optname);
switch (optname) {
case SO_GET_RING_VERSION:
@@ -4483,7 +5476,7 @@
hash_filtering_rule rule;
u_int hash_idx;
- if(pfr->filtering_hash == NULL) {
+ if(pfr->sw_filtering_hash == NULL) {
printk("[PF_RING] so_get_hash_filtering_rule_stats(): no hash failure\n");
return -EFAULT;
}
@@ -4493,7 +5486,7 @@
return -EFAULT;
}
- if(debug)
+ if(enable_debug)
printk("[PF_RING] so_get_hash_filtering_rule_stats"
"(vlan=%u, proto=%u, sip=%u, sport=%u, dip=%u, dport=%u)\n",
rule.vlan_id, rule.proto,
@@ -4505,13 +5498,13 @@
rule.host_peer_a, rule.host_peer_b,
rule.port_peer_a, rule.port_peer_b) % DEFAULT_RING_HASH_SIZE;
- if(pfr->filtering_hash[hash_idx] != NULL) {
- filtering_hash_bucket *bucket;
+ if(pfr->sw_filtering_hash[hash_idx] != NULL) {
+ sw_filtering_hash_bucket *bucket;
read_lock(&pfr->ring_rules_lock);
- bucket = pfr->filtering_hash[hash_idx];
+ bucket = pfr->sw_filtering_hash[hash_idx];
- if(debug)
+ if(enable_debug)
printk("[PF_RING] so_get_hash_filtering_rule_stats(): bucket=%p\n",
bucket);
@@ -4547,7 +5540,7 @@
read_unlock(&pfr->ring_rules_lock);
} else {
- if(debug)
+ if(enable_debug)
printk("[PF_RING] so_get_hash_filtering_rule_stats(): entry not found [hash_idx=%d]\n",
hash_idx);
}
@@ -4570,15 +5563,15 @@
if(copy_from_user(&rule_id, optval, sizeof(rule_id)))
return -EFAULT;
- if(debug)
+ if(enable_debug)
printk("[PF_RING] SO_GET_FILTERING_RULE_STATS: rule_id=%d\n",
rule_id);
read_lock(&pfr->ring_rules_lock);
- list_for_each_safe(ptr, tmp_ptr, &pfr->rules) {
- filtering_rule_element *rule;
+ list_for_each_safe(ptr, tmp_ptr, &pfr->sw_filtering_rules) {
+ sw_filtering_rule_element *rule;
- rule = list_entry(ptr, filtering_rule_element, list);
+ rule = list_entry(ptr, sw_filtering_rule_element, list);
if(rule->rule.rule_id == rule_id) {
buffer = kmalloc(len, GFP_ATOMIC);
@@ -4588,14 +5581,12 @@
else {
if((plugin_registration[rule->rule.plugin_action.plugin_id] == NULL)
||
- (plugin_registration[rule->rule.plugin_action.plugin_id]->
- pfring_plugin_get_stats == NULL)) {
+ (plugin_registration[rule->rule.plugin_action.plugin_id]->pfring_plugin_get_stats == NULL)) {
printk("[PF_RING] Found rule %d but pluginId %d is not registered\n",
rule_id, rule->rule.plugin_action.plugin_id);
rc = -EFAULT;
} else
- rc = plugin_registration
- [rule->rule.plugin_action.plugin_id]->
+ rc = plugin_registration[rule->rule.plugin_action.plugin_id]->
pfring_plugin_get_stats(pfr, rule, NULL, buffer, len);
if(rc > 0) {
@@ -4619,8 +5610,7 @@
case SO_GET_MAPPED_DNA_DEVICE:
{
- if((pfr->dna_device == NULL)
- || (len < sizeof(dna_device)))
+ if((pfr->dna_device == NULL) || (len < sizeof(dna_device)))
return -EFAULT;
if(copy_to_user(optval, pfr->dna_device, sizeof(dna_device)))
@@ -4633,13 +5623,23 @@
{
u_int8_t num_rx_channels;
- if(pfr->ring_netdev == &none_dev) {
+ if(pfr->ring_netdev == &none_device_element) {
/* Device not yet bound */
num_rx_channels = UNKNOWN_NUM_RX_CHANNELS;
} else {
- num_rx_channels = pfr->num_rx_channels;
+ if(pfr->ring_netdev->is_dna_device)
+ num_rx_channels = pfr->ring_netdev->num_dna_rx_queues;
+ else
+ num_rx_channels = max_val(pfr->num_rx_channels, get_num_rx_queues(pfr->ring_netdev->dev));
}
+ if(enable_debug)
+ printk("[PF_RING] --> SO_GET_NUM_RX_CHANNELS[%s]=%d [dna=%d/dns_rx_channels=%d][%p]\n",
+ pfr->ring_netdev->dev->name, num_rx_channels,
+ pfr->ring_netdev->is_dna_device,
+ pfr->ring_netdev->num_dna_rx_queues,
+ pfr->ring_netdev);
+
if(copy_to_user(optval, &num_rx_channels, sizeof(num_rx_channels)))
return -EFAULT;
}
@@ -4649,9 +5649,8 @@
if(len < sizeof(pfr->ring_id))
return -EINVAL;
-#ifdef RING_DEBUG
- printk("[PF_RING] --> SO_GET_RING_ID=%d\n", pfr->ring_id);
-#endif
+ if(enable_debug)
+ printk("[PF_RING] --> SO_GET_RING_ID=%d\n", pfr->ring_id);
if(copy_to_user(optval, &pfr->ring_id, sizeof(pfr->ring_id)))
return -EFAULT;
@@ -4661,16 +5660,76 @@
if(len < sizeof(pfr->kernel_consumer_plugin_id))
return -EINVAL;
-#ifdef RING_DEBUG
- printk("[PF_RING] --> SO_GET_PACKET_CONSUMER_MODE=%d\n",
- pfr->kernel_consumer_plugin_id);
-#endif
+ if(enable_debug)
+ printk("[PF_RING] --> SO_GET_PACKET_CONSUMER_MODE=%d\n",
+ pfr->kernel_consumer_plugin_id);
if(copy_to_user(optval, &pfr->kernel_consumer_plugin_id,
sizeof(pfr->kernel_consumer_plugin_id)))
return -EFAULT;
break;
+ case SO_GET_BOUND_DEVICE_ADDRESS:
+ if(len < 6) return -EINVAL;
+
+ if(pfr->dna_device != NULL) {
+ if(copy_to_user(optval, pfr->dna_device->device_address, 6))
+ return -EFAULT;
+ } else if((pfr->ring_netdev != NULL)
+ && (pfr->ring_netdev->dev != NULL)) {
+ if(copy_to_user(optval, pfr->ring_netdev->dev->dev_addr, 6))
+ return -EFAULT;
+ } else
+ return -EFAULT;
+ break;
+
+ case SO_GET_NUM_QUEUED_PKTS:
+ {
+ u_int32_t num_queued = num_queued_pkts(pfr);
+
+ if(len < sizeof(num_queued))
+ return -EINVAL;
+
+ if(copy_to_user(optval, &num_queued, sizeof(num_queued)))
+ return -EFAULT;
+ }
+ break;
+
+ case SO_GET_PKT_HEADER_LEN:
+ if(len < sizeof(pfr->slot_header_len))
+ return -EINVAL;
+
+ if(copy_to_user(optval, &pfr->slot_header_len, sizeof(pfr->slot_header_len)))
+ return -EFAULT;
+ break;
+
+ case SO_GET_LOOPBACK_TEST:
+ /* Used for testing purposes only */
+ {
+ /* printk("SO_GET_LOOPBACK_TEST (len=%d)\n", len); */
+
+ if(len > 0) {
+ if(len > loobpack_test_buffer_len) return(-EFAULT);
+
+ if(loobpack_test_buffer == NULL) {
+ loobpack_test_buffer = kmalloc(loobpack_test_buffer_len, GFP_ATOMIC);
+
+ if(loobpack_test_buffer == NULL)
+ return(-EFAULT); /* Not enough memory */
+ }
+
+ {
+ u_int i;
+
+ for(i=0; i<len; i++) loobpack_test_buffer[i] = i;
+ }
+
+ if(copy_to_user(optval, loobpack_test_buffer, len))
+ return -EFAULT;
+ }
+ }
+ break;
+
default:
return -ENOPROTOOPT;
}
@@ -4684,7 +5743,7 @@
/* ************************************* */
void dna_device_handler(dna_device_operation operation,
- unsigned long packet_memory,
+ unsigned long rx_packet_memory,
u_int packet_memory_num_slots,
u_int packet_memory_slot_len,
u_int packet_memory_tot_len,
@@ -4692,48 +5751,78 @@
u_int descr_packet_memory_num_slots,
u_int descr_packet_memory_slot_len,
u_int descr_packet_memory_tot_len,
+ unsigned long tx_packet_memory,
+ void *tx_descr_packet_memory,
u_int channel_id,
void *phys_card_memory,
u_int phys_card_memory_len,
struct net_device *netdev,
dna_device_model device_model,
+ u_char *device_address,
wait_queue_head_t * packet_waitqueue,
u_int8_t * interrupt_received,
void *adapter_ptr,
- dna_wait_packet wait_packet_function_ptr)
+ dna_wait_packet wait_packet_function_ptr,
+ dna_device_notify dev_notify_function_ptr)
{
- int debug = 0;
-
- if(debug)
- printk("[PF_RING] dna_device_handler(%s)\n", netdev->name);
+ if(enable_debug)
+ printk("[PF_RING] dna_device_handler(%s@%u [operation=%s])\n",
+ netdev->name, channel_id,
+ operation == add_device_mapping ? "add_device_mapping" : "remove_device_mapping");
if(operation == add_device_mapping) {
dna_device_list *next;
next = kmalloc(sizeof(dna_device_list), GFP_ATOMIC);
if(next != NULL) {
- next->dev.packet_memory = packet_memory;
- next->dev.packet_memory_num_slots =
- packet_memory_num_slots;
- next->dev.packet_memory_slot_len =
- packet_memory_slot_len;
+ memset(next, 0, sizeof(dna_device_list));
+
+ next->in_use = 0;
+ next->dev.rx_packet_memory = rx_packet_memory;
+ next->dev.packet_memory_num_slots = packet_memory_num_slots;
+ next->dev.packet_memory_slot_len = packet_memory_slot_len;
next->dev.packet_memory_tot_len = packet_memory_tot_len;
- next->dev.descr_packet_memory = descr_packet_memory;
+ next->dev.rx_descr_packet_memory = descr_packet_memory;
next->dev.descr_packet_memory_num_slots = descr_packet_memory_num_slots;
- next->dev.descr_packet_memory_slot_len = descr_packet_memory_slot_len;
- next->dev.descr_packet_memory_tot_len = descr_packet_memory_tot_len;
+ next->dev.descr_packet_memory_slot_len = descr_packet_memory_slot_len;
+ next->dev.descr_packet_memory_tot_len = descr_packet_memory_tot_len;
next->dev.phys_card_memory = phys_card_memory;
next->dev.phys_card_memory_len = phys_card_memory_len;
+ /* TX */
+ next->dev.tx_packet_memory = tx_packet_memory;
+ next->dev.tx_descr_packet_memory = tx_descr_packet_memory;
next->dev.channel_id = channel_id;
next->dev.netdev = netdev;
next->dev.device_model = device_model;
+ memcpy(next->dev.device_address, device_address, 6);
next->dev.packet_waitqueue = packet_waitqueue;
next->dev.interrupt_received = interrupt_received;
next->dev.adapter_ptr = adapter_ptr;
- next->dev.wait_packet_function_ptr =
- wait_packet_function_ptr;
+ next->dev.wait_packet_function_ptr = wait_packet_function_ptr;
+ next->dev.usage_notification = dev_notify_function_ptr;
list_add(&next->list, &ring_dna_devices_list);
dna_devices_list_size++;
+ /* Increment usage count to avoid unloading it while DNA modules are in use */
+ try_module_get(THIS_MODULE);
+
+ /* We now have to update the device list */
+ {
+ struct list_head *ptr, *tmp_ptr;
+
+ list_for_each_safe(ptr, tmp_ptr, &ring_aware_device_list) {
+ ring_device_element *dev_ptr = list_entry(ptr, ring_device_element, device_list);
+
+ if(strcmp(dev_ptr->dev->name, netdev->name) == 0) {
+ dev_ptr->num_dna_rx_queues = max_val(dev_ptr->num_dna_rx_queues, channel_id+1);
+ dev_ptr->is_dna_device = 1, dev_ptr->dna_device_model = device_model;
+
+ if(enable_debug)
+ printk("[PF_RING] ==>> Updating DNA %s [num_dna_rx_queues=%d][%p]\n",
+ dev_ptr->dev->name, dev_ptr->num_dna_rx_queues, dev_ptr);
+ break;
+ }
+ }
+ }
} else {
printk("[PF_RING] Could not kmalloc slot!!\n");
}
@@ -4749,12 +5838,14 @@
list_del(ptr);
kfree(entry);
dna_devices_list_size--;
+ /* Decrement usage count for DNA devices */
+ module_put(THIS_MODULE);
break;
}
}
}
- if(debug)
+ if(enable_debug)
printk("[PF_RING] dna_device_handler(%s): [dna_devices_list_size=%d]\n",
netdev->name, dna_devices_list_size);
}
@@ -4832,7 +5923,7 @@
// 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))
+#if(LINUX_VERSION_CODE > KERNEL_VERSION(2,6,11))
static struct proto ring_proto = {
.name = "PF_RING",
.owner = THIS_MODULE,
@@ -4859,17 +5950,30 @@
struct list_head *ptr, *tmp_ptr;
list_for_each_safe(ptr, tmp_ptr, &ring_aware_device_list) {
- ring_device_element *dev_ptr;
+ ring_device_element *dev_ptr = list_entry(ptr, ring_device_element, device_list);
- dev_ptr = list_entry(ptr, ring_device_element, list);
if(dev_ptr->dev == dev) {
+ struct list_head *ring_ptr, *ring_tmp_ptr;
+
if(dev_ptr->proc_entry) {
- if(dev_ptr->has_hw_filtering)
+#ifdef ENABLE_PROC_WRITE_RULE
+ if(dev_ptr->device_type != standard_nic_family)
remove_proc_entry(PROC_RULES, dev_ptr->proc_entry);
+#endif
remove_proc_entry(PROC_INFO, dev_ptr->proc_entry);
remove_proc_entry(dev_ptr->dev->name, ring_proc_dev_dir);
}
+
+ /* We now have to "un-bind" existing sockets */
+ list_for_each_safe(ring_ptr, ring_tmp_ptr, &ring_table) {
+ struct ring_element *entry = list_entry(ring_ptr, struct ring_element, list);
+ struct pf_ring_socket *pfr = ring_sk(entry->sk);
+
+ if (pfr->ring_netdev == dev_ptr)
+ pfr->ring_netdev = &none_device_element; /* Unbinding socket */
+ }
+
list_del(ptr);
kfree(dev_ptr);
break;
@@ -4886,10 +5990,10 @@
return(-ENOMEM);
memset(dev_ptr, 0, sizeof(ring_device_element));
- INIT_LIST_HEAD(&dev_ptr->list);
+ INIT_LIST_HEAD(&dev_ptr->device_list);
dev_ptr->dev = dev;
dev_ptr->proc_entry = proc_mkdir(dev_ptr->dev->name, ring_proc_dev_dir);
- dev_ptr->has_hw_filtering = 0;
+ dev_ptr->device_type = standard_nic_family; /* Default */
create_proc_read_entry(PROC_INFO, 0 /* read-only */,
dev_ptr->proc_entry,
@@ -4897,140 +6001,165 @@
dev_ptr);
#if(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31))
- /* Dirty trick to fix at some point; FIXME */
+ /* Dirty trick to fix at some point used to discover Intel 82599 interfaces: FIXME */
if((dev_ptr->dev->ethtool_ops != NULL) && (dev_ptr->dev->ethtool_ops->set_eeprom != NULL)) {
- struct ethtool_eeprom eeprom; /* Used to to the magic [MAGIC_HW_FILTERING_RULE_ELEMENT] */
- hw_filtering_rule_element element;
+ struct ethtool_eeprom eeprom; /* Used to to the magic [MAGIC_HW_FILTERING_RULE_REQUEST] */
int rc;
- memset(&element, 0, sizeof(element));
- eeprom.len = 0, eeprom.magic = MAGIC_HW_FILTERING_RULE_ELEMENT;
- element.command = CHECK_COMMAND;
- rc = dev_ptr->dev->ethtool_ops->set_eeprom(dev_ptr->dev, &eeprom, (u8*)&element);
+ eeprom.len = 0 /* check */, eeprom.magic = MAGIC_HW_FILTERING_RULE_REQUEST;
+
+ rc = dev_ptr->dev->ethtool_ops->set_eeprom(dev_ptr->dev, &eeprom, (u8*)NULL);
+
+ if(enable_debug)
+ printk("[PF_RING] set_eeprom returned %d\n", rc);
if(rc == 0) {
/* This device supports hardware filtering */
- struct proc_dir_entry *entry;
+ dev_ptr->device_type = intel_82599_family;
+ /* Setup handlers */
+ dev_ptr->hw_filters.filter_handlers.five_tuple_handler = i82599_generic_handler;
+ dev_ptr->hw_filters.filter_handlers.perfect_filter_handler = i82599_generic_handler;
+
+#ifdef ENABLE_PROC_WRITE_RULE
entry = create_proc_read_entry(PROC_RULES, 0666 /* rw */,
dev_ptr->proc_entry,
- ring_proc_dev_rule_read,
- dev_ptr);
+ ring_proc_dev_rule_read, dev_ptr);
if(entry) {
entry->write_proc = ring_proc_dev_rule_write;
- dev_ptr->has_hw_filtering = 1;
- printk("[PF_RING] Device %s DOES support hardware packet filtering\n", dev->name);
+ printk("[PF_RING] Device %s (Intel 82599) DOES support hardware packet filtering\n", dev->name);
} else
printk("[PF_RING] Error while creating /proc entry 'rules' for device %s\n", dev->name);
+#endif
} else
printk("[PF_RING] Device %s does NOT support hardware packet filtering [1]\n", dev->name);
} else
printk("[PF_RING] Device %s does NOT support hardware packet filtering [2]\n", dev->name);
#endif
- list_add(&dev_ptr->list, &ring_aware_device_list);
+ list_add(&dev_ptr->device_list, &ring_aware_device_list);
return(0);
}
/* ************************************ */
+void pf_ring_add_module_dependency(void) {
+ /* Don't actually do anything */
+}
+EXPORT_SYMBOL(pf_ring_add_module_dependency);
+
+/* ************************************ */
+
static int ring_notifier(struct notifier_block *this, unsigned long msg, void *data)
{
struct net_device *dev = data;
struct pfring_hooks *hook;
- int debug = 0;
- /* Skip non ethernet interfaces */
- if(strncmp(dev->name, "eth", 3) && strncmp(dev->name, "lan", 3)) {
- if(debug) printk("[PF_RING] packet_notifier(%s): skipping non ethernet device\n", dev->name);
- return NOTIFY_DONE;
- }
+ if(dev != NULL) {
+ if(enable_debug) printk("[PF_RING] packet_notifier(%lu)\n", msg);
- switch(msg) {
- case NETDEV_PRE_UP:
- case NETDEV_UP:
- case NETDEV_DOWN:
- break;
- case NETDEV_REGISTER:
- if(debug) printk("[PF_RING] packet_notifier(%s) [REGISTER][pfring_ptr=%p][hook=%p]\n",
- dev->name, dev->pfring_ptr, &ring_hooks);
-
- if(dev->pfring_ptr == NULL) {
- dev->pfring_ptr = &ring_hooks;
- add_device_to_ring_list(dev);
+ /* Skip non ethernet interfaces */
+ if(strncmp(dev->name, "eth", 3) && strncmp(dev->name, "lan", 3)) {
+ if(enable_debug) printk("[PF_RING] packet_notifier(%s): skipping non ethernet device\n", dev->name);
+ return NOTIFY_DONE;
}
- break;
- case NETDEV_UNREGISTER:
- if(debug) printk("[PF_RING] packet_notifier(%s) [UNREGISTER][pfring_ptr=%p]\n",
- dev->name, dev->pfring_ptr);
+ switch(msg) {
+ case NETDEV_PRE_UP:
+ case NETDEV_UP:
+ case NETDEV_DOWN:
+ break;
+ case NETDEV_REGISTER:
+ if(enable_debug)
+ printk("[PF_RING] packet_notifier(%s) [REGISTER][pfring_ptr=%p][hook=%p]\n",
+ dev->name, dev->pfring_ptr, &ring_hooks);
+
+ if(dev->pfring_ptr == NULL) {
+ dev->pfring_ptr = &ring_hooks;
+ if(add_device_to_ring_list(dev) != 0) {
+ printk("[PF_RING] Error in add_device_to_ring_list(%s)\n", dev->name);
+ }
+ }
+ break;
- hook = (struct pfring_hooks*)dev->pfring_ptr;
- if(hook->magic == PF_RING) {
- remove_device_from_ring_list(dev);
- dev->pfring_ptr = NULL;
- }
- /* We don't have to worry updating rules that might have used this
- device (just removed) as reflection device. This because whenever
- we set a rule with reflection, we do dev_put() so such device is
- busy until we remove the rule
- */
- break;
+ case NETDEV_UNREGISTER:
+ if(enable_debug)
+ printk("[PF_RING] packet_notifier(%s) [UNREGISTER][pfring_ptr=%p]\n",
+ dev->name, dev->pfring_ptr);
+
+ hook = (struct pfring_hooks*)dev->pfring_ptr;
+ if(hook && (hook->magic == PF_RING)) {
+ remove_device_from_ring_list(dev);
+ dev->pfring_ptr = NULL;
+ }
+ /* We don't have to worry updating rules that might have used this
+ device (just removed) as reflection device. This because whenever
+ we set a rule with reflection, we do dev_put() so such device is
+ busy until we remove the rule
+ */
+ break;
- case NETDEV_CHANGE: /* Interface state change */
- case NETDEV_CHANGEADDR: /* Interface address changed (e.g. during device probing) */
- break;
- case NETDEV_CHANGENAME: /* Rename interface ethX -> ethY */
- {
- struct list_head *ptr, *tmp_ptr;
+ case NETDEV_CHANGE: /* Interface state change */
+ case NETDEV_CHANGEADDR: /* Interface address changed (e.g. during device probing) */
+ break;
+ case NETDEV_CHANGENAME: /* Rename interface ethX -> ethY */
+ {
+ struct list_head *ptr, *tmp_ptr;
- if(debug) printk("[PF_RING] Device change name %s\n", dev->name);
+ if(enable_debug) printk("[PF_RING] Device change name %s\n", dev->name);
- list_for_each_safe(ptr, tmp_ptr, &ring_aware_device_list) {
- ring_device_element *dev_ptr = list_entry(ptr, ring_device_element, list);
+ list_for_each_safe(ptr, tmp_ptr, &ring_aware_device_list) {
+ ring_device_element *dev_ptr = list_entry(ptr, ring_device_element, device_list);
- if(dev_ptr->dev == dev) {
- if(debug) printk("[PF_RING] ==>> FOUND device change name %s -> %s\n",
- dev_ptr->proc_entry->name, dev->name);
-
- /* Remove old entry */
- if(dev_ptr->has_hw_filtering)
- remove_proc_entry(PROC_RULES, dev_ptr->proc_entry);
-
- remove_proc_entry(PROC_INFO, dev_ptr->proc_entry);
- remove_proc_entry(dev_ptr->proc_entry->name, ring_proc_dev_dir);
- /* Add new entry */
- dev_ptr->proc_entry = proc_mkdir(dev_ptr->dev->name, ring_proc_dev_dir);
- create_proc_read_entry(PROC_INFO, 0 /* read-only */,
- dev_ptr->proc_entry,
- ring_proc_dev_get_info /* read */,
- dev_ptr);
+ if(dev_ptr->dev == dev) {
+ if(enable_debug)
+ printk("[PF_RING] ==>> FOUND device change name %s -> %s\n",
+ dev_ptr->proc_entry->name, dev->name);
+
+ /* Remove old entry */
+#ifdef ENABLE_PROC_WRITE_RULE
+ if(dev_ptr->device_type != standard_nic_family)
+ remove_proc_entry(PROC_RULES, dev_ptr->proc_entry);
+#endif
+
+ remove_proc_entry(PROC_INFO, dev_ptr->proc_entry);
+ remove_proc_entry(dev_ptr->proc_entry->name, ring_proc_dev_dir);
+ /* Add new entry */
+ dev_ptr->proc_entry = proc_mkdir(dev_ptr->dev->name, ring_proc_dev_dir);
+ create_proc_read_entry(PROC_INFO, 0 /* read-only */,
+ dev_ptr->proc_entry,
+ ring_proc_dev_get_info /* read */,
+ dev_ptr);
+#ifdef ENABLE_PROC_WRITE_RULE
#if(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31))
- if(dev_ptr->has_hw_filtering) {
- struct proc_dir_entry *entry;
+ if(dev_ptr->device_type != standard_nic_family) {
+ struct proc_dir_entry *entry;
- entry= create_proc_read_entry(PROC_RULES, 0666 /* rw */,
- dev_ptr->proc_entry,
- ring_proc_dev_rule_read,
- dev_ptr);
- if(entry)
- entry->write_proc = ring_proc_dev_rule_write;
- }
+ entry= create_proc_read_entry(PROC_RULES, 0666 /* rw */,
+ dev_ptr->proc_entry,
+ ring_proc_dev_rule_read,
+ dev_ptr);
+ if(entry)
+ entry->write_proc = ring_proc_dev_rule_write;
+ }
+#endif
#endif
- dev_ptr->proc_entry->name = dev->name;
- break;
+ dev_ptr->proc_entry->name = dev->name;
+ break;
+ }
}
}
- }
- break;
+ break;
- default:
- if(debug) printk("[PF_RING] packet_notifier(%s): unhandled message [msg=%lu][pfring_ptr=%p]\n",
- dev->name, msg, dev->pfring_ptr);
- break;
+ default:
+ if(enable_debug)
+ printk("[PF_RING] packet_notifier(%s): unhandled message [msg=%lu][pfring_ptr=%p]\n",
+ dev->name, msg, dev->pfring_ptr);
+ break;
+ }
}
return NOTIFY_DONE;
@@ -5063,12 +6192,14 @@
list_for_each_safe(ptr, tmp_ptr, &ring_aware_device_list) {
ring_device_element *dev_ptr;
- dev_ptr = list_entry(ptr, ring_device_element, list);
+ dev_ptr = list_entry(ptr, ring_device_element, device_list);
hook = (struct pfring_hooks*)dev_ptr->dev->pfring_ptr;
+#ifdef ENABLE_PROC_WRITE_RULE
/* Remove /proc entry for the selected device */
- if(dev_ptr->has_hw_filtering)
+ if(dev_ptr->device_type != standard_nic_family)
remove_proc_entry(PROC_RULES, dev_ptr->proc_entry);
+#endif
remove_proc_entry(PROC_INFO, dev_ptr->proc_entry);
remove_proc_entry(dev_ptr->dev->name, ring_proc_dev_dir);
@@ -5101,12 +6232,15 @@
}
sock_unregister(PF_RING);
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,11))
+#if(LINUX_VERSION_CODE > KERNEL_VERSION(2,6,11))
proto_unregister(&ring_proto);
#endif
unregister_netdevice_notifier(&ring_netdev_notifier);
ring_proc_term();
+ if(loobpack_test_buffer != NULL)
+ kfree(loobpack_test_buffer);
+
printk("[PF_RING] unloaded\n");
}
@@ -5114,21 +6248,23 @@
static int __init ring_init(void)
{
+ static struct net_device any_dev, none_dev;
int i;
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,11))
+#if(LINUX_VERSION_CODE > KERNEL_VERSION(2,6,11))
int rc;
#endif
printk("[PF_RING] Welcome to PF_RING %s ($Revision: %s$)\n"
- "(C) 2004-10 L.Deri <deri@ntop.org>\n",
+ "(C) 2004-11 L.Deri <deri@ntop.org>\n",
RING_VERSION, SVN_REV);
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,11))
+#if(LINUX_VERSION_CODE > KERNEL_VERSION(2,6,11))
if((rc = proto_register(&ring_proto, 0)) != 0)
return(rc);
#endif
INIT_LIST_HEAD(&ring_table);
+ INIT_LIST_HEAD(&virtual_filtering_devices_list);
INIT_LIST_HEAD(&ring_cluster_list);
INIT_LIST_HEAD(&ring_aware_device_list);
INIT_LIST_HEAD(&ring_dna_devices_list);
@@ -5136,11 +6272,19 @@
for(i = 0; i < MAX_NUM_DEVICES; i++)
INIT_LIST_HEAD(&device_ring_list[i]);
+ init_ring_readers();
+
memset(&any_dev, 0, sizeof(any_dev));
strcpy(any_dev.name, "any");
+ any_dev.ifindex = MAX_NUM_IFIDX-1, any_dev.type = ARPHRD_ETHER;
+ memset(&any_device_element, 0, sizeof(any_device_element));
+ any_device_element.dev = &any_dev, any_device_element.device_type = standard_nic_family;
memset(&none_dev, 0, sizeof(none_dev));
strcpy(none_dev.name, "none");
+ none_dev.ifindex = MAX_NUM_IFIDX-2;
+ memset(&none_device_element, 0, sizeof(none_device_element));
+ none_device_element.dev = &none_dev, none_device_element.device_type = standard_nic_family;
ring_proc_init();
sock_register(&ring_family_ops);
|