ipsec: Use the new tunnel API types to add flow label and TTL copy 62/31162/2
authorNeale Ranns <neale@graphiant.com>
Thu, 4 Feb 2021 11:09:33 +0000 (11:09 +0000)
committerMatthew Smith <mgsmith@netgate.com>
Mon, 8 Feb 2021 19:37:28 +0000 (19:37 +0000)
support

Type: feature

Signed-off-by: Neale Ranns <neale@graphiant.com>
Change-Id: I6d4a9b187daa725d4b2cbb66e11616802d44d2d3

21 files changed:
src/plugins/dpdk/ipsec/esp_encrypt.c
src/plugins/ikev2/ikev2.c
src/vnet/ipsec/ah_encrypt.c
src/vnet/ipsec/esp_encrypt.c
src/vnet/ipsec/ipsec.api
src/vnet/ipsec/ipsec_api.c
src/vnet/ipsec/ipsec_cli.c
src/vnet/ipsec/ipsec_format.c
src/vnet/ipsec/ipsec_input.c
src/vnet/ipsec/ipsec_itf.c
src/vnet/ipsec/ipsec_sa.c
src/vnet/ipsec/ipsec_sa.h
src/vnet/ipsec/ipsec_tun.c
src/vnet/ipsec/ipsec_tun.h
src/vnet/ipsec/ipsec_types.api
src/vnet/tunnel/tunnel.c
test/template_ipsec.py
test/test_ipsec_ah.py
test/test_ipsec_esp.py
test/test_ipsec_tun_if_esp.py
test/vpp_ipsec.py

index 984bb64..f50291f 100644 (file)
@@ -357,9 +357,9 @@ dpdk_esp_encrypt_inline (vlib_main_t * vm,
                    clib_host_to_net_u32 (0xfe320000);
 
                  oh0->ip4.src_address.as_u32 =
-                   sa0->tunnel_src_addr.ip4.as_u32;
+                   sa0->tunnel.t_src.ip.ip4.as_u32;
                  oh0->ip4.dst_address.as_u32 =
-                   sa0->tunnel_dst_addr.ip4.as_u32;
+                   sa0->tunnel.t_dst.ip.ip4.as_u32;
 
                  if (ipsec_sa_is_set_UDP_ENCAP (sa0))
                    {
@@ -392,13 +392,13 @@ dpdk_esp_encrypt_inline (vlib_main_t * vm,
                  oh6_0->ip6.protocol = IP_PROTOCOL_IPSEC_ESP;
                  oh6_0->ip6.hop_limit = 254;
                  oh6_0->ip6.src_address.as_u64[0] =
-                   sa0->tunnel_src_addr.ip6.as_u64[0];
+                   sa0->tunnel.t_src.ip.ip6.as_u64[0];
                  oh6_0->ip6.src_address.as_u64[1] =
-                   sa0->tunnel_src_addr.ip6.as_u64[1];
+                   sa0->tunnel.t_src.ip.ip6.as_u64[1];
                  oh6_0->ip6.dst_address.as_u64[0] =
-                   sa0->tunnel_dst_addr.ip6.as_u64[0];
+                   sa0->tunnel.t_dst.ip.ip6.as_u64[0];
                  oh6_0->ip6.dst_address.as_u64[1] =
-                   sa0->tunnel_dst_addr.ip6.as_u64[1];
+                   sa0->tunnel.t_dst.ip.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);
index aa57deb..0df7faa 100644 (file)
@@ -1823,8 +1823,8 @@ typedef struct
   u32 remote_spi;
   ipsec_crypto_alg_t encr_type;
   ipsec_integ_alg_t integ_type;
-  ip46_address_t local_ip;
-  ip46_address_t remote_ip;
+  ip_address_t local_ip;
+  ip_address_t remote_ip;
   ipsec_key_t loc_ckey, rem_ckey, loc_ikey, rem_ikey;
   u8 is_rekey;
   u32 old_remote_sa_id;
@@ -1839,12 +1839,32 @@ ikev2_add_tunnel_from_main (ikev2_add_ipsec_tunnel_args_t * a)
   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,
-                           &a->local_ip, &a->remote_ip, 0,
+      rv = ipip_add_tunnel (IPIP_TRANSPORT_IP4, ~0, &ip_addr_46 (&a->local_ip),
+                           &ip_addr_46 (&a->remote_ip), 0,
                            TUNNEL_ENCAP_DECAP_FLAG_NONE, IP_DSCP_CS0,
                            TUNNEL_MODE_P2P, &sw_if_index);
 
@@ -1883,24 +1903,18 @@ ikev2_add_tunnel_from_main (ikev2_add_ipsec_tunnel_args_t * a)
       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, 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);
+  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);
   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), 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);
+  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);
   if (rv)
     goto err1;
 
