IPSEC: API modernisation

- use enums to enumerate the algoritms and protocols that are supported
- use address_t types to simplify encode/deocde
- use typedefs of entry objects to get consistency between add/del API and dump

Change-Id: I7e7c58c06a150e2439633ba9dca58bc1049677ee
Signed-off-by: Neale Ranns <nranns@cisco.com>
diff --git a/src/vat/api_format.c b/src/vat/api_format.c
index 85bf9d0..3755354 100644
--- a/src/vat/api_format.c
+++ b/src/vat/api_format.c
@@ -361,20 +361,6 @@
   return 1;
 }
 
-uword
-unformat_ipsec_crypto_alg (unformat_input_t * input, va_list * args)
-{
-  u32 *r = va_arg (*args, u32 *);
-
-  if (0);
-#define _(v,f,s) else if (unformat (input, s)) *r = IPSEC_CRYPTO_ALG_##f;
-  foreach_ipsec_crypto_alg
-#undef _
-    else
-    return 0;
-  return 1;
-}
-
 u8 *
 format_ipsec_crypto_alg (u8 * s, va_list * args)
 {
@@ -392,20 +378,6 @@
   return format (s, "%s", t);
 }
 
-uword
-unformat_ipsec_integ_alg (unformat_input_t * input, va_list * args)
-{
-  u32 *r = va_arg (*args, u32 *);
-
-  if (0);
-#define _(v,f,s) else if (unformat (input, s)) *r = IPSEC_INTEG_ALG_##f;
-  foreach_ipsec_integ_alg
-#undef _
-    else
-    return 0;
-  return 1;
-}
-
 u8 *
 format_ipsec_integ_alg (u8 * s, va_list * args)
 {
@@ -473,6 +445,34 @@
 
 #endif /* VPP_API_TEST_BUILTIN */
 
+uword
+unformat_ipsec_api_crypto_alg (unformat_input_t * input, va_list * args)
+{
+  u32 *r = va_arg (*args, u32 *);
+
+  if (0);
+#define _(v,f,s) else if (unformat (input, s)) *r = IPSEC_API_CRYPTO_ALG_##f;
+  foreach_ipsec_crypto_alg
+#undef _
+    else
+    return 0;
+  return 1;
+}
+
+uword
+unformat_ipsec_api_integ_alg (unformat_input_t * input, va_list * args)
+{
+  u32 *r = va_arg (*args, u32 *);
+
+  if (0);
+#define _(v,f,s) else if (unformat (input, s)) *r = IPSEC_API_INTEG_ALG_##f;
+  foreach_ipsec_integ_alg
+#undef _
+    else
+    return 0;
+  return 1;
+}
+
 static uword
 unformat_policer_rate_type (unformat_input_t * input, va_list * args)
 {
@@ -5208,8 +5208,8 @@
 _(input_acl_set_interface_reply)                        \
 _(ipsec_spd_add_del_reply)                              \
 _(ipsec_interface_add_del_spd_reply)                    \
-_(ipsec_spd_add_del_entry_reply)                        \
-_(ipsec_sad_add_del_entry_reply)                        \
+_(ipsec_spd_entry_add_del_reply)                        \
+_(ipsec_sad_entry_add_del_reply)                        \
 _(ipsec_sa_set_key_reply)                               \
 _(ipsec_tunnel_if_add_del_reply)                        \
 _(ipsec_tunnel_if_set_key_reply)                        \
@@ -5463,8 +5463,8 @@
 _(IP_DETAILS, ip_details)                                               \
 _(IPSEC_SPD_ADD_DEL_REPLY, ipsec_spd_add_del_reply)                     \
 _(IPSEC_INTERFACE_ADD_DEL_SPD_REPLY, ipsec_interface_add_del_spd_reply) \
-_(IPSEC_SPD_ADD_DEL_ENTRY_REPLY, ipsec_spd_add_del_entry_reply)         \
-_(IPSEC_SAD_ADD_DEL_ENTRY_REPLY, ipsec_sad_add_del_entry_reply)         \
+_(IPSEC_SPD_ENTRY_ADD_DEL_REPLY, ipsec_spd_entry_add_del_reply)         \
+_(IPSEC_SAD_ENTRY_ADD_DEL_REPLY, ipsec_sad_entry_add_del_reply)         \
 _(IPSEC_SA_DETAILS, ipsec_sa_details)                                   \
 _(IPSEC_SA_SET_KEY_REPLY, ipsec_sa_set_key_reply)                       \
 _(IPSEC_TUNNEL_IF_ADD_DEL_REPLY, ipsec_tunnel_if_add_del_reply)         \
@@ -14829,26 +14829,24 @@
 }
 
 static int
-api_ipsec_spd_add_del_entry (vat_main_t * vam)
+api_ipsec_spd_entry_add_del (vat_main_t * vam)
 {
   unformat_input_t *i = vam->input;
-  vl_api_ipsec_spd_add_del_entry_t *mp;
+  vl_api_ipsec_spd_entry_add_del_t *mp;
   u8 is_add = 1, is_outbound = 0, is_ipv6 = 0, is_ip_any = 1;
   u32 spd_id = 0, sa_id = 0, protocol = 0, policy = 0;
   i32 priority = 0;
   u32 rport_start = 0, rport_stop = (u32) ~ 0;
   u32 lport_start = 0, lport_stop = (u32) ~ 0;
-  ip4_address_t laddr4_start, laddr4_stop, raddr4_start, raddr4_stop;
-  ip6_address_t laddr6_start, laddr6_stop, raddr6_start, raddr6_stop;
+  vl_api_address_t laddr_start = { }, laddr_stop =
+  {
+  }, raddr_start =
+  {
+  }, raddr_stop =
+  {
+  };
   int ret;
 
-  laddr4_start.as_u32 = raddr4_start.as_u32 = 0;
-  laddr4_stop.as_u32 = raddr4_stop.as_u32 = (u32) ~ 0;
-  laddr6_start.as_u64[0] = raddr6_start.as_u64[0] = 0;
-  laddr6_start.as_u64[1] = raddr6_start.as_u64[1] = 0;
-  laddr6_stop.as_u64[0] = raddr6_stop.as_u64[0] = (u64) ~ 0;
-  laddr6_stop.as_u64[1] = raddr6_stop.as_u64[1] = (u64) ~ 0;
-
   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
     {
       if (unformat (i, "del"))
@@ -14873,58 +14871,18 @@
 	;
       else if (unformat (i, "rport_stop %d", &rport_stop))
 	;
-      else
-	if (unformat
-	    (i, "laddr_start %U", unformat_ip4_address, &laddr4_start))
-	{
-	  is_ipv6 = 0;
-	  is_ip_any = 0;
-	}
-      else
-	if (unformat (i, "laddr_stop %U", unformat_ip4_address, &laddr4_stop))
-	{
-	  is_ipv6 = 0;
-	  is_ip_any = 0;
-	}
-      else
-	if (unformat
-	    (i, "raddr_start %U", unformat_ip4_address, &raddr4_start))
-	{
-	  is_ipv6 = 0;
-	  is_ip_any = 0;
-	}
-      else
-	if (unformat (i, "raddr_stop %U", unformat_ip4_address, &raddr4_stop))
-	{
-	  is_ipv6 = 0;
-	  is_ip_any = 0;
-	}
-      else
-	if (unformat
-	    (i, "laddr_start %U", unformat_ip6_address, &laddr6_start))
-	{
-	  is_ipv6 = 1;
-	  is_ip_any = 0;
-	}
-      else
-	if (unformat (i, "laddr_stop %U", unformat_ip6_address, &laddr6_stop))
-	{
-	  is_ipv6 = 1;
-	  is_ip_any = 0;
-	}
-      else
-	if (unformat
-	    (i, "raddr_start %U", unformat_ip6_address, &raddr6_start))
-	{
-	  is_ipv6 = 1;
-	  is_ip_any = 0;
-	}
-      else
-	if (unformat (i, "raddr_stop %U", unformat_ip6_address, &raddr6_stop))
-	{
-	  is_ipv6 = 1;
-	  is_ip_any = 0;
-	}
+      else if (unformat (i, "laddr_start %U",
+			 unformat_vl_api_address, &laddr_start))
+	is_ip_any = 0;
+      else if (unformat (i, "laddr_stop %U", unformat_vl_api_address,
+			 &laddr_stop))
+	is_ip_any = 0;
+      else if (unformat (i, "raddr_start %U", unformat_vl_api_address,
+			 &raddr_start))
+	is_ip_any = 0;
+      else if (unformat (i, "raddr_stop %U", unformat_vl_api_address,
+			 &raddr_stop))
+	is_ip_any = 0;
       else
 	if (unformat (i, "action %U", unformat_ipsec_policy_action, &policy))
 	{
@@ -14942,65 +14900,51 @@
 
     }
 
-  M (IPSEC_SPD_ADD_DEL_ENTRY, mp);
+  M (IPSEC_SPD_ENTRY_ADD_DEL, mp);
 
-  mp->spd_id = ntohl (spd_id);
-  mp->priority = ntohl (priority);
-  mp->is_outbound = is_outbound;
-
-  mp->is_ipv6 = is_ipv6;
-  if (is_ipv6 || is_ip_any)
-    {
-      clib_memcpy (mp->remote_address_start, &raddr6_start,
-		   sizeof (ip6_address_t));
-      clib_memcpy (mp->remote_address_stop, &raddr6_stop,
-		   sizeof (ip6_address_t));
-      clib_memcpy (mp->local_address_start, &laddr6_start,
-		   sizeof (ip6_address_t));
-      clib_memcpy (mp->local_address_stop, &laddr6_stop,
-		   sizeof (ip6_address_t));
-    }
-  else
-    {
-      clib_memcpy (mp->remote_address_start, &raddr4_start,
-		   sizeof (ip4_address_t));
-      clib_memcpy (mp->remote_address_stop, &raddr4_stop,
-		   sizeof (ip4_address_t));
-      clib_memcpy (mp->local_address_start, &laddr4_start,
-		   sizeof (ip4_address_t));
-      clib_memcpy (mp->local_address_stop, &laddr4_stop,
-		   sizeof (ip4_address_t));
-    }
-  mp->protocol = (u8) protocol;
-  mp->local_port_start = ntohs ((u16) lport_start);
-  mp->local_port_stop = ntohs ((u16) lport_stop);
-  mp->remote_port_start = ntohs ((u16) rport_start);
-  mp->remote_port_stop = ntohs ((u16) rport_stop);
-  mp->policy = (u8) policy;
-  mp->sa_id = ntohl (sa_id);
   mp->is_add = is_add;
-  mp->is_ip_any = is_ip_any;
+
+  mp->entry.spd_id = ntohl (spd_id);
+  mp->entry.priority = ntohl (priority);
+  mp->entry.is_outbound = is_outbound;
+
+  clib_memcpy (&mp->entry.remote_address_start, &raddr_start,
+	       sizeof (vl_api_address_t));
+  clib_memcpy (&mp->entry.remote_address_stop, &raddr_stop,
+	       sizeof (vl_api_address_t));
+  clib_memcpy (&mp->entry.local_address_start, &laddr_start,
+	       sizeof (vl_api_address_t));
+  clib_memcpy (&mp->entry.local_address_stop, &laddr_stop,
+	       sizeof (vl_api_address_t));
+
+  mp->entry.protocol = (u8) protocol;
+  mp->entry.local_port_start = ntohs ((u16) lport_start);
+  mp->entry.local_port_stop = ntohs ((u16) lport_stop);
+  mp->entry.remote_port_start = ntohs ((u16) rport_start);
+  mp->entry.remote_port_stop = ntohs ((u16) rport_stop);
+  mp->entry.policy = (u8) policy;
+  mp->entry.sa_id = ntohl (sa_id);
+  mp->entry.is_ip_any = is_ip_any;
+
   S (mp);
   W (ret);
   return ret;
 }
 
 static int
-api_ipsec_sad_add_del_entry (vat_main_t * vam)
+api_ipsec_sad_entry_add_del (vat_main_t * vam)
 {
   unformat_input_t *i = vam->input;
-  vl_api_ipsec_sad_add_del_entry_t *mp;
+  vl_api_ipsec_sad_entry_add_del_t *mp;
   u32 sad_id = 0, spi = 0;
   u8 *ck = 0, *ik = 0;
   u8 is_add = 1;
 
-  u8 protocol = IPSEC_PROTOCOL_AH;
-  u8 is_tunnel = 0, is_tunnel_ipv6 = 0;
-  u32 crypto_alg = 0, integ_alg = 0;
-  ip4_address_t tun_src4;
-  ip4_address_t tun_dst4;
-  ip6_address_t tun_src6;
-  ip6_address_t tun_dst6;
+  vl_api_ipsec_crypto_alg_t crypto_alg = IPSEC_API_CRYPTO_ALG_NONE;
+  vl_api_ipsec_integ_alg_t integ_alg = IPSEC_API_INTEG_ALG_NONE;
+  vl_api_ipsec_sad_flags_t flags = IPSEC_API_SAD_FLAG_NONE;
+  vl_api_ipsec_proto_t protocol = IPSEC_API_PROTO_AH;
+  vl_api_address_t tun_src, tun_dst;
   int ret;
 
   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
@@ -15012,51 +14956,30 @@
       else if (unformat (i, "spi %d", &spi))
 	;
       else if (unformat (i, "esp"))
-	protocol = IPSEC_PROTOCOL_ESP;
-      else if (unformat (i, "tunnel_src %U", unformat_ip4_address, &tun_src4))
+	protocol = IPSEC_API_PROTO_ESP;
+      else
+	if (unformat (i, "tunnel_src %U", unformat_vl_api_address, &tun_src))
 	{
-	  is_tunnel = 1;
-	  is_tunnel_ipv6 = 0;
-	}
-      else if (unformat (i, "tunnel_dst %U", unformat_ip4_address, &tun_dst4))
-	{
-	  is_tunnel = 1;
-	  is_tunnel_ipv6 = 0;
-	}
-      else if (unformat (i, "tunnel_src %U", unformat_ip6_address, &tun_src6))
-	{
-	  is_tunnel = 1;
-	  is_tunnel_ipv6 = 1;
-	}
-      else if (unformat (i, "tunnel_dst %U", unformat_ip6_address, &tun_dst6))
-	{
-	  is_tunnel = 1;
-	  is_tunnel_ipv6 = 1;
+	  flags |= IPSEC_API_SAD_FLAG_IS_TUNNEL;
+	  if (ADDRESS_IP6 == tun_src.af)
+	    flags |= IPSEC_API_SAD_FLAG_IS_TUNNEL_V6;
 	}
       else
-	if (unformat
-	    (i, "crypto_alg %U", unformat_ipsec_crypto_alg, &crypto_alg))
+	if (unformat (i, "tunnel_dst %U", unformat_vl_api_address, &tun_dst))
 	{
-	  if (crypto_alg >= IPSEC_CRYPTO_N_ALG)
-	    {
-	      clib_warning ("unsupported crypto-alg: '%U'",
-			    format_ipsec_crypto_alg, crypto_alg);
-	      return -99;
-	    }
+	  flags |= IPSEC_API_SAD_FLAG_IS_TUNNEL;
+	  if (ADDRESS_IP6 == tun_src.af)
+	    flags |= IPSEC_API_SAD_FLAG_IS_TUNNEL_V6;
 	}
+      else
+	if (unformat (i, "crypto_alg %U",
+		      unformat_ipsec_api_crypto_alg, &crypto_alg))
+	;
       else if (unformat (i, "crypto_key %U", unformat_hex_string, &ck))
 	;
-      else
-	if (unformat
-	    (i, "integ_alg %U", unformat_ipsec_integ_alg, &integ_alg))
-	{
-	  if (integ_alg >= IPSEC_INTEG_N_ALG)
-	    {
-	      clib_warning ("unsupported integ-alg: '%U'",
-			    format_ipsec_integ_alg, integ_alg);
-	      return -99;
-	    }
-	}
+      else if (unformat (i, "integ_alg %U",
+			 unformat_ipsec_api_integ_alg, &integ_alg))
+	;
       else if (unformat (i, "integ_key %U", unformat_hex_string, &ik))
 	;
       else
@@ -15067,46 +14990,37 @@
 
     }
 
-  M (IPSEC_SAD_ADD_DEL_ENTRY, mp);
+  M (IPSEC_SAD_ENTRY_ADD_DEL, mp);
 
-  mp->sad_id = ntohl (sad_id);
   mp->is_add = is_add;
-  mp->protocol = protocol;
-  mp->spi = ntohl (spi);
-  mp->is_tunnel = is_tunnel;
-  mp->is_tunnel_ipv6 = is_tunnel_ipv6;
-  mp->crypto_algorithm = crypto_alg;
-  mp->integrity_algorithm = integ_alg;
-  mp->crypto_key_length = vec_len (ck);
-  mp->integrity_key_length = vec_len (ik);
+  mp->entry.sad_id = ntohl (sad_id);
+  mp->entry.protocol = protocol;
+  mp->entry.spi = ntohl (spi);
+  mp->entry.flags = flags;
 
-  if (mp->crypto_key_length > sizeof (mp->crypto_key))
-    mp->crypto_key_length = sizeof (mp->crypto_key);
+  mp->entry.crypto_algorithm = crypto_alg;
+  mp->entry.integrity_algorithm = integ_alg;
+  mp->entry.crypto_key.length = vec_len (ck);
+  mp->entry.integrity_key.length = vec_len (ik);
 
-  if (mp->integrity_key_length > sizeof (mp->integrity_key))
-    mp->integrity_key_length = sizeof (mp->integrity_key);
+  if (mp->entry.crypto_key.length > sizeof (mp->entry.crypto_key.data))
+    mp->entry.crypto_key.length = sizeof (mp->entry.crypto_key.data);
+
+  if (mp->entry.integrity_key.length > sizeof (mp->entry.integrity_key.data))
+    mp->entry.integrity_key.length = sizeof (mp->entry.integrity_key.data);
 
   if (ck)
-    clib_memcpy (mp->crypto_key, ck, mp->crypto_key_length);
+    clib_memcpy (mp->entry.crypto_key.data, ck, mp->entry.crypto_key.length);
   if (ik)
-    clib_memcpy (mp->integrity_key, ik, mp->integrity_key_length);
+    clib_memcpy (mp->entry.integrity_key.data, ik,
+		 mp->entry.integrity_key.length);
 
-  if (is_tunnel)
+  if (flags & IPSEC_API_SAD_FLAG_IS_TUNNEL)
     {
-      if (is_tunnel_ipv6)
-	{
-	  clib_memcpy (mp->tunnel_src_address, &tun_src6,
-		       sizeof (ip6_address_t));
-	  clib_memcpy (mp->tunnel_dst_address, &tun_dst6,
-		       sizeof (ip6_address_t));
-	}
-      else
-	{
-	  clib_memcpy (mp->tunnel_src_address, &tun_src4,
-		       sizeof (ip4_address_t));
-	  clib_memcpy (mp->tunnel_dst_address, &tun_dst4,
-		       sizeof (ip4_address_t));
-	}
+      clib_memcpy (&mp->entry.tunnel_src, &tun_src,
+		   sizeof (mp->entry.tunnel_src));
+      clib_memcpy (&mp->entry.tunnel_dst, &tun_dst,
+		   sizeof (mp->entry.tunnel_dst));
     }
 
   S (mp);
@@ -15141,19 +15055,19 @@
   M (IPSEC_SA_SET_KEY, mp);
 
   mp->sa_id = ntohl (sa_id);
-  mp->crypto_key_length = vec_len (ck);
-  mp->integrity_key_length = vec_len (ik);
+  mp->crypto_key.length = vec_len (ck);
+  mp->integrity_key.length = vec_len (ik);
 
-  if (mp->crypto_key_length > sizeof (mp->crypto_key))
-    mp->crypto_key_length = sizeof (mp->crypto_key);
+  if (mp->crypto_key.length > sizeof (mp->crypto_key.data))
+    mp->crypto_key.length = sizeof (mp->crypto_key.data);
 
-  if (mp->integrity_key_length > sizeof (mp->integrity_key))
-    mp->integrity_key_length = sizeof (mp->integrity_key);
+  if (mp->integrity_key.length > sizeof (mp->integrity_key.data))
+    mp->integrity_key.length = sizeof (mp->integrity_key.data);
 
   if (ck)
-    clib_memcpy (mp->crypto_key, ck, mp->crypto_key_length);
+    clib_memcpy (mp->crypto_key.data, ck, mp->crypto_key.length);
   if (ik)
-    clib_memcpy (mp->integrity_key, ik, mp->integrity_key_length);
+    clib_memcpy (mp->integrity_key.data, ik, mp->integrity_key.length);
 
   S (mp);
   W (ret);
@@ -15205,7 +15119,7 @@
 	;
       else
 	if (unformat
-	    (i, "crypto_alg %U", unformat_ipsec_crypto_alg, &crypto_alg))
+	    (i, "crypto_alg %U", unformat_ipsec_api_crypto_alg, &crypto_alg))
 	{
 	  if (crypto_alg >= IPSEC_CRYPTO_N_ALG)
 	    {
@@ -15216,7 +15130,7 @@
 	}
       else
 	if (unformat
-	    (i, "integ_alg %U", unformat_ipsec_integ_alg, &integ_alg))
+	    (i, "integ_alg %U", unformat_ipsec_api_integ_alg, &integ_alg))
 	{
 	  if (integ_alg >= IPSEC_INTEG_N_ALG)
 	    {
@@ -15427,15 +15341,20 @@
       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
 	;
       else
-	if (unformat (i, "local crypto %U", unformat_ipsec_crypto_alg, &alg))
+	if (unformat
+	    (i, "local crypto %U", unformat_ipsec_api_crypto_alg, &alg))
 	key_type = IPSEC_IF_SET_KEY_TYPE_LOCAL_CRYPTO;
       else
-	if (unformat (i, "remote crypto %U", unformat_ipsec_crypto_alg, &alg))
+	if (unformat
+	    (i, "remote crypto %U", unformat_ipsec_api_crypto_alg, &alg))
 	key_type = IPSEC_IF_SET_KEY_TYPE_REMOTE_CRYPTO;
-      else if (unformat (i, "local integ %U", unformat_ipsec_integ_alg, &alg))
+      else
+	if (unformat
+	    (i, "local integ %U", unformat_ipsec_api_integ_alg, &alg))
 	key_type = IPSEC_IF_SET_KEY_TYPE_LOCAL_INTEG;
       else
-	if (unformat (i, "remote integ %U", unformat_ipsec_integ_alg, &alg))
+	if (unformat
+	    (i, "remote integ %U", unformat_ipsec_api_integ_alg, &alg))
 	key_type = IPSEC_IF_SET_KEY_TYPE_REMOTE_INTEG;
       else if (unformat (i, "%U", unformat_hex_string, &key))
 	;
@@ -23239,10 +23158,10 @@
 _(ipsec_spd_add_del, "spd_id <n> [del]")                                \
 _(ipsec_interface_add_del_spd, "(<intfc> | sw_if_index <id>)\n"         \
   "  spid_id <n> ")                                                     \
-_(ipsec_sad_add_del_entry, "sad_id <n> spi <n> crypto_alg <alg>\n"      \
+_(ipsec_sad_entry_add_del, "sad_id <n> spi <n> crypto_alg <alg>\n"      \
   "  crypto_key <hex> tunnel_src <ip4|ip6> tunnel_dst <ip4|ip6>\n"      \
   "  integ_alg <alg> integ_key <hex>")                                  \
-_(ipsec_spd_add_del_entry, "spd_id <n> priority <n> action <action>\n"  \
+_(ipsec_spd_entry_add_del, "spd_id <n> priority <n> action <action>\n"  \
   "  (inbound|outbound) [sa_id <n>] laddr_start <ip4|ip6>\n"            \
   "  laddr_stop <ip4|ip6> raddr_start <ip4|ip6> raddr_stop <ip4|ip6>\n" \
   "  [lport_start <n> lport_stop <n>] [rport_start <n> rport_stop <n>]" ) \
diff --git a/src/vnet/ipsec/ipsec.api b/src/vnet/ipsec/ipsec.api
index 2b015f9..92c39ac 100644
--- a/src/vnet/ipsec/ipsec.api
+++ b/src/vnet/ipsec/ipsec.api
@@ -1,3 +1,4 @@
+/* Hey Emacs use -*- mode: C -*- */
 /*
  * Copyright (c) 2015-2016 Cisco and/or its affiliates.
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -13,7 +14,9 @@
  * limitations under the License.
  */
 
-option version = "2.1.0";
+option version = "3.0.0";
+
+import "vnet/ip/ip_types.api";
 
 /** \brief IPsec: Add/delete Security Policy Database
     @param client_index - opaque cookie to identify the sender
@@ -50,121 +53,236 @@
   u32 spd_id;
 };
 
-/** \brief IPsec: Add/delete Security Policy Database entry
+
+enum ipsec_spd_action
+{
+  /* bypass - no IPsec processing */
+  IPSEC_API_SPD_ACTION_BYPASS = 0,
+  /* discard - discard packet with ICMP processing */
+  IPSEC_API_SPD_ACTION_DISCARD,
+  /* resolve - send request to control plane for SA resolving */
+  IPSEC_API_SPD_ACTION_RESOLVE,
+  /* protect - apply IPsec policy using following parameters */
+  IPSEC_API_SPD_ACTION_PROTECT,
+};
+
+/** \brief IPsec: Security Policy Database entry
 
     See RFC 4301, 4.4.1.1 on how to match packet to selectors
 
-    @param client_index - opaque cookie to identify the sender
-    @param context - sender context, to match reply w/ request
-    @param is_add - add SPD if non-zero, else delete
     @param spd_id - SPD instance id (control plane allocated)
     @param priority - priority of SPD entry (non-unique value).  Used to order SPD matching - higher priorities match before lower
     @param is_outbound - entry applies to outbound traffic if non-zero, otherwise applies to inbound traffic
-    @param is_ipv6 - remote/local address are IPv6 if non-zero, else IPv4
     @param remote_address_start - start of remote address range to match
     @param remote_address_stop - end of remote address range to match
     @param local_address_start - start of local address range to match
     @param local_address_stop - end of local address range to match
-    @param protocol - protocol type to match [0 means any]
+    @param protocol - protocol type to match [0 means any] otherwise IANA value
     @param remote_port_start - start of remote port range to match ...
     @param remote_port_stop - end of remote port range to match [0 to 65535 means ANY, 65535 to 0 means OPAQUE]
     @param local_port_start - start of local port range to match ...
     @param local_port_stop - end of remote port range to match [0 to 65535 means ANY, 65535 to 0 means OPAQUE]
-    @param policy - 0 = bypass (no IPsec processing), 1 = discard (discard packet with ICMP processing), 2 = resolve (send request to control plane for SA resolving, and discard without ICMP processing), 3 = protect (apply IPsec policy using following parameters)
+    @param policy - action to perform on match
     @param sa_id - SAD instance id (control plane allocated)
-
 */
-
-autoreply define ipsec_spd_add_del_entry
+typedef ipsec_spd_entry
 {
-  u32 client_index;
-  u32 context;
-  u8 is_add;
-
   u32 spd_id;
   i32 priority;
   u8 is_outbound;
 
-  // Selector
-  u8 is_ipv6;
-  u8 is_ip_any;
-  u8 remote_address_start[16];
-  u8 remote_address_stop[16];
-  u8 local_address_start[16];
-  u8 local_address_stop[16];
-
+  u32 sa_id;
+  vl_api_ipsec_spd_action_t policy;
   u8 protocol;
 
+  // Selector
+  u8 is_ip_any;
+  vl_api_address_t remote_address_start;
+  vl_api_address_t remote_address_stop;
+  vl_api_address_t local_address_start;
+  vl_api_address_t local_address_stop;
+
   u16 remote_port_start;
   u16 remote_port_stop;
   u16 local_port_start;
   u16 local_port_stop;
+};
 
-  // Policy
-  u8 policy;
-  u32 sa_id;
+/** \brief IPsec: Add/delete Security Policy Database entry
+
+    @param client_index - opaque cookie to identify the sender
+    @param context - sender context, to match reply w/ request
+    @param is_add - add SPD if non-zero, else delete
+    @param entry - Description of the entry to add/dell
+*/
+autoreply define ipsec_spd_entry_add_del
+{
+  u32 client_index;
+  u32 context;
+  u8 is_add;
+  vl_api_ipsec_spd_entry_t entry;
+};
+
+/** \brief Dump IPsec all SPD IDs
+    @param client_index - opaque cookie to identify the sender
+    @param context - sender context, to match reply w/ request
+*/
+define ipsec_spds_dump {
+  u32 client_index;
+  u32 context;
+};
+
+/** \brief Dump IPsec all SPD IDs response
+    @param client_index - opaque cookie to identify the sender
+    @param spd_id - SPD instance id (control plane allocated)
+    @param npolicies - number of policies in SPD
+*/
+define ipsec_spds_details {
+  u32 context;
+  u32 spd_id;
+  u32 npolicies;
+}; 
+
+/** \brief Dump ipsec policy database data
+    @param client_index - opaque cookie to identify the sender
+    @param context - sender context, to match reply w/ request
+    @param spd_id - SPD instance id
+    @param sa_id - SA id, optional, set to ~0 to see all policies in SPD
+*/
+define ipsec_spd_dump {
+    u32 client_index;
+    u32 context;
+    u32 spd_id;
+    u32 sa_id;
+};
+
+/** \brief IPsec policy database response
+    @param context - sender context which was passed in the request
+    €param entry - The SPD entry.
+    @param bytes - byte count of packets matching this policy
+    @param packets - count of packets matching this policy
+*/
+define ipsec_spd_details {
+    u32 context;
+    vl_api_ipsec_spd_entry_t entry;
+    u64 bytes;
+    u64 packets;
+};
+
+/*
+ * @brief Support cryptographic algorithms
+ */
+enum ipsec_crypto_alg
+{
+  IPSEC_API_CRYPTO_ALG_NONE = 0,
+  IPSEC_API_CRYPTO_ALG_AES_CBC_128,
+  IPSEC_API_CRYPTO_ALG_AES_CBC_192,
+  IPSEC_API_CRYPTO_ALG_AES_CBC_256,
+  IPSEC_API_CRYPTO_ALG_AES_CTR_128,
+  IPSEC_API_CRYPTO_ALG_AES_CTR_192,
+  IPSEC_API_CRYPTO_ALG_AES_CTR_256,
+  IPSEC_API_CRYPTO_ALG_AES_GCM_128,
+  IPSEC_API_CRYPTO_ALG_AES_GCM_192,
+  IPSEC_API_CRYPTO_ALG_AES_GCM_256,
+  IPSEC_API_CRYPTO_ALG_DES_CBC,
+  IPSEC_API_CRYPTO_ALG_3DES_CBC,
+};
+
+/*
+ * @brief Supported Integrity Algorithms
+ */
+enum ipsec_integ_alg
+{
+  IPSEC_API_INTEG_ALG_NONE = 0,
+  /* RFC2403 */
+  IPSEC_API_INTEG_ALG_MD5_96,
+  /* RFC2404 */
+  IPSEC_API_INTEG_ALG_SHA1_96,
+  /* draft-ietf-ipsec-ciph-sha-256-00 */
+  IPSEC_API_INTEG_ALG_SHA_256_96,
+  /* RFC4868 */
+  IPSEC_API_INTEG_ALG_SHA_256_128,
+  /* RFC4868 */
+  IPSEC_API_INTEG_ALG_SHA_384_192,
+  /* RFC4868 */
+  IPSEC_API_INTEG_ALG_SHA_512_256,
+};
+
+enum ipsec_sad_flags
+{
+  IPSEC_API_SAD_FLAG_NONE = 0,
+  /* Enable extended sequence numbers */
+  IPSEC_API_SAD_FLAG_USE_EXTENDED_SEQ_NUM = 0x01,
+  /* Enable Anti-replay */
+  IPSEC_API_SAD_FLAG_USE_ANTI_REPLAY = 0x02,
+  /* IPsec tunnel mode if non-zero, else transport mode */
+  IPSEC_API_SAD_FLAG_IS_TUNNEL = 0x04,
+  /* IPsec tunnel mode is IPv6 if non-zero,
+   *  else IPv4 tunnel only valid if is_tunnel is non-zero */
+  IPSEC_API_SAD_FLAG_IS_TUNNEL_V6 = 0x08,
+  /* enable UDP encapsulation for NAT traversal */
+  IPSEC_API_SAD_FLAG_UDP_ENCAP = 0x10,
+};
+
+enum ipsec_proto
+{
+  IPSEC_API_PROTO_ESP,
+  IPSEC_API_PROTO_AH,
+};
+
+typedef key
+{
+  /* the length of the key */
+  u8 length;
+  /* The data for the key */
+  u8 data[128];
+};
+
+/** \brief IPsec: Security Association Database entry
+    @param client_index - opaque cookie to identify the sender
+    @param context - sender context, to match reply w/ request
+    @param is_add - add SAD entry if non-zero, else delete
+    @param sad_id - sad id
+    @param spi - security parameter index
+    @param protocol - 0 = AH, 1 = ESP
+    @param crypto_algorithm - a supported crypto algorithm
+    @param crypto_key - crypto keying material
+    @param integrity_algorithm - one of the supported algorithms
+    @param integrity_key - integrity keying material
+    @param tunnel_src_address - IPsec tunnel source address IPv6 if is_tunnel_ipv6 is non-zero, else IPv4. Only valid if is_tunnel is non-zero
+    @param tunnel_dst_address - IPsec tunnel destination address IPv6 if is_tunnel_ipv6 is non-zero, else IPv4. Only valid if is_tunnel is non-zero
+ */
+typedef ipsec_sad_entry
+{
+  u32 sad_id;
+
+  u32 spi;
+
+  vl_api_ipsec_proto_t protocol;
+
+  vl_api_ipsec_crypto_alg_t crypto_algorithm;
+  vl_api_key_t crypto_key;
+
+  vl_api_ipsec_integ_alg_t integrity_algorithm;
+  vl_api_key_t integrity_key;
+
+  vl_api_ipsec_sad_flags_t flags;
+
+  vl_api_address_t tunnel_src;
+  vl_api_address_t tunnel_dst;
 };
 
 /** \brief IPsec: Add/delete Security Association Database entry
     @param client_index - opaque cookie to identify the sender
     @param context - sender context, to match reply w/ request
-    @param is_add - add SAD entry if non-zero, else delete
-
-    @param sad_id - sad id
-
-    @param spi - security parameter index
-
-    @param protocol - 0 = AH, 1 = ESP
-
-    @param crypto_algorithm - 0 = Null, 1 = AES-CBC-128, 2 = AES-CBC-192, 3 = AES-CBC-256, 4 = 3DES-CBC
-    @param crypto_key_length - length of crypto_key in bytes
-    @param crypto_key - crypto keying material
-
-    @param integrity_algorithm - 0 = None, 1 = MD5-96, 2 = SHA1-96, 3 = SHA-256, 4 = SHA-384, 5=SHA-512
-    @param integrity_key_length - length of integrity_key in bytes
-    @param integrity_key - integrity keying material
-
-    @param use_extended_sequence_number - use ESN when non-zero
-
-    @param is_tunnel - IPsec tunnel mode if non-zero, else transport mode
-    @param is_tunnel_ipv6 - IPsec tunnel mode is IPv6 if non-zero, else IPv4 tunnel only valid if is_tunnel is non-zero
-    @param tunnel_src_address - IPsec tunnel source address IPv6 if is_tunnel_ipv6 is non-zero, else IPv4. Only valid if is_tunnel is non-zero
-    @param tunnel_dst_address - IPsec tunnel destination address IPv6 if is_tunnel_ipv6 is non-zero, else IPv4. Only valid if is_tunnel is non-zero
-    @param udp_encap - enable UDP encapsulation for NAT traversal
-
-    To be added:
-     Anti-replay
-     IPsec tunnel address copy mode (to support GDOI)
+    @param entry - Entry to add or delete
  */
-
-autoreply define ipsec_sad_add_del_entry
+autoreply define ipsec_sad_entry_add_del
 {
   u32 client_index;
   u32 context;
   u8 is_add;
-
-  u32 sad_id;
-
-  u32 spi;
-
-  u8 protocol;
-
-  u8 crypto_algorithm;
-  u8 crypto_key_length;
-  u8 crypto_key[128];
-
-  u8 integrity_algorithm;
-  u8 integrity_key_length;
-  u8 integrity_key[128];
-
-  u8 use_extended_sequence_number;
-  u8 use_anti_replay;
-
-  u8 is_tunnel;
-  u8 is_tunnel_ipv6;
-  u8 tunnel_src_address[16];
-  u8 tunnel_dst_address[16];
-  u8 udp_encap;
+  vl_api_ipsec_sad_entry_t entry;
 };
 
 /** \brief IPsec: Update Security Association keys
@@ -173,10 +291,7 @@
 
     @param sa_id - sa id
 
-    @param crypto_key_length - length of crypto_key in bytes
     @param crypto_key - crypto keying material
-
-    @param integrity_key_length - length of integrity_key in bytes
     @param integrity_key - integrity keying material
 */
 
@@ -187,11 +302,8 @@
 
   u32 sa_id;
 
-  u8 crypto_key_length;
-  u8 crypto_key[128];
-
-  u8 integrity_key_length;
-  u8 integrity_key[128];
+  vl_api_key_t crypto_key;
+  vl_api_key_t integrity_key;
 };
 
 /** \brief IKEv2: Add/delete profile
@@ -441,80 +553,6 @@
   u32 ispi;
 };
 
-/** \brief Dump IPsec all SPD IDs
-    @param client_index - opaque cookie to identify the sender
-    @param context - sender context, to match reply w/ request
-*/
-define ipsec_spds_dump {
-  u32 client_index;
-  u32 context;
-};
-
-/** \brief Dump IPsec all SPD IDs response
-    @param client_index - opaque cookie to identify the sender
-    @param spd_id - SPD instance id (control plane allocated)
-    @param npolicies - number of policies in SPD
-*/
-define ipsec_spds_details {
-  u32 context;
-  u32 spd_id;
-  u32 npolicies;
-}; 
-
-/** \brief Dump ipsec policy database data
-    @param client_index - opaque cookie to identify the sender
-    @param context - sender context, to match reply w/ request
-    @param spd_id - SPD instance id
-    @param sa_id - SA id, optional, set to ~0 to see all policies in SPD
-*/
-define ipsec_spd_dump {
-    u32 client_index;
-    u32 context;
-    u32 spd_id;
-    u32 sa_id;
-};
-
-/** \brief IPsec policy database response
-    @param context - sender context which was passed in the request
-    @param spd_id - SPD instance id
-    @param priority - numeric value to control policy evaluation order
-    @param is_outbound - [1|0] to indicate if direction is [out|in]bound
-    @param is_ipv6 - [1|0] to indicate if address family is ipv[6|4]
-    @param local_start_addr - first address in local traffic selector range
-    @param local_stop_addr - last address in local traffic selector range
-    @param local_start_port - first port in local traffic selector range
-    @param local_stop_port - last port in local traffic selector range
-    @param remote_start_addr - first address in remote traffic selector range
-    @param remote_stop_addr - last address in remote traffic selector range
-    @param remote_start_port - first port in remote traffic selector range
-    @param remote_stop_port - last port in remote traffic selector range
-    @param protocol - traffic selector protocol
-    @param policy - policy action
-    @param sa_id - SA id
-    @param bytes - byte count of packets matching this policy
-    @param packets - count of packets matching this policy
-*/
-define ipsec_spd_details {
-    u32 context;
-    u32 spd_id;
-    i32 priority;
-    u8 is_outbound;
-    u8 is_ipv6;
-    u8 local_start_addr[16];
-    u8 local_stop_addr[16];
-    u16 local_start_port;
-    u16 local_stop_port;
-    u8 remote_start_addr[16];
-    u8 remote_stop_addr[16];
-    u16 remote_start_port;
-    u16 remote_stop_port;
-    u8 protocol;
-    u8 policy;
-    u32 sa_id;
-    u64 bytes;
-    u64 packets;
-};
-
 /** \brief IPsec: Get SPD interfaces
     @param client_index - opaque cookie to identify the sender
     @param context - sender context, to match reply w/ request
@@ -728,7 +766,7 @@
 define ipsec_backend_details {
   u32 context;
   u8 name[128];
-  u8 protocol;
+  vl_api_ipsec_proto_t protocol;
   u8 index;
   u8 active;
 };
@@ -742,7 +780,7 @@
 autoreply define ipsec_select_backend {
   u32 client_index;
   u32 context;
-  u8 protocol;
+  vl_api_ipsec_proto_t protocol;
   u8 index;
 };
 
diff --git a/src/vnet/ipsec/ipsec.h b/src/vnet/ipsec/ipsec.h
index 691bc07..93369fe 100644
--- a/src/vnet/ipsec/ipsec.h
+++ b/src/vnet/ipsec/ipsec.h
@@ -68,9 +68,11 @@
 #define _(v, f, s) IPSEC_POLICY_ACTION_##f = v,
   foreach_ipsec_policy_action
 #undef _
-    IPSEC_POLICY_N_ACTION,
 } ipsec_policy_action_t;
 
+#define IPSEC_POLICY_N_ACTION (IPSEC_POLICY_ACTION_PROTECT + 1)
+
+
 #define foreach_ipsec_crypto_alg    \
   _ (0, NONE, "none")               \
   _ (1, AES_CBC_128, "aes-cbc-128") \
@@ -220,7 +222,7 @@
   port_range_t rport;
 
   // Policy
-  u8 policy;
+  ipsec_policy_action_t policy;
   u32 sa_id;
   u32 sa_index;
 
diff --git a/src/vnet/ipsec/ipsec_api.c b/src/vnet/ipsec/ipsec_api.c
index fc09f77..eb78dbd 100644
--- a/src/vnet/ipsec/ipsec_api.c
+++ b/src/vnet/ipsec/ipsec_api.c
@@ -23,6 +23,7 @@
 #include <vnet/interface.h>
 #include <vnet/api_errno.h>
 #include <vnet/ip/ip.h>
+#include <vnet/ip/ip_types_api.h>
 #include <vnet/fib/fib.h>
 
 #include <vnet/vnet_msg_enum.h>
@@ -51,8 +52,8 @@
 #define foreach_vpe_api_msg                                     \
 _(IPSEC_SPD_ADD_DEL, ipsec_spd_add_del)                         \
 _(IPSEC_INTERFACE_ADD_DEL_SPD, ipsec_interface_add_del_spd)     \
-_(IPSEC_SPD_ADD_DEL_ENTRY, ipsec_spd_add_del_entry)             \
-_(IPSEC_SAD_ADD_DEL_ENTRY, ipsec_sad_add_del_entry)             \
+_(IPSEC_SPD_ENTRY_ADD_DEL, ipsec_spd_entry_add_del)             \
+_(IPSEC_SAD_ENTRY_ADD_DEL, ipsec_sad_entry_add_del)             \
 _(IPSEC_SA_SET_KEY, ipsec_sa_set_key)                           \
 _(IPSEC_SA_DUMP, ipsec_sa_dump)                                 \
 _(IPSEC_SPDS_DUMP, ipsec_spds_dump)                             \
@@ -119,11 +120,29 @@
   REPLY_MACRO (VL_API_IPSEC_INTERFACE_ADD_DEL_SPD_REPLY);
 }
 
-static void vl_api_ipsec_spd_add_del_entry_t_handler
-  (vl_api_ipsec_spd_add_del_entry_t * mp)
+static int
+ipsec_spd_action_decode (vl_api_ipsec_spd_action_t in,
+			 ipsec_policy_action_t * out)
+{
+  in = clib_net_to_host_u32 (in);
+
+  switch (in)
+    {
+#define _(v,f,s) case IPSEC_API_SPD_ACTION_##f: \
+      *out = IPSEC_POLICY_ACTION_##f;              \
+      return (0);
+      foreach_ipsec_policy_action
+#undef _
+    }
+  return (VNET_API_ERROR_UNIMPLEMENTED);
+}
+
+static void vl_api_ipsec_spd_entry_add_del_t_handler
+  (vl_api_ipsec_spd_entry_add_del_t * mp)
 {
   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
-  vl_api_ipsec_spd_add_del_entry_reply_t *rmp;
+  vl_api_ipsec_spd_entry_add_del_reply_t *rmp;
+  ip46_type_t itype;
   int rv;
 
 #if WITH_LIBSSL > 0
@@ -131,45 +150,42 @@
 
   clib_memset (&p, 0, sizeof (p));
 
-  p.id = ntohl (mp->spd_id);
-  p.priority = ntohl (mp->priority);
-  p.is_outbound = mp->is_outbound;
-  p.is_ipv6 = mp->is_ipv6;
+  p.id = ntohl (mp->entry.spd_id);
+  p.priority = ntohl (mp->entry.priority);
+  p.is_outbound = mp->entry.is_outbound;
 
-  if (mp->is_ipv6 || mp->is_ip_any)
-    {
-      clib_memcpy (&p.raddr.start, mp->remote_address_start, 16);
-      clib_memcpy (&p.raddr.stop, mp->remote_address_stop, 16);
-      clib_memcpy (&p.laddr.start, mp->local_address_start, 16);
-      clib_memcpy (&p.laddr.stop, mp->local_address_stop, 16);
-    }
-  else
-    {
-      clib_memcpy (&p.raddr.start.ip4.data, mp->remote_address_start, 4);
-      clib_memcpy (&p.raddr.stop.ip4.data, mp->remote_address_stop, 4);
-      clib_memcpy (&p.laddr.start.ip4.data, mp->local_address_start, 4);
-      clib_memcpy (&p.laddr.stop.ip4.data, mp->local_address_stop, 4);
-    }
-  p.protocol = mp->protocol;
-  p.rport.start = ntohs (mp->remote_port_start);
-  p.rport.stop = ntohs (mp->remote_port_stop);
-  p.lport.start = ntohs (mp->local_port_start);
-  p.lport.stop = ntohs (mp->local_port_stop);
+  itype = ip_address_decode (&mp->entry.remote_address_start, &p.raddr.start);
+  ip_address_decode (&mp->entry.remote_address_stop, &p.raddr.stop);
+  ip_address_decode (&mp->entry.local_address_start, &p.laddr.start);
+  ip_address_decode (&mp->entry.local_address_stop, &p.laddr.stop);
+
+  p.is_ipv6 = (itype == IP46_TYPE_IP6);
+
+  p.protocol = mp->entry.protocol;
+  p.rport.start = ntohs (mp->entry.remote_port_start);
+  p.rport.stop = ntohs (mp->entry.remote_port_stop);
+  p.lport.start = ntohs (mp->entry.local_port_start);
+  p.lport.stop = ntohs (mp->entry.local_port_stop);
+
+  rv = ipsec_spd_action_decode (mp->entry.policy, &p.policy);
+
+  if (rv)
+    goto out;
+
   /* policy action resolve unsupported */
-  if (mp->policy == IPSEC_POLICY_ACTION_RESOLVE)
+  if (p.policy == IPSEC_POLICY_ACTION_RESOLVE)
     {
       clib_warning ("unsupported action: 'resolve'");
       rv = VNET_API_ERROR_UNIMPLEMENTED;
       goto out;
     }
-  p.policy = mp->policy;
-  p.sa_id = ntohl (mp->sa_id);
+  p.sa_id = ntohl (mp->entry.sa_id);
 
   rv = ipsec_add_del_policy (vm, &p, mp->is_add);
   if (rv)
     goto out;
 
-  if (mp->is_ip_any)
+  if (mp->entry.is_ip_any)
     {
       p.is_ipv6 = 1;
       rv = ipsec_add_del_policy (vm, &p, mp->is_add);
@@ -180,14 +196,89 @@
 #endif
 
 out:
-  REPLY_MACRO (VL_API_IPSEC_SPD_ADD_DEL_ENTRY_REPLY);
+  REPLY_MACRO (VL_API_IPSEC_SPD_ENTRY_ADD_DEL_REPLY);
 }
 
-static void vl_api_ipsec_sad_add_del_entry_t_handler
-  (vl_api_ipsec_sad_add_del_entry_t * mp)
+static int
+ipsec_proto_decode (vl_api_ipsec_proto_t in, ipsec_protocol_t * out)
+{
+  in = clib_net_to_host_u32 (in);
+
+  switch (in)
+    {
+    case IPSEC_API_PROTO_ESP:
+      *out = IPSEC_PROTOCOL_ESP;
+      return (0);
+    case IPSEC_API_PROTO_AH:
+      *out = IPSEC_PROTOCOL_AH;
+      return (0);
+    }
+  return (VNET_API_ERROR_UNIMPLEMENTED);
+}
+
+static int
+ipsec_crypto_algo_decode (vl_api_ipsec_crypto_alg_t in,
+			  ipsec_crypto_alg_t * out)
+{
+  in = clib_net_to_host_u32 (in);
+
+  switch (in)
+    {
+#define _(v,f,s) case IPSEC_API_CRYPTO_ALG_##f: \
+      *out = IPSEC_CRYPTO_ALG_##f;              \
+      return (0);
+      foreach_ipsec_crypto_alg
+#undef _
+    }
+  return (VNET_API_ERROR_UNIMPLEMENTED);
+}
+
+static int
+ipsec_integ_algo_decode (vl_api_ipsec_integ_alg_t in, ipsec_integ_alg_t * out)
+{
+  in = clib_net_to_host_u32 (in);
+
+  switch (in)
+    {
+#define _(v,f,s) case IPSEC_API_INTEG_ALG_##f:  \
+      *out = IPSEC_INTEG_ALG_##f;               \
+      return (0);
+      foreach_ipsec_integ_alg
+#undef _
+    }
+  return (VNET_API_ERROR_UNIMPLEMENTED);
+}
+
+static void
+vl_api_ipsec_key_decode (const vl_api_key_t * key, u8 * len, u8 out[128])
+{
+  *len = key->length;
+  clib_memcpy (out, key->data, key->length);
+}
+
+static void
+vl_api_ipsec_sad_flags_decode (vl_api_ipsec_sad_flags_t in, ipsec_sa_t * sa)
+{
+  in = clib_net_to_host_u32 (in);
+
+  if (in & IPSEC_API_SAD_FLAG_USE_EXTENDED_SEQ_NUM)
+    sa->use_esn = 1;
+  if (in & IPSEC_API_SAD_FLAG_USE_ANTI_REPLAY)
+    sa->use_anti_replay = 1;
+  if (in & IPSEC_API_SAD_FLAG_IS_TUNNEL)
+    sa->is_tunnel = 1;
+  if (in & IPSEC_API_SAD_FLAG_IS_TUNNEL_V6)
+    sa->is_tunnel_ip6 = 1;
+  if (in & IPSEC_API_SAD_FLAG_UDP_ENCAP)
+    sa->udp_encap = 1;
+}
+
+
+static void vl_api_ipsec_sad_entry_add_del_t_handler
+  (vl_api_ipsec_sad_entry_add_del_t * mp)
 {
   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
-  vl_api_ipsec_sad_add_del_entry_reply_t *rmp;
+  vl_api_ipsec_sad_entry_add_del_reply_t *rmp;
   int rv;
 #if WITH_LIBSSL > 0
   ipsec_main_t *im = &ipsec_main;
@@ -195,47 +286,36 @@
 
   clib_memset (&sa, 0, sizeof (sa));
 
-  sa.id = ntohl (mp->sad_id);
-  sa.spi = ntohl (mp->spi);
-  sa.protocol = mp->protocol;
-  /* check for unsupported crypto-alg */
-  if (mp->crypto_algorithm >= IPSEC_CRYPTO_N_ALG)
-    {
-      clib_warning ("unsupported crypto-alg: '%U'", format_ipsec_crypto_alg,
-		    mp->crypto_algorithm);
-      rv = VNET_API_ERROR_UNIMPLEMENTED;
-      goto out;
-    }
-  sa.crypto_alg = mp->crypto_algorithm;
-  sa.crypto_key_len = mp->crypto_key_length;
-  clib_memcpy (&sa.crypto_key, mp->crypto_key, sizeof (sa.crypto_key));
-  /* check for unsupported integ-alg */
-  if (mp->integrity_algorithm >= IPSEC_INTEG_N_ALG)
-    {
-      clib_warning ("unsupported integ-alg: '%U'", format_ipsec_integ_alg,
-		    mp->integrity_algorithm);
-      rv = VNET_API_ERROR_UNIMPLEMENTED;
-      goto out;
-    }
+  sa.id = ntohl (mp->entry.sad_id);
+  sa.spi = ntohl (mp->entry.spi);
 
-  sa.integ_alg = mp->integrity_algorithm;
-  sa.integ_key_len = mp->integrity_key_length;
-  clib_memcpy (&sa.integ_key, mp->integrity_key, sizeof (sa.integ_key));
-  sa.use_esn = mp->use_extended_sequence_number;
-  sa.is_tunnel = mp->is_tunnel;
-  sa.is_tunnel_ip6 = mp->is_tunnel_ipv6;
-  sa.udp_encap = mp->udp_encap;
-  if (sa.is_tunnel_ip6)
+  rv = ipsec_proto_decode (mp->entry.protocol, &sa.protocol);
+
+  if (rv)
+    goto out;
+
+  rv = ipsec_crypto_algo_decode (mp->entry.crypto_algorithm, &sa.crypto_alg);
+
+  if (rv)
+    goto out;
+
+  rv = ipsec_integ_algo_decode (mp->entry.integrity_algorithm, &sa.integ_alg);
+
+  if (rv)
+    goto out;
+
+  vl_api_ipsec_key_decode (&mp->entry.crypto_key,
+			   &sa.crypto_key_len, sa.crypto_key);
+  vl_api_ipsec_key_decode (&mp->entry.integrity_key,
+			   &sa.integ_key_len, sa.integ_key);
+
+  vl_api_ipsec_sad_flags_decode (mp->entry.flags, &sa);
+
+  if (sa.is_tunnel_ip6 || sa.is_tunnel)
     {
-      clib_memcpy (&sa.tunnel_src_addr, mp->tunnel_src_address, 16);
-      clib_memcpy (&sa.tunnel_dst_addr, mp->tunnel_dst_address, 16);
+      ip_address_decode (&mp->entry.tunnel_src, &sa.tunnel_src_addr);
+      ip_address_decode (&mp->entry.tunnel_dst, &sa.tunnel_dst_addr);
     }
-  else
-    {
-      clib_memcpy (&sa.tunnel_src_addr.ip4.data, mp->tunnel_src_address, 4);
-      clib_memcpy (&sa.tunnel_dst_addr.ip4.data, mp->tunnel_dst_address, 4);
-    }
-  sa.use_anti_replay = mp->use_anti_replay;
 
   clib_error_t *err = ipsec_check_support_cb (im, &sa);
   if (err)
@@ -252,7 +332,7 @@
 #endif
 
 out:
-  REPLY_MACRO (VL_API_IPSEC_SAD_ADD_DEL_ENTRY_REPLY);
+  REPLY_MACRO (VL_API_IPSEC_SAD_ENTRY_ADD_DEL_REPLY);
 }
 
 static void
@@ -293,6 +373,22 @@
 #endif
 }
 
+vl_api_ipsec_spd_action_t
+ipsec_spd_action_encode (ipsec_policy_action_t in)
+{
+  vl_api_ipsec_spd_action_t out = IPSEC_API_SPD_ACTION_BYPASS;
+
+  switch (in)
+    {
+#define _(v,f,s) case IPSEC_POLICY_ACTION_##f: \
+      out = IPSEC_API_SPD_ACTION_##f;          \
+      break;
+      foreach_ipsec_policy_action
+#undef _
+    }
+  return (clib_host_to_net_u32 (out));
+}
+
 static void
 send_ipsec_spd_details (ipsec_policy_t * p, vl_api_registration_t * reg,
 			u32 context)
@@ -304,31 +400,26 @@
   mp->_vl_msg_id = ntohs (VL_API_IPSEC_SPD_DETAILS);
   mp->context = context;
 
-  mp->spd_id = htonl (p->id);
-  mp->priority = htonl (p->priority);
-  mp->is_outbound = p->is_outbound;
-  mp->is_ipv6 = p->is_ipv6;
-  if (p->is_ipv6)
-    {
-      memcpy (mp->local_start_addr, &p->laddr.start.ip6, 16);
-      memcpy (mp->local_stop_addr, &p->laddr.stop.ip6, 16);
-      memcpy (mp->remote_start_addr, &p->raddr.start.ip6, 16);
-      memcpy (mp->remote_stop_addr, &p->raddr.stop.ip6, 16);
-    }
-  else
-    {
-      memcpy (mp->local_start_addr, &p->laddr.start.ip4, 4);
-      memcpy (mp->local_stop_addr, &p->laddr.stop.ip4, 4);
-      memcpy (mp->remote_start_addr, &p->raddr.start.ip4, 4);
-      memcpy (mp->remote_stop_addr, &p->raddr.stop.ip4, 4);
-    }
-  mp->local_start_port = htons (p->lport.start);
-  mp->local_stop_port = htons (p->lport.stop);
-  mp->remote_start_port = htons (p->rport.start);
-  mp->remote_stop_port = htons (p->rport.stop);
-  mp->protocol = p->protocol;
-  mp->policy = p->policy;
-  mp->sa_id = htonl (p->sa_id);
+  mp->entry.spd_id = htonl (p->id);
+  mp->entry.priority = htonl (p->priority);
+  mp->entry.is_outbound = p->is_outbound;
+
+  ip_address_encode (&p->laddr.start, IP46_TYPE_ANY,
+		     &mp->entry.local_address_start);
+  ip_address_encode (&p->laddr.stop, IP46_TYPE_ANY,
+		     &mp->entry.local_address_stop);
+  ip_address_encode (&p->raddr.start, IP46_TYPE_ANY,
+		     &mp->entry.remote_address_start);
+  ip_address_encode (&p->raddr.stop, IP46_TYPE_ANY,
+		     &mp->entry.remote_address_stop);
+  mp->entry.local_port_start = htons (p->lport.start);
+  mp->entry.local_port_stop = htons (p->lport.stop);
+  mp->entry.remote_port_start = htons (p->rport.start);
+  mp->entry.remote_port_stop = htons (p->rport.stop);
+  mp->entry.protocol = p->protocol;
+  mp->entry.policy = ipsec_spd_action_encode (p->policy);
+  mp->entry.sa_id = htonl (p->sa_id);
+
   mp->bytes = clib_host_to_net_u64 (p->counter.bytes);
   mp->packets = clib_host_to_net_u64 (p->counter.packets);
 
@@ -432,10 +523,11 @@
 #if WITH_LIBSSL > 0
   ipsec_sa_t sa;
   sa.id = ntohl (mp->sa_id);
-  sa.crypto_key_len = mp->crypto_key_length;
-  clib_memcpy (&sa.crypto_key, mp->crypto_key, sizeof (sa.crypto_key));
-  sa.integ_key_len = mp->integrity_key_length;
-  clib_memcpy (&sa.integ_key, mp->integrity_key, sizeof (sa.integ_key));
+
+  vl_api_ipsec_key_decode (&mp->crypto_key,
+			   &sa.crypto_key_len, sa.crypto_key);
+  vl_api_ipsec_key_decode (&mp->integrity_key,
+			   &sa.integ_key_len, sa.integ_key);
 
   rv = ipsec_set_sa_key (vm, &sa);
 #else
@@ -1033,7 +1125,7 @@
     mp->context = context;
     snprintf ((char *)mp->name, sizeof (mp->name), "%.*s", vec_len (ab->name),
               ab->name);
-    mp->protocol = IPSEC_PROTOCOL_AH;
+    mp->protocol = ntohl (IPSEC_API_PROTO_AH);
     mp->index = ab - im->ah_backends;
     mp->active = mp->index == im->ah_current_backend ? 1 : 0;
     vl_api_send_msg (rp, (u8 *)mp);
@@ -1045,7 +1137,7 @@
     mp->context = context;
     snprintf ((char *)mp->name, sizeof (mp->name), "%.*s", vec_len (eb->name),
               eb->name);
-    mp->protocol = IPSEC_PROTOCOL_ESP;
+    mp->protocol = ntohl (IPSEC_API_PROTO_ESP);
     mp->index = eb - im->esp_backends;
     mp->active = mp->index == im->esp_current_backend ? 1 : 0;
     vl_api_send_msg (rp, (u8 *)mp);
@@ -1058,14 +1150,21 @@
 {
   ipsec_main_t *im = &ipsec_main;
   vl_api_ipsec_select_backend_reply_t *rmp;
+  ipsec_protocol_t protocol;
   int rv = 0;
   if (pool_elts (im->sad) > 0)
     {
       rv = VNET_API_ERROR_INSTANCE_IN_USE;
       goto done;
     }
+
+  rv = ipsec_proto_decode (mp->protocol, &protocol);
+
+  if (rv)
+    goto done;
+
 #if WITH_LIBSSL > 0
-  switch (mp->protocol)
+  switch (protocol)
     {
     case IPSEC_PROTOCOL_ESP:
       if (pool_is_free_index (im->esp_backends, mp->index))
diff --git a/test/template_ipsec.py b/test/template_ipsec.py
index ed7c1a3..7888a67 100644
--- a/test/template_ipsec.py
+++ b/test/template_ipsec.py
@@ -8,60 +8,71 @@
 
 from framework import VppTestCase, VppTestRunner
 from util import ppp
+from vpp_papi import VppEnum
 
 
 class IPsecIPv4Params(object):
+
     addr_type = socket.AF_INET
     addr_any = "0.0.0.0"
     addr_bcast = "255.255.255.255"
     addr_len = 32
     is_ipv6 = 0
-    remote_tun_if_host = '1.1.1.1'
 
-    scapy_tun_sa_id = 10
-    scapy_tun_spi = 1001
-    vpp_tun_sa_id = 20
-    vpp_tun_spi = 1000
+    def __init__(self):
+        self.remote_tun_if_host = '1.1.1.1'
 
-    scapy_tra_sa_id = 30
-    scapy_tra_spi = 2001
-    vpp_tra_sa_id = 40
-    vpp_tra_spi = 2000
+        self.scapy_tun_sa_id = 10
+        self.scapy_tun_spi = 1001
+        self.vpp_tun_sa_id = 20
+        self.vpp_tun_spi = 1000
 
-    auth_algo_vpp_id = 2  # internal VPP enum value for SHA1_96
-    auth_algo = 'HMAC-SHA1-96'  # scapy name
-    auth_key = 'C91KUR9GYMm5GfkEvNjX'
+        self.scapy_tra_sa_id = 30
+        self.scapy_tra_spi = 2001
+        self.vpp_tra_sa_id = 40
+        self.vpp_tra_spi = 2000
 
-    crypt_algo_vpp_id = 1  # internal VPP enum value for AES_CBC_128
-    crypt_algo = 'AES-CBC'  # scapy name
-    crypt_key = 'JPjyOWBeVEQiMe7h'
+        self.auth_algo_vpp_id = (VppEnum.vl_api_ipsec_integ_alg_t.
+                                 IPSEC_API_INTEG_ALG_SHA1_96)
+        self.auth_algo = 'HMAC-SHA1-96'  # scapy name
+        self.auth_key = 'C91KUR9GYMm5GfkEvNjX'
+
+        self.crypt_algo_vpp_id = (VppEnum.vl_api_ipsec_crypto_alg_t.
+                                  IPSEC_API_CRYPTO_ALG_AES_CBC_128)
+        self.crypt_algo = 'AES-CBC'  # scapy name
+        self.crypt_key = 'JPjyOWBeVEQiMe7h'
 
 
 class IPsecIPv6Params(object):
+
     addr_type = socket.AF_INET6
     addr_any = "0::0"
     addr_bcast = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"
     addr_len = 128
     is_ipv6 = 1
-    remote_tun_if_host = '1111:1111:1111:1111:1111:1111:1111:1111'
 
-    scapy_tun_sa_id = 50
-    scapy_tun_spi = 3001
-    vpp_tun_sa_id = 60
-    vpp_tun_spi = 3000
+    def __init__(self):
+        self.remote_tun_if_host = '1111:1111:1111:1111:1111:1111:1111:1111'
 
-    scapy_tra_sa_id = 70
-    scapy_tra_spi = 4001
-    vpp_tra_sa_id = 80
-    vpp_tra_spi = 4000
+        self.scapy_tun_sa_id = 50
+        self.scapy_tun_spi = 3001
+        self.vpp_tun_sa_id = 60
+        self.vpp_tun_spi = 3000
 
-    auth_algo_vpp_id = 4  # internal VPP enum value for SHA_256_128
-    auth_algo = 'SHA2-256-128'  # scapy name
-    auth_key = 'C91KUR9GYMm5GfkEvNjX'
+        self.scapy_tra_sa_id = 70
+        self.scapy_tra_spi = 4001
+        self.vpp_tra_sa_id = 80
+        self.vpp_tra_spi = 4000
 
-    crypt_algo_vpp_id = 3  # internal VPP enum value for AES_CBC_256
-    crypt_algo = 'AES-CBC'  # scapy name
-    crypt_key = 'JPjyOWBeVEQiMe7hJPjyOWBeVEQiMe7h'
+        self.auth_algo_vpp_id = (VppEnum.vl_api_ipsec_integ_alg_t.
+                                 IPSEC_API_INTEG_ALG_SHA_256_128)
+        self.auth_algo = 'SHA2-256-128'  # scapy name
+        self.auth_key = 'C91KUR9GYMm5GfkEvNjX'
+
+        self.crypt_algo_vpp_id = (VppEnum.vl_api_ipsec_crypto_alg_t.
+                                  IPSEC_API_CRYPTO_ALG_AES_CBC_256)
+        self.crypt_algo = 'AES-CBC'  # scapy name
+        self.crypt_key = 'JPjyOWBeVEQiMe7hJPjyOWBeVEQiMe7h'
 
 
 class TemplateIpsec(VppTestCase):
@@ -101,8 +112,10 @@
         self.tun_spd_id = 1
         self.tra_spd_id = 2
 
-        self.vpp_esp_protocol = 1
-        self.vpp_ah_protocol = 0
+        self.vpp_esp_protocol = (VppEnum.vl_api_ipsec_proto_t.
+                                 IPSEC_API_PROTO_ESP)
+        self.vpp_ah_protocol = (VppEnum.vl_api_ipsec_proto_t.
+                                IPSEC_API_PROTO_AH)
 
         self.create_pg_interfaces(range(3))
         self.interfaces = list(self.pg_interfaces)
diff --git a/test/test_ipsec_ah.py b/test/test_ipsec_ah.py
index 63e368c..caec8d4 100644
--- a/test/test_ipsec_ah.py
+++ b/test/test_ipsec_ah.py
@@ -10,6 +10,7 @@
         VppIpsecSpdItfBinding
 from vpp_ip_route import VppIpRoute, VppRoutePath
 from vpp_ip import DpoProto
+from vpp_papi import VppEnum
 
 
 class TemplateIpsecAh(TemplateIpsec):
@@ -83,6 +84,8 @@
         remote_tun_if_host = params.remote_tun_if_host
         addr_any = params.addr_any
         addr_bcast = params.addr_bcast
+        e = VppEnum.vl_api_ipsec_spd_action_t
+
         VppIpsecSA(self, scapy_tun_sa_id, scapy_tun_spi,
                    auth_algo_vpp_id, auth_key,
                    crypt_algo_vpp_id, crypt_key,
@@ -111,28 +114,32 @@
                          remote_tun_if_host,
                          self.pg1.remote_addr[addr_type],
                          self.pg1.remote_addr[addr_type],
-                         0, priority=10, policy=3,
+                         0, priority=10,
+                         policy=e.IPSEC_API_SPD_ACTION_PROTECT,
                          is_outbound=0).add_vpp_config()
         VppIpsecSpdEntry(self, self.tun_spd, scapy_tun_sa_id,
                          self.pg1.remote_addr[addr_type],
                          self.pg1.remote_addr[addr_type],
                          remote_tun_if_host,
                          remote_tun_if_host,
-                         0, priority=10, policy=3).add_vpp_config()
+                         0, policy=e.IPSEC_API_SPD_ACTION_PROTECT,
+                         priority=10).add_vpp_config()
 
         VppIpsecSpdEntry(self, self.tun_spd, vpp_tun_sa_id,
                          remote_tun_if_host,
                          remote_tun_if_host,
                          self.pg0.local_addr[addr_type],
                          self.pg0.local_addr[addr_type],
-                         0, priority=20, policy=3,
+                         0, priority=20,
+                         policy=e.IPSEC_API_SPD_ACTION_PROTECT,
                          is_outbound=0).add_vpp_config()
         VppIpsecSpdEntry(self, self.tun_spd, scapy_tun_sa_id,
                          self.pg0.local_addr[addr_type],
                          self.pg0.local_addr[addr_type],
                          remote_tun_if_host,
                          remote_tun_if_host,
-                         0, priority=20, policy=3).add_vpp_config()
+                         0, policy=e.IPSEC_API_SPD_ACTION_PROTECT,
+                         priority=20).add_vpp_config()
 
     def config_ah_tra(self, params):
         addr_type = params.addr_type
@@ -146,17 +153,20 @@
         crypt_key = params.crypt_key
         addr_any = params.addr_any
         addr_bcast = params.addr_bcast
+        flags = (VppEnum.vl_api_ipsec_sad_flags_t.
+                 IPSEC_API_SAD_FLAG_USE_ANTI_REPLAY)
+        e = VppEnum.vl_api_ipsec_spd_action_t
 
         VppIpsecSA(self, scapy_tra_sa_id, scapy_tra_spi,
                    auth_algo_vpp_id, auth_key,
                    crypt_algo_vpp_id, crypt_key,
                    self.vpp_ah_protocol,
-                   use_anti_replay=1).add_vpp_config()
+                   flags=flags).add_vpp_config()
         VppIpsecSA(self, vpp_tra_sa_id, vpp_tra_spi,
                    auth_algo_vpp_id, auth_key,
                    crypt_algo_vpp_id, crypt_key,
                    self.vpp_ah_protocol,
-                   use_anti_replay=1).add_vpp_config()
+                   flags=flags).add_vpp_config()
 
         VppIpsecSpdEntry(self, self.tra_spd, vpp_tra_sa_id,
                          addr_any, addr_bcast,
@@ -173,14 +183,16 @@
                          self.tra_if.local_addr[addr_type],
                          self.tra_if.remote_addr[addr_type],
                          self.tra_if.remote_addr[addr_type],
-                         0, priority=10, policy=3,
+                         0, priority=10,
+                         policy=e.IPSEC_API_SPD_ACTION_PROTECT,
                          is_outbound=0).add_vpp_config()
         VppIpsecSpdEntry(self, self.tra_spd, scapy_tra_sa_id,
                          self.tra_if.local_addr[addr_type],
                          self.tra_if.local_addr[addr_type],
                          self.tra_if.remote_addr[addr_type],
                          self.tra_if.remote_addr[addr_type],
-                         0, priority=10, policy=3).add_vpp_config()
+                         0, policy=e.IPSEC_API_SPD_ACTION_PROTECT,
+                         priority=10).add_vpp_config()
 
 
 class TestIpsecAh1(TemplateIpsecAh, IpsecTraTests, IpsecTunTests):
