IPSEC: move SA counters into the stats segment
[vpp.git] / src / vnet / ipsec / ikev2.c
index 2c1074d..d85feee 100644 (file)
 #include <vnet/vnet.h>
 #include <vnet/pg/pg.h>
 #include <vppinfra/error.h>
+#include <vppinfra/random.h>
 #include <vnet/udp/udp.h>
 #include <vnet/ipsec/ipsec.h>
 #include <vnet/ipsec/ikev2.h>
 #include <vnet/ipsec/ikev2_priv.h>
 #include <openssl/sha.h>
 
+ikev2_main_t ikev2_main;
+
 static int ikev2_delete_tunnel_interface (vnet_main_t * vnm,
                                          ikev2_sa_t * sa,
                                          ikev2_child_sa_t * child);
@@ -158,7 +161,7 @@ ikev2_select_proposal (ikev2_sa_proposal_t * proposals,
        {
          bitmap |= 1 << transform->type;
          vec_add2 (rv->transforms, new_t, 1);
-         clib_memcpy (new_t, transform, sizeof (*new_t));
+         clib_memcpy_fast (new_t, transform, sizeof (*new_t));
          new_t->attrs = vec_dup (transform->attrs);
        }
     }
@@ -303,16 +306,16 @@ static void
 ikev2_delete_sa (ikev2_sa_t * sa)
 {
   ikev2_main_t *km = &ikev2_main;
-  u32 cpu_index = os_get_cpu_number ();
+  u32 thread_index = vlib_get_thread_index ();
   uword *p;
 
   ikev2_sa_free_all_vec (sa);
 
-  p = hash_get (km->per_thread_data[cpu_index].sa_by_rspi, sa->rspi);
+  p = hash_get (km->per_thread_data[thread_index].sa_by_rspi, sa->rspi);
   if (p)
     {
-      hash_unset (km->per_thread_data[cpu_index].sa_by_rspi, sa->rspi);
-      pool_put (km->per_thread_data[cpu_index].sas, sa);
+      hash_unset (km->per_thread_data[thread_index].sa_by_rspi, sa->rspi);
+      pool_put (km->per_thread_data[thread_index].sas, sa);
     }
 }
 
@@ -466,37 +469,37 @@ ikev2_calc_keys (ikev2_sa_t * sa)
 
   /* SK_d */
   sa->sk_d = vec_new (u8, tr_prf->key_trunc);
-  clib_memcpy (sa->sk_d, keymat + pos, tr_prf->key_trunc);
+  clib_memcpy_fast (sa->sk_d, keymat + pos, tr_prf->key_trunc);
   pos += tr_prf->key_trunc;
 
   /* SK_ai */
   sa->sk_ai = vec_new (u8, tr_integ->key_len);
-  clib_memcpy (sa->sk_ai, keymat + pos, tr_integ->key_len);
+  clib_memcpy_fast (sa->sk_ai, keymat + pos, tr_integ->key_len);
   pos += tr_integ->key_len;
 
   /* SK_ar */
   sa->sk_ar = vec_new (u8, tr_integ->key_len);
-  clib_memcpy (sa->sk_ar, keymat + pos, tr_integ->key_len);
+  clib_memcpy_fast (sa->sk_ar, keymat + pos, tr_integ->key_len);
   pos += tr_integ->key_len;
 
   /* SK_ei */
   sa->sk_ei = vec_new (u8, tr_encr->key_len);
-  clib_memcpy (sa->sk_ei, keymat + pos, tr_encr->key_len);
+  clib_memcpy_fast (sa->sk_ei, keymat + pos, tr_encr->key_len);
   pos += tr_encr->key_len;
 
   /* SK_er */
   sa->sk_er = vec_new (u8, tr_encr->key_len);
-  clib_memcpy (sa->sk_er, keymat + pos, tr_encr->key_len);
+  clib_memcpy_fast (sa->sk_er, keymat + pos, tr_encr->key_len);
   pos += tr_encr->key_len;
 
   /* SK_pi */
   sa->sk_pi = vec_new (u8, tr_prf->key_len);
-  clib_memcpy (sa->sk_pi, keymat + pos, tr_prf->key_len);
+  clib_memcpy_fast (sa->sk_pi, keymat + pos, tr_prf->key_len);
   pos += tr_prf->key_len;
 
   /* SK_pr */
   sa->sk_pr = vec_new (u8, tr_prf->key_len);
-  clib_memcpy (sa->sk_pr, keymat + pos, tr_prf->key_len);
+  clib_memcpy_fast (sa->sk_pr, keymat + pos, tr_prf->key_len);
   pos += tr_prf->key_len;
 
   vec_free (keymat);
