VPP-1122 dpdk/ipsec: fix transport mode pkt len
[vpp.git] / src / plugins / dpdk / ipsec / esp_encrypt.c
index ac60fdd..07b2dae 100644 (file)
@@ -158,6 +158,7 @@ dpdk_esp_encrypt_node_fn (vlib_main_t * vm,
          u32 iv_size;
          u16 orig_sz;
          u8 trunc_size;
+         u16 rewrite_len;
          struct rte_mbuf *mb0 = 0;
          struct rte_crypto_op *op;
          u16 res_idx;
@@ -197,13 +198,7 @@ dpdk_esp_encrypt_node_fn (vlib_main_t * vm,
                vec_elt_at_index (dcm->cipher_algs, sa0->crypto_alg);
              auth_alg = vec_elt_at_index (dcm->auth_algs, sa0->integ_alg);
 
-#if DPDK_NO_AEAD
-             is_aead = ((sa0->crypto_alg == IPSEC_CRYPTO_ALG_AES_GCM_128) ||
-                        (sa0->crypto_alg == IPSEC_CRYPTO_ALG_AES_GCM_192) ||
-                        (sa0->crypto_alg == IPSEC_CRYPTO_ALG_AES_GCM_256));
-#else
              is_aead = (cipher_alg->type == RTE_CRYPTO_SYM_XFORM_AEAD);
-#endif
 
              if (is_aead)
                auth_alg = cipher_alg;
@@ -273,6 +268,7 @@ dpdk_esp_encrypt_node_fn (vlib_main_t * vm,
 
          if (sa0->is_tunnel)
            {
+             rewrite_len = 0;
              if (!is_ipv6 && !sa0->is_tunnel_ip6)      /* ip4inip4 */
                {
                  /* in tunnel mode send it back to FIB */
@@ -350,12 +346,12 @@ dpdk_esp_encrypt_node_fn (vlib_main_t * vm,
          else                  /* transport mode */
            {
              priv->next = DPDK_CRYPTO_INPUT_NEXT_INTERFACE_OUTPUT;
-             u16 rewrite_len = vnet_buffer (b0)->ip.save_rewrite_length;
+             rewrite_len = vnet_buffer (b0)->ip.save_rewrite_length;
              u16 adv = sizeof (esp_header_t) + iv_size;
-             vlib_buffer_advance (b0, -rewrite_len - adv);
+             vlib_buffer_advance (b0, -adv - rewrite_len);
              u8 *src = ((u8 *) ih0) - rewrite_len;
              u8 *dst = vlib_buffer_get_current (b0);
-             oh0 = (ip4_and_esp_header_t *) (dst + rewrite_len);
+             oh0 = vlib_buffer_get_current (b0) + rewrite_len;
 
              if (is_ipv6)
                {
@@ -369,13 +365,12 @@ dpdk_esp_encrypt_node_fn (vlib_main_t * vm,
                }
              else              /* ipv4 */
                {
-                 orig_sz -= ip4_header_bytes (&ih0->ip4);
+                 u16 ip_size = ip4_header_bytes (&ih0->ip4);
+                 orig_sz -= ip_size;
                  next_hdr_type = ih0->ip4.protocol;
-                 memmove (dst, src,
-                          rewrite_len + ip4_header_bytes (&ih0->ip4));
+                 memmove (dst, src, rewrite_len + ip_size);
                  oh0->ip4.protocol = IP_PROTOCOL_IPSEC_ESP;
-                 esp0 =
-                   (esp_header_t *) (oh0 + ip4_header_bytes (&ih0->ip4));
+                 esp0 = (esp_header_t *) (((u8 *) oh0) + ip_size);
                }
              esp0->spi = clib_host_to_net_u32 (sa0->spi);
              esp0->seq = clib_host_to_net_u32 (sa0->seq);
@@ -389,6 +384,7 @@ dpdk_esp_encrypt_node_fn (vlib_main_t * vm,
          u8 *padding =
            vlib_buffer_put_uninit (b0, pad_bytes + 2 + trunc_size);
 
+         /* The extra pad bytes would be overwritten by the digest */
          if (pad_bytes)
            clib_memcpy (padding, pad_data, 16);
 
@@ -399,11 +395,13 @@ dpdk_esp_encrypt_node_fn (vlib_main_t * vm,
          if (is_ipv6)
            {
              u16 len = b0->current_length - sizeof (ip6_header_t);
-             oh6_0->ip6.payload_length = clib_host_to_net_u16 (len);
+             oh6_0->ip6.payload_length =
+               clib_host_to_net_u16 (len - rewrite_len);
            }
          else
            {
-             oh0->ip4.length = clib_host_to_net_u16 (b0->current_length);
+             oh0->ip4.length =
+               clib_host_to_net_u16 (b0->current_length - rewrite_len);
              oh0->ip4.checksum = ip4_header_checksum (&oh0->ip4);
            }
 
@@ -416,9 +414,9 @@ dpdk_esp_encrypt_node_fn (vlib_main_t * vm,
          mb0->pkt_len = vlib_buffer_get_tail (b0) - ((u8 *) esp0);
          mb0->data_off = ((void *) esp0) - mb0->buf_addr;
 
-         u32 cipher_off, cipher_len;
-         u32 auth_len = 0, aad_size = 0;
+         u32 cipher_off, cipher_len, auth_len = 0;
          u32 *aad = NULL;
+
          u8 *digest = vlib_buffer_get_tail (b0) - trunc_size;
          u64 digest_paddr =
            mb0->buf_physaddr + digest - ((u8 *) mb0->buf_addr);
@@ -436,8 +434,6 @@ dpdk_esp_encrypt_node_fn (vlib_main_t * vm,
 
              cipher_off = sizeof (esp_header_t) + iv_size;
              cipher_len = pad_payload_len;
-
-             iv_size = 12;     /* CTR/GCM IV size, not ESP IV size */
            }
 
          if (is_aead)
@@ -446,13 +442,11 @@ dpdk_esp_encrypt_node_fn (vlib_main_t * vm,
              aad[0] = clib_host_to_net_u32 (sa0->spi);
              aad[1] = clib_host_to_net_u32 (sa0->seq);
 
-             if (sa0->use_esn)
-               {
-                 aad[2] = clib_host_to_net_u32 (sa0->seq_hi);
-                 aad_size = 12;
-               }
+             /* aad[3] should always be 0 */
+             if (PREDICT_FALSE (sa0->use_esn))
+               aad[2] = clib_host_to_net_u32 (sa0->seq_hi);
              else
-               aad_size = 8;
+               aad[2] = 0;
            }
          else
            {
@@ -460,15 +454,14 @@ dpdk_esp_encrypt_node_fn (vlib_main_t * vm,
                vlib_buffer_get_tail (b0) - ((u8 *) esp0) - trunc_size;
              if (sa0->use_esn)
                {
-                 *((u32 *) digest) = sa0->seq_hi;
+                 u32 *_digest = (u32 *) digest;
+                 _digest[0] = clib_host_to_net_u32 (sa0->seq_hi);
                  auth_len += 4;
                }
            }
 
-         crypto_op_setup (is_aead, mb0, op, session,
-                          cipher_off, cipher_len, (u8 *) icb, iv_size,
-                          0, auth_len, (u8 *) aad, aad_size,
-                          digest, digest_paddr, trunc_size);
+         crypto_op_setup (is_aead, mb0, op, session, cipher_off, cipher_len,
+                          0, auth_len, (u8 *) aad, digest, digest_paddr);
 
        trace:
          if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))