Revert "ipsec: Use the new tunnel API types to add flow label and TTL copy"

This reverts commit c7eaa711f3e25580687df0618e9ca80d3dc85e5f.

Reason for revert: The jenkins job named 'vpp-merge-master-ubuntu1804-x86_64' had 2 IPv6 AH tests fail after the change was merged. Those 2 tests also failed the next time that job ran after an unrelated change was merged.

Change-Id: I0e2c3ee895114029066c82624e79807af575b6c0
Signed-off-by: Matthew Smith <mgsmith@netgate.com>
diff --git a/src/plugins/dpdk/ipsec/esp_encrypt.c b/src/plugins/dpdk/ipsec/esp_encrypt.c
index f50291f..984bb64 100644
--- a/src/plugins/dpdk/ipsec/esp_encrypt.c
+++ b/src/plugins/dpdk/ipsec/esp_encrypt.c
@@ -357,9 +357,9 @@
 		    clib_host_to_net_u32 (0xfe320000);
 
 		  oh0->ip4.src_address.as_u32 =
-		    sa0->tunnel.t_src.ip.ip4.as_u32;
+		    sa0->tunnel_src_addr.ip4.as_u32;
 		  oh0->ip4.dst_address.as_u32 =
-		    sa0->tunnel.t_dst.ip.ip4.as_u32;
+		    sa0->tunnel_dst_addr.ip4.as_u32;
 
 		  if (ipsec_sa_is_set_UDP_ENCAP (sa0))
 		    {
@@ -392,13 +392,13 @@
 		  oh6_0->ip6.protocol = IP_PROTOCOL_IPSEC_ESP;
 		  oh6_0->ip6.hop_limit = 254;
 		  oh6_0->ip6.src_address.as_u64[0] =
-		    sa0->tunnel.t_src.ip.ip6.as_u64[0];
+		    sa0->tunnel_src_addr.ip6.as_u64[0];
 		  oh6_0->ip6.src_address.as_u64[1] =
-		    sa0->tunnel.t_src.ip.ip6.as_u64[1];
+		    sa0->tunnel_src_addr.ip6.as_u64[1];
 		  oh6_0->ip6.dst_address.as_u64[0] =
-		    sa0->tunnel.t_dst.ip.ip6.as_u64[0];
+		    sa0->tunnel_dst_addr.ip6.as_u64[0];
 		  oh6_0->ip6.dst_address.as_u64[1] =
-		    sa0->tunnel.t_dst.ip.ip6.as_u64[1];
+		    sa0->tunnel_dst_addr.ip6.as_u64[1];
 		  esp0 = &oh6_0->esp;
 		  oh6_0->esp.spi = clib_host_to_net_u32 (sa0->spi);
 		  oh6_0->esp.seq = clib_host_to_net_u32 (sa0->seq);
diff --git a/src/plugins/ikev2/ikev2.c b/src/plugins/ikev2/ikev2.c
index 0df7faa..aa57deb 100644
--- a/src/plugins/ikev2/ikev2.c
+++ b/src/plugins/ikev2/ikev2.c
@@ -1823,8 +1823,8 @@
   u32 remote_spi;
   ipsec_crypto_alg_t encr_type;
   ipsec_integ_alg_t integ_type;
-  ip_address_t local_ip;
-  ip_address_t remote_ip;
+  ip46_address_t local_ip;
+  ip46_address_t remote_ip;
   ipsec_key_t loc_ckey, rem_ckey, loc_ikey, rem_ikey;
   u8 is_rekey;
   u32 old_remote_sa_id;
@@ -1839,32 +1839,12 @@
   ikev2_main_t *km = &ikev2_main;
   u32 sw_if_index;
   int rv = 0;
-  tunnel_t tun_in = {
-    .t_flags = TUNNEL_FLAG_NONE,
-    .t_encap_decap_flags = TUNNEL_ENCAP_DECAP_FLAG_NONE,
-    .t_dscp = 0,
-    .t_mode = TUNNEL_MODE_P2P,
-    .t_table_id = 0,
-    .t_hop_limit = 255,
-    .t_src = a->local_ip,
-    .t_dst = a->remote_ip,
-  };
-  tunnel_t tun_out = {
-    .t_flags = TUNNEL_FLAG_NONE,
-    .t_encap_decap_flags = TUNNEL_ENCAP_DECAP_FLAG_NONE,
-    .t_dscp = 0,
-    .t_mode = TUNNEL_MODE_P2P,
-    .t_table_id = 0,
-    .t_hop_limit = 255,
-    .t_src = a->remote_ip,
-    .t_dst = a->local_ip,
-  };
 
   if (~0 == a->sw_if_index)
     {
       /* no tunnel associated with the SA/profile - create a new one */
-      rv = ipip_add_tunnel (IPIP_TRANSPORT_IP4, ~0, &ip_addr_46 (&a->local_ip),
-			    &ip_addr_46 (&a->remote_ip), 0,
+      rv = ipip_add_tunnel (IPIP_TRANSPORT_IP4, ~0,
+			    &a->local_ip, &a->remote_ip, 0,
 			    TUNNEL_ENCAP_DECAP_FLAG_NONE, IP_DSCP_CS0,
 			    TUNNEL_MODE_P2P, &sw_if_index);
 
@@ -1903,18 +1883,24 @@
       vec_add1 (sas_in, a->old_remote_sa_id);
     }
 
-  rv = ipsec_sa_add_and_lock (a->local_sa_id, a->local_spi, IPSEC_PROTOCOL_ESP,
-			      a->encr_type, &a->loc_ckey, a->integ_type,
-			      &a->loc_ikey, a->flags, a->salt_local,
-			      a->src_port, a->dst_port, &tun_out, NULL);
+  rv = ipsec_sa_add_and_lock (a->local_sa_id,
+			      a->local_spi,
+			      IPSEC_PROTOCOL_ESP, a->encr_type,
+			      &a->loc_ckey, a->integ_type, &a->loc_ikey,
+			      a->flags, 0, a->salt_local, &a->local_ip,
+			      &a->remote_ip, TUNNEL_ENCAP_DECAP_FLAG_NONE,
+			      IP_DSCP_CS0, NULL, a->src_port, a->dst_port);
   if (rv)
     goto err0;
 
-  rv = ipsec_sa_add_and_lock (
-    a->remote_sa_id, a->remote_spi, IPSEC_PROTOCOL_ESP, a->encr_type,
-    &a->rem_ckey, a->integ_type, &a->rem_ikey,
-    (a->flags | IPSEC_SA_FLAG_IS_INBOUND), a->salt_remote,
-    a->ipsec_over_udp_port, a->ipsec_over_udp_port, &tun_in, NULL);
+  rv = ipsec_sa_add_and_lock (a->remote_sa_id, a->remote_spi,
+			      IPSEC_PROTOCOL_ESP, a->encr_type, &a->rem_ckey,
+			      a->integ_type, &a->rem_ikey,
+			      (a->flags | IPSEC_SA_FLAG_IS_INBOUND), 0,
+			      a->salt_remote, &a->remote_ip,
+			      &a->local_ip, TUNNEL_ENCAP_DECAP_FLAG_NONE,
+			      IP_DSCP_CS0, NULL,
+			      a->ipsec_over_udp_port, a->ipsec_over_udp_port);
   if (rv)
     goto err1;
 
@@ -1958,16 +1944,16 @@
 
   if (sa->is_initiator)
     {
-      ip_address_copy (&a.local_ip, &sa->iaddr);
-      ip_address_copy (&a.remote_ip, &sa->raddr);
+      ip_address_to_46 (&sa->iaddr, &a.local_ip);
+      ip_address_to_46 (&sa->raddr, &a.remote_ip);
       proposals = child->r_proposals;
       a.local_spi = child->r_proposals[0].spi;
       a.remote_spi = child->i_proposals[0].spi;
     }
   else
     {
-      ip_address_copy (&a.local_ip, &sa->raddr);
-      ip_address_copy (&a.remote_ip, &sa->iaddr);
+      ip_address_to_46 (&sa->raddr, &a.local_ip);
+      ip_address_to_46 (&sa->iaddr, &a.remote_ip);
       proposals = child->i_proposals;
       a.local_spi = child->i_proposals[0].spi;
       a.remote_spi = child->r_proposals[0].spi;
diff --git a/src/vnet/ipsec/ah_encrypt.c b/src/vnet/ipsec/ah_encrypt.c
index 7213e47..a4c3491 100644
--- a/src/vnet/ipsec/ah_encrypt.c
+++ b/src/vnet/ipsec/ah_encrypt.c
@@ -251,7 +251,7 @@
 	  oh6_0->ip6.ip_version_traffic_class_and_flow_label =
 	    ih6_0->ip6.ip_version_traffic_class_and_flow_label;
 
-	  ip6_set_dscp_network_order (&oh6_0->ip6, sa0->tunnel.t_dscp);
+	  ip6_set_dscp_network_order (&oh6_0->ip6, sa0->dscp);
 
 	  tunnel_encap_fixup_6o6 (sa0->tunnel_flags,
 				  &ih6_0->ip6, &oh6_0->ip6);
@@ -287,8 +287,8 @@
 	  oh0 = vlib_buffer_get_current (b[0]);
 	  pd->ttl = ih0->ip4.ttl;
 
-	  if (sa0->tunnel.t_dscp)
-	    pd->tos = sa0->tunnel.t_dscp << 2;
+	  if (sa0->dscp)
+	    pd->tos = sa0->dscp << 2;
 	  else
 	    {
 	      pd->tos = ih0->ip4.tos;
diff --git a/src/vnet/ipsec/esp_encrypt.c b/src/vnet/ipsec/esp_encrypt.c
index e64de26..08f82db 100644
--- a/src/vnet/ipsec/esp_encrypt.c
+++ b/src/vnet/ipsec/esp_encrypt.c
@@ -829,7 +829,6 @@
 	    }
 	  else
 	    next[0] = ESP_ENCRYPT_NEXT_INTERFACE_OUTPUT;
-	  b[0]->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
 	}
       else			/* transport mode */
 	{
diff --git a/src/vnet/ipsec/ipsec.api b/src/vnet/ipsec/ipsec.api
index 8d4580a..c009d8d 100644
--- a/src/vnet/ipsec/ipsec.api
+++ b/src/vnet/ipsec/ipsec.api
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-option version = "5.0.1";
+option version = "5.0.0";
 
 import "vnet/ipsec/ipsec_types.api";
 import "vnet/interface_types.api";
@@ -191,7 +191,6 @@
  */
 define ipsec_sad_entry_add_del
 {
-  option deprecated;
   u32 client_index;
   u32 context;
   bool is_add;
@@ -204,17 +203,8 @@
   bool is_add;
   vl_api_ipsec_sad_entry_v2_t entry;
 };
-define ipsec_sad_entry_add_del_v3
-{
-  u32 client_index;
-  u32 context;
-  bool is_add;
-  vl_api_ipsec_sad_entry_v3_t entry;
-};
-
 define ipsec_sad_entry_add_del_reply
 {
-  option deprecated;
   u32 context;
   i32 retval;
   u32 stat_index;
@@ -225,12 +215,6 @@
   i32 retval;
   u32 stat_index;
 };
-define ipsec_sad_entry_add_del_v3_reply
-{
-  u32 context;
-  i32 retval;
-  u32 stat_index;
-};
 
 /** \brief Add or Update Protection for a tunnel with IPSEC
 
@@ -394,7 +378,6 @@
 */
 define ipsec_sa_dump
 {
-  option deprecated;
   u32 client_index;
   u32 context;
   u32 sa_id;
@@ -405,12 +388,6 @@
   u32 context;
   u32 sa_id;
 };
-define ipsec_sa_v3_dump
-{
-  u32 client_index;
-  u32 context;
-  u32 sa_id;
-};
 
 /** \brief IPsec security association database response
     @param context - sender context which was passed in the request
@@ -425,7 +402,6 @@
     @param stat_index - index for the SA in the stats segment @ /net/ipsec/sa
 */
 define ipsec_sa_details {
-  option deprecated;
   u32 context;
   vl_api_ipsec_sad_entry_t entry;
 
@@ -449,17 +425,6 @@
 
   u32 stat_index;
 };
-define ipsec_sa_v3_details {
-  u32 context;
-  vl_api_ipsec_sad_entry_v3_t entry;
-
-  vl_api_interface_index_t sw_if_index;
-  u64 seq_outbound;
-  u64 last_seq_inbound;
-  u64 replay_window;
-
-  u32 stat_index;
-};
 
 /** \brief Dump IPsec backends
     @param client_index - opaque cookie to identify the sender
diff --git a/src/vnet/ipsec/ipsec_api.c b/src/vnet/ipsec/ipsec_api.c
index a3e0545..1a419e5 100644
--- a/src/vnet/ipsec/ipsec_api.c
+++ b/src/vnet/ipsec/ipsec_api.c
@@ -54,28 +54,26 @@
 
 #include <vlibapi/api_helper_macros.h>
 
-#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_ENTRY_ADD_DEL, ipsec_spd_entry_add_del)                        \
-  _ (IPSEC_SAD_ENTRY_ADD_DEL, ipsec_sad_entry_add_del)                        \
-  _ (IPSEC_SAD_ENTRY_ADD_DEL_V2, ipsec_sad_entry_add_del_v2)                  \
-  _ (IPSEC_SAD_ENTRY_ADD_DEL_V3, ipsec_sad_entry_add_del_v3)                  \
-  _ (IPSEC_SA_DUMP, ipsec_sa_dump)                                            \
-  _ (IPSEC_SA_V2_DUMP, ipsec_sa_v2_dump)                                      \
-  _ (IPSEC_SA_V3_DUMP, ipsec_sa_v3_dump)                                      \
-  _ (IPSEC_SPDS_DUMP, ipsec_spds_dump)                                        \
-  _ (IPSEC_SPD_DUMP, ipsec_spd_dump)                                          \
-  _ (IPSEC_SPD_INTERFACE_DUMP, ipsec_spd_interface_dump)                      \
-  _ (IPSEC_ITF_CREATE, ipsec_itf_create)                                      \
-  _ (IPSEC_ITF_DELETE, ipsec_itf_delete)                                      \
-  _ (IPSEC_ITF_DUMP, ipsec_itf_dump)                                          \
-  _ (IPSEC_SELECT_BACKEND, ipsec_select_backend)                              \
-  _ (IPSEC_BACKEND_DUMP, ipsec_backend_dump)                                  \
-  _ (IPSEC_TUNNEL_PROTECT_UPDATE, ipsec_tunnel_protect_update)                \
-  _ (IPSEC_TUNNEL_PROTECT_DEL, ipsec_tunnel_protect_del)                      \
-  _ (IPSEC_TUNNEL_PROTECT_DUMP, ipsec_tunnel_protect_dump)                    \
-  _ (IPSEC_SET_ASYNC_MODE, ipsec_set_async_mode)
+#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_ENTRY_ADD_DEL, ipsec_spd_entry_add_del)             \
+_(IPSEC_SAD_ENTRY_ADD_DEL, ipsec_sad_entry_add_del)             \
+_(IPSEC_SAD_ENTRY_ADD_DEL_V2, ipsec_sad_entry_add_del_v2)       \
+_(IPSEC_SA_DUMP, ipsec_sa_dump)                                 \
+_(IPSEC_SA_V2_DUMP, ipsec_sa_v2_dump)                           \
+_(IPSEC_SPDS_DUMP, ipsec_spds_dump)                             \
+_(IPSEC_SPD_DUMP, ipsec_spd_dump)                               \
+_(IPSEC_SPD_INTERFACE_DUMP, ipsec_spd_interface_dump)		\
+_(IPSEC_ITF_CREATE, ipsec_itf_create)                           \
+_(IPSEC_ITF_DELETE, ipsec_itf_delete)                           \
+_(IPSEC_ITF_DUMP, ipsec_itf_dump)                               \
+_(IPSEC_SELECT_BACKEND, ipsec_select_backend)                   \
+_(IPSEC_BACKEND_DUMP, ipsec_backend_dump)                       \
+_(IPSEC_TUNNEL_PROTECT_UPDATE, ipsec_tunnel_protect_update)     \
+_(IPSEC_TUNNEL_PROTECT_DEL, ipsec_tunnel_protect_del)           \
+_(IPSEC_TUNNEL_PROTECT_DUMP, ipsec_tunnel_protect_dump)         \
+_(IPSEC_SET_ASYNC_MODE, ipsec_set_async_mode)
 
 static void
 vl_api_ipsec_spd_add_del_t_handler (vl_api_ipsec_spd_add_del_t * mp)
@@ -337,21 +335,17 @@
 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_entry_add_del_reply_t *rmp;
+  ip46_address_t tun_src = { }, tun_dst =
+  {
+  };
   ipsec_key_t crypto_key, integ_key;
   ipsec_crypto_alg_t crypto_alg;
   ipsec_integ_alg_t integ_alg;
   ipsec_protocol_t proto;
   ipsec_sa_flags_t flags;
   u32 id, spi, sa_index = ~0;
-  tunnel_t tun = {
-    .t_flags = TUNNEL_FLAG_NONE,
-    .t_encap_decap_flags = TUNNEL_ENCAP_DECAP_FLAG_NONE,
-    .t_dscp = 0,
-    .t_mode = TUNNEL_MODE_P2P,
-    .t_table_id = 0,
-    .t_hop_limit = 255,
-  };
   int rv;
 
 #if WITH_LIBSSL > 0
@@ -379,14 +373,19 @@
 
   flags = ipsec_sa_flags_decode (mp->entry.flags);
 
-  ip_address_decode2 (&mp->entry.tunnel_src, &tun.t_src);
-  ip_address_decode2 (&mp->entry.tunnel_dst, &tun.t_dst);
+  ip_address_decode (&mp->entry.tunnel_src, &tun_src);
+  ip_address_decode (&mp->entry.tunnel_dst, &tun_dst);
 
   if (mp->is_add)
-    rv = ipsec_sa_add_and_lock (
-      id, spi, proto, crypto_alg, &crypto_key, integ_alg, &integ_key, flags,
-      mp->entry.salt, htons (mp->entry.udp_src_port),
-      htons (mp->entry.udp_dst_port), &tun, &sa_index);
+    rv = ipsec_sa_add_and_lock (id, spi, proto,
+				crypto_alg, &crypto_key,
+				integ_alg, &integ_key, flags,
+				0, mp->entry.salt, &tun_src, &tun_dst,
+				TUNNEL_ENCAP_DECAP_FLAG_NONE,
+				IP_DSCP_CS0,
+				&sa_index,
+				htons (mp->entry.udp_src_port),
+				htons (mp->entry.udp_dst_port));
   else
     rv = ipsec_sa_unlock_id (id);
 
@@ -408,6 +407,10 @@
 {
   vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main ();
   vl_api_ipsec_sad_entry_add_del_v2_reply_t *rmp;
+  ip46_address_t tun_src = { }, tun_dst =
+  {
+  };
+  tunnel_encap_decap_flags_t tunnel_flags;
   ipsec_key_t crypto_key, integ_key;
   ipsec_crypto_alg_t crypto_alg;
   ipsec_integ_alg_t integ_alg;
@@ -415,14 +418,6 @@
   ipsec_sa_flags_t flags;
   u32 id, spi, sa_index = ~0;
   int rv;
-  tunnel_t tun = {
-    .t_flags = TUNNEL_FLAG_NONE,
-    .t_encap_decap_flags = TUNNEL_ENCAP_DECAP_FLAG_NONE,
-    .t_dscp = 0,
-    .t_mode = TUNNEL_MODE_P2P,
-    .t_table_id = htonl (mp->entry.tx_table_id),
-    .t_hop_limit = 255,
-  };
 
 #if WITH_LIBSSL > 0
 
@@ -444,8 +439,8 @@
   if (rv)
     goto out;
 
-  rv = tunnel_encap_decap_flags_decode (mp->entry.tunnel_flags,
-					&tun.t_encap_decap_flags);
+  rv =
+    tunnel_encap_decap_flags_decode (mp->entry.tunnel_flags, &tunnel_flags);
 
   if (rv)
     goto out;
@@ -454,16 +449,16 @@
   ipsec_key_decode (&mp->entry.integrity_key, &integ_key);
 
   flags = ipsec_sa_flags_decode (mp->entry.flags);
-  tun.t_dscp = ip_dscp_decode (mp->entry.dscp);
 
-  ip_address_decode2 (&mp->entry.tunnel_src, &tun.t_src);
-  ip_address_decode2 (&mp->entry.tunnel_dst, &tun.t_dst);
+  ip_address_decode (&mp->entry.tunnel_src, &tun_src);
+  ip_address_decode (&mp->entry.tunnel_dst, &tun_dst);
 
   if (mp->is_add)
     rv = ipsec_sa_add_and_lock (
       id, spi, proto, crypto_alg, &crypto_key, integ_alg, &integ_key, flags,
-      mp->entry.salt, htons (mp->entry.udp_src_port),
-      htons (mp->entry.udp_dst_port), &tun, &sa_index);
+      htonl (mp->entry.tx_table_id), mp->entry.salt, &tun_src, &tun_dst,
+      tunnel_flags, ip_dscp_decode (mp->entry.dscp), &sa_index,
+      htons (mp->entry.udp_src_port), htons (mp->entry.udp_dst_port));
   else
     rv = ipsec_sa_unlock_id (id);
 
@@ -481,70 +476,6 @@
 }
 
 static void
-vl_api_ipsec_sad_entry_add_del_v3_t_handler (
-  vl_api_ipsec_sad_entry_add_del_v3_t *mp)
-{
-  vl_api_ipsec_sad_entry_add_del_v3_reply_t *rmp;
-  ipsec_key_t crypto_key, integ_key;
-  ipsec_crypto_alg_t crypto_alg;
-  ipsec_integ_alg_t integ_alg;
-  ipsec_protocol_t proto;
-  ipsec_sa_flags_t flags;
-  u32 id, spi, sa_index = ~0;
-  tunnel_t tun;
-  int rv;
-
-#if WITH_LIBSSL > 0
-
-  id = ntohl (mp->entry.sad_id);
-  spi = ntohl (mp->entry.spi);
-
-  rv = ipsec_proto_decode (mp->entry.protocol, &proto);
-
-  if (rv)
-    goto out;
-
-  rv = ipsec_crypto_algo_decode (mp->entry.crypto_algorithm, &crypto_alg);
-
-  if (rv)
-    goto out;
-
-  rv = ipsec_integ_algo_decode (mp->entry.integrity_algorithm, &integ_alg);
-
-  if (rv)
-    goto out;
-
-  flags = ipsec_sa_flags_decode (mp->entry.flags);
-
-  if (flags & IPSEC_SA_FLAG_IS_TUNNEL)
-    {
-      rv = tunnel_decode (&mp->entry.tunnel, &tun);
-
-      if (rv)
-	goto out;
-    }
-
-  ipsec_key_decode (&mp->entry.crypto_key, &crypto_key);
-  ipsec_key_decode (&mp->entry.integrity_key, &integ_key);
-
-  if (mp->is_add)
-    rv = ipsec_sa_add_and_lock (
-      id, spi, proto, crypto_alg, &crypto_key, integ_alg, &integ_key, flags,
-      mp->entry.salt, htons (mp->entry.udp_src_port),
-      htons (mp->entry.udp_dst_port), &tun, &sa_index);
-  else
-    rv = ipsec_sa_unlock_id (id);
-
-#else
-  rv = VNET_API_ERROR_UNIMPLEMENTED;
-#endif
-
-out:
-  REPLY_MACRO2 (VL_API_IPSEC_SAD_ENTRY_ADD_DEL_V3_REPLY,
-		{ rmp->stat_index = htonl (sa_index); });
-}
-
-static void
 send_ipsec_spds_details (ipsec_spd_t * spd, vl_api_registration_t * reg,
 			 u32 context)
 {
@@ -815,7 +746,8 @@
   mp->entry.sad_id = htonl (sa->id);
   mp->entry.spi = htonl (sa->spi);
   mp->entry.protocol = ipsec_proto_encode (sa->protocol);
-  mp->entry.tx_table_id = htonl (sa->tunnel.t_table_id);
+  mp->entry.tx_table_id =
+    htonl (fib_table_get_table_id (sa->tx_fib_index, FIB_PROTOCOL_IP4));
 
   mp->entry.crypto_algorithm = ipsec_crypto_algo_encode (sa->crypto_alg);
   ipsec_key_encode (&sa->crypto_key, &mp->entry.crypto_key);
@@ -841,8 +773,10 @@
 
   if (ipsec_sa_is_set_IS_TUNNEL (sa))
     {
-      ip_address_encode2 (&sa->tunnel.t_src, &mp->entry.tunnel_src);
-      ip_address_encode2 (&sa->tunnel.t_dst, &mp->entry.tunnel_dst);
+      ip_address_encode (&sa->tunnel_src_addr, IP46_TYPE_ANY,
+			 &mp->entry.tunnel_src);
+      ip_address_encode (&sa->tunnel_dst_addr, IP46_TYPE_ANY,
+			 &mp->entry.tunnel_dst);
     }
   if (ipsec_sa_is_set_UDP_ENCAP (sa))
     {
@@ -904,7 +838,8 @@
   mp->entry.sad_id = htonl (sa->id);
   mp->entry.spi = htonl (sa->spi);
   mp->entry.protocol = ipsec_proto_encode (sa->protocol);
-  mp->entry.tx_table_id = htonl (sa->tunnel.t_table_id);
+  mp->entry.tx_table_id =
+    htonl (fib_table_get_table_id (sa->tx_fib_index, FIB_PROTOCOL_IP4));
 
   mp->entry.crypto_algorithm = ipsec_crypto_algo_encode (sa->crypto_alg);
   ipsec_key_encode (&sa->crypto_key, &mp->entry.crypto_key);
@@ -930,8 +865,10 @@
 
   if (ipsec_sa_is_set_IS_TUNNEL (sa))
     {
-      ip_address_encode2 (&sa->tunnel.t_src, &mp->entry.tunnel_src);
-      ip_address_encode2 (&sa->tunnel.t_dst, &mp->entry.tunnel_dst);
+      ip_address_encode (&sa->tunnel_src_addr, IP46_TYPE_ANY,
+			 &mp->entry.tunnel_src);
+      ip_address_encode (&sa->tunnel_dst_addr, IP46_TYPE_ANY,
+			 &mp->entry.tunnel_dst);
     }
   if (ipsec_sa_is_set_UDP_ENCAP (sa))
     {
@@ -939,9 +876,8 @@
       mp->entry.udp_dst_port = sa->udp_hdr.dst_port;
     }
 
-  mp->entry.tunnel_flags =
-    tunnel_encap_decap_flags_encode (sa->tunnel.t_encap_decap_flags);
-  mp->entry.dscp = ip_dscp_encode (sa->tunnel.t_dscp);
+  mp->entry.tunnel_flags = tunnel_encap_decap_flags_encode (sa->tunnel_flags);
+  mp->entry.dscp = ip_dscp_encode (sa->dscp);
 
   mp->seq_outbound = clib_host_to_net_u64 (((u64) sa->seq));
   mp->last_seq_inbound = clib_host_to_net_u64 (((u64) sa->last_seq));
@@ -961,7 +897,7 @@
 }
 
 static void
-vl_api_ipsec_sa_v2_dump_t_handler (vl_api_ipsec_sa_v2_dump_t *mp)
+vl_api_ipsec_sa_v2_dump_t_handler (vl_api_ipsec_sa_dump_t * mp)
 {
   vl_api_registration_t *reg;
 
@@ -982,92 +918,6 @@
 #endif
 }
 
-static walk_rc_t
-send_ipsec_sa_v3_details (ipsec_sa_t *sa, void *arg)
-{
-  ipsec_dump_walk_ctx_t *ctx = arg;
-  vl_api_ipsec_sa_v3_details_t *mp;
-  ipsec_main_t *im = &ipsec_main;
-
-  mp = vl_msg_api_alloc (sizeof (*mp));
-  clib_memset (mp, 0, sizeof (*mp));
-  mp->_vl_msg_id = ntohs (VL_API_IPSEC_SA_V3_DETAILS);
-  mp->context = ctx->context;
-
-  mp->entry.sad_id = htonl (sa->id);
-  mp->entry.spi = htonl (sa->spi);
-  mp->entry.protocol = ipsec_proto_encode (sa->protocol);
-
-  mp->entry.crypto_algorithm = ipsec_crypto_algo_encode (sa->crypto_alg);
-  ipsec_key_encode (&sa->crypto_key, &mp->entry.crypto_key);
-
-  mp->entry.integrity_algorithm = ipsec_integ_algo_encode (sa->integ_alg);
-  ipsec_key_encode (&sa->integ_key, &mp->entry.integrity_key);
-
-  mp->entry.flags = ipsec_sad_flags_encode (sa);
-  mp->entry.salt = clib_host_to_net_u32 (sa->salt);
-
-  if (ipsec_sa_is_set_IS_PROTECT (sa))
-    {
-      ipsec_sa_dump_match_ctx_t ctx = {
-	.sai = sa - im->sad,
-	.sw_if_index = ~0,
-      };
-      ipsec_tun_protect_walk (ipsec_sa_dump_match_sa, &ctx);
-
-      mp->sw_if_index = htonl (ctx.sw_if_index);
-    }
-  else
-    mp->sw_if_index = ~0;
-
-  if (ipsec_sa_is_set_IS_TUNNEL (sa))
-    tunnel_encode (&sa->tunnel, &mp->entry.tunnel);
-
-  if (ipsec_sa_is_set_UDP_ENCAP (sa))
-    {
-      mp->entry.udp_src_port = sa->udp_hdr.src_port;
-      mp->entry.udp_dst_port = sa->udp_hdr.dst_port;
-    }
-
-  mp->seq_outbound = clib_host_to_net_u64 (((u64) sa->seq));
-  mp->last_seq_inbound = clib_host_to_net_u64 (((u64) sa->last_seq));
-  if (ipsec_sa_is_set_USE_ESN (sa))
-    {
-      mp->seq_outbound |= (u64) (clib_host_to_net_u32 (sa->seq_hi));
-      mp->last_seq_inbound |= (u64) (clib_host_to_net_u32 (sa->last_seq_hi));
-    }
-  if (ipsec_sa_is_set_USE_ANTI_REPLAY (sa))
-    mp->replay_window = clib_host_to_net_u64 (sa->replay_window);
-
-  mp->stat_index = clib_host_to_net_u32 (sa->stat_index);
-
-  vl_api_send_msg (ctx->reg, (u8 *) mp);
-
-  return (WALK_CONTINUE);
-}
-
-static void
-vl_api_ipsec_sa_v3_dump_t_handler (vl_api_ipsec_sa_v3_dump_t *mp)
-{
-  vl_api_registration_t *reg;
-
-#if WITH_LIBSSL > 0
-  reg = vl_api_client_index_to_registration (mp->client_index);
-  if (!reg)
-    return;
-
-  ipsec_dump_walk_ctx_t ctx = {
-    .reg = reg,
-    .context = mp->context,
-  };
-
-  ipsec_sa_walk (send_ipsec_sa_v3_details, &ctx);
-
-#else
-  clib_warning ("unimplemented");
-#endif
-}
-
 static void
 vl_api_ipsec_backend_dump_t_handler (vl_api_ipsec_backend_dump_t * mp)
 {
diff --git a/src/vnet/ipsec/ipsec_cli.c b/src/vnet/ipsec/ipsec_cli.c
index eed910e..b708e50 100644
--- a/src/vnet/ipsec/ipsec_cli.c
+++ b/src/vnet/ipsec/ipsec_cli.c
@@ -86,6 +86,9 @@
 			     vlib_cli_command_t * cmd)
 {
   unformat_input_t _line_input, *line_input = &_line_input;
+  ip46_address_t tun_src = { }, tun_dst =
+  {
+  };
   ipsec_crypto_alg_t crypto_alg;
   ipsec_integ_alg_t integ_alg;
   ipsec_protocol_t proto;
@@ -98,7 +101,8 @@
   u16 udp_src, udp_dst;
   int is_add, rv;
   u32 m_args = 0;
-  tunnel_t tun;
+  ip_dscp_t dscp;
+  u32 tx_table_id;
 
   salt = 0;
   error = NULL;
@@ -108,6 +112,8 @@
   integ_alg = IPSEC_INTEG_ALG_NONE;
   crypto_alg = IPSEC_CRYPTO_ALG_NONE;
   udp_src = udp_dst = IPSEC_UDP_PORT_NONE;
+  dscp = IP_DSCP_CS0;
+  tx_table_id = 0;
 
   if (!unformat_user (input, unformat_line_input, line_input))
     return 0;
@@ -143,16 +149,22 @@
       else if (unformat (line_input, "integ-alg %U",
 			 unformat_ipsec_integ_alg, &integ_alg))
 	;
-      else if (unformat (line_input, " %U", unformat_tunnel, &tun))
+      else if (unformat (line_input, "tunnel-src %U",
+			 unformat_ip46_address, &tun_src, IP46_TYPE_ANY))
 	{
 	  flags |= IPSEC_SA_FLAG_IS_TUNNEL;
-	  if (AF_IP6 == tunnel_get_af (&tun))
+	  if (!ip46_address_is_ip4 (&tun_src))
 	    flags |= IPSEC_SA_FLAG_IS_TUNNEL_V6;
 	}
+      else if (unformat (line_input, "tunnel-dst %U",
+			 unformat_ip46_address, &tun_dst, IP46_TYPE_ANY))
+	;
       else if (unformat (line_input, "udp-src-port %d", &i))
 	udp_src = i;
       else if (unformat (line_input, "udp-dst-port %d", &i))
 	udp_dst = i;
+      else if (unformat (line_input, "tx-table-id %d", &tx_table_id))
+	;
       else if (unformat (line_input, "inbound"))
 	flags |= IPSEC_SA_FLAG_IS_INBOUND;
       else if (unformat (line_input, "use-anti-replay"))
@@ -188,9 +200,12 @@
 	  error = clib_error_return (0, "missing spi");
 	  goto done;
 	}
-      rv = ipsec_sa_add_and_lock (id, spi, proto, crypto_alg, &ck, integ_alg,
-				  &ik, flags, clib_host_to_net_u32 (salt),
-				  udp_src, udp_dst, &tun, &sai);
+      rv = ipsec_sa_add_and_lock (id, spi, proto, crypto_alg,
+				  &ck, integ_alg, &ik, flags,
+				  tx_table_id, clib_host_to_net_u32 (salt),
+				  &tun_src, &tun_dst,
+				  TUNNEL_ENCAP_DECAP_FLAG_NONE, dscp,
+				  &sai, udp_src, udp_dst);
     }
   else
     {
diff --git a/src/vnet/ipsec/ipsec_format.c b/src/vnet/ipsec/ipsec_format.c
index 001aa01..19321e7 100644
--- a/src/vnet/ipsec/ipsec_format.c
+++ b/src/vnet/ipsec/ipsec_format.c
@@ -273,6 +273,7 @@
   ipsec_format_flags_t flags = va_arg (*args, ipsec_format_flags_t);
   ipsec_main_t *im = &ipsec_main;
   vlib_counter_t counts;
+  u32 tx_table_id;
   ipsec_sa_t *sa;
 
   if (pool_is_free_index (im->sad, sai))
@@ -317,7 +318,26 @@
   s = format (s, "\n   packets %u bytes %u", counts.packets, counts.bytes);
 
   if (ipsec_sa_is_set_IS_TUNNEL (sa))
-    s = format (s, "\n%U", format_tunnel, &sa->tunnel, 3);
+    {
+      tx_table_id = fib_table_get_table_id (
+	sa->tx_fib_index,
+	(ipsec_sa_is_set_IS_TUNNEL_V6 (sa) ? FIB_PROTOCOL_IP6 :
+					     FIB_PROTOCOL_IP4));
+      s = format (s, "\n   table-ID %d tunnel %U src %U dst %U flags %U",
+		  tx_table_id,
+		  format_ip_dscp, sa->dscp,
+		  format_ip46_address, &sa->tunnel_src_addr, IP46_TYPE_ANY,
+		  format_ip46_address, &sa->tunnel_dst_addr, IP46_TYPE_ANY,
+		  format_tunnel_encap_decap_flags, sa->tunnel_flags);
+      if (!ipsec_sa_is_set_IS_INBOUND (sa))
+	{
+	  s =
+	    format (s, "\n    resovle via fib-entry: %d",
+		    sa->fib_entry_index);
+	  s = format (s, "\n    stacked on:");
+	  s = format (s, "\n      %U", format_dpo_id, &sa->dpo, 6);
+	}
+    }
 
 done:
   return (s);
diff --git a/src/vnet/ipsec/ipsec_input.c b/src/vnet/ipsec/ipsec_input.c
index 2ebc6c5..aa7627d 100644
--- a/src/vnet/ipsec/ipsec_input.c
+++ b/src/vnet/ipsec/ipsec_input.c
@@ -118,10 +118,10 @@
 
     if (ipsec_sa_is_set_IS_TUNNEL (s))
       {
-	if (da != clib_net_to_host_u32 (s->tunnel.t_dst.ip.ip4.as_u32))
+	if (da != clib_net_to_host_u32 (s->tunnel_dst_addr.ip4.as_u32))
 	  continue;
 
-	if (sa != clib_net_to_host_u32 (s->tunnel.t_src.ip.ip4.as_u32))
+	if (sa != clib_net_to_host_u32 (s->tunnel_src_addr.ip4.as_u32))
 	  continue;
 
 	return p;
@@ -174,10 +174,10 @@
 
     if (ipsec_sa_is_set_IS_TUNNEL (s))
       {
-	if (!ip6_address_is_equal (sa, &s->tunnel.t_src.ip.ip6))
+	if (!ip6_address_is_equal (sa, &s->tunnel_src_addr.ip6))
 	  continue;
 
-	if (!ip6_address_is_equal (da, &s->tunnel.t_dst.ip.ip6))
+	if (!ip6_address_is_equal (da, &s->tunnel_dst_addr.ip6))
 	  continue;
 
 	return p;
diff --git a/src/vnet/ipsec/ipsec_itf.c b/src/vnet/ipsec/ipsec_itf.c
index 5f04fcf..4a0f9e7 100644
--- a/src/vnet/ipsec/ipsec_itf.c
+++ b/src/vnet/ipsec/ipsec_itf.c
@@ -70,11 +70,20 @@
   if (hw->flags & VNET_HW_INTERFACE_FLAG_LINK_UP)
     {
       const ipsec_sa_t *sa;
-      fib_prefix_t dst;
 
       sa = ipsec_sa_get (sai);
-      ip_address_to_fib_prefix (&sa->tunnel.t_dst, &dst);
-      adj_midchain_delegate_stack (ai, sa->tunnel.t_fib_index, &dst);
+
+      /* *INDENT-OFF* */
+      const fib_prefix_t dst = {
+        .fp_len = (ipsec_sa_is_set_IS_TUNNEL_V6(sa) ? 128 : 32),
+        .fp_proto = (ipsec_sa_is_set_IS_TUNNEL_V6(sa)?
+                     FIB_PROTOCOL_IP6 :
+                     FIB_PROTOCOL_IP4),
+        .fp_addr = sa->tunnel_dst_addr,
+      };
+      /* *INDENT-ON* */
+
+      adj_midchain_delegate_stack (ai, sa->tx_fib_index, &dst);
     }
   else
     adj_midchain_delegate_unstack (ai);
diff --git a/src/vnet/ipsec/ipsec_sa.c b/src/vnet/ipsec/ipsec_sa.c
index 0a24aa2..515eb25 100644
--- a/src/vnet/ipsec/ipsec_sa.c
+++ b/src/vnet/ipsec/ipsec_sa.c
@@ -72,9 +72,15 @@
 ipsec_sa_stack (ipsec_sa_t * sa)
 {
   ipsec_main_t *im = &ipsec_main;
+  fib_forward_chain_type_t fct;
   dpo_id_t tmp = DPO_INVALID;
 
-  tunnel_contribute_forwarding (&sa->tunnel, &tmp);
+  fct =
+    fib_forw_chain_type_from_fib_proto ((ipsec_sa_is_set_IS_TUNNEL_V6 (sa) ?
+					 FIB_PROTOCOL_IP6 :
+					 FIB_PROTOCOL_IP4));
+
+  fib_entry_contribute_forwarding (sa->fib_entry_index, fct, &tmp);
 
   if (IPSEC_PROTOCOL_AH == sa->protocol)
     dpo_stack_from_node ((ipsec_sa_is_set_IS_TUNNEL_V6 (sa) ?
@@ -166,11 +172,21 @@
 }
 
 int
-ipsec_sa_add_and_lock (u32 id, u32 spi, ipsec_protocol_t proto,
-		       ipsec_crypto_alg_t crypto_alg, const ipsec_key_t *ck,
-		       ipsec_integ_alg_t integ_alg, const ipsec_key_t *ik,
-		       ipsec_sa_flags_t flags, u32 salt, u16 src_port,
-		       u16 dst_port, const tunnel_t *tun, u32 *sa_out_index)
+ipsec_sa_add_and_lock (u32 id,
+		       u32 spi,
+		       ipsec_protocol_t proto,
+		       ipsec_crypto_alg_t crypto_alg,
+		       const ipsec_key_t * ck,
+		       ipsec_integ_alg_t integ_alg,
+		       const ipsec_key_t * ik,
+		       ipsec_sa_flags_t flags,
+		       u32 tx_table_id,
+		       u32 salt,
+		       const ip46_address_t * tun_src,
+		       const ip46_address_t * tun_dst,
+		       tunnel_encap_decap_flags_t tunnel_flags,
+		       ip_dscp_t dscp,
+		       u32 * sa_out_index, u16 src_port, u16 dst_port)
 {
   vlib_main_t *vm = vlib_get_main ();
   ipsec_main_t *im = &ipsec_main;
@@ -178,7 +194,6 @@
   ipsec_sa_t *sa;
   u32 sa_index;
   uword *p;
-  int rv;
 
   p = hash_get (im->sa_index_by_sa_id, id);
   if (p)
@@ -193,12 +208,13 @@
   vlib_validate_combined_counter (&ipsec_sa_counters, sa_index);
   vlib_zero_combined_counter (&ipsec_sa_counters, sa_index);
 
-  tunnel_copy (tun, &sa->tunnel);
   sa->id = id;
   sa->spi = spi;
   sa->stat_index = sa_index;
   sa->protocol = proto;
   sa->flags = flags;
+  sa->tunnel_flags = tunnel_flags;
+  sa->dscp = dscp;
   sa->salt = salt;
   sa->thread_index = (vlib_num_workers ()) ? ~0 : 0;
   if (integ_alg != IPSEC_INTEG_ALG_NONE)
@@ -210,6 +226,8 @@
   ipsec_sa_set_async_op_ids (sa);
 
   clib_memcpy (&sa->crypto_key, ck, sizeof (sa->crypto_key));
+  ip46_address_copy (&sa->tunnel_src_addr, tun_src);
+  ip46_address_copy (&sa->tunnel_dst_addr, tun_dst);
 
   sa->crypto_key_index = vnet_crypto_key_add (vm,
 					      im->crypto_algs[crypto_alg].alg,
@@ -263,33 +281,59 @@
 
   if (ipsec_sa_is_set_IS_TUNNEL (sa) && !ipsec_sa_is_set_IS_INBOUND (sa))
     {
-      sa->tunnel_flags = sa->tunnel.t_encap_decap_flags;
-
-      rv = tunnel_resolve (&sa->tunnel, FIB_NODE_TYPE_IPSEC_SA, sa_index);
-
-      if (rv)
+      fib_protocol_t fproto = (ipsec_sa_is_set_IS_TUNNEL_V6 (sa) ?
+			       FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4);
+      fib_prefix_t pfx = {
+	.fp_addr = sa->tunnel_dst_addr,
+	.fp_len = (ipsec_sa_is_set_IS_TUNNEL_V6 (sa) ? 128 : 32),
+	.fp_proto = fproto,
+      };
+      sa->tx_fib_index = fib_table_find (fproto, tx_table_id);
+      if (sa->tx_fib_index == ~((u32) 0))
 	{
 	  pool_put (im->sad, sa);
-	  return rv;
+	  return VNET_API_ERROR_NO_SUCH_FIB;
 	}
+
+      sa->fib_entry_index = fib_entry_track (sa->tx_fib_index,
+					     &pfx,
+					     FIB_NODE_TYPE_IPSEC_SA,
+					     sa_index, &sa->sibling);
       ipsec_sa_stack (sa);
 
       /* generate header templates */
       if (ipsec_sa_is_set_IS_TUNNEL_V6 (sa))
 	{
-	  tunnel_build_v6_hdr (&sa->tunnel,
-			       (ipsec_sa_is_set_UDP_ENCAP (sa) ?
-				  IP_PROTOCOL_UDP :
-				  IP_PROTOCOL_IPSEC_ESP),
-			       &sa->ip6_hdr);
+	  sa->ip6_hdr.ip_version_traffic_class_and_flow_label = 0x60;
+	  ip6_set_dscp_network_order (&sa->ip6_hdr, sa->dscp);
+
+	  sa->ip6_hdr.hop_limit = 254;
+	  sa->ip6_hdr.src_address.as_u64[0] =
+	    sa->tunnel_src_addr.ip6.as_u64[0];
+	  sa->ip6_hdr.src_address.as_u64[1] =
+	    sa->tunnel_src_addr.ip6.as_u64[1];
+	  sa->ip6_hdr.dst_address.as_u64[0] =
+	    sa->tunnel_dst_addr.ip6.as_u64[0];
+	  sa->ip6_hdr.dst_address.as_u64[1] =
+	    sa->tunnel_dst_addr.ip6.as_u64[1];
+	  if (ipsec_sa_is_set_UDP_ENCAP (sa))
+	    sa->ip6_hdr.protocol = IP_PROTOCOL_UDP;
+	  else
+	    sa->ip6_hdr.protocol = IP_PROTOCOL_IPSEC_ESP;
 	}
       else
 	{
-	  tunnel_build_v4_hdr (&sa->tunnel,
-			       (ipsec_sa_is_set_UDP_ENCAP (sa) ?
-				  IP_PROTOCOL_UDP :
-				  IP_PROTOCOL_IPSEC_ESP),
-			       &sa->ip4_hdr);
+	  sa->ip4_hdr.ip_version_and_header_length = 0x45;
+	  sa->ip4_hdr.ttl = 254;
+	  sa->ip4_hdr.src_address.as_u32 = sa->tunnel_src_addr.ip4.as_u32;
+	  sa->ip4_hdr.dst_address.as_u32 = sa->tunnel_dst_addr.ip4.as_u32;
+	  sa->ip4_hdr.tos = sa->dscp << 2;
+
+	  if (ipsec_sa_is_set_UDP_ENCAP (sa))
+	    sa->ip4_hdr.protocol = IP_PROTOCOL_UDP;
+	  else
+	    sa->ip4_hdr.protocol = IP_PROTOCOL_IPSEC_ESP;
+	  sa->ip4_hdr.checksum = ip4_header_checksum (&sa->ip4_hdr);
 	}
     }
 
@@ -326,7 +370,6 @@
 
   sa_index = sa - im->sad;
   hash_unset (im->sa_index_by_sa_id, sa->id);
-  tunnel_unresolve (&sa->tunnel);
 
   /* no recovery possible when deleting an SA */
   (void) ipsec_call_add_del_callbacks (im, sa, sa_index, 0);
@@ -335,7 +378,10 @@
     ipsec_unregister_udp_port (clib_net_to_host_u16 (sa->udp_hdr.dst_port));
 
   if (ipsec_sa_is_set_IS_TUNNEL (sa) && !ipsec_sa_is_set_IS_INBOUND (sa))
-    dpo_reset (&sa->dpo);
+    {
+      fib_entry_untrack (sa->fib_entry_index, sa->sibling);
+      dpo_reset (&sa->dpo);
+    }
   vnet_crypto_key_del (vm, sa->crypto_key_index);
   if (sa->integ_alg != IPSEC_INTEG_ALG_NONE)
     vnet_crypto_key_del (vm, sa->integ_key_index);
diff --git a/src/vnet/ipsec/ipsec_sa.h b/src/vnet/ipsec/ipsec_sa.h
index 84abd6e..7a52e83 100644
--- a/src/vnet/ipsec/ipsec_sa.h
+++ b/src/vnet/ipsec/ipsec_sa.h
@@ -174,7 +174,8 @@
 
   ipsec_protocol_t protocol;
   tunnel_encap_decap_flags_t tunnel_flags;
-  u8 __pad[2];
+  ip_dscp_t dscp;
+  u8 __pad2[1];
 
   /* data accessed by dataplane code should be above this comment */
     CLIB_CACHE_LINE_ALIGN_MARK (cacheline2);
@@ -202,7 +203,8 @@
     u64 data;
   } async_op_data;
 
-  tunnel_t tunnel;
+  ip46_address_t tunnel_src_addr;
+  ip46_address_t tunnel_dst_addr;
 
   fib_node_t node;
 
@@ -212,6 +214,10 @@
   vnet_crypto_alg_t integ_calg;
   vnet_crypto_alg_t crypto_calg;
 
+  fib_node_index_t fib_entry_index;
+  u32 sibling;
+  u32 tx_fib_index;
+
   /* else u8 packed */
   ipsec_crypto_alg_t crypto_alg;
   ipsec_integ_alg_t integ_alg;
@@ -252,12 +258,21 @@
 
 extern void ipsec_mk_key (ipsec_key_t * key, const u8 * data, u8 len);
 
-extern int
-ipsec_sa_add_and_lock (u32 id, u32 spi, ipsec_protocol_t proto,
-		       ipsec_crypto_alg_t crypto_alg, const ipsec_key_t *ck,
-		       ipsec_integ_alg_t integ_alg, const ipsec_key_t *ik,
-		       ipsec_sa_flags_t flags, u32 salt, u16 src_port,
-		       u16 dst_port, const tunnel_t *tun, u32 *sa_out_index);
+extern int ipsec_sa_add_and_lock (u32 id,
+				  u32 spi,
+				  ipsec_protocol_t proto,
+				  ipsec_crypto_alg_t crypto_alg,
+				  const ipsec_key_t * ck,
+				  ipsec_integ_alg_t integ_alg,
+				  const ipsec_key_t * ik,
+				  ipsec_sa_flags_t flags,
+				  u32 tx_table_id,
+				  u32 salt,
+				  const ip46_address_t * tunnel_src_addr,
+				  const ip46_address_t * tunnel_dst_addr,
+				  tunnel_encap_decap_flags_t tunnel_flags,
+				  ip_dscp_t dscp,
+				  u32 * sa_index, u16 src_port, u16 dst_port);
 extern index_t ipsec_sa_find_and_lock (u32 id);
 extern int ipsec_sa_unlock_id (u32 id);
 extern void ipsec_sa_unlock (index_t sai);
diff --git a/src/vnet/ipsec/ipsec_tun.c b/src/vnet/ipsec/ipsec_tun.c
index 7434025..63e063f 100644
--- a/src/vnet/ipsec/ipsec_tun.c
+++ b/src/vnet/ipsec/ipsec_tun.c
@@ -470,13 +470,13 @@
   ({
     if (ipsec_sa_is_set_IS_TUNNEL (sa))
       {
-	itp->itp_crypto.src = ip_addr_46 (&sa->tunnel.t_dst);
-	itp->itp_crypto.dst = ip_addr_46 (&sa->tunnel.t_src);
-	if (!(itp->itp_flags & IPSEC_PROTECT_ITF))
-	  {
-	    ipsec_sa_set_IS_PROTECT (sa);
-	    itp->itp_flags |= IPSEC_PROTECT_ENCAPED;
-	  }
+        itp->itp_crypto.src = sa->tunnel_dst_addr;
+        itp->itp_crypto.dst = sa->tunnel_src_addr;
+        if (!(itp->itp_flags & IPSEC_PROTECT_ITF))
+          {
+            ipsec_sa_set_IS_PROTECT (sa);
+            itp->itp_flags |= IPSEC_PROTECT_ENCAPED;
+          }
       }
     else
       {
diff --git a/src/vnet/ipsec/ipsec_tun.h b/src/vnet/ipsec/ipsec_tun.h
index 070831f..7ae0099 100644
--- a/src/vnet/ipsec/ipsec_tun.h
+++ b/src/vnet/ipsec/ipsec_tun.h
@@ -162,6 +162,10 @@
 extern void ipsec_tun_register_nodes (ip_address_family_t af);
 extern void ipsec_tun_unregister_nodes (ip_address_family_t af);
 
+// FIXME
+extern vlib_node_registration_t ipsec4_tun_input_node;
+extern vlib_node_registration_t ipsec6_tun_input_node;
+
 /*
  * DP API
  */
diff --git a/src/vnet/ipsec/ipsec_types.api b/src/vnet/ipsec/ipsec_types.api
index b473559..ca1b378 100644
--- a/src/vnet/ipsec/ipsec_types.api
+++ b/src/vnet/ipsec/ipsec_types.api
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-option version = "3.0.1";
+option version = "3.0.0";
 
 import "vnet/ip/ip_types.api";
 import "vnet/tunnel/tunnel_types.api";
@@ -162,28 +162,6 @@
   u16 udp_dst_port [default=4500];
 };
 
-typedef ipsec_sad_entry_v3
-{
-  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_tunnel_t tunnel;
-
-  u32 salt;
-  u16 udp_src_port [default=4500];
-  u16 udp_dst_port [default=4500];
-};
-
 
 /*
  * Local Variables:
diff --git a/src/vnet/tunnel/tunnel.c b/src/vnet/tunnel/tunnel.c
index d45a462..1bd03eb 100644
--- a/src/vnet/tunnel/tunnel.c
+++ b/src/vnet/tunnel/tunnel.c
@@ -174,14 +174,16 @@
 
   unformat (input, "src %U", unformat_ip_address, &t->t_src);
   unformat (input, "dst %U", unformat_ip_address, &t->t_dst);
-  unformat (input, "table-id %d", &t->t_table_id);
-  unformat (input, "hop-limit %d", &t->t_hop_limit);
+  unformat (input, "table-id:%d", &t->t_table_id);
+  unformat (input, "hop-limit:%d", &t->t_hop_limit);
   unformat (input, "%U", unformat_ip_dscp, &t->t_dscp);
   unformat (input, "%U", unformat_tunnel_encap_decap_flags,
 	    &t->t_encap_decap_flags);
   unformat (input, "%U", unformat_tunnel_flags, &t->t_flags);
   unformat (input, "%U", unformat_tunnel_mode, &t->t_mode);
 
+  ASSERT (!"Check not 4 and 6");
+
   return (1);
 }