ipsec: Dedicated IPSec interface type
[vpp.git] / src / vnet / ipsec / ipsec_tun.c
index 9b76d31..fb530c8 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #include <vnet/ipsec/ipsec_tun.h>
+#include <vnet/ipsec/ipsec_itf.h>
 #include <vnet/ipsec/esp.h>
 #include <vnet/udp/udp.h>
 #include <vnet/adj/adj_delegate.h>
@@ -126,14 +127,20 @@ ipsec_tun_protect_from_const_base (const adj_delegate_t * ad)
 }
 
 static u32
-ipsec_tun_protect_get_adj_next (const ipsec_tun_protect_t * itp)
+ipsec_tun_protect_get_adj_next (vnet_link_t linkt,
+                               const ipsec_tun_protect_t * itp)
 {
   ipsec_main_t *im;
   ipsec_sa_t *sa;
   bool is_ip4;
   u32 next;
 
-  is_ip4 = ip46_address_is_ip4 (&itp->itp_tun.src);
+
+  if (itp->itp_flags & IPSEC_PROTECT_ITF)
+    is_ip4 = linkt == VNET_LINK_IP4;
+  else
+    is_ip4 = ip46_address_is_ip4 (&itp->itp_tun.src);
+
   sa = ipsec_sa_get (itp->itp_out_sa);
   im = &ipsec_main;
 
@@ -169,7 +176,7 @@ ipsec_tun_protect_add_adj (adj_index_t ai, const ipsec_tun_protect_t * itp)
     {
       ipsec_tun_protect_sa_by_adj_index[ai] = itp->itp_out_sa;
       adj_nbr_midchain_update_next_node
-       (ai, ipsec_tun_protect_get_adj_next (itp));
+       (ai, ipsec_tun_protect_get_adj_next (adj_get_link_type (ai), itp));
     }
 }
 
@@ -249,6 +256,9 @@ ipsec_tun_protect_adj_add (adj_index_t ai, void *arg)
                    itp - ipsec_tun_protect_pool);
   ipsec_tun_protect_add_adj (ai, itp);
 
+  if (itp->itp_flags & IPSEC_PROTECT_ITF)
+    ipsec_itf_adj_stack (ai, itp->itp_out_sa);
+
   return (ADJ_WALK_RC_CONTINUE);
 }
 
@@ -349,9 +359,14 @@ ipsec_tun_protect_rx_db_remove (ipsec_main_t * im,
 static adj_walk_rc_t
 ipsec_tun_protect_adj_remove (adj_index_t ai, void *arg)
 {
+  ipsec_tun_protect_t *itp = arg;
+
   adj_delegate_remove (ai, ipsec_tun_adj_delegate_type);
   ipsec_tun_protect_add_adj (ai, NULL);
 
+  if (itp->itp_flags & IPSEC_PROTECT_ITF)
+    ipsec_itf_adj_unstack (ai);
+
   return (ADJ_WALK_RC_CONTINUE);
 }
 
@@ -404,8 +419,11 @@ ipsec_tun_protect_set_crypto_addr (ipsec_tun_protect_t * itp)
       {
         itp->itp_crypto.src = sa->tunnel_dst_addr;
         itp->itp_crypto.dst = sa->tunnel_src_addr;
-        ipsec_sa_set_IS_PROTECT (sa);
-        itp->itp_flags |= IPSEC_PROTECT_ENCAPED;
+        if (!(itp->itp_flags & IPSEC_PROTECT_ITF))
+          {
+            ipsec_sa_set_IS_PROTECT (sa);
+            itp->itp_flags |= IPSEC_PROTECT_ENCAPED;
+          }
       }
     else
       {
@@ -657,6 +675,7 @@ ipsec_tun_protect_update (u32 sw_if_index,
       pool_get_zero (ipsec_tun_protect_pool, itp);
 
       itp->itp_sw_if_index = sw_if_index;
+      itp->itp_ai = ADJ_INDEX_INVALID;
 
       itp->itp_n_sa_in = vec_len (sas_in);
       for (ii = 0; ii < itp->itp_n_sa_in; ii++)
@@ -673,7 +692,24 @@ ipsec_tun_protect_update (u32 sw_if_index,
       if (rv)
        goto out;
 
-      if (ip46_address_is_zero (&itp->itp_tun.dst))
+      if (ip46_address_is_zero (&itp->itp_tun.src))
+       {
+         /* must be one of thos pesky ipsec interfaces that has no encap.
+          * the encap then MUST comefrom the tunnel mode SA.
+          */
+         ipsec_sa_t *sa;
+
+         sa = ipsec_sa_get (itp->itp_out_sa);
+
+         if (!ipsec_sa_is_set_IS_TUNNEL (sa))
+           {
+             rv = VNET_API_ERROR_INVALID_DST_ADDRESS;
+             goto out;
+           }
+
+         itp->itp_flags |= IPSEC_PROTECT_ITF;
+       }
+      else if (ip46_address_is_zero (&itp->itp_tun.dst))
        {
          /* tunnel has no destination address, presumably because it's p2mp
             in which case we use the nh that this is protection for */
@@ -690,7 +726,7 @@ ipsec_tun_protect_update (u32 sw_if_index,
 
       /*
        * add to the tunnel DB for ingress
-       *  - if the SA is in trasnport mode, then the packates will arrivw
+       *  - if the SA is in trasnport mode, then the packates will arrive
        *    with the IP src,dst of the protected tunnel, in which case we can
        *    simply strip the IP header and hand the payload to the protocol
        *    appropriate input handler
@@ -752,6 +788,9 @@ ipsec_tun_protect_del (u32 sw_if_index, const ip_address_t * nh)
   itp = ipsec_tun_protect_get (itpi);
   ipsec_tun_protect_unconfig (im, itp);
 
+  if (ADJ_INDEX_INVALID != itp->itp_ai)
+    adj_unlock (itp->itp_ai);
+
   clib_mem_free (itp->itp_key);
   pool_put (ipsec_tun_protect_pool, itp);
 
@@ -828,13 +867,7 @@ ipsec_tun_protect_adj_delegate_adj_created (adj_index_t ai)
   itpi = ipsec_tun_protect_find (adj->rewrite_header.sw_if_index, &ip);
 
   if (INDEX_INVALID != itpi)
-    {
-      const ipsec_tun_protect_t *itp;
-
-      itp = ipsec_tun_protect_get (itpi);
-      adj_delegate_add (adj_get (ai), ipsec_tun_adj_delegate_type, itpi);
-      ipsec_tun_protect_add_adj (ai, itp);
-    }
+    ipsec_tun_protect_adj_add (ai, ipsec_tun_protect_get (itpi));
 }
 
 static u8 *