diff --git a/test/test_ipsec_api.py b/test/test_ipsec_api.py
index 30496b3..8aea42a 100644
--- a/test/test_ipsec_api.py
+++ b/test/test_ipsec_api.py
@@ -1,7 +1,8 @@
 import unittest
 
 from framework import VppTestCase, VppTestRunner
-from template_ipsec import IPsecIPv4Params
+from template_ipsec import TemplateIpsec, IPsecIPv4Params
+from vpp_papi import VppEnum
 
 
 class IpsecApiTestCase(VppTestCase):
@@ -13,8 +14,10 @@
         self.pg0.config_ip4()
         self.pg0.admin_up()
 
-        self.vpp_esp_protocol = 1
-        self.vpp_ah_protocol = 0
+        self.vpp_esp_protocol = (VppEnum.vl_api_ipsec_proto_t.
+                                 IPSEC_API_PROTO_ESP)
+        self.vpp_ah_protocol = (VppEnum.vl_api_ipsec_proto_t.
+                                IPSEC_API_PROTO_AH)
         self.ipv4_params = IPsecIPv4Params()
 
     def tearDown(self):
@@ -59,24 +62,22 @@
         crypt_algo_vpp_id = params.crypt_algo_vpp_id
         crypt_key = params.crypt_key
 
