I’ve added a new feature that I would like to share.


The pf_ring feature allows packets sampling of packets that belong to a sw
filtered session.

In other words, if a sw filter is applied, you will be able not to block
100% of the packets (till filtering rule removal). Some packets will be
allowed to “pass” the filter.

The use case is keeping the advantage of improved performance by filtering
most (e.g. 90%) of the traffic, while being able to get some (e.g. 10%) of
the traffic for analysis purposes. This will allow the application not be
100% blind.



This feature is not good for applications that are sensitive to
out-of-sequence packets.



Technical code details:

1.       New pf_ring param “filtering_sampling_segment_size” is set to 100
by default.

2.       New pf_ring userspace API int
pfring_set_sw_filtering_sampling_rate(pfring *ring, u_int32_t rate /* 0 =
no sampling */) was added.

This API should be used right after adding a new SW hash filtering rule,
with a “rate” parameter.

A rate=10 means that the 10 first packets of every segment of 100 filtered
packets of the session, will be forwarded.

If the API is not called, then the default rate=0, thus no change in
current behavior (i.e. 100% of the packets are filtered, since 0 filtered
packets are forwarded).

3.       I’ve had to add a new member variable to struct pf_ring_socket
which is ‘sw_filtering_hash_filtered’ that counts the actual filtered
packets.

Current ‘sw_filtering_hash_match’ is not good enough anymore for this
purpose since it counts the matches before excluding the forwarded packets,
but it has a great help

in calculating the sampled filtered packets.



Technical build/test details:

1.       Functionality was tested based on pf_ring version 6.6.0 (on CentOS
7)

2.       Attached patch was created based on latest pf_ring code-base
(Sep-7, 2017), and tested for compilation only. Not functionality.



If this feature will ever make it to the main code, it would be great.



Any comments are welcome.



Amir
diff -Naur PF_RING-dev.20170907/kernel/linux/pf_ring.h 
PF_RING-dev.20170907.sampling/kernel/linux/pf_ring.h
--- PF_RING-dev.20170907/kernel/linux/pf_ring.h 2017-09-07 13:02:53.000000000 
+0300
+++ PF_RING-dev.20170907.sampling/kernel/linux/pf_ring.h        2017-09-07 
13:35:43.508272000 +0300
@@ -65,6 +65,7 @@
 #define SO_SET_POLL_WATERMARK            117
 #define SO_SET_VIRTUAL_FILTERING_DEVICE  118
 #define SO_REHASH_RSS_PACKET             119
+#define SO_SET_SW_FILTERING_SAMPLING_RATE 120
 #define SO_SHUTDOWN_RING                 124
 #define SO_PURGE_IDLE_RULES              125 /* inactivity (sec) */
 #define SO_SET_SOCKET_MODE               126
@@ -1078,6 +1079,7 @@
   sw_filtering_hash_bucket **sw_filtering_hash;
   u_int64_t sw_filtering_hash_match;
   u_int64_t sw_filtering_hash_miss;
+  u_int64_t sw_filtering_hash_filtered;
   u_int32_t num_sw_filtering_hash;
 
   /* Sw Filtering Rules - wildcard */
@@ -1087,6 +1089,8 @@
   /* Hw Filtering Rules */
   u_int16_t num_hw_filtering_rules;
   struct list_head hw_filtering_rules;
+  /* Sw Filtering - sampling rate */
+  u_int32_t sw_filtering_sampling_rate;
 
   /* Locks */
   atomic_t num_ring_users;
diff -Naur PF_RING-dev.20170907/kernel/pf_ring.c 
PF_RING-dev.20170907.sampling/kernel/pf_ring.c
--- PF_RING-dev.20170907/kernel/pf_ring.c       2017-09-07 13:02:53.000000000 
+0300
+++ PF_RING-dev.20170907.sampling/kernel/pf_ring.c      2017-09-07 
13:54:45.102938000 +0300
@@ -365,6 +365,7 @@
 static unsigned int force_ring_lock = 0;
 static unsigned int enable_debug = 0;
 static unsigned int transparent_mode = 0;
+static unsigned int filtering_sampling_segment_size = 100;
 static atomic_t ring_id_serial = ATOMIC_INIT(0);
 
 #if defined(RHEL_RELEASE_CODE)