@@ -1944,16 +1958,16 @@ ikev2_create_tunnel_interface (vlib_main_t * vm,
 
   if (sa->is_initiator)
     {
-      ip_address_to_46 (&sa->iaddr, &a.local_ip);
-      ip_address_to_46 (&sa->raddr, &a.remote_ip);
+      ip_address_copy (&a.local_ip, &sa->iaddr);
+      ip_address_copy (&a.remote_ip, &sa->raddr);
       proposals = child->r_proposals;
       a.local_spi = child->r_proposals[0].spi;
       a.remote_spi = child->i_proposals[0].spi;
     }
   else
     {
-      ip_address_to_46 (&sa->raddr, &a.local_ip);
-      ip_address_to_46 (&sa->iaddr, &a.remote_ip);
+      ip_address_copy (&a.local_ip, &sa->raddr);
+      ip_address_copy (&a.remote_ip, &sa->iaddr);
       proposals = child->i_proposals;
       a.local_spi = child->i_proposals[0].spi;
       a.remote_spi = child->r_proposals[0].spi;
index a4c3491..7213e47 100644 (file)
@@ -251,7 +251,7 @@ ah_encrypt_inline (vlib_main_t * vm,
          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->dscp);
+         ip6_set_dscp_network_order (&oh6_0->ip6, sa0->tunnel.t_dscp);
 
          tunnel_encap_fixup_6o6 (sa0->tunnel_flags,
                                  &ih6_0->ip6, &oh6_0->ip6);
@@ -287,8 +287,8 @@ ah_encrypt_inline (vlib_main_t * vm,
          oh0 = vlib_buffer_get_current (b[0]);
          pd->ttl = ih0->ip4.ttl;
 
-         if (sa0->dscp)
-           pd->tos = sa0->dscp << 2;
+         if (sa0->tunnel.t_dscp)
+           pd->tos = sa0->tunnel.t_dscp << 2;
          else
            {
              pd->tos = ih0->ip4.tos;
index 08f82db..e64de26 100644 (file)
@@ -829,6 +829,7 @@ esp_encrypt_inline (vlib_main_t *vm, vlib_node_runtime_t *node,
            }
          else
            next[0] = ESP_ENCRYPT_NEXT_INTERFACE_OUTPUT;
+         b[0]->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
        }
       else                     /* transport mode */
        {
index c009d8d..8d4580a 100644 (file)
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-option version = "5.0.0";
+option version = "5.0.1";
 
 import "vnet/ipsec/ipsec_types.api";
 import "vnet/interface_types.api";
@@ -191,6 +191,7 @@ define ipsec_spd_details {
  */
 define ipsec_sad_entry_add_del
 {
+  option deprecated;
   u32 client_index;
   u32 context;
   bool is_add;
@@ -203,8 +204,17 @@ define ipsec_sad_entry_add_del_v2
   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;
@@ -215,6 +225,12 @@ define ipsec_sad_entry_add_del_v2_reply
   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
 
@@ -378,6 +394,7 @@ define ipsec_itf_details
 */
 define ipsec_sa_dump
 {
+  option deprecated;
   u32 client_index;
   u32 context;
   u32 sa_id;
@@ -388,6 +405,12 @@ define ipsec_sa_v2_dump
   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
@@ -402,6 +425,7 @@ define ipsec_sa_v2_dump
     @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;
 
@@ -425,6 +449,17 @@ define ipsec_sa_v2_details {
 
   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
index 1a419e5..a3e0545 100644 (file)
 
 #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_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)
+#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)
 
 static void
 vl_api_ipsec_spd_add_del_t_handler (vl_api_ipsec_spd_add_del_t * mp)
@@ -335,17 +337,21 @@ out:
 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
@@ -373,19 +379,14 @@ static void vl_api_ipsec_sad_entry_add_del_t_handler
 
   flags = ipsec_sa_flags_decode (mp->entry.flags);
 
-  ip_address_decode (&mp->entry.tunnel_src, &tun_src);
-  ip_address_decode (&mp->entry.tunnel_dst, &tun_dst);
+  ip_address_decode2 (&mp->entry.tunnel_src, &tun.t_src);
+  ip_address_decode2 (&mp->entry.tunnel_dst, &tun.t_dst);
 
   if (mp->is_add)
-    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));
+    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);
 
@@ -407,10 +408,6 @@ static void vl_api_ipsec_sad_entry_add_del_v2_t_handler
 {
   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;
@@ -418,6 +415,14 @@ static void vl_api_ipsec_sad_entry_add_del_v2_t_handler
   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
 
@@ -439,8 +444,8 @@ static void vl_api_ipsec_sad_entry_add_del_v2_t_handler
   if (rv)
     goto out;
 
-  rv =
-    tunnel_encap_decap_flags_decode (mp->entry.tunnel_flags, &tunnel_flags);
+  rv = tunnel_encap_decap_flags_decode (mp->entry.tunnel_flags,
+                                       &tun.t_encap_decap_flags);
 
   if (rv)
     goto out;
@@ -449,16 +454,16 @@ static void vl_api_ipsec_sad_entry_add_del_v2_t_handler
   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_decode (&mp->entry.tunnel_src, &tun_src);
-  ip_address_decode (&mp->entry.tunnel_dst, &tun_dst);
+  ip_address_decode2 (&mp->entry.tunnel_src, &tun.t_src);
+  ip_address_decode2 (&mp->entry.tunnel_dst, &tun.t_dst);
 
   if (mp->is_add)
     rv = ipsec_sa_add_and_lock (
       id, spi, proto, crypto_alg, &crypto_key, integ_alg, &integ_key, flags,
-      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));
+      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);
 
@@ -475,6 +480,70 @@ out:
   /* *INDENT-ON* */
 }
 
+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)
@@ -746,8 +815,7 @@ send_ipsec_sa_details (ipsec_sa_t * sa, void *arg)
   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 (fib_table_get_table_id (sa->tx_fib_index, FIB_PROTOCOL_IP4));
+  mp->entry.tx_table_id = htonl (sa->tunnel.t_table_id);
 
   mp->entry.crypto_algorithm = ipsec_crypto_algo_encode (sa->crypto_alg);
   ipsec_key_encode (&sa->crypto_key, &mp->entry.crypto_key);
@@ -773,10 +841,8 @@ send_ipsec_sa_details (ipsec_sa_t * sa, void *arg)
 
   if (ipsec_sa_is_set_IS_TUNNEL (sa))
     {
-      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);
+      ip_address_encode2 (&sa->tunnel.t_src, &mp->entry.tunnel_src);
+      ip_address_encode2 (&sa->tunnel.t_dst, &mp->entry.tunnel_dst);
     }
   if (ipsec_sa_is_set_UDP_ENCAP (sa))
     {
@@ -838,8 +904,7 @@ send_ipsec_sa_v2_details (ipsec_sa_t * sa, void *arg)
   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 (fib_table_get_table_id (sa->tx_fib_index, FIB_PROTOCOL_IP4));
+  mp->entry.tx_table_id = htonl (sa->tunnel.t_table_id);
 
   mp->entry.crypto_algorithm = ipsec_crypto_algo_encode (sa->crypto_alg);
   ipsec_key_encode (&sa->crypto_key, &mp->entry.crypto_key);
@@ -865,10 +930,8 @@ send_ipsec_sa_v2_details (ipsec_sa_t * sa, void *arg)
 
   if (ipsec_sa_is_set_IS_TUNNEL (sa))
     {
-      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);
+      ip_address_encode2 (&sa->tunnel.t_src, &mp->entry.tunnel_src);
+      ip_address_encode2 (&sa->tunnel.t_dst, &mp->entry.tunnel_dst);
     }
   if (ipsec_sa_is_set_UDP_ENCAP (sa))
     {
@@ -876,8 +939,9 @@ send_ipsec_sa_v2_details (ipsec_sa_t * sa, void *arg)
       mp->entry.udp_dst_port = sa->udp_hdr.dst_port;
     }
 
-  mp->entry.tunnel_flags = tunnel_encap_decap_flags_encode (sa->tunnel_flags);
-  mp->entry.dscp = ip_dscp_encode (sa->dscp);
+  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->seq_outbound = clib_host_to_net_u64 (((u64) sa->seq));
   mp->last_seq_inbound = clib_host_to_net_u64 (((u64) sa->last_seq));
@@ -897,7 +961,7 @@ send_ipsec_sa_v2_details (ipsec_sa_t * sa, void *arg)
 }
 
 static void