-        self.vapi.ipsec_sad_add_del_entry(scapy_tun_sa_id, scapy_tun_spi,
+        self.vapi.ipsec_sad_entry_add_del(scapy_tun_sa_id, scapy_tun_spi,
                                           auth_algo_vpp_id, auth_key,
                                           crypt_algo_vpp_id, crypt_key,
                                           self.vpp_ah_protocol,
-                                          self.pg0.local_addr_n[addr_type],
-                                          self.pg0.remote_addr_n[addr_type],
-                                          is_tunnel=1, is_tunnel_ipv6=is_ipv6)
+                                          self.pg0.local_addr[addr_type],
+                                          self.pg0.remote_addr[addr_type])
         with self.vapi.assert_negative_api_retval():
             self.vapi.ipsec_select_backend(
                 protocol=self.vpp_ah_protocol, index=0)
 
-        self.vapi.ipsec_sad_add_del_entry(scapy_tun_sa_id, scapy_tun_spi,
+        self.vapi.ipsec_sad_entry_add_del(scapy_tun_sa_id, scapy_tun_spi,
                                           auth_algo_vpp_id, auth_key,
                                           crypt_algo_vpp_id, crypt_key,
                                           self.vpp_ah_protocol,
-                                          self.pg0.local_addr_n[addr_type],
-                                          self.pg0.remote_addr_n[addr_type],
-                                          is_tunnel=1, is_tunnel_ipv6=is_ipv6,
+                                          self.pg0.local_addr[addr_type],
+                                          self.pg0.remote_addr[addr_type],
                                           is_add=0)
         self.vapi.ipsec_select_backend(
             protocol=self.vpp_ah_protocol, index=0)
diff --git a/test/test_ipsec_esp.py b/test/test_ipsec_esp.py
index 96e4833..ae62aec 100644
--- a/test/test_ipsec_esp.py
+++ b/test/test_ipsec_esp.py
@@ -9,6 +9,7 @@
         VppIpsecSpdItfBinding
 from vpp_ip_route import VppIpRoute, VppRoutePath
 from vpp_ip import DpoProto
+from vpp_papi import VppEnum
 
 
 class TemplateIpsecEsp(TemplateIpsec):
@@ -94,6 +95,7 @@
         remote_tun_if_host = params.remote_tun_if_host
         addr_any = params.addr_any
         addr_bcast = params.addr_bcast
+        e = VppEnum.vl_api_ipsec_spd_action_t
 
         VppIpsecSA(self, scapy_tun_sa_id, scapy_tun_spi,
                    auth_algo_vpp_id, auth_key,
@@ -123,28 +125,32 @@
                          self.pg1.remote_addr[addr_type],
                          self.pg1.remote_addr[addr_type],
                          0,
-                         priority=10, policy=3,
+                         priority=10,
+                         policy=e.IPSEC_API_SPD_ACTION_PROTECT,
                          is_outbound=0).add_vpp_config()
         VppIpsecSpdEntry(self, self.tun_spd, scapy_tun_sa_id,
                          self.pg1.remote_addr[addr_type],
                          self.pg1.remote_addr[addr_type],
                          remote_tun_if_host, remote_tun_if_host,
                          0,
-                         priority=10, policy=3).add_vpp_config()
+                         policy=e.IPSEC_API_SPD_ACTION_PROTECT,
+                         priority=10).add_vpp_config()
 
         VppIpsecSpdEntry(self, self.tun_spd, vpp_tun_sa_id,
                          remote_tun_if_host, remote_tun_if_host,
                          self.pg0.local_addr[addr_type],
                          self.pg0.local_addr[addr_type],
                          0,
-                         priority=20, policy=3,
+                         priority=20,
+                         policy=e.IPSEC_API_SPD_ACTION_PROTECT,
                          is_outbound=0).add_vpp_config()
         VppIpsecSpdEntry(self, self.tun_spd, scapy_tun_sa_id,
                          self.pg0.local_addr[addr_type],
                          self.pg0.local_addr[addr_type],
                          remote_tun_if_host, remote_tun_if_host,
                          0,
-                         priority=20, policy=3).add_vpp_config()
+                         policy=e.IPSEC_API_SPD_ACTION_PROTECT,
+                         priority=20).add_vpp_config()
 
     def config_esp_tra(self, params):
         addr_type = params.addr_type
