vnet: throttling configuration improvement

To allow a more flexible throttling configuration, the number of bits
used in the throttling bitmap can be chosen.

Type: improvement
Signed-off-by: Maxime Peim <mpeim@cisco.com>
Change-Id: I7bfe391dd64729011b03f3e5b89408dfc340e036
diff --git a/src/vnet/ip-neighbor/ip4_neighbor.c b/src/vnet/ip-neighbor/ip4_neighbor.c
index 5a6e8dd..2d4b295 100644
--- a/src/vnet/ip-neighbor/ip4_neighbor.c
+++ b/src/vnet/ip-neighbor/ip4_neighbor.c
@@ -328,7 +328,7 @@
   vlib_thread_main_t *tm = &vlib_thread_main;
   u32 n_vlib_mains = tm->n_vlib_mains;
 
-  throttle_init (&arp_throttle, n_vlib_mains, 1e-3);
+  throttle_init (&arp_throttle, n_vlib_mains, THROTTLE_BITS, 1e-3);
 
   return (NULL);
 }
diff --git a/src/vnet/ip-neighbor/ip6_neighbor.c b/src/vnet/ip-neighbor/ip6_neighbor.c
index 576ae57..e3a47df 100644
--- a/src/vnet/ip-neighbor/ip6_neighbor.c
+++ b/src/vnet/ip-neighbor/ip6_neighbor.c
@@ -338,7 +338,7 @@
 {
   vlib_thread_main_t *tm = &vlib_thread_main;
 
-  throttle_init (&nd_throttle, tm->n_vlib_mains, 1e-3);
+  throttle_init (&nd_throttle, tm->n_vlib_mains, THROTTLE_BITS, 1e-3);
 
   return 0;
 }
diff --git a/src/vnet/ip/icmp4.c b/src/vnet/ip/icmp4.c
index f91a1b5..562cbce 100644
--- a/src/vnet/ip/icmp4.c
+++ b/src/vnet/ip/icmp4.c
@@ -590,7 +590,7 @@
   vlib_thread_main_t *tm = &vlib_thread_main;
   u32 n_vlib_mains = tm->n_vlib_mains;
 
-  throttle_init (&icmp_throttle, n_vlib_mains, 1e-3);
+  throttle_init (&icmp_throttle, n_vlib_mains, THROTTLE_BITS, 1e-3);
 
   return 0;
 }
diff --git a/src/vnet/ip/icmp6.c b/src/vnet/ip/icmp6.c
index 4cabc0e..8d95e48 100644
--- a/src/vnet/ip/icmp6.c
+++ b/src/vnet/ip/icmp6.c
@@ -644,7 +644,7 @@
   vlib_thread_main_t *tm = &vlib_thread_main;
   u32 n_vlib_mains = tm->n_vlib_mains;
 
-  throttle_init (&icmp_throttle, n_vlib_mains, 1e-3);
+  throttle_init (&icmp_throttle, n_vlib_mains, THROTTLE_BITS, 1e-3);
 
   return (NULL);
 }
diff --git a/src/vnet/util/throttle.c b/src/vnet/util/throttle.c
index 0985b4a..8b8e030 100644
--- a/src/vnet/util/throttle.c
+++ b/src/vnet/util/throttle.c
@@ -16,17 +16,18 @@
 #include <vnet/util/throttle.h>
 
 void
-throttle_init (throttle_t * t, u32 n_threads, f64 time)
+throttle_init (throttle_t *t, u32 n_threads, u32 buckets, f64 time)
 {
   u32 i;
 
   t->time = time;
+  t->buckets = 1 << max_log2 (buckets);
   vec_validate (t->bitmaps, n_threads);
   vec_validate (t->seeds, n_threads);
   vec_validate (t->last_seed_change_time, n_threads);
 
   for (i = 0; i < n_threads; i++)
-    vec_validate (t->bitmaps[i], (THROTTLE_BITS / BITS (uword)) - 1);
+    clib_bitmap_alloc (t->bitmaps[i], t->buckets);
 }
 
 /*
diff --git a/src/vnet/util/throttle.h b/src/vnet/util/throttle.h
index 38ace28..53435c4 100644
--- a/src/vnet/util/throttle.h
+++ b/src/vnet/util/throttle.h
@@ -31,11 +31,13 @@
   uword **bitmaps;
   u64 *seeds;
   f64 *last_seed_change_time;
+  u32 buckets;
 } throttle_t;
 
 #define THROTTLE_BITS	(512)
 
-extern void throttle_init (throttle_t * t, u32 n_threads, f64 time);
+extern void throttle_init (throttle_t *t, u32 n_threads, u32 buckets,
+			   f64 time);
 
 always_inline u64
 throttle_seed (throttle_t * t, u32 thread_index, f64 time_now)
@@ -43,7 +45,7 @@
   if (time_now - t->last_seed_change_time[thread_index] > t->time)
     {
       (void) random_u64 (&t->seeds[thread_index]);
-      clib_memset (t->bitmaps[thread_index], 0, THROTTLE_BITS / BITS (u8));
+      clib_bitmap_zero (t->bitmaps[thread_index]);
 
       t->last_seed_change_time[thread_index] = time_now;
     }
@@ -53,21 +55,14 @@
 always_inline int
 throttle_check (throttle_t * t, u32 thread_index, u64 hash, u64 seed)
 {
-  int drop;
-  uword m;
-  u32 w;
+  ASSERT (is_pow2 (t->buckets));
 
   hash = clib_xxhash (hash ^ seed);
 
   /* Select bit number */
-  hash &= THROTTLE_BITS - 1;
-  w = hash / BITS (uword);
-  m = (uword) 1 << (hash % BITS (uword));
+  hash &= t->buckets - 1;
 
-  drop = (t->bitmaps[thread_index][w] & m) != 0;
-  t->bitmaps[thread_index][w] |= m;
-
-  return (drop);
+  return clib_bitmap_set_no_check (t->bitmaps[thread_index], hash, 1);
 }
 
 #endif