@@ -526,22 +529,22 @@ ikev2_calc_child_keys (ikev2_sa_t * sa, ikev2_child_sa_t * child)
 
   /* SK_ei */
   child->sk_ei = vec_new (u8, ctr_encr->key_len);
-  clib_memcpy (child->sk_ei, keymat + pos, ctr_encr->key_len);
+  clib_memcpy_fast (child->sk_ei, keymat + pos, ctr_encr->key_len);
   pos += ctr_encr->key_len;
 
   /* SK_ai */
   child->sk_ai = vec_new (u8, ctr_integ->key_len);
-  clib_memcpy (child->sk_ai, keymat + pos, ctr_integ->key_len);
+  clib_memcpy_fast (child->sk_ai, keymat + pos, ctr_integ->key_len);
   pos += ctr_integ->key_len;
 
   /* SK_er */
   child->sk_er = vec_new (u8, ctr_encr->key_len);
-  clib_memcpy (child->sk_er, keymat + pos, ctr_encr->key_len);
+  clib_memcpy_fast (child->sk_er, keymat + pos, ctr_encr->key_len);
   pos += ctr_encr->key_len;
 
   /* SK_ar */
   child->sk_ar = vec_new (u8, ctr_integ->key_len);
-  clib_memcpy (child->sk_ar, keymat + pos, ctr_integ->key_len);
+  clib_memcpy_fast (child->sk_ar, keymat + pos, ctr_integ->key_len);
   pos += ctr_integ->key_len;
 
   ASSERT (pos == len);
@@ -776,29 +779,31 @@ ikev2_initial_contact_cleanup (ikev2_sa_t * sa)
   ikev2_sa_t *tmp;
   u32 i, *delete = 0;
   ikev2_child_sa_t *c;
-  u32 cpu_index = os_get_cpu_number ();
+  u32 thread_index = vlib_get_thread_index ();
 
   if (!sa->initial_contact)
     return;
 
   /* find old IKE SAs with the same authenticated identity */
   /* *INDENT-OFF* */
