ipsec: huge anti-replay window support
[vpp.git] / src / vnet / ipsec / ipsec_sa.c
index 98160cd..1656b9a 100644 (file)
@@ -329,7 +329,8 @@ ipsec_sa_add_and_lock (u32 id, u32 spi, ipsec_protocol_t proto,
                       ipsec_crypto_alg_t crypto_alg, const ipsec_key_t *ck,
                       ipsec_integ_alg_t integ_alg, const ipsec_key_t *ik,
                       ipsec_sa_flags_t flags, u32 salt, u16 src_port,
-                      u16 dst_port, const tunnel_t *tun, u32 *sa_out_index)
+                      u16 dst_port, u32 anti_replay_window_size,
+                      const tunnel_t *tun, u32 *sa_out_index)
 {
   vlib_main_t *vm = vlib_get_main ();
   ipsec_main_t *im = &ipsec_main;
@@ -379,6 +380,9 @@ ipsec_sa_add_and_lock (u32 id, u32 spi, ipsec_protocol_t proto,
   ipsec_sa_set_crypto_alg (sa, crypto_alg);
   ipsec_sa_set_async_op_ids (sa);
 
+  if (ipsec_sa_is_set_USE_ANTI_REPLAY (sa) && anti_replay_window_size > 64)
+    ipsec_sa_set_ANTI_REPLAY_HUGE (sa);
+
   clib_memcpy (&sa->crypto_key, ck, sizeof (sa->crypto_key));
 
   sa->crypto_sync_key_index = vnet_crypto_key_add (
@@ -488,6 +492,18 @@ ipsec_sa_add_and_lock (u32 id, u32 spi, ipsec_protocol_t proto,
                                 !ipsec_sa_is_set_IS_TUNNEL_V6 (sa));
     }
 
+  /* window size rounded up to next power of 2 */
+  if (ipsec_sa_is_set_ANTI_REPLAY_HUGE (sa))
+    {
+      anti_replay_window_size = 1 << max_log2 (anti_replay_window_size);
+      sa->replay_window_huge =
+       clib_bitmap_set_region (0, 0, 1, anti_replay_window_size);
+    }
+  else
+    {
+      sa->replay_window = ~0;
+    }
+
   hash_set (im->sa_index_by_sa_id, sa->id, sa_index);
 
   if (sa_out_index)
@@ -525,6 +541,8 @@ ipsec_sa_del (ipsec_sa_t * sa)
   vnet_crypto_key_del (vm, sa->crypto_sync_key_index);
   if (sa->integ_alg != IPSEC_INTEG_ALG_NONE)
     vnet_crypto_key_del (vm, sa->integ_sync_key_index);
+  if (ipsec_sa_is_set_ANTI_REPLAY_HUGE (sa))
+    clib_bitmap_free (sa->replay_window_huge);
   pool_put (ipsec_sa_pool, sa);
 }