@@ -158,17 +164,20 @@
         crypt_key = params.crypt_key
         addr_any = params.addr_any
         addr_bcast = params.addr_bcast
+        flags = (VppEnum.vl_api_ipsec_sad_flags_t.
+                 IPSEC_API_SAD_FLAG_USE_ANTI_REPLAY)
+        e = VppEnum.vl_api_ipsec_spd_action_t
 
         VppIpsecSA(self, scapy_tra_sa_id, scapy_tra_spi,
                    auth_algo_vpp_id, auth_key,
                    crypt_algo_vpp_id, crypt_key,
                    self.vpp_esp_protocol,
-                   use_anti_replay=1).add_vpp_config()
+                   flags=flags).add_vpp_config()
         VppIpsecSA(self, vpp_tra_sa_id, vpp_tra_spi,
                    auth_algo_vpp_id, auth_key,
                    crypt_algo_vpp_id, crypt_key,
                    self.vpp_esp_protocol,
-                   use_anti_replay=1).add_vpp_config()
+                   flags=flags).add_vpp_config()
 
         VppIpsecSpdEntry(self, self.tra_spd, vpp_tra_sa_id,
                          addr_any, addr_bcast,
@@ -185,14 +194,16 @@
                          self.tra_if.local_addr[addr_type],
                          self.tra_if.remote_addr[addr_type],
                          self.tra_if.remote_addr[addr_type],
-                         0, priority=10, policy=3,
+                         0, priority=10,
+                         policy=e.IPSEC_API_SPD_ACTION_PROTECT,
                          is_outbound=0).add_vpp_config()
         VppIpsecSpdEntry(self, self.tra_spd, scapy_tra_sa_id,
                          self.tra_if.local_addr[addr_type],
                          self.tra_if.local_addr[addr_type],
                          self.tra_if.remote_addr[addr_type],
                          self.tra_if.remote_addr[addr_type],
-                         0, priority=10, policy=3).add_vpp_config()
+                         0, policy=e.IPSEC_API_SPD_ACTION_PROTECT,
+                         priority=10).add_vpp_config()
 
 
 class TestIpsecEsp1(TemplateIpsecEsp, IpsecTraTests, IpsecTunTests):