@@ -382,6 +383,7 @@
 module_param(force_ring_lock, uint, 0644);
 module_param(enable_debug, uint, 0644);
 module_param(transparent_mode, uint, 0644);
+module_param(filtering_sampling_segment_size, uint, 0644);
 
 MODULE_PARM_DESC(min_num_slots, "Min number of ring slots");
 MODULE_PARM_DESC(perfect_rules_hash_size, "Perfect rules hash size");
@@ -397,6 +399,7 @@
 MODULE_PARM_DESC(enable_debug, "Set to 1 to enable PF_RING debug tracing into 
the syslog, 2 for more verbosity");
 MODULE_PARM_DESC(transparent_mode,
                 "(deprecated)");
+MODULE_PARM_DESC(filtering_sampling_segment_size, "Size of filtered packets 
segment for sampling (currently, for sw hash filters only)");
 
 /* ********************************** */
 
@@ -1360,20 +1363,21 @@
 
   if(m->private == NULL) {
     /* /proc/net/pf_ring/info */
-    seq_printf(m, "PF_RING Version          : %s (%s)\n", RING_VERSION, 
GIT_REV);
-    seq_printf(m, "Total rings              : %d\n", 
atomic_read(&ring_table_size));
+    seq_printf(m, "PF_RING Version                 : %s (%s)\n", RING_VERSION, 
GIT_REV);
+    seq_printf(m, "Total rings                     : %d\n", 
atomic_read(&ring_table_size));
     seq_printf(m, "\nStandard (non ZC) Options\n");
-    seq_printf(m, "Ring slots               : %d\n", min_num_slots);
-    seq_printf(m, "Slot version             : %d\n", RING_FLOWSLOT_VERSION);
-    seq_printf(m, "Capture TX               : %s\n", enable_tx_capture ? "Yes 
[RX+TX]" : "No [RX only]");
-    seq_printf(m, "IP Defragment            : %s\n", enable_ip_defrag ? "Yes" 
: "No");
-    seq_printf(m, "Socket Mode              : %s\n", quick_mode ? "Quick" : 
"Standard");
+    seq_printf(m, "Ring slots                      : %d\n", min_num_slots);
+    seq_printf(m, "Slot version                    : %d\n", 
RING_FLOWSLOT_VERSION);
+    seq_printf(m, "Capture TX                      : %s\n", enable_tx_capture 
? "Yes [RX+TX]" : "No [RX only]");
+    seq_printf(m, "IP Defragment                   : %s\n", enable_ip_defrag ? 
"Yes" : "No");
+    seq_printf(m, "Socket Mode                     : %s\n", quick_mode ? 
"Quick" : "Standard");
 
     if(enable_frag_coherence) {
       purge_idle_fragment_cache();
-      seq_printf(m, "Cluster Fragment Queue   : %u\n", num_cluster_fragments);
-      seq_printf(m, "Cluster Fragment Discard : %u\n", 
num_cluster_discarded_fragments);
+      seq_printf(m, "Cluster Fragment Queue          : %u\n", 
num_cluster_fragments);
+      seq_printf(m, "Cluster Fragment Discard        : %u\n", 
num_cluster_discarded_fragments);
     }
+       seq_printf(m, "Filtering sampling segment size : %d\n", 
filtering_sampling_segment_size);
   } else {
     /* Detailed statistics about a PF_RING */
     struct pf_ring_socket *pfr = (struct pf_ring_socket *)m->private;
@@ -1383,7 +1387,7 @@
       struct list_head *ptr, *tmp_ptr;
       fsi = pfr->slots_info;
 
-      seq_printf(m, "Bound Device(s)    : ");
+      seq_printf(m, "Bound Device(s)                 : ");
 
       if(pfr->custom_bound_device_name[0] != '\0') {
        seq_printf(m, pfr->custom_bound_device_name);
@@ -1400,59 +1404,61 @@
 
       seq_printf(m, "\n");
 
-      seq_printf(m, "Active             : %d\n", pfr->ring_active);
-      seq_printf(m, "Breed              : %s\n", (pfr->zc_device_entry != 
NULL) ? "ZC" : "Standard");
-      seq_printf(m, "Appl. Name         : %s\n", pfr->appl_name ? 
pfr->appl_name : "<unknown>");
-      seq_printf(m, "Socket Mode        : %s\n", sockmode2string(pfr->mode));
+      seq_printf(m, "Active                : %d\n", pfr->ring_active);
+      seq_printf(m, "Breed                 : %s\n", (pfr->zc_device_entry != 
NULL) ? "ZC" : "Standard");
+      seq_printf(m, "Appl. Name            : %s\n", pfr->appl_name ? 
pfr->appl_name : "<unknown>");
+      seq_printf(m, "Socket Mode           : %s\n", 
sockmode2string(pfr->mode));
       if (pfr->mode != send_only_mode) {
-        seq_printf(m, "Capture Direction  : %s\n", 
direction2string(pfr->direction));
+        seq_printf(m, "Capture Direction     : %s\n", 
direction2string(pfr->direction));
         if (pfr->zc_device_entry == NULL) {
-          seq_printf(m, "Sampling Rate      : %d\n", pfr->sample_rate);
-          seq_printf(m, "IP Defragment      : %s\n", enable_ip_defrag ? "Yes" 
: "No");
-          seq_printf(m, "BPF Filtering      : %s\n", pfr->bpfFilter ? 
"Enabled" : "Disabled");
-          seq_printf(m, "Sw Filt Hash Rules : %d\n", 
pfr->num_sw_filtering_hash);
-          seq_printf(m, "Sw Filt WC Rules   : %d\n", 
pfr->num_sw_filtering_rules);
-          seq_printf(m, "Sw Filt Hash Match : %llu\n", 
pfr->sw_filtering_hash_match);
-          seq_printf(m, "Sw Filt Hash Miss  : %llu\n", 
pfr->sw_filtering_hash_miss);
+          seq_printf(m, "Sampling Rate         : %d\n", pfr->sample_rate);
+          seq_printf(m, "IP Defragment         : %s\n", enable_ip_defrag ? 
"Yes" : "No");
+          seq_printf(m, "BPF Filtering         : %s\n", pfr->bpfFilter ? 
"Enabled" : "Disabled");
+          seq_printf(m, "Sw Filt Hash Rules    : %d\n", 
pfr->num_sw_filtering_hash);
+          seq_printf(m, "Sw Filt WC Rules      : %d\n", 
pfr->num_sw_filtering_rules);
+          seq_printf(m, "Sw Filt Hash Match    : %llu\n", 
pfr->sw_filtering_hash_match);
+          seq_printf(m, "Sw Filt Hash Miss     : %llu\n", 
pfr->sw_filtering_hash_miss);
+          seq_printf(m, "Sw Filt Hash Filtered : %llu\n", 
pfr->sw_filtering_hash_filtered);            
+          seq_printf(m, "Sw Filt Sampling Rate : %u\n", 
pfr->sw_filtering_sampling_rate);
         }
-        seq_printf(m, "Hw Filt Rules      : %d\n", 
pfr->num_hw_filtering_rules);
-        seq_printf(m, "Poll Pkt Watermark : %d\n", 
pfr->poll_num_pkts_watermark);
-        seq_printf(m, "Num Poll Calls     : %u\n", pfr->num_poll_calls);
+        seq_printf(m, "Hw Filt Rules         : %d\n", 
pfr->num_hw_filtering_rules);
+        seq_printf(m, "Poll Pkt Watermark    : %d\n", 
pfr->poll_num_pkts_watermark);
+        seq_printf(m, "Num Poll Calls        : %u\n", pfr->num_poll_calls);
       }
 
       if(pfr->zc_device_entry != NULL) {
         /* ZC */
-        seq_printf(m, "Channel Id         : %d\n", 
pfr->zc_device_entry->zc_dev.channel_id);
+        seq_printf(m, "Channel Id            : %d\n", 
pfr->zc_device_entry->zc_dev.channel_id);
         if (pfr->mode != send_only_mode)
-          seq_printf(m, "Num RX Slots       : %d\n", 
pfr->zc_device_entry->zc_dev.mem_info.rx.packet_memory_num_slots);
+          seq_printf(m, "Num RX Slots          : %d\n", 
pfr->zc_device_entry->zc_dev.mem_info.rx.packet_memory_num_slots);
         if (pfr->mode != recv_only_mode)
-         seq_printf(m, "Num TX Slots       : %d\n", 
pfr->zc_device_entry->zc_dev.mem_info.tx.packet_memory_num_slots);
+         seq_printf(m, "Num TX Slots          : %d\n", 
pfr->zc_device_entry->zc_dev.mem_info.tx.packet_memory_num_slots);
       } else if(fsi != NULL) {
         /* Standard PF_RING */
-       seq_printf(m, "Channel Id Mask    : 0x%016llX\n", pfr->channel_id_mask);
+       seq_printf(m, "Channel Id Mask       : 0x%016llX\n", 
pfr->channel_id_mask);
         if (pfr->cluster_id != 0)
-          seq_printf(m, "Cluster Id         : %d\n", pfr->cluster_id);
-       seq_printf(m, "Slot Version       : %d [%s]\n", fsi->version, 
RING_VERSION);
-       seq_printf(m, "Min Num Slots      : %d\n", fsi->min_num_slots);
-       seq_printf(m, "Bucket Len         : %d\n", fsi->data_len);
-       seq_printf(m, "Slot Len           : %d [bucket+header]\n", 
fsi->slot_len);
-       seq_printf(m, "Tot Memory         : %llu\n", fsi->tot_mem);
+          seq_printf(m, "Cluster Id            : %d\n", pfr->cluster_id);
+       seq_printf(m, "Slot Version          : %d [%s]\n", fsi->version, 
RING_VERSION);
+       seq_printf(m, "Min Num Slots         : %d\n", fsi->min_num_slots);
+       seq_printf(m, "Bucket Len            : %d\n", fsi->data_len);
+       seq_printf(m, "Slot Len              : %d [bucket+header]\n", 
fsi->slot_len);
+       seq_printf(m, "Tot Memory            : %llu\n", fsi->tot_mem);
         if (pfr->mode != send_only_mode) {
-         seq_printf(m, "Tot Packets        : %lu\n", (unsigned 
long)fsi->tot_pkts);
-         seq_printf(m, "Tot Pkt Lost       : %lu\n", (unsigned 
long)fsi->tot_lost);
-         seq_printf(m, "Tot Insert         : %lu\n", (unsigned 
long)fsi->tot_insert);
-         seq_printf(m, "Tot Read           : %lu\n", (unsigned 
long)fsi->tot_read);
-         seq_printf(m, "Insert Offset      : %lu\n", (unsigned 
long)fsi->insert_off);
-         seq_printf(m, "Remove Offset      : %lu\n", (unsigned 
long)fsi->remove_off);
-         seq_printf(m, "Num Free Slots     : %lu\n",  (unsigned 
long)get_num_ring_free_slots(pfr));
+         seq_printf(m, "Tot Packets           : %lu\n", (unsigned 
long)fsi->tot_pkts);
+         seq_printf(m, "Tot Pkt Lost          : %lu\n", (unsigned 
long)fsi->tot_lost);
+         seq_printf(m, "Tot Insert            : %lu\n", (unsigned 
long)fsi->tot_insert);
+         seq_printf(m, "Tot Read              : %lu\n", (unsigned 
long)fsi->tot_read);
+         seq_printf(m, "Insert Offset         : %lu\n", (unsigned 
long)fsi->insert_off);
+         seq_printf(m, "Remove Offset         : %lu\n", (unsigned 
long)fsi->remove_off);
+         seq_printf(m, "Num Free Slots        : %lu\n",  (unsigned 
long)get_num_ring_free_slots(pfr));
         }
         if (pfr->mode != recv_only_mode) {
-         seq_printf(m, "TX: Send Ok        : %lu\n", (unsigned 
long)fsi->good_pkt_sent);
-         seq_printf(m, "TX: Send Errors    : %lu\n", (unsigned 
long)fsi->pkt_send_error);
+         seq_printf(m, "TX: Send Ok           : %lu\n", (unsigned 
long)fsi->good_pkt_sent);
+         seq_printf(m, "TX: Send Errors       : %lu\n", (unsigned 
long)fsi->pkt_send_error);
         }
         if (pfr->mode != send_only_mode) {
-         seq_printf(m, "Reflect: Fwd Ok    : %lu\n", (unsigned 
long)fsi->tot_fwd_ok);
-         seq_printf(m, "Reflect: Fwd Errors: %lu\n", (unsigned 
long)fsi->tot_fwd_notok);
+         seq_printf(m, "Reflect: Fwd Ok       : %lu\n", (unsigned 
long)fsi->tot_fwd_ok);
+         seq_printf(m, "Reflect: Fwd Errors   : %lu\n", (unsigned 
long)fsi->tot_fwd_notok);
         }
       }
     } else
@@ -3467,8 +3473,17 @@
   /* [2.1] Search the hash */
   if(pfr->sw_filtering_hash != NULL) {
     hash_found = check_perfect_rules(skb, pfr, hdr, &fwd_pkt, displ);
-    if (hash_found)
+    if (hash_found) {
       pfr->sw_filtering_hash_match++;
+         /* If there is a filter for the session, let the first 
'sw_filtering_sampling_rate' (e.g. 10) packets
+          * of every 'filtering_sampling_segment_size' (e.g. 100) filtered 
packets, to pass the filter
+          */
+         if ( pfr->sw_filtering_sampling_rate && fwd_pkt==0 && 
((pfr->sw_filtering_hash_match % filtering_sampling_segment_size) < 
pfr->sw_filtering_sampling_rate) ) {
+               fwd_pkt=1;
+         } else {
+               pfr->sw_filtering_hash_filtered++;
+         }
+    }
     else
       pfr->sw_filtering_hash_miss++;
   }
@@ -4097,6 +4112,7 @@
   pfr->master_ring = NULL;
   pfr->ring_dev = &none_device_element; /* Unbound socket */
   pfr->sample_rate = 1;        /* No sampling */
+  pfr->sw_filtering_sampling_rate = 0; /* No filtering sampling */
   sk->sk_family = PF_RING;
   sk->sk_destruct = ring_sock_destruct;
   pfr->ring_id = atomic_inc_return(&ring_id_serial);
@@ -6509,6 +6525,13 @@
       return(-EFAULT);
     break;
 
+  case SO_SET_SW_FILTERING_SAMPLING_RATE:
+         if(optlen != sizeof(pfr->sw_filtering_sampling_rate))
+               return(-EINVAL);
+         if(copy_from_user(&pfr->sw_filtering_sampling_rate, optval, 
sizeof(pfr->sw_filtering_sampling_rate)))
+               return(-EFAULT);
+         break;
+
   case SO_ACTIVATE_RING:
     debug_printk(2, "* SO_ACTIVATE_RING *\n");
 
@@ -8006,13 +8029,14 @@
   if(transparent_mode != 0)
     printk("[PF_RING] Warning: transparent_mode is deprecated!\n");
 
-  printk("[PF_RING] Min # ring slots %d\n", min_num_slots);
-  printk("[PF_RING] Slot version     %d\n",
+  printk("[PF_RING] Min # ring slots                 %d\n", min_num_slots);
+  printk("[PF_RING] Slot version                     %d\n",
         RING_FLOWSLOT_VERSION);
-  printk("[PF_RING] Capture TX       %s\n",
+  printk("[PF_RING] Capture TX                       %s\n",
         enable_tx_capture ? "Yes [RX+TX]" : "No [RX only]");
-  printk("[PF_RING] IP Defragment    %s\n",
+  printk("[PF_RING] IP Defragment                    %s\n",
         enable_ip_defrag ? "Yes" : "No");
+  printk("[PF_RING] Filtering sampling segment size  %d\n", 
filtering_sampling_segment_size);   
 
   if((rc = proto_register(&ring_proto, 0)) != 0)
     return(rc);
diff -Naur PF_RING-dev.20170907/userland/c++/PFring.h 
PF_RING-dev.20170907.sampling/userland/c++/PFring.h
--- PF_RING-dev.20170907/userland/c++/PFring.h  2017-09-07 13:02:53.000000000 
+0300
+++ PF_RING-dev.20170907.sampling/userland/c++/PFring.h 2017-09-07 
13:56:31.888988000 +0300
@@ -79,6 +79,8 @@
   inline int enable_ring()       { return pfring_enable_ring(ring); };
   inline int set_sampling_rate(u_int32_t rate /* 1 = no sampling */)
     { return pfring_set_sampling_rate(ring, rate); };
+  inline int set_sw_filtering_sampling_rate(u_int32_t rate /* 0 = no sampling 
*/)
+    { return pfring_set_sw_filtering_sampling_rate(ring, rate); };
   inline int get_version(u_int32_t *version) 
     { return pfring_version(ring, version); };
   inline int get_socket_id()  { return ring->fd; };
diff -Naur PF_RING-dev.20170907/userland/lib/notused/pfring_mod_multi.c 
PF_RING-dev.20170907.sampling/userland/lib/notused/pfring_mod_multi.c
--- PF_RING-dev.20170907/userland/lib/notused/pfring_mod_multi.c        
2017-09-07 13:02:53.000000000 +0300
+++ PF_RING-dev.20170907.sampling/userland/lib/notused/pfring_mod_multi.c       
2017-09-07 13:57:21.413025000 +0300
@@ -161,6 +161,18 @@
 
 /* ******************************* */
 
+int pfring_mod_multi_set_sw_filtering_sampling_rate(pfring *ring, u_int32_t 
rate /* 0 = no sampling */) {
+  struct ring_list_element *elem = (struct ring_list_element *) 
ring->priv_data;
+  while(elem != NULL) {
+    if(pfring_set_sw_filtering_sampling_rate(elem->ring, rate)<0)
+      return -1;
+    elem = elem->next;
+  }
+  return 0;
+}
+
+/* ******************************* */
+
 int pfring_mod_multi_set_direction(pfring *ring, packet_direction direction) {
   struct ring_list_element *elem = (struct ring_list_element *) 
ring->priv_data;
   while(elem != NULL) {
diff -Naur PF_RING-dev.20170907/userland/lib/pfring.c 
PF_RING-dev.20170907.sampling/userland/lib/pfring.c
--- PF_RING-dev.20170907/userland/lib/pfring.c  2017-09-07 13:02:53.000000000 
+0300
+++ PF_RING-dev.20170907.sampling/userland/lib/pfring.c 2017-09-07 
13:58:19.247064000 +0300
@@ -757,6 +757,23 @@
 
 /* **************************************************** */
 
+int pfring_set_sw_filtering_sampling_rate(pfring *ring, u_int32_t rate /* 0 = 
no sampling */) {
+  if(ring && ring->set_sw_filtering_sampling_rate) {
+    int rc;
+
+    rc = ring->set_sw_filtering_sampling_rate(ring, rate);
+
+    if (rc == 0)
+      ring->sw_filtering_sampling_rate = rate;
+
+    return(rc);
+  }
+
+  return(PF_RING_ERROR_NOT_SUPPORTED);
+}
+
+/* **************************************************** */
+
 int pfring_set_packet_slicing(pfring *ring, packet_slicing_level level, 
u_int32_t additional_bytes) {
   if (ring && ring->set_packet_slicing) {
     int rc;
diff -Naur PF_RING-dev.20170907/userland/lib/pfring.h 
PF_RING-dev.20170907.sampling/userland/lib/pfring.h
--- PF_RING-dev.20170907/userland/lib/pfring.h  2017-09-07 13:02:53.000000000 
+0300
+++ PF_RING-dev.20170907.sampling/userland/lib/pfring.h 2017-09-07 
14:00:23.512178000 +0300
@@ -244,6 +244,7 @@
   u_int8_t  (*get_num_rx_channels)          (pfring *);
   int       (*get_card_settings)            (pfring *, pfring_card_settings *);
   int       (*set_sampling_rate)            (pfring *, u_int32_t);
+  int       (*set_sw_filtering_sampling_rate)(pfring *, u_int32_t);
   int       (*set_packet_slicing)           (pfring *, packet_slicing_level, 
u_int32_t);
   int       (*get_selectable_fd)            (pfring *);
   int       (*set_direction)                (pfring *, packet_direction);
@@ -306,6 +307,7 @@
   u_int32_t caplen;
   u_int16_t slot_header_len, mtu_len /* 0 = unknown */;
   u_int32_t sampling_rate, sampling_counter;
+  u_int32_t sw_filtering_sampling_rate;
   packet_slicing_level slicing_level;
   u_int32_t slicing_additional_bytes;
   u_int8_t is_shutting_down, socket_default_accept_policy;
@@ -750,6 +752,15 @@
 int pfring_remove_filtering_rule(pfring *ring, u_int16_t rule_id);
 
 /**
+ * Implement packet sampling during sw filtering directly into the kernel. 
Note that this solution is much more efficient than implementing it in 
user-space. 
+ * Sampled packets during filtering are only those that already has been 
filtered (if any).
+ * @param ring The PF_RING handle on which sampling is applied. 
+ * @param rate The sampling rate. Rate of X means that first X packets out of 
'filtering_sampling_segment_size' are forwarded. This means that a sampling 
rate of 0 disables sampling.
+ * @return 0 on success, a negative value otherwise.
+ */
+int pfring_set_sw_filtering_sampling_rate(pfring *ring, u_int32_t rate /* 0 = 
no sampling */);
+
+/**
  * Remove hash filtering rules inactive for the specified number of seconds.
  * @param ring           The PF_RING handle on which the rules will be removed.
  * @param inactivity_sec The inactivity threshold.
diff -Naur PF_RING-dev.20170907/userland/lib/pfring_mod.c 
PF_RING-dev.20170907.sampling/userland/lib/pfring_mod.c
--- PF_RING-dev.20170907/userland/lib/pfring_mod.c      2017-09-07 
13:02:53.000000000 +0300
+++ PF_RING-dev.20170907.sampling/userland/lib/pfring_mod.c     2017-09-07 
14:01:59.409271000 +0300
@@ -204,6 +204,7 @@
   ring->send = pfring_mod_send;
   ring->get_num_rx_channels = pfring_mod_get_num_rx_channels;
   ring->set_sampling_rate = pfring_mod_set_sampling_rate;
+  ring->set_sw_filtering_sampling_rate = 
pfring_mod_set_sw_filtering_sampling_rate;
   ring->get_selectable_fd = pfring_mod_get_selectable_fd;
   ring->set_direction = pfring_mod_set_direction;
   ring->set_socket_mode = pfring_mod_set_socket_mode;
@@ -417,6 +418,12 @@
   return(setsockopt(ring->fd, 0, SO_SET_SAMPLING_RATE, &rate, sizeof(rate)));
 }
 
+/* **************************************************** */
+
+int pfring_mod_set_sw_filtering_sampling_rate(pfring *ring, u_int32_t rate /* 
0 = no sampling */) {
+  return(setsockopt(ring->fd, 0, SO_SET_SW_FILTERING_SAMPLING_RATE, &rate, 
sizeof(rate)));
+}
+
 /* ******************************* */
 
 int pfring_mod_stats(pfring *ring, pfring_stat *stats) {
diff -Naur PF_RING-dev.20170907/userland/lib/pfring_mod.h 
PF_RING-dev.20170907.sampling/userland/lib/pfring_mod.h
--- PF_RING-dev.20170907/userland/lib/pfring_mod.h      2017-09-07 
13:02:53.000000000 +0300
+++ PF_RING-dev.20170907.sampling/userland/lib/pfring_mod.h     2017-09-07 
14:02:24.792303000 +0300
@@ -35,6 +35,7 @@
 int pfring_mod_send(pfring *ring, char *pkt, u_int pkt_len, u_int8_t 
flush_packet);
 u_int8_t pfring_mod_get_num_rx_channels(pfring *ring);
 int pfring_mod_set_sampling_rate(pfring *ring, u_int32_t rate);
+int pfring_mod_set_sw_filtering_sampling_rate(pfring *ring, u_int32_t rate);
 int pfring_mod_get_selectable_fd(pfring *ring);
 int pfring_mod_set_direction(pfring *ring, packet_direction direction);
 int pfring_mod_set_socket_mode(pfring *ring, socket_mode mode);
_______________________________________________
Ntop-misc mailing list
[email protected]
http://listgateway.unipi.it/mailman/listinfo/ntop-misc

Reply via email to