-  pool_foreach (tmp, km->per_thread_data[cpu_index].sas, ({
+  pool_foreach (tmp, km->per_thread_data[thread_index].sas, ({
         if (tmp->i_id.type != sa->i_id.type ||
             vec_len(tmp->i_id.data) != vec_len(sa->i_id.data) ||
             memcmp(sa->i_id.data, tmp->i_id.data, vec_len(sa->i_id.data)))
           continue;
 
         if (sa->rspi != tmp->rspi)
-          vec_add1(delete, tmp - km->per_thread_data[cpu_index].sas);
+          vec_add1(delete, tmp - km->per_thread_data[thread_index].sas);
   }));
   /* *INDENT-ON* */
 
   for (i = 0; i < vec_len (delete); i++)
     {
-      tmp = pool_elt_at_index (km->per_thread_data[cpu_index].sas, delete[i]);
-      vec_foreach (c, tmp->childs)
-       ikev2_delete_tunnel_interface (km->vnet_main, tmp, c);
+      tmp =
+       pool_elt_at_index (km->per_thread_data[thread_index].sas, delete[i]);
+      vec_foreach (c,
+                  tmp->childs) ikev2_delete_tunnel_interface (km->vnet_main,
+                                                              tmp, c);
       ikev2_delete_sa (tmp);
     }
 
@@ -873,25 +878,26 @@ ikev2_process_auth_req (vlib_main_t * vm, ikev2_sa_t * sa, ike_header_t * ike)
              first_child_sa->i_proposals = ikev2_parse_sa_payload (ikep);
            }
        }
-      else if (payload == IKEV2_PAYLOAD_IDI || payload == IKEV2_PAYLOAD_IDR)   /* 35, 36 */
+      else if (payload == IKEV2_PAYLOAD_IDI)   /* 35 */
        {
          ike_id_payload_header_t *id = (ike_id_payload_header_t *) ikep;
 
-         if (sa->is_initiator)
-           {
-             sa->r_id.type = id->id_type;
-             vec_free (sa->r_id.data);
-             vec_add (sa->r_id.data, id->payload, plen - sizeof (*id));
-           }
-         else
-           {
-             sa->i_id.type = id->id_type;
-             vec_free (sa->i_id.data);
-             vec_add (sa->i_id.data, id->payload, plen - sizeof (*id));
-           }
+         sa->i_id.type = id->id_type;
+         vec_free (sa->i_id.data);
+         vec_add (sa->i_id.data, id->payload, plen - sizeof (*id));
 
-         clib_warning ("received payload %s, len %u id_type %u",
-                       (payload == IKEV2_PAYLOAD_IDI ? "IDi" : "IDr"),
+         clib_warning ("received payload IDi, len %u id_type %u",
+                       plen - sizeof (*id), id->id_type);
+       }
+      else if (payload == IKEV2_PAYLOAD_IDR)   /* 36 */
+       {
+         ike_id_payload_header_t *id = (ike_id_payload_header_t *) ikep;
+
+         sa->r_id.type = id->id_type;
+         vec_free (sa->r_id.data);
+         vec_add (sa->r_id.data, id->payload, plen - sizeof (*id));
+
+         clib_warning ("received payload IDr len %u id_type %u",
                        plen - sizeof (*id), id->id_type);
        }
       else if (payload == IKEV2_PAYLOAD_AUTH)  /* 39 */
@@ -1100,7 +1106,7 @@ ikev2_process_create_child_sa_req (vlib_main_t * vm, ikev2_sa_t * sa,
        }
       else if (payload == IKEV2_PAYLOAD_NONCE)
        {
-         clib_memcpy (nonce, ikep->payload, plen - sizeof (*ikep));
+         clib_memcpy_fast (nonce, ikep->payload, plen - sizeof (*ikep));
        }
       else if (payload == IKEV2_PAYLOAD_TSI)
        {
@@ -1474,6 +1480,7 @@ ikev2_create_tunnel_interface (vnet_main_t * vnm, ikev2_sa_t * sa,
   ikev2_sa_transform_t *tr;
   ikev2_sa_proposal_t *proposals;
   u8 encr_type = 0;
+  u8 integ_type = 0;
 
   if (!child->r_proposals)
     {
@@ -1481,20 +1488,20 @@ ikev2_create_tunnel_interface (vnet_main_t * vnm, ikev2_sa_t * sa,
       return 1;
     }
 
-  memset (&a, 0, sizeof (a));
+  clib_memset (&a, 0, sizeof (a));
   a.is_add = 1;
   if (sa->is_initiator)
     {
-      a.local_ip.as_u32 = sa->iaddr.as_u32;
-      a.remote_ip.as_u32 = sa->raddr.as_u32;
+      a.local_ip.ip4.as_u32 = sa->iaddr.as_u32;
+      a.remote_ip.ip4.as_u32 = sa->raddr.as_u32;
       proposals = child->i_proposals;
       a.local_spi = child->r_proposals[0].spi;
       a.remote_spi = child->i_proposals[0].spi;
     }
   else
     {
-      a.local_ip.as_u32 = sa->raddr.as_u32;
-      a.remote_ip.as_u32 = sa->iaddr.as_u32;
+      a.local_ip.ip4.as_u32 = sa->raddr.as_u32;
+      a.remote_ip.ip4.as_u32 = sa->iaddr.as_u32;
       proposals = child->r_proposals;
       a.local_spi = child->i_proposals[0].spi;
       a.remote_spi = child->r_proposals[0].spi;
@@ -1544,8 +1551,21 @@ ikev2_create_tunnel_interface (vnet_main_t * vnm, ikev2_sa_t * sa,
   tr = ikev2_sa_get_td_for_type (proposals, IKEV2_TRANSFORM_TYPE_INTEG);
   if (tr)
     {
-      if (tr->integ_type != IKEV2_TRANSFORM_INTEG_TYPE_AUTH_HMAC_SHA1_96)
-       {
+      switch (tr->integ_type)
+       {
+       case IKEV2_TRANSFORM_INTEG_TYPE_AUTH_HMAC_SHA2_256_128:
+         integ_type = IPSEC_INTEG_ALG_SHA_256_128;
+         break;
+       case IKEV2_TRANSFORM_INTEG_TYPE_AUTH_HMAC_SHA2_384_192:
+         integ_type = IPSEC_INTEG_ALG_SHA_384_192;
+         break;
+       case IKEV2_TRANSFORM_INTEG_TYPE_AUTH_HMAC_SHA2_512_256:
+         integ_type = IPSEC_INTEG_ALG_SHA_512_256;
+         break;
+       case IKEV2_TRANSFORM_INTEG_TYPE_AUTH_HMAC_SHA1_96:
+         integ_type = IPSEC_INTEG_ALG_SHA1_96;
+         break;
+       default:
          ikev2_set_state (sa, IKEV2_STATE_NO_PROPOSAL_CHOSEN);
          return 1;
        }
@@ -1574,17 +1594,17 @@ ikev2_create_tunnel_interface (vnet_main_t * vnm, ikev2_sa_t * sa,
       rem_ckey = child->sk_ei;
     }
 
-  a.integ_alg = IPSEC_INTEG_ALG_SHA1_96;
+  a.integ_alg = integ_type;
   a.local_integ_key_len = vec_len (loc_ikey);
-  clib_memcpy (a.local_integ_key, loc_ikey, a.local_integ_key_len);
+  clib_memcpy_fast (a.local_integ_key, loc_ikey, a.local_integ_key_len);
   a.remote_integ_key_len = vec_len (rem_ikey);
-  clib_memcpy (a.remote_integ_key, rem_ikey, a.remote_integ_key_len);
+  clib_memcpy_fast (a.remote_integ_key, rem_ikey, a.remote_integ_key_len);
 
   a.crypto_alg = encr_type;
   a.local_crypto_key_len = vec_len (loc_ckey);
-  clib_memcpy (a.local_crypto_key, loc_ckey, a.local_crypto_key_len);
+  clib_memcpy_fast (a.local_crypto_key, loc_ckey, a.local_crypto_key_len);
   a.remote_crypto_key_len = vec_len (rem_ckey);
-  clib_memcpy (a.remote_crypto_key, rem_ckey, a.remote_crypto_key_len);
+  clib_memcpy_fast (a.remote_crypto_key, rem_ckey, a.remote_crypto_key_len);
 
   if (sa->profile && sa->profile->lifetime)
     {
@@ -1592,8 +1612,16 @@ ikev2_create_tunnel_interface (vnet_main_t * vnm, ikev2_sa_t * sa,
        + sa->profile->lifetime;
       if (sa->profile->lifetime_jitter)
        {
+         // This is not much better than rand(3), which Coverity warns
+         // is unsuitable for security applications; random_u32 is
+         // however fast. If this perturbance to the expiration time
+         // needs to use a better RNG then we may need to use something
+         // like /dev/urandom which has significant overhead.
+         u32 rnd = (u32) (vlib_time_now (vnm->vlib_main) * 1e6);
+         rnd = random_u32 (&rnd);
+
          child->time_to_expiration +=
-           1 + (rand () % sa->profile->lifetime_jitter);
+           1 + (rnd % sa->profile->lifetime_jitter);
        }
     }
 
@@ -1614,8 +1642,8 @@ ikev2_delete_tunnel_interface (vnet_main_t * vnm, ikev2_sa_t * sa,
        return 0;
 
       a.is_add = 0;
-      a.local_ip.as_u32 = sa->iaddr.as_u32;
-      a.remote_ip.as_u32 = sa->raddr.as_u32;
+      a.local_ip.ip4.as_u32 = sa->iaddr.as_u32;
+      a.remote_ip.ip4.as_u32 = sa->raddr.as_u32;
       a.local_spi = child->r_proposals[0].spi;
       a.remote_spi = child->i_proposals[0].spi;
     }
@@ -1625,8 +1653,8 @@ ikev2_delete_tunnel_interface (vnet_main_t * vnm, ikev2_sa_t * sa,
        return 0;
 
       a.is_add = 0;
-      a.local_ip.as_u32 = sa->raddr.as_u32;
-      a.remote_ip.as_u32 = sa->iaddr.as_u32;
+      a.local_ip.ip4.as_u32 = sa->raddr.as_u32;
+      a.remote_ip.ip4.as_u32 = sa->iaddr.as_u32;
       a.local_spi = child->i_proposals[0].spi;
       a.remote_spi = child->r_proposals[0].spi;
     }
@@ -1804,7 +1832,7 @@ ikev2_generate_message (ikev2_sa_t * sa, ike_header_t * ike, void *user)
          ikev2_sa_proposal_t *proposals = (ikev2_sa_proposal_t *) user;
          ikev2_notify_t notify;
          u8 *data = vec_new (u8, 4);
-         memset (&notify, 0, sizeof (notify));
+         clib_memset (&notify, 0, sizeof (notify));
          notify.protocol_id = IKEV2_PROTOCOL_ESP;
          notify.spi = sa->childs[0].i_proposals->spi;
          *(u32 *) data = clib_host_to_net_u32 (notify.spi);
@@ -1870,7 +1898,7 @@ ikev2_generate_message (ikev2_sa_t * sa, ike_header_t * ike, void *user)
       tlen += vec_len (chain->data);
       ike->nextpayload = chain->first_payload_type;
       ike->length = clib_host_to_net_u32 (tlen);
-      clib_memcpy (ike->payload, chain->data, vec_len (chain->data));
+      clib_memcpy_fast (ike->payload, chain->data, vec_len (chain->data));
 
       /* store whole IKE payload - needed for PSK auth */
       vec_free (sa->last_sa_init_res_packet_data);
@@ -1902,8 +1930,8 @@ ikev2_generate_message (ikev2_sa_t * sa, ike_header_t * ike, void *user)
        ikev2_calc_integr (tr_integ, sa->is_initiator ? sa->sk_ai : sa->sk_ar,
                           (u8 *) ike, tlen - tr_integ->key_trunc);
 
-      clib_memcpy (ike->payload + tlen - tr_integ->key_trunc - sizeof (*ike),
-                  integ, tr_integ->key_trunc);
+      clib_memcpy_fast (ike->payload + tlen - tr_integ->key_trunc -
+                       sizeof (*ike), integ, tr_integ->key_trunc);
 
       /* store whole IKE payload - needed for retransmit */
       vec_free (sa->last_res_packet_data);
@@ -1922,10 +1950,10 @@ ikev2_retransmit_sa_init (ike_header_t * ike,
 {
   ikev2_main_t *km = &ikev2_main;
   ikev2_sa_t *sa;
-  u32 cpu_index = os_get_cpu_number ();
+  u32 thread_index = vlib_get_thread_index ();
 
   /* *INDENT-OFF* */
-  pool_foreach (sa, km->per_thread_data[cpu_index].sas, ({
+  pool_foreach (sa, km->per_thread_data[thread_index].sas, ({
     if (sa->ispi == clib_net_to_host_u64(ike->ispi) &&
         sa->iaddr.as_u32 == iaddr.as_u32 &&
         sa->raddr.as_u32 == raddr.as_u32)
@@ -1958,7 +1986,7 @@ ikev2_retransmit_sa_init (ike_header_t * ike,
                       ike->flags = tmp->flags;
                       ike->msgid = tmp->msgid;
                       ike->length = tmp->length;
-                      clib_memcpy(ike->payload, tmp->payload,
+                      clib_memcpy_fast(ike->payload, tmp->payload,
                              clib_net_to_host_u32(tmp->length) - sizeof(*ike));
                       clib_warning("IKE_SA_INIT retransmit from %U to %U",
                                    format_ip4_address, &raddr,
@@ -2010,8 +2038,8 @@ ikev2_retransmit_resp (ikev2_sa_t * sa, ike_header_t * ike)
       ike->flags = tmp->flags;
       ike->msgid = tmp->msgid;
       ike->length = tmp->length;
-      clib_memcpy (ike->payload, tmp->payload,
-                  clib_net_to_host_u32 (tmp->length) - sizeof (*ike));
+      clib_memcpy_fast (ike->payload, tmp->payload,
+                       clib_net_to_host_u32 (tmp->length) - sizeof (*ike));
       clib_warning ("IKE msgid %u retransmit from %U to %U",
                    msg_id,
                    format_ip4_address, &sa->raddr,
@@ -2029,6 +2057,7 @@ ikev2_retransmit_resp (ikev2_sa_t * sa, ike_header_t * ike)
     }
 }
 
+
 static uword
 ikev2_node_fn (vlib_main_t * vm,
               vlib_node_runtime_t * node, vlib_frame_t * frame)
@@ -2036,7 +2065,7 @@ ikev2_node_fn (vlib_main_t * vm,
   u32 n_left_from, *from, *to_next;
   ikev2_next_t next_index;
   ikev2_main_t *km = &ikev2_main;
-  u32 cpu_index = os_get_cpu_number ();
+  u32 thread_index = vlib_get_thread_index ();
 
   from = vlib_frame_vector_args (frame);
   n_left_from = frame->n_vectors;
@@ -2087,7 +2116,7 @@ ikev2_node_fn (vlib_main_t * vm,
          if (ike0->exchange == IKEV2_EXCHANGE_SA_INIT)
            {
              sa0 = &sa;
-             memset (sa0, 0, sizeof (*sa0));
+             clib_memset (sa0, 0, sizeof (*sa0));
 
              if (ike0->flags & IKEV2_HDR_FLAG_INITIATOR)
                {
@@ -2134,11 +2163,14 @@ ikev2_node_fn (vlib_main_t * vm,
                      if (sa0->state == IKEV2_STATE_SA_INIT)
                        {
                          /* add SA to the pool */
-                         pool_get (km->per_thread_data[cpu_index].sas, sa0);
-                         clib_memcpy (sa0, &sa, sizeof (*sa0));
-                         hash_set (km->per_thread_data[cpu_index].sa_by_rspi,
+                         pool_get (km->per_thread_data[thread_index].sas,
+                                   sa0);
+                         clib_memcpy_fast (sa0, &sa, sizeof (*sa0));
+                         hash_set (km->
+                                   per_thread_data[thread_index].sa_by_rspi,
                                    sa0->rspi,
-                                   sa0 - km->per_thread_data[cpu_index].sas);
+                                   sa0 -
+                                   km->per_thread_data[thread_index].sas);
                        }
                      else
                        {
@@ -2146,7 +2178,7 @@ ikev2_node_fn (vlib_main_t * vm,
                        }
                    }
                }
-             else
+             else              //received sa_init without initiator flag
                {
                  ikev2_process_sa_init_resp (vm, sa0, ike0);
 
@@ -2169,11 +2201,11 @@ ikev2_node_fn (vlib_main_t * vm,
                  if (sa0->state == IKEV2_STATE_SA_INIT)
                    {
                      /* add SA to the pool */
-                     pool_get (km->per_thread_data[cpu_index].sas, sa0);
-                     clib_memcpy (sa0, &sa, sizeof (*sa0));
-                     hash_set (km->per_thread_data[cpu_index].sa_by_rspi,
+                     pool_get (km->per_thread_data[thread_index].sas, sa0);
+                     clib_memcpy_fast (sa0, &sa, sizeof (*sa0));
+                     hash_set (km->per_thread_data[thread_index].sa_by_rspi,
                                sa0->rspi,
-                               sa0 - km->per_thread_data[cpu_index].sas);
+                               sa0 - km->per_thread_data[thread_index].sas);
                    }
                  else
                    {
@@ -2184,12 +2216,13 @@ ikev2_node_fn (vlib_main_t * vm,
          else if (ike0->exchange == IKEV2_EXCHANGE_IKE_AUTH)
            {
              uword *p;
-             p = hash_get (km->per_thread_data[cpu_index].sa_by_rspi,
+             p = hash_get (km->per_thread_data[thread_index].sa_by_rspi,
                            clib_net_to_host_u64 (ike0->rspi));
              if (p)
                {
-                 sa0 = pool_elt_at_index (km->per_thread_data[cpu_index].sas,
-                                          p[0]);
+                 sa0 =
+                   pool_elt_at_index (km->per_thread_data[thread_index].sas,
+                                      p[0]);
 
                  r = ikev2_retransmit_resp (sa0, ike0);
                  if (r == 1)
@@ -2240,12 +2273,13 @@ ikev2_node_fn (vlib_main_t * vm,
          else if (ike0->exchange == IKEV2_EXCHANGE_INFORMATIONAL)
            {
              uword *p;
-             p = hash_get (km->per_thread_data[cpu_index].sa_by_rspi,
+             p = hash_get (km->per_thread_data[thread_index].sa_by_rspi,
                            clib_net_to_host_u64 (ike0->rspi));
              if (p)
                {
-                 sa0 = pool_elt_at_index (km->per_thread_data[cpu_index].sas,
-                                          p[0]);
+                 sa0 =
+                   pool_elt_at_index (km->per_thread_data[thread_index].sas,
+                                      p[0]);
 
                  r = ikev2_retransmit_resp (sa0, ike0);
                  if (r == 1)
@@ -2305,12 +2339,13 @@ ikev2_node_fn (vlib_main_t * vm,
          else if (ike0->exchange == IKEV2_EXCHANGE_CREATE_CHILD_SA)
            {
              uword *p;
-             p = hash_get (km->per_thread_data[cpu_index].sa_by_rspi,
+             p = hash_get (km->per_thread_data[thread_index].sa_by_rspi,
                            clib_net_to_host_u64 (ike0->rspi));
              if (p)
                {
-                 sa0 = pool_elt_at_index (km->per_thread_data[cpu_index].sas,
-                                          p[0]);
+                 sa0 =
+                   pool_elt_at_index (km->per_thread_data[thread_index].sas,
+                                      p[0]);
 
                  r = ikev2_retransmit_resp (sa0, ike0);
                  if (r == 1)
@@ -2438,7 +2473,7 @@ VLIB_REGISTER_NODE (ikev2_node,static) = {
 };
 /* *INDENT-ON* */
 
-
+// set ikev2 proposals when vpp is used as initiator
 static clib_error_t *
 ikev2_set_initiator_proposals (vlib_main_t * vm, ikev2_sa_t * sa,
                               ikev2_transforms_set * ts,
@@ -2456,7 +2491,7 @@ ikev2_set_initiator_proposals (vlib_main_t * vm, ikev2_sa_t * sa,
   vec_foreach (td, km->supported_transforms)
   {
     if (td->type == IKEV2_TRANSFORM_TYPE_ENCR
-       && td->encr_type == IKEV2_TRANSFORM_ENCR_TYPE_AES_CBC
+       && td->encr_type == ts->crypto_alg
        && td->key_len == ts->crypto_key_size / 8)
       {
        u16 attr[2];
@@ -2481,7 +2516,7 @@ ikev2_set_initiator_proposals (vlib_main_t * vm, ikev2_sa_t * sa,
   vec_foreach (td, km->supported_transforms)
   {
     if (td->type == IKEV2_TRANSFORM_TYPE_INTEG
-       && td->integ_type == IKEV2_TRANSFORM_INTEG_TYPE_AUTH_HMAC_SHA1_96)
+       && td->integ_type == ts->integ_alg)
       {
        vec_add1 (proposal->transforms, *td);
        error = 0;
@@ -2490,6 +2525,8 @@ ikev2_set_initiator_proposals (vlib_main_t * vm, ikev2_sa_t * sa,
   }
   if (error)
     {
+      clib_warning
+       ("Didn't find any supported algorithm for IKEV2_TRANSFORM_TYPE_INTEG");
       r = clib_error_return (0, "Unsupported algorithm");
       return r;
     }
@@ -2501,7 +2538,7 @@ ikev2_set_initiator_proposals (vlib_main_t * vm, ikev2_sa_t * sa,
       vec_foreach (td, km->supported_transforms)
       {
        if (td->type == IKEV2_TRANSFORM_TYPE_PRF
-           && td->prf_type == IKEV2_TRANSFORM_PRF_TYPE_PRF_HMAC_SHA1)
+           && td->prf_type == IKEV2_TRANSFORM_PRF_TYPE_PRF_HMAC_SHA2_256)
          {
            vec_add1 (proposal->transforms, *td);
            error = 0;
@@ -2654,7 +2691,7 @@ ikev2_add_del_profile (vlib_main_t * vm, u8 * name, int is_add)
        return clib_error_return (0, "policy %v already exists", name);
 
       pool_get (km->profiles, p);
-      memset (p, 0, sizeof (*p));
+      clib_memset (p, 0, sizeof (*p));
       p->name = vec_dup (name);
       p->responder.sw_if_index = ~0;
       uword index = p - km->profiles;
@@ -2919,7 +2956,7 @@ ikev2_initiate_sa_init (vlib_main_t * vm, u8 * name)
 
     /* Prepare the SA and the IKE payload */
     ikev2_sa_t sa;
-    memset (&sa, 0, sizeof (ikev2_sa_t));
+    clib_memset (&sa, 0, sizeof (ikev2_sa_t));
     ikev2_payload_chain_t *chain = 0;
     ikev2_payload_new_chain (chain);
 
@@ -2956,20 +2993,20 @@ ikev2_initiate_sa_init (vlib_main_t * vm, u8 * name)
     u8 *nat_detection_sha1 = vec_new (u8, 20);
 
     u64 tmpspi = clib_host_to_net_u64 (sa.ispi);
-    clib_memcpy (&nat_detection_source[0], &tmpspi, sizeof (tmpspi));
+    clib_memcpy_fast (&nat_detection_source[0], &tmpspi, sizeof (tmpspi));
     tmpspi = clib_host_to_net_u64 (sa.rspi);
-    clib_memcpy (&nat_detection_source[8], &tmpspi, sizeof (tmpspi));
+    clib_memcpy_fast (&nat_detection_source[8], &tmpspi, sizeof (tmpspi));
     u16 tmpport = clib_host_to_net_u16 (500);
-    clib_memcpy (&nat_detection_source[8 + 8 + 4], &tmpport,
-                sizeof (tmpport));
+    clib_memcpy_fast (&nat_detection_source[8 + 8 + 4], &tmpport,
+                     sizeof (tmpport));
     u32 tmpip = clib_host_to_net_u32 (if_ip->as_u32);
-    clib_memcpy (&nat_detection_source[8 + 8], &tmpip, sizeof (tmpip));
+    clib_memcpy_fast (&nat_detection_source[8 + 8], &tmpip, sizeof (tmpip));
     SHA1 (nat_detection_source, sizeof (nat_detection_source),
          nat_detection_sha1);
     ikev2_payload_add_notify (chain, IKEV2_NOTIFY_MSG_NAT_DETECTION_SOURCE_IP,
                              nat_detection_sha1);
     tmpip = clib_host_to_net_u32 (p->responder.ip4.as_u32);
-    clib_memcpy (&nat_detection_source[8 + 8], &tmpip, sizeof (tmpip));
+    clib_memcpy_fast (&nat_detection_source[8 + 8], &tmpip, sizeof (tmpip));
     SHA1 (nat_detection_source, sizeof (nat_detection_source),
          nat_detection_sha1);
     ikev2_payload_add_notify (chain,
@@ -2979,18 +3016,18 @@ ikev2_initiate_sa_init (vlib_main_t * vm, u8 * name)
 
     u8 *sig_hash_algo = vec_new (u8, 8);
     u64 tmpsig = clib_host_to_net_u64 (0x0001000200030004);
-    clib_memcpy (sig_hash_algo, &tmpsig, sizeof (tmpsig));
+    clib_memcpy_fast (sig_hash_algo, &tmpsig, sizeof (tmpsig));
     ikev2_payload_add_notify (chain,
                              IKEV2_NOTIFY_MSG_SIGNATURE_HASH_ALGORITHMS,
                              sig_hash_algo);
     vec_free (sig_hash_algo);
 
 
-    /* Buffer update and bolierplate */
+    /* Buffer update and boilerplate */
     len += vec_len (chain->data);
     ike0->nextpayload = chain->first_payload_type;
     ike0->length = clib_host_to_net_u32 (len);
-    clib_memcpy (ike0->payload, chain->data, vec_len (chain->data));
+    clib_memcpy_fast (ike0->payload, chain->data, vec_len (chain->data));
     ikev2_payload_destroy_chain (chain);
 
     ike0->version = IKE_VERSION_2;
@@ -3010,14 +3047,19 @@ ikev2_initiate_sa_init (vlib_main_t * vm, u8 * name)
     sa.i_auth.method = p->auth.method;
     sa.i_auth.hex = p->auth.hex;
     sa.i_auth.data = vec_dup (p->auth.data);
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+    clib_memcpy_fast (sa.i_auth.key, p->auth.key,
+                     EVP_PKEY_size (p->auth.key));
+#else
     sa.i_auth.key = vec_dup (p->auth.key);
+#endif
     vec_add (sa.childs[0].tsi, &p->loc_ts, 1);
     vec_add (sa.childs[0].tsr, &p->rem_ts, 1);
 
     /* add SA to the pool */
     ikev2_sa_t *sa0 = 0;
     pool_get (km->sais, sa0);
-    clib_memcpy (sa0, &sa, sizeof (*sa0));
+    clib_memcpy_fast (sa0, &sa, sizeof (*sa0));
     hash_set (km->sa_by_ispi, sa0->ispi, sa0 - km->sais);
 
     ikev2_send_ike (vm, if_ip, &p->responder.ip4, bi0, len);
@@ -3255,7 +3297,7 @@ ikev2_init (vlib_main_t * vm)
   vlib_thread_main_t *tm = vlib_get_thread_main ();
   int thread_id;
 
-  memset (km, 0, sizeof (ikev2_main_t));
+  clib_memset (km, 0, sizeof (ikev2_main_t));
   km->vnet_main = vnet_get_main ();
   km->vlib_main = vm;
 
@@ -3305,7 +3347,7 @@ ikev2_mngr_process_child_sa (ikev2_sa_t * sa, ikev2_child_sa_t * csa)
          else if (csa->rekey_retries > 0)
            {
              csa->rekey_retries--;
-             clib_warning ("Rekeing Child SA 0x%x, retries left %d",
+             clib_warning ("Rekeying Child SA 0x%x, retries left %d",
                            csa->i_proposals->spi, csa->rekey_retries);
              if (csa->rekey_retries == 0)
                {
@@ -3334,6 +3376,7 @@ ikev2_mngr_process_ipsec_sa (ipsec_sa_t * ipsec_sa)
   ikev2_sa_t *fsa = 0;
   ikev2_child_sa_t *fchild = 0;
   f64 now = vlib_time_now (vm);
+  vlib_counter_t counts;
 
   /* Search for the SA and child SA */
   vec_foreach (tkm, km->per_thread_data)
@@ -3352,11 +3395,13 @@ ikev2_mngr_process_ipsec_sa (ipsec_sa_t * ipsec_sa)
     }));
     /* *INDENT-ON* */
   }
+  vlib_get_combined_counter (&ipsec_sa_counters,
+                            ipsec_sa->stat_index, &counts);
 
   if (fchild && fsa && fsa->profile && fsa->profile->lifetime_maxdata)
     {
       if (!fchild->is_expired
-         && ipsec_sa->total_data_size > fsa->profile->lifetime_maxdata)
+         && counts.bytes > fsa->profile->lifetime_maxdata)
        {
          fchild->time_to_expiration = now;
        }