diff --git a/test/test_ipsec_nat.py b/test/test_ipsec_nat.py
index 89418b1..cdb9cb4 100644
--- a/test/test_ipsec_nat.py
+++ b/test/test_ipsec_nat.py
@@ -11,6 +11,7 @@
         VppIpsecSpdItfBinding
 from vpp_ip_route import VppIpRoute, VppRoutePath
 from vpp_ip import DpoProto
+from vpp_papi import VppEnum
 
 
 class IPSecNATTestCase(TemplateIpsec):
@@ -155,6 +156,9 @@
         crypt_key = params.crypt_key
         addr_any = params.addr_any
         addr_bcast = params.addr_bcast
+        flags = (VppEnum.vl_api_ipsec_sad_flags_t.
+                 IPSEC_API_SAD_FLAG_UDP_ENCAP)
+        e = VppEnum.vl_api_ipsec_spd_action_t
 
         VppIpsecSA(self, scapy_tun_sa_id, scapy_tun_spi,
                    auth_algo_vpp_id, auth_key,
@@ -162,14 +166,14 @@
                    self.vpp_esp_protocol,
                    self.pg1.remote_addr[addr_type],
                    self.tun_if.remote_addr[addr_type],
-                   udp_encap=1).add_vpp_config()
+                   flags=flags).add_vpp_config()
         VppIpsecSA(self, vpp_tun_sa_id, vpp_tun_spi,
                    auth_algo_vpp_id, auth_key,
                    crypt_algo_vpp_id, crypt_key,
                    self.vpp_esp_protocol,
                    self.tun_if.remote_addr[addr_type],
                    self.pg1.remote_addr[addr_type],
-                   udp_encap=1).add_vpp_config()
+                   flags=flags).add_vpp_config()
 
         VppIpsecSpdEntry(self, self.tun_spd, scapy_tun_sa_id,
                          addr_any, addr_bcast,
@@ -198,14 +202,16 @@
                          self.tun_if.remote_addr[addr_type],
                          self.pg1.remote_addr[addr_type],
                          self.pg1.remote_addr[addr_type],
-                         0, priority=10, policy=3,
+                         0, priority=10,
+                         policy=e.IPSEC_API_SPD_ACTION_PROTECT,
                          is_outbound=0).add_vpp_config()
         VppIpsecSpdEntry(self, self.tun_spd, scapy_tun_sa_id,
                          self.pg1.remote_addr[addr_type],
                          self.pg1.remote_addr[addr_type],
                          self.tun_if.remote_addr[addr_type],
                          self.tun_if.remote_addr[addr_type],
-                         0, priority=10, policy=3).add_vpp_config()
+                         0, policy=e.IPSEC_API_SPD_ACTION_PROTECT,
+                         priority=10).add_vpp_config()
 
     def test_ipsec_nat_tun(self):
         """ IPSec/NAT tunnel test case """