-vl_api_ipsec_sa_v2_dump_t_handler (vl_api_ipsec_sa_dump_t * mp)
+vl_api_ipsec_sa_v2_dump_t_handler (vl_api_ipsec_sa_v2_dump_t *mp)
 {
   vl_api_registration_t *reg;
 
@@ -918,6 +982,92 @@ vl_api_ipsec_sa_v2_dump_t_handler (vl_api_ipsec_sa_dump_t * mp)
 #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)
 {
index b708e50..eed910e 100644 (file)
@@ -86,9 +86,6 @@ ipsec_sa_add_del_command_fn (vlib_main_t * vm,
                             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;
@@ -101,8 +98,7 @@ ipsec_sa_add_del_command_fn (vlib_main_t * vm,
   u16 udp_src, udp_dst;
   int is_add, rv;
   u32 m_args = 0;
-  ip_dscp_t dscp;
-  u32 tx_table_id;
+  tunnel_t tun;
 
   salt = 0;
   error = NULL;
@@ -112,8 +108,6 @@ ipsec_sa_add_del_command_fn (vlib_main_t * vm,
   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;
@@ -149,22 +143,16 @@ ipsec_sa_add_del_command_fn (vlib_main_t * vm,
       else if (unformat (line_input, "integ-alg %U",
                         unformat_ipsec_integ_alg, &integ_alg))
        ;
-      else if (unformat (line_input, "tunnel-src %U",
-                        unformat_ip46_address, &tun_src, IP46_TYPE_ANY))
+      else if (unformat (line_input, " %U", unformat_tunnel, &tun))
        {
          flags |= IPSEC_SA_FLAG_IS_TUNNEL;
-         if (!ip46_address_is_ip4 (&tun_src))
+         if (AF_IP6 == tunnel_get_af (&tun))
            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"))
@@ -200,12 +188,9 @@ ipsec_sa_add_del_command_fn (vlib_main_t * vm,
          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,
-                                 tx_table_id, clib_host_to_net_u32 (salt),
-                                 &tun_src, &tun_dst,
-                                 TUNNEL_ENCAP_DECAP_FLAG_NONE, dscp,
-                                 &sai, udp_src, udp_dst);
+      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);
     }
   else
     {
index 19321e7..001aa01 100644 (file)
@@ -273,7 +273,6 @@ format_ipsec_sa (u8 * s, va_list * args)
   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))
@@ -318,26 +317,7 @@ format_ipsec_sa (u8 * s, va_list * args)
   s = format (s, "\n   packets %u bytes %u", counts.packets, counts.bytes);
 
   if (ipsec_sa_is_set_IS_TUNNEL (sa))
-    {
-      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);
-       }
-    }
+    s = format (s, "\n%U", format_tunnel, &sa->tunnel, 3);
 
 done:
   return (s);
index aa7627d..2ebc6c5 100644 (file)
@@ -118,10 +118,10 @@ ipsec_input_protect_policy_match (ipsec_spd_t * spd, u32 sa, u32 da, u32 spi)
 
     if (ipsec_sa_is_set_IS_TUNNEL (s))
       {
-       if (da != clib_net_to_host_u32 (s->tunnel_dst_addr.ip4.as_u32))
+       if (da != clib_net_to_host_u32 (s->tunnel.t_dst.ip.ip4.as_u32))
          continue;
 
-       if (sa != clib_net_to_host_u32 (s->tunnel_src_addr.ip4.as_u32))
+       if (sa != clib_net_to_host_u32 (s->tunnel.t_src.ip.ip4.as_u32))
          continue;
 
        return p;
@@ -174,10 +174,10 @@ ipsec6_input_protect_policy_match (ipsec_spd_t * spd,
 
     if (ipsec_sa_is_set_IS_TUNNEL (s))
       {
-       if (!ip6_address_is_equal (sa, &s->tunnel_src_addr.ip6))
+       if (!ip6_address_is_equal (sa, &s->tunnel.t_src.ip.ip6))
          continue;
 
-       if (!ip6_address_is_equal (da, &s->tunnel_dst_addr.ip6))
+       if (!ip6_address_is_equal (da, &s->tunnel.t_dst.ip.ip6))
          continue;
 
        return p;
index 4a0f9e7..5f04fcf 100644 (file)
@@ -70,20 +70,11 @@ ipsec_itf_adj_stack (adj_index_t ai, u32 sai)
   if (hw->flags & VNET_HW_INTERFACE_FLAG_LINK_UP)
     {
       const ipsec_sa_t *sa;
+      fib_prefix_t dst;
 
       sa = ipsec_sa_get (sai);
-
-      /* *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);
+      ip_address_to_fib_prefix (&sa->tunnel.t_dst, &dst);
+      adj_midchain_delegate_stack (ai, sa->tunnel.t_fib_index, &dst);
     }
   else
     adj_midchain_delegate_unstack (ai);
index 515eb25..0a24aa2 100644 (file)
@@ -72,15 +72,9 @@ static void
 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;
 
-  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);
+  tunnel_contribute_forwarding (&sa->tunnel, &tmp);
 
   if (IPSEC_PROTOCOL_AH == sa->protocol)
     dpo_stack_from_node ((ipsec_sa_is_set_IS_TUNNEL_V6 (sa) ?
@@ -172,21 +166,11 @@ ipsec_sa_set_async_op_ids (ipsec_sa_t * sa)
 }
 
 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 * 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)
+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)
 {
   vlib_main_t *vm = vlib_get_main ();
   ipsec_main_t *im = &ipsec_main;
@@ -194,6 +178,7 @@ ipsec_sa_add_and_lock (u32 id,
   ipsec_sa_t *sa;
   u32 sa_index;
   uword *p;
+  int rv;
 
   p = hash_get (im->sa_index_by_sa_id, id);
   if (p)
@@ -208,13 +193,12 @@ ipsec_sa_add_and_lock (u32 id,
   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)
@@ -226,8 +210,6 @@ ipsec_sa_add_and_lock (u32 id,
   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,
@@ -281,59 +263,33 @@ ipsec_sa_add_and_lock (u32 id,
 
   if (ipsec_sa_is_set_IS_TUNNEL (sa) && !ipsec_sa_is_set_IS_INBOUND (sa))
     {
-      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))
+      sa->tunnel_flags = sa->tunnel.t_encap_decap_flags;
+
+      rv = tunnel_resolve (&sa->tunnel, FIB_NODE_TYPE_IPSEC_SA, sa_index);
+
+      if (rv)
        {
          pool_put (im->sad, sa);
-         return VNET_API_ERROR_NO_SUCH_FIB;
+         return rv;
        }
-
-      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))
        {
-         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;
+         tunnel_build_v6_hdr (&sa->tunnel,
+                              (ipsec_sa_is_set_UDP_ENCAP (sa) ?
+                                 IP_PROTOCOL_UDP :
+                                 IP_PROTOCOL_IPSEC_ESP),
+                              &sa->ip6_hdr);
        }
       else
        {
-         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);
+         tunnel_build_v4_hdr (&sa->tunnel,
+                              (ipsec_sa_is_set_UDP_ENCAP (sa) ?
+                                 IP_PROTOCOL_UDP :
+                                 IP_PROTOCOL_IPSEC_ESP),
+                              &sa->ip4_hdr);
        }
     }
 
@@ -370,6 +326,7 @@ ipsec_sa_del (ipsec_sa_t * sa)
 
   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);
@@ -378,10 +335,7 @@ ipsec_sa_del (ipsec_sa_t * sa)
     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))
-    {
-      fib_entry_untrack (sa->fib_entry_index, sa->sibling);
-      dpo_reset (&sa->dpo);
-    }
+    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);
index 7a52e83..84abd6e 100644 (file)
@@ -174,8 +174,7 @@ typedef struct
 
   ipsec_protocol_t protocol;
   tunnel_encap_decap_flags_t tunnel_flags;
-  ip_dscp_t dscp;
-  u8 __pad2[1];
+  u8 __pad[2];
 
   /* data accessed by dataplane code should be above this comment */
     CLIB_CACHE_LINE_ALIGN_MARK (cacheline2);
@@ -203,8 +202,7 @@ typedef struct
     u64 data;
   } async_op_data;
 
-  ip46_address_t tunnel_src_addr;
-  ip46_address_t tunnel_dst_addr;
+  tunnel_t tunnel;
 
   fib_node_t node;
 
@@ -214,10 +212,6 @@ typedef struct
   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;
@@ -258,21 +252,12 @@ extern vlib_combined_counter_main_t ipsec_sa_counters;
 
 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 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 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 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);
index 63e063f..7434025 100644 (file)
@@ -470,13 +470,13 @@ ipsec_tun_protect_set_crypto_addr (ipsec_tun_protect_t * itp)
   ({
     if (ipsec_sa_is_set_IS_TUNNEL (sa))
       {
-        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;
-          }
+       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;
+         }
       }
     else
       {
index 7ae0099..070831f 100644 (file)
@@ -162,10 +162,6 @@ extern u8 *format_ipsec_tun_protect_index (u8 * s, va_list * args);
 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
  */
index ca1b378..b473559 100644 (file)
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-option version = "3.0.0";
+option version = "3.0.1";
 
 import "vnet/ip/ip_types.api";
 import "vnet/tunnel/tunnel_types.api";
@@ -162,6 +162,28 @@ typedef ipsec_sad_entry_v2
   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:
index 1bd03eb..d45a462 100644 (file)
@@ -174,16 +174,14 @@ unformat_tunnel (unformat_input_t *input, va_list *args)
 
   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);
 }
 
index 918c993..0c1f5a1 100644 (file)
@@ -37,6 +37,11 @@ class IPsecIPv4Params:
         self.vpp_tra_sa_id = 400
         self.vpp_tra_spi = 4000
 
+        self.outer_hop_limit = 64
+        self.inner_hop_limit = 255
+        self.outer_flow_label = 0
+        self.inner_flow_label = 0x12345
+
         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
@@ -76,6 +81,11 @@ class IPsecIPv6Params:
         self.vpp_tra_sa_id = 800
         self.vpp_tra_spi = 4000
 
+        self.outer_hop_limit = 64
+        self.inner_hop_limit = 255
+        self.outer_flow_label = 0
+        self.inner_flow_label = 0x12345
+
         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
@@ -242,7 +252,9 @@ class TemplateIpsec(VppTestCase):
     def gen_encrypt_pkts6(self, p, sa, sw_intf, src, dst, count=1,
                           payload_size=54):
         return [Ether(src=sw_intf.remote_mac, dst=sw_intf.local_mac) /
-                sa.encrypt(IPv6(src=src, dst=dst) /
+                sa.encrypt(IPv6(src=src, dst=dst,
+                                hlim=p.inner_hop_limit,
+                                fl=p.inner_flow_label) /
                            ICMPv6EchoRequest(id=0, seq=1,
                                              data='X' * payload_size))
                 for i in range(count)]
@@ -252,9 +264,10 @@ class TemplateIpsec(VppTestCase):
                 IP(src=src, dst=dst) / ICMP() / Raw(b'X' * payload_size)
                 for i in range(count)]
 
-    def gen_pkts6(self, sw_intf, src, dst, count=1, payload_size=54):
+    def gen_pkts6(self, p, sw_intf, src, dst, count=1, payload_size=54):
         return [Ether(src=sw_intf.remote_mac, dst=sw_intf.local_mac) /
-                IPv6(src=src, dst=dst) /
+                IPv6(src=src, dst=dst,
+                     hlim=p.inner_hop_limit, fl=p.inner_flow_label) /
                 ICMPv6EchoRequest(id=0, seq=1, data='X' * payload_size)
                 for i in range(count)]
 
@@ -945,7 +958,7 @@ class IpsecTun4(object):
                 self.assert_equal(recv_pkt[IPv6].src, p.remote_tun_if_host6)
                 self.assert_equal(recv_pkt[IPv6].dst, self.pg1.remote_ip6)
                 self.assert_packet_checksums_valid(recv_pkt)
-            send_pkts = self.gen_pkts6(self.pg1, src=self.pg1.remote_ip6,
+            send_pkts = self.gen_pkts6(p, self.pg1, src=self.pg1.remote_ip6,
                                        dst=p.remote_tun_if_host6, count=count)
             recv_pkts = self.send_and_expect(self.pg1, send_pkts, self.tun_if)
             for recv_pkt in recv_pkts:
@@ -1034,6 +1047,9 @@ class IpsecTun6(object):
             self.assert_packet_checksums_valid(rx)
             self.assertEqual(len(rx) - len(Ether()) - len(IPv6()),
                              rx[IPv6].plen)
+            self.assert_equal(rx[IPv6].hlim, p.outer_hop_limit)
+            if p.outer_flow_label:
+                self.assert_equal(rx[IPv6].fl, p.outer_flow_label)
             try:
                 decrypt_pkt = p.vpp_tun_sa.decrypt(rx[IPv6])
                 if not decrypt_pkt.haslayer(IPv6):
@@ -1041,6 +1057,8 @@ class IpsecTun6(object):
                 self.assert_packet_checksums_valid(decrypt_pkt)
                 self.assert_equal(decrypt_pkt.src, self.pg1.remote_ip6)
                 self.assert_equal(decrypt_pkt.dst, p.remote_tun_if_host)
+                self.assert_equal(decrypt_pkt.hlim, p.inner_hop_limit - 1)
+                self.assert_equal(decrypt_pkt.fl, p.inner_flow_label)
             except:
                 self.logger.debug(ppp("Unexpected packet:", rx))
                 try:
@@ -1076,7 +1094,7 @@ class IpsecTun6(object):
             recv_pkts = self.send_and_expect(self.tun_if, send_pkts, self.pg1)
             self.verify_decrypted6(p_in, recv_pkts)
 
-            send_pkts = self.gen_pkts6(self.pg1, src=self.pg1.remote_ip6,
+            send_pkts = self.gen_pkts6(p_in, self.pg1, src=self.pg1.remote_ip6,
                                        dst=p_out.remote_tun_if_host,
                                        count=count,
                                        payload_size=payload_size)
@@ -1108,7 +1126,7 @@ class IpsecTun6(object):
                                              self.pg1, n_rx=1)
             self.verify_decrypted6(p, recv_pkts)
 
-            send_pkts = self.gen_pkts6(self.pg1, src=self.pg1.remote_ip6,
+            send_pkts = self.gen_pkts6(p, self.pg1, src=self.pg1.remote_ip6,
                                        dst=p.remote_tun_if_host,
                                        count=1,
                                        payload_size=64)
@@ -1198,7 +1216,7 @@ class IpsecTun6HandoffTests(IpsecTun6):
                                              self.pg1, worker=worker)
             self.verify_decrypted6(p, recv_pkts)
 
-            send_pkts = self.gen_pkts6(self.pg1, src=self.pg1.remote_ip6,
+            send_pkts = self.gen_pkts6(p, self.pg1, src=self.pg1.remote_ip6,
                                        dst=p.remote_tun_if_host,
                                        count=N_PKTS)
             recv_pkts = self.send_and_expect(self.pg1, send_pkts,
index d44492d..ef6725e 100644 (file)
@@ -126,6 +126,8 @@ class ConfigIpsecAH(TemplateIpsec):
         tun_flags = params.tun_flags
         e = VppEnum.vl_api_ipsec_spd_action_t
         objs = []
+        params.outer_hop_limit = 253
+        params.outer_flow_label = 0x12345
 
         params.tun_sa_in = VppIpsecSA(self, scapy_tun_sa_id, scapy_tun_spi,
                                       auth_algo_vpp_id, auth_key,
@@ -336,7 +338,7 @@ class TestIpsecAhTun(TemplateIpsecAh, IpsecTun46Tests):
                 Raw(b'X' * payload_size)
                 for i in range(count)]
 
-    def gen_pkts6(self, sw_intf, src, dst, count=1, payload_size=54):
+    def gen_pkts6(self, p, sw_intf, src, dst, count=1, payload_size=54):
         # set the DSCP + ECN - flags are set to copy both
         return [Ether(src=sw_intf.remote_mac, dst=sw_intf.local_mac) /
                 IPv6(src=src, dst=dst, tc=5) /
@@ -375,7 +377,7 @@ class TestIpsecAhTun2(TemplateIpsecAh, IpsecTun46Tests):
                 Raw(b'X' * payload_size)
                 for i in range(count)]
 
-    def gen_pkts6(self, sw_intf, src, dst, count=1, payload_size=54):
+    def gen_pkts6(self, p, sw_intf, src, dst, count=1, payload_size=54):
         # set the DSCP + ECN - flags are set to copy both
         return [Ether(src=sw_intf.remote_mac, dst=sw_intf.local_mac) /
                 IPv6(src=src, dst=dst, tc=0) /
index 178b1d2..11d4404 100644 (file)
@@ -123,7 +123,8 @@ class ConfigIpsecESP(TemplateIpsec):
                                       tun_flags=tun_flags,
                                       dscp=params.dscp,
                                       flags=flags,
-                                      salt=salt)
+                                      salt=salt,
+                                      hop_limit=params.outer_hop_limit)
         params.tun_sa_out = VppIpsecSA(self, vpp_tun_sa_id, vpp_tun_spi,
                                        auth_algo_vpp_id, auth_key,
                                        crypt_algo_vpp_id, crypt_key,
@@ -133,7 +134,8 @@ class ConfigIpsecESP(TemplateIpsec):
                                        tun_flags=tun_flags,
                                        dscp=params.dscp,
                                        flags=flags,
-                                       salt=salt)
+                                       salt=salt,
+                                       hop_limit=params.outer_hop_limit)
         objs.append(params.tun_sa_in)
         objs.append(params.tun_sa_out)
 
@@ -401,7 +403,7 @@ class TestIpsecEspTun(TemplateIpsecEsp, IpsecTun46Tests):
                 Raw(b'X' * payload_size)
                 for i in range(count)]
 
-    def gen_pkts6(self, sw_intf, src, dst, count=1, payload_size=54):
+    def gen_pkts6(self, p, sw_intf, src, dst, count=1, payload_size=54):
         # set the DSCP + ECN - flags are set to copy both
         return [Ether(src=sw_intf.remote_mac, dst=sw_intf.local_mac) /
                 IPv6(src=src, dst=dst, tc=5) /
@@ -433,15 +435,13 @@ class TestIpsecEspTun2(TemplateIpsecEsp, IpsecTun46Tests):
         super(TestIpsecEspTun2, self).setUp()
 
     def gen_pkts(self, sw_intf, src, dst, count=1, payload_size=54):
-        # set the DSCP + ECN - flags are set to copy only DSCP
         return [Ether(src=sw_intf.remote_mac, dst=sw_intf.local_mac) /
                 IP(src=src, dst=dst) /
                 UDP(sport=4444, dport=4444) /
                 Raw(b'X' * payload_size)
                 for i in range(count)]
 
-    def gen_pkts6(self, sw_intf, src, dst, count=1, payload_size=54):
-        # set the DSCP + ECN - flags are set to copy both
+    def gen_pkts6(self, p, sw_intf, src, dst, count=1, payload_size=54):
         return [Ether(src=sw_intf.remote_mac, dst=sw_intf.local_mac) /
                 IPv6(src=src, dst=dst) /
                 UDP(sport=4444, dport=4444) /
@@ -449,13 +449,13 @@ class TestIpsecEspTun2(TemplateIpsecEsp, IpsecTun46Tests):
                 for i in range(count)]
 
     def verify_encrypted(self, p, sa, rxs):
-        # just check that only the DSCP is copied
+        # just check that only the DSCP is set
         for rx in rxs:
             self.assertEqual(rx[IP].tos,
                              VppEnum.vl_api_ip_dscp_t.IP_API_DSCP_EF << 2)
 
     def verify_encrypted6(self, p, sa, rxs):
-        # just check that the DSCP & ECN are copied
+        # just check that the DSCP is set
         for rx in rxs:
             self.assertEqual(rx[IPv6].tc,
                              VppEnum.vl_api_ip_dscp_t.IP_API_DSCP_AF11 << 2)
@@ -684,6 +684,7 @@ class RunTestIpsecEspAll(ConfigIpsecESP,
             p.crypt_key = algo['key']
             p.salt = algo['salt']
             p.flags = p.flags | flag
+            p.outer_flow_label = 243224
 
         self.reporter.send_keep_alive(self)
 
index 5bcd9dd..2ef1351 100644 (file)
@@ -1494,7 +1494,7 @@ class TestIpsecGre6IfEspTra(TemplateIpsec,
                            Raw(b'X' * payload_size))
                 for i in range(count)]
 
-    def gen_pkts6(self, sw_intf, src, dst, count=1,
+    def gen_pkts6(self, p, sw_intf, src, dst, count=1,
                   payload_size=100):
         return [Ether(src=sw_intf.remote_mac, dst=sw_intf.local_mac) /
                 IPv6(src="1::1", dst="1::2") /
@@ -1724,7 +1724,7 @@ class TestIpsecMGreIfEspTra6(TemplateIpsec, IpsecTun6):
                            Raw(b'X' * payload_size))
                 for i in range(count)]
 
-    def gen_pkts6(self, sw_intf, src, dst, count=1,
+    def gen_pkts6(self, p, sw_intf, src, dst, count=1,
                   payload_size=100):
         return [Ether(src=sw_intf.remote_mac, dst=sw_intf.local_mac) /
                 IPv6(src="1::1", dst=dst) /
@@ -2263,7 +2263,7 @@ class TestIpsec6TunProtectTun(TemplateIpsec,
                            Raw(b'X' * payload_size))
                 for i in range(count)]
 
-    def gen_pkts6(self, sw_intf, src, dst, count=1,
+    def gen_pkts6(self, p, sw_intf, src, dst, count=1,
                   payload_size=100):
         return [Ether(src=sw_intf.remote_mac, dst=sw_intf.local_mac) /
                 IPv6(src=src, dst=dst) /
@@ -2659,12 +2659,19 @@ class TemplateIpsecItf6(object):
     def config_sa_tun(self, p, src, dst):
         config_tun_params(p, self.encryption_type, None, src, dst)
 
+        if not hasattr(p, 'tun_flags'):
+            p.tun_flags = None
+        if not hasattr(p, 'hop_limit'):
+            p.hop_limit = 255
+
         p.tun_sa_out = VppIpsecSA(self, p.scapy_tun_sa_id, p.scapy_tun_spi,
                                   p.auth_algo_vpp_id, p.auth_key,
                                   p.crypt_algo_vpp_id, p.crypt_key,
                                   self.vpp_esp_protocol,
                                   src, dst,
-                                  flags=p.flags)
+                                  flags=p.flags,
+                                  tun_flags=p.tun_flags,
+                                  hop_limit=p.hop_limit)
         p.tun_sa_out.add_vpp_config()
 
         p.tun_sa_in = VppIpsecSA(self, p.vpp_tun_sa_id, p.vpp_tun_spi,
@@ -2729,8 +2736,13 @@ class TestIpsecItf6(TemplateIpsec,
     def test_tun_44(self):
         """IPSEC interface IPv6"""
 
+        tf = VppEnum.vl_api_tunnel_encap_decap_flags_t
         n_pkts = 127
         p = self.ipv6_params
+        p.inner_hop_limit = 24
+        p.outer_hop_limit = 23
+        p.outer_flow_label = 243224
+        p.tun_flags = tf.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_HOP_LIMIT
 
         self.config_network(p)
         self.config_sa_tun(p,
@@ -2776,6 +2788,12 @@ class TestIpsecItf6(TemplateIpsec,
         np.vpp_tun_sa_id += 1
         np.tun_if.local_spi = p.vpp_tun_spi
         np.tun_if.remote_spi = p.scapy_tun_spi
+        np.inner_hop_limit = 24
+        np.outer_hop_limit = 128
+        np.inner_flow_label = 0xabcde
+        np.outer_flow_label = 0xabcde
+        np.hop_limit = 128
+        np.tun_flags = tf.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_FLOW_LABEL
 
         self.config_sa_tun(np,
                            self.pg0.local_ip6,
@@ -2828,6 +2846,7 @@ class TestIpsecMIfEsp4(TemplateIpsec, IpsecTun4):
             try:
                 self.assertEqual(rx[IP].tos,
                                  VppEnum.vl_api_ip_dscp_t.IP_API_DSCP_EF << 2)
+                self.assertEqual(rx[IP].ttl, p.hop_limit)
                 pkt = sa.decrypt(rx[IP])
                 if not pkt.haslayer(IP):
                     pkt = IP(pkt[Raw].load)
@@ -2876,6 +2895,7 @@ class TestIpsecMIfEsp4(TemplateIpsec, IpsecTun4):
             p.scapy_tra_spi = p.scapy_tra_spi + ii
             p.vpp_tra_sa_id = p.vpp_tra_sa_id + ii
             p.vpp_tra_spi = p.vpp_tra_spi + ii
+            p.hop_limit = ii+10
             p.tun_sa_out = VppIpsecSA(
                 self, p.scapy_tun_sa_id, p.scapy_tun_spi,
                 p.auth_algo_vpp_id, p.auth_key,
@@ -2883,7 +2903,8 @@ class TestIpsecMIfEsp4(TemplateIpsec, IpsecTun4):
                 self.vpp_esp_protocol,
                 self.pg0.local_ip4,
                 self.pg0.remote_hosts[ii].ip4,
-                dscp=VppEnum.vl_api_ip_dscp_t.IP_API_DSCP_EF)
+                dscp=VppEnum.vl_api_ip_dscp_t.IP_API_DSCP_EF,
+                hop_limit=p.hop_limit)
             p.tun_sa_out.add_vpp_config()
 
             p.tun_sa_in = VppIpsecSA(
@@ -2893,7 +2914,8 @@ class TestIpsecMIfEsp4(TemplateIpsec, IpsecTun4):
                 self.vpp_esp_protocol,
                 self.pg0.remote_hosts[ii].ip4,
                 self.pg0.local_ip4,
-                dscp=VppEnum.vl_api_ip_dscp_t.IP_API_DSCP_EF)
+                dscp=VppEnum.vl_api_ip_dscp_t.IP_API_DSCP_EF,
+                hop_limit=p.hop_limit)
             p.tun_sa_in.add_vpp_config()
 
             p.tun_protect = VppIpsecTunProtect(
index 013e3d7..d0ceeae 100644 (file)
@@ -194,7 +194,7 @@ class VppIpsecSA(VppObject):
                  tun_src=None, tun_dst=None,
                  flags=None, salt=0, tun_flags=None,
                  dscp=None,
-                 udp_src=None, udp_dst=None):
+                 udp_src=None, udp_dst=None, hop_limit=None):
         e = VppEnum.vl_api_ipsec_sad_flags_t
         self.test = test
         self.id = id
@@ -206,6 +206,7 @@ class VppIpsecSA(VppObject):
         self.proto = proto
         self.salt = salt
 
+        self.table_id = 0
         self.tun_src = tun_src
         self.tun_dst = tun_dst
         if not flags:
@@ -228,6 +229,18 @@ class VppIpsecSA(VppObject):
         self.dscp = VppEnum.vl_api_ip_dscp_t.IP_API_DSCP_CS0
         if dscp:
             self.dscp = dscp
+        self.hop_limit = 255
+        if hop_limit:
+            self.hop_limit = hop_limit
+
+    def tunnel_encode(self):
+        return {'src': (self.tun_src if self.tun_src else []),
+                'dst': (self.tun_dst if self.tun_dst else []),
+                'encap_decap_flags': self.tun_flags,
+                'dscp': self.dscp,
+                'hop_limit': self.hop_limit,
+                'table_id': self.table_id
+                }
 
     def add_vpp_config(self):
         entry = {
@@ -244,10 +257,7 @@ class VppIpsecSA(VppObject):
                 'length': len(self.crypto_key),
             },
             'protocol': self.proto,
-            'tunnel_src': (self.tun_src if self.tun_src else []),
-            'tunnel_dst': (self.tun_dst if self.tun_dst else []),
-            'tunnel_flags': self.tun_flags,
-            'dscp': self.dscp,
+            'tunnel': self.tunnel_encode(),
             'flags': self.flags,
             'salt': self.salt
         }
@@ -256,13 +266,13 @@ class VppIpsecSA(VppObject):
             entry['udp_src_port'] = self.udp_src
         if self.udp_dst:
             entry['udp_dst_port'] = self.udp_dst
-        r = self.test.vapi.ipsec_sad_entry_add_del_v2(is_add=1, entry=entry)
+        r = self.test.vapi.ipsec_sad_entry_add_del_v3(is_add=1, entry=entry)
         self.stat_index = r.stat_index
         self.test.registry.register(self, self.test.logger)
         return self
 
     def remove_vpp_config(self):
-        r = self.test.vapi.ipsec_sad_entry_add_del_v2(
+        r = self.test.vapi.ipsec_sad_entry_add_del_v3(
             is_add=0,
             entry={
                 'sad_id': self.id,
@@ -278,9 +288,7 @@ class VppIpsecSA(VppObject):
                     'length': len(self.crypto_key),
                 },
                 'protocol': self.proto,
-                'tunnel_src': (self.tun_src if self.tun_src else []),
-                'tunnel_dst': (self.tun_dst if self.tun_dst else []),
-                'flags': self.flags,
+                'tunnel': self.tunnel_encode(),
                 'salt': self.salt
             })
 
@@ -290,7 +298,7 @@ class VppIpsecSA(VppObject):
     def query_vpp_config(self):
         e = VppEnum.vl_api_ipsec_sad_flags_t
 
-        bs = self.test.vapi.ipsec_sa_v2_dump()
+        bs = self.test.vapi.ipsec_sa_v3_dump()
         for b in bs:
             if b.entry.sad_id == self.id:
                 # if udp encap is configured then the ports should match