+ p->ipsec_over_udp_port = IPSEC_UDP_PORT_NONE;
+}
+
+static void
+ikev2_initiate_delete_ike_sa_internal (vlib_main_t * vm,
+ ikev2_main_per_thread_data_t * tkm,
+ ikev2_sa_t * sa)
+{
+ ikev2_main_t *km = &ikev2_main;
+ ip_address_t *src, *dst;
+ vlib_buffer_t *b0;
+
+ /* Create the Initiator notification for IKE SA removal */
+ ike_header_t *ike0;
+ u32 bi0 = 0;
+ int len;
+
+ bi0 = ikev2_get_new_ike_header_buff (vm, &b0);
+ if (!bi0)
+ {
+ ikev2_log_error ("buffer alloc failure");
+ return;
+ }
+
+ ike0 = vlib_buffer_get_current (b0);
+ ike0->exchange = IKEV2_EXCHANGE_INFORMATIONAL;
+ ike0->ispi = clib_host_to_net_u64 (sa->ispi);
+ ike0->rspi = clib_host_to_net_u64 (sa->rspi);
+ vec_resize (sa->del, 1);
+ sa->del->protocol_id = IKEV2_PROTOCOL_IKE;
+ sa->del->spi = sa->ispi;
+ ike0->msgid = clib_host_to_net_u32 (sa->last_init_msg_id + 1);
+ sa->last_init_msg_id = clib_net_to_host_u32 (ike0->msgid);
+ len = ikev2_generate_message (b0, sa, ike0, 0, 0);
+ if (~0 == len)
+ return;
+
+ if (sa->is_initiator)
+ {
+ src = &sa->iaddr;
+ dst = &sa->raddr;
+ }
+ else
+ {
+ dst = &sa->iaddr;
+ src = &sa->raddr;
+ }
+
+ ikev2_send_ike (vm, src, dst, bi0, len,
+ ikev2_get_port (sa), sa->dst_port, 0);
+
+ /* delete local SA */
+ ikev2_child_sa_t *c;
+ vec_foreach (c, sa->childs)
+ ikev2_delete_tunnel_interface (km->vnet_main, sa, c);
+
+ u64 rspi = sa->rspi;
+ ikev2_sa_free_all_vec (sa);
+ uword *p = hash_get (tkm->sa_by_rspi, rspi);
+ if (p)
+ {
+ hash_unset (tkm->sa_by_rspi, rspi);
+ pool_put (tkm->sas, sa);
+ }
+}
+
+static void
+ikev2_cleanup_profile_sessions (ikev2_main_t * km, ikev2_profile_t * p)
+{
+ ikev2_main_per_thread_data_t *tkm;
+ ikev2_sa_t *sa;
+ u32 pi = p - km->profiles;
+ u32 *sai;
+ u32 *del_sai = 0;
+
+ /* *INDENT-OFF* */
+ pool_foreach(sa, km->sais, ({
+ if (pi == sa->profile_index)
+ vec_add1 (del_sai, sa - km->sais);
+ }));
+ /* *INDENT-ON* */
+
+ vec_foreach (sai, del_sai)
+ {
+ sa = pool_elt_at_index (km->sais, sai[0]);
+ ikev2_sa_free_all_vec (sa);
+ hash_unset (km->sa_by_ispi, sa->ispi);
+ pool_put (km->sais, sa);
+ }
+ vec_reset_length (del_sai);
+
+ vec_foreach (tkm, km->per_thread_data)
+ {
+ /* *INDENT-OFF* */
+ pool_foreach (sa, tkm->sas, ({
+ if (sa->profile_index != ~0 && pi == sa->profile_index)
+ vec_add1 (del_sai, sa - tkm->sas);
+ }));
+ /* *INDENT-ON* */
+
+ vec_foreach (sai, del_sai)
+ {
+ sa = pool_elt_at_index (tkm->sas, sai[0]);
+ ikev2_initiate_delete_ike_sa_internal (km->vlib_main, tkm, sa);
+ }
+
+ vec_reset_length (del_sai);
+ }
+
+ vec_free (del_sai);
+}
+
+static void
+ikev2_profile_free (ikev2_profile_t * p)
+{
+ vec_free (p->name);
+
+ vec_free (p->auth.data);
+ if (p->auth.key)
+ EVP_PKEY_free (p->auth.key);
+
+ vec_free (p->loc_id.data);
+ vec_free (p->rem_id.data);