diff --git a/test/vpp_ipsec.py b/test/vpp_ipsec.py
index 8c6da77..1218c4b 100644
--- a/test/vpp_ipsec.py
+++ b/test/vpp_ipsec.py
@@ -1,5 +1,6 @@
 from vpp_object import *
 from ipaddress import ip_address
+from vpp_papi import VppEnum
 
 try:
     text_type = unicode
@@ -82,7 +83,7 @@
                  remote_start, remote_stop,
                  proto,
                  priority=100,
-                 policy=0,
+                 policy=None,
                  is_outbound=1,
                  remote_port_start=0,
                  remote_port_stop=65535,
@@ -98,7 +99,11 @@
         self.proto = proto
         self.is_outbound = is_outbound
         self.priority = priority
-        self.policy = policy
+        if not policy:
+            self.policy = (VppEnum.vl_api_ipsec_spd_action_t.
+                           IPSEC_API_SPD_ACTION_BYPASS)
+        else:
+            self.policy = policy
         self.is_ipv6 = (0 if self.local_start.version == 4 else 1)
         self.local_port_start = local_port_start
         self.local_port_stop = local_port_stop
@@ -106,13 +111,13 @@
         self.remote_port_stop = remote_port_stop
 
     def add_vpp_config(self):
-        self.test.vapi.ipsec_spd_add_del_entry(
+        self.test.vapi.ipsec_spd_entry_add_del(
             self.spd.id,
             self.sa_id,
-            self.local_start.packed,
-            self.local_stop.packed,
-            self.remote_start.packed,
-            self.remote_stop.packed,
+            self.local_start,
+            self.local_stop,
+            self.remote_start,
+            self.remote_stop,
             protocol=self.proto,
             is_ipv6=self.is_ipv6,
             is_outbound=self.is_outbound,
@@ -125,13 +130,13 @@
         self.test.registry.register(self, self.test.logger)
 
     def remove_vpp_config(self):
-        self.test.vapi.ipsec_spd_add_del_entry(
+        self.test.vapi.ipsec_spd_entry_add_del(
             self.spd.id,
             self.sa_id,
-            self.local_start.packed,
-            self.local_stop.packed,
-            self.remote_start.packed,
-            self.remote_stop.packed,
+            self.local_start,
+            self.local_stop,
+            self.remote_start,
+            self.remote_stop,
             protocol=self.proto,
             is_ipv6=self.is_ipv6,
             is_outbound=self.is_outbound,
@@ -157,12 +162,12 @@
     def query_vpp_config(self):
         ss = self.test.vapi.ipsec_spd_dump(self.spd.id)
         for s in ss:
-            if s.sa_id == self.sa_id and \
-               s.is_outbound == self.is_outbound and \
-               s.priority == self.priority and \
-               s.policy == self.policy and \
-               s.is_ipv6 == self.is_ipv6 and \
-               s.remote_start_port == self.remote_port_start:
+            if s.entry.sa_id == self.sa_id and \
+               s.entry.is_outbound == self.is_outbound and \
+               s.entry.priority == self.priority and \
+               s.entry.policy == self.policy and \
+               s.entry.remote_address_start == self.remote_start and \
+               s.entry.remote_port_start == self.remote_port_start:
                 return True
         return False
 
@@ -177,8 +182,8 @@
                  crypto_alg, crypto_key,
                  proto,
                  tun_src=None, tun_dst=None,
-                 use_anti_replay=0,
-                 udp_encap=0):
+                 flags=None):
+        e = VppEnum.vl_api_ipsec_sad_flags_t
         self.test = test
         self.id = id
         self.spi = spi
@@ -187,22 +192,23 @@
         self.crypto_alg = crypto_alg
         self.crypto_key = crypto_key
         self.proto = proto
-        self.is_tunnel = 0
-        self.is_tunnel_v6 = 0
+
         self.tun_src = tun_src
         self.tun_dst = tun_dst
+        if not flags:
+            self.flags = e.IPSEC_API_SAD_FLAG_NONE
+        else:
+            self.flags = flags
         if (tun_src):
             self.tun_src = ip_address(text_type(tun_src))
-            self.is_tunnel = 1
+            self.flags = self.flags | e.IPSEC_API_SAD_FLAG_IS_TUNNEL
             if (self.tun_src.version == 6):
-                self.is_tunnel_v6 = 1
+                self.flags = self.flags | e.IPSEC_API_SAD_FLAG_IS_TUNNEL_V6
         if (tun_dst):
             self.tun_dst = ip_address(text_type(tun_dst))
-        self.use_anti_replay = use_anti_replay
-        self.udp_encap = udp_encap
 
     def add_vpp_config(self):
-        self.test.vapi.ipsec_sad_add_del_entry(
+        self.test.vapi.ipsec_sad_entry_add_del(
             self.id,
             self.spi,
             self.integ_alg,
@@ -210,16 +216,13 @@
             self.crypto_alg,
             self.crypto_key,
             self.proto,
-            (self.tun_src.packed if self.tun_src else []),
-            (self.tun_dst.packed if self.tun_dst else []),
-            is_tunnel=self.is_tunnel,
-            is_tunnel_ipv6=self.is_tunnel_v6,
-            use_anti_replay=self.use_anti_replay,
-            udp_encap=self.udp_encap)
+            (self.tun_src if self.tun_src else []),
+            (self.tun_dst if self.tun_dst else []),
+            flags=self.flags)
         self.test.registry.register(self, self.test.logger)
 
     def remove_vpp_config(self):
-        self.test.vapi.ipsec_sad_add_del_entry(
+        self.test.vapi.ipsec_sad_entry_add_del(
             self.id,
             self.spi,
             self.integ_alg,
@@ -227,12 +230,9 @@
             self.crypto_alg,
             self.crypto_key,
             self.proto,
-            (self.tun_src.packed if self.tun_src else []),
-            (self.tun_dst.packed if self.tun_dst else []),
-            is_tunnel=self.is_tunnel,
-            is_tunnel_ipv6=self.is_tunnel_v6,
-            use_anti_replay=self.use_anti_replay,
-            udp_encap=self.udp_encap,
+            (self.tun_src if self.tun_src else []),
+            (self.tun_dst if self.tun_dst else []),
+            flags=self.flags,
             is_add=0)
 
     def __str__(self):
diff --git a/test/vpp_papi_provider.py b/test/vpp_papi_provider.py
index efe1454..d22cc7c 100644
--- a/test/vpp_papi_provider.py
+++ b/test/vpp_papi_provider.py
@@ -3369,7 +3369,7 @@
                         {'spd_index': spd_index if spd_index else 0,
                          'spd_index_valid': 1 if spd_index else 0})
 
-    def ipsec_sad_add_del_entry(self,
+    def ipsec_sad_entry_add_del(self,
                                 sad_id,
                                 spi,
                                 integrity_algorithm,
@@ -3379,12 +3379,8 @@
                                 protocol,
                                 tunnel_src_address='',
                                 tunnel_dst_address='',
-                                is_tunnel=1,
-                                is_tunnel_ipv6=0,
-                                is_add=1,
-                                udp_encap=0,
-                                use_anti_replay=0,
-                                use_extended_sequence_number=0):
+                                flags=0,
+                                is_add=1):
         """ IPSEC SA add/del
         :param sad_id: security association ID
         :param spi: security param index of the SA in decimal
@@ -3401,31 +3397,35 @@
              crypto and ipsec algorithms
         """
         return self.api(
-            self.papi.ipsec_sad_add_del_entry,
-            {'sad_id': sad_id,
-             'spi': spi,
-             'tunnel_src_address': tunnel_src_address,
-             'tunnel_dst_address': tunnel_dst_address,
-             'protocol': protocol,
-             'integrity_algorithm': integrity_algorithm,
-             'integrity_key_length': len(integrity_key),
-             'integrity_key': integrity_key,
-             'crypto_algorithm': crypto_algorithm,
-             'crypto_key_length': len(crypto_key) if crypto_key is not None
-             else 0,
-             'crypto_key': crypto_key,
-             'is_add': is_add,
-             'is_tunnel': is_tunnel,
-             'is_tunnel_ipv6': is_tunnel_ipv6,
-             'udp_encap': udp_encap,
-             'use_extended_sequence_number': use_extended_sequence_number,
-             'use_anti_replay': use_anti_replay})
+            self.papi.ipsec_sad_entry_add_del,
+            {
+                'is_add': is_add,
+                'entry':
+                {
+                    'sad_id': sad_id,
+                    'spi': spi,
+                    'tunnel_src': tunnel_src_address,
+                    'tunnel_dst': tunnel_dst_address,
+                    'protocol': protocol,
+                    'integrity_algorithm': integrity_algorithm,
+                    'integrity_key': {
+                        'length': len(integrity_key),
+                        'data': integrity_key,
+                    },
+                    'crypto_algorithm': crypto_algorithm,
+                    'crypto_key': {
+                        'length': len(crypto_key),
+                        'data': crypto_key,
+                    },
+                    'flags': flags,
+                }
+            })
 
     def ipsec_sa_dump(self, sa_id=None):
         return self.api(self.papi.ipsec_sa_dump,
                         {'sa_id': sa_id if sa_id else 0xffffffff})
 
-    def ipsec_spd_add_del_entry(self,
+    def ipsec_spd_entry_add_del(self,
                                 spd_id,
                                 sa_id,
                                 local_address_start,
@@ -3464,24 +3464,28 @@
         :param is_add: (Default value = 1)
         """
         return self.api(
-            self.papi.ipsec_spd_add_del_entry,
-            {'spd_id': spd_id,
-             'sa_id': sa_id,
-             'local_address_start': local_address_start,
-             'local_address_stop': local_address_stop,
-             'remote_address_start': remote_address_start,
-             'remote_address_stop': remote_address_stop,
-             'local_port_start': local_port_start,
-             'local_port_stop': local_port_stop,
-             'remote_port_start': remote_port_start,
-             'remote_port_stop': remote_port_stop,
-             'is_add': is_add,
-             'protocol': protocol,
-             'policy': policy,
-             'priority': priority,
-             'is_outbound': is_outbound,
-             'is_ipv6': is_ipv6,
-             'is_ip_any': is_ip_any})
+            self.papi.ipsec_spd_entry_add_del,
+            {
+                'is_add': is_add,
+                'entry':
+                {
+                    'spd_id': spd_id,
+                    'sa_id': sa_id,
+                    'local_address_start': local_address_start,
+                    'local_address_stop': local_address_stop,
+                    'remote_address_start': remote_address_start,
+                    'remote_address_stop': remote_address_stop,
+                    'local_port_start': local_port_start,
+                    'local_port_stop': local_port_stop,
+                    'remote_port_start': remote_port_start,
+                    'remote_port_stop': remote_port_stop,
+                    'protocol': protocol,
+                    'policy': policy,
+                    'priority': priority,
+                    'is_outbound': is_outbound,
+                    'is_ip_any': is_ip_any
+                }
+            })
 
     def ipsec_spd_dump(self, spd_id, sa_id=0xffffffff):
         return self.api(self.papi.ipsec_spd_dump,