dpdk-ipsec: Fix for multipoint IPSEC
[vpp.git] / src / plugins / dpdk / ipsec / esp_encrypt.c
index 5fa84fb..c024f97 100644 (file)
@@ -24,6 +24,7 @@
 #include <vnet/udp/udp.h>
 #include <dpdk/buffer.h>
 #include <dpdk/ipsec/ipsec.h>
+#include <vnet/ipsec/ipsec_tun.h>
 #include <dpdk/device/dpdk.h>
 #include <dpdk/device/dpdk_priv.h>
 
@@ -66,6 +67,8 @@ static char *esp_encrypt_error_strings[] = {
 
 extern vlib_node_registration_t dpdk_esp4_encrypt_node;
 extern vlib_node_registration_t dpdk_esp6_encrypt_node;
+extern vlib_node_registration_t dpdk_esp4_encrypt_tun_node;
+extern vlib_node_registration_t dpdk_esp6_encrypt_tun_node;
 
 typedef struct
 {
@@ -215,11 +218,10 @@ dpdk_esp_encrypt_inline (vlib_main_t * vm,
 
          if (is_tun)
            {
-             u32 tmp;
              /* we are on a ipsec tunnel's feature arc */
-             sa_index0 = *(u32 *) vnet_feature_next_with_data (&tmp, b0,
-                                                               sizeof
-                                                               (sa_index0));
+             vnet_buffer (b0)->ipsec.sad_index =
+               sa_index0 = ipsec_tun_protect_get_sa_out
+               (vnet_buffer (b0)->ip.adj_index[VLIB_TX]);
            }
          else
            sa_index0 = vnet_buffer (b0)->ipsec.sad_index;
@@ -411,8 +413,16 @@ dpdk_esp_encrypt_inline (vlib_main_t * vm,
            }
          else                  /* transport mode */
            {
-             priv->next = DPDK_CRYPTO_INPUT_NEXT_INTERFACE_OUTPUT;
-             rewrite_len = vnet_buffer (b0)->ip.save_rewrite_length;
+             if (is_tun)
+               {
+                 rewrite_len = 0;
+                 priv->next = DPDK_CRYPTO_INPUT_NEXT_MIDCHAIN;
+               }
+             else
+               {
+                 priv->next = DPDK_CRYPTO_INPUT_NEXT_INTERFACE_OUTPUT;
+                 rewrite_len = vnet_buffer (b0)->ip.save_rewrite_length;
+               }
              u16 adv = sizeof (esp_header_t) + iv_size + udp_encap_adv;
              vlib_buffer_advance (b0, -adv - rewrite_len);
              u8 *src = ((u8 *) ih0) - rewrite_len;
@@ -475,13 +485,13 @@ dpdk_esp_encrypt_inline (vlib_main_t * vm,
          f0->pad_length = pad_bytes;
          f0->next_header = next_hdr_type;
 
-         if (ipsec_sa_is_set_IS_TUNNEL_V6 (sa0))
+         if (oh6_0)
            {
              u16 len = b0->current_length - sizeof (ip6_header_t);
              oh6_0->ip6.payload_length =
                clib_host_to_net_u16 (len - rewrite_len);
            }
-         else
+         else if (oh0)
            {
              oh0->ip4.length =
                clib_host_to_net_u16 (b0->current_length - rewrite_len);
@@ -494,6 +504,8 @@ dpdk_esp_encrypt_inline (vlib_main_t * vm,
                                          ip4_header_bytes (&ouh0->ip4));
                }
            }
+         else                  /* should never happen */
+           clib_warning ("No outer header found for ESP packet");
 
          b0->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
 
@@ -509,7 +521,8 @@ dpdk_esp_encrypt_inline (vlib_main_t * vm,
          u64 digest_paddr =
            mb0->buf_physaddr + digest - ((u8 *) mb0->buf_addr);
 
-         if (!is_aead && cipher_alg->alg == RTE_CRYPTO_CIPHER_AES_CBC)
+         if (!is_aead && (cipher_alg->alg == RTE_CRYPTO_CIPHER_AES_CBC ||
+                          cipher_alg->alg == RTE_CRYPTO_CIPHER_NULL))
            {
              cipher_off = sizeof (esp_header_t);
              cipher_len = iv_size + pad_payload_len;
@@ -527,14 +540,19 @@ dpdk_esp_encrypt_inline (vlib_main_t * vm,
          if (is_aead)
            {
              aad = (u32 *) priv->aad;
-             aad[0] = clib_host_to_net_u32 (sa0->spi);
-             aad[1] = clib_host_to_net_u32 (sa0->seq);
+             aad[0] = esp0->spi;
 
              /* aad[3] should always be 0 */
              if (PREDICT_FALSE (ipsec_sa_is_set_USE_ESN (sa0)))
-               aad[2] = clib_host_to_net_u32 (sa0->seq_hi);
+               {
+                 aad[1] = clib_host_to_net_u32 (sa0->seq_hi);
+                 aad[2] = esp0->seq;
+               }
              else
-               aad[2] = 0;
+               {
+                 aad[1] = esp0->seq;
+                 aad[2] = 0;
+               }
            }
          else
            {
@@ -568,7 +586,10 @@ dpdk_esp_encrypt_inline (vlib_main_t * vm,
     }
   if (is_ip6)
     {
-      vlib_node_increment_counter (vm, dpdk_esp6_encrypt_node.index,
+      vlib_node_increment_counter (vm,
+                                  (is_tun ?
+                                   dpdk_esp6_encrypt_tun_node.index :
+                                   dpdk_esp6_encrypt_node.index),
                                   ESP_ENCRYPT_ERROR_RX_PKTS,
                                   from_frame->n_vectors);
 
@@ -577,7 +598,10 @@ dpdk_esp_encrypt_inline (vlib_main_t * vm,
     }
   else
     {
-      vlib_node_increment_counter (vm, dpdk_esp4_encrypt_node.index,
+      vlib_node_increment_counter (vm,
+                                  (is_tun ?
+                                   dpdk_esp4_encrypt_tun_node.index :
+                                   dpdk_esp4_encrypt_node.index),
                                   ESP_ENCRYPT_ERROR_RX_PKTS,
                                   from_frame->n_vectors);