ipip: Tunnel flags controlling copying data to/from payload/encap
[vpp.git] / src / vnet / ipsec / esp_encrypt.c
index 041b268..186e122 100644 (file)
@@ -65,6 +65,7 @@ typedef struct
   u32 sa_index;
   u32 spi;
   u32 seq;
+  u32 sa_seq_hi;
   u8 udp_encap;
   ipsec_crypto_alg_t crypto_alg;
   ipsec_integ_alg_t integ_alg;
@@ -80,8 +81,9 @@ format_esp_encrypt_trace (u8 * s, va_list * args)
 
   s =
     format (s,
-           "esp: sa-index %d spi %u (0x%08x) seq %u crypto %U integrity %U%s",
-           t->sa_index, t->spi, t->spi, t->seq, format_ipsec_crypto_alg,
+           "esp: sa-index %d spi %u (0x%08x) seq %u sa-seq-hi %u crypto %U integrity %U%s",
+           t->sa_index, t->spi, t->spi, t->seq, t->sa_seq_hi,
+           format_ipsec_crypto_alg,
            t->crypto_alg, format_ipsec_integ_alg, t->integ_alg,
            t->udp_encap ? " udp-encap-enabled" : "");
   return s;
@@ -89,7 +91,9 @@ format_esp_encrypt_trace (u8 * s, va_list * args)
 
 /* pad packet in input buffer */
 static_always_inline u8 *
-esp_add_footer_and_icv (vlib_buffer_t * b, u8 block_size, u8 icv_sz)
+esp_add_footer_and_icv (vlib_buffer_t * b, u8 block_size, u8 icv_sz,
+                       u16 * next, vlib_node_runtime_t * node,
+                       u16 buffer_data_size)
 {
   static const u8 pad_data[ESP_MAX_BLOCK_SIZE] = {
     0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
@@ -102,8 +106,15 @@ esp_add_footer_and_icv (vlib_buffer_t * b, u8 block_size, u8 icv_sz)
   esp_footer_t *f = (esp_footer_t *) (vlib_buffer_get_current (b) +
                                      new_length - sizeof (esp_footer_t));
 
+  if (b->current_data + new_length + icv_sz > buffer_data_size)
+    {
+      b->error = node->errors[ESP_ENCRYPT_ERROR_NO_TRAILER_SPACE];
+      next[0] = ESP_ENCRYPT_NEXT_DROP;
+      return 0;
+    }
+
   if (pad_bytes)
-    clib_memcpy_fast ((u8 *) f - pad_bytes, pad_data, ESP_MAX_BLOCK_SIZE);
+    clib_memcpy_fast ((u8 *) f - pad_bytes, pad_data, pad_bytes);
 
   f->pad_length = pad_bytes;
   b->current_length = new_length + icv_sz;
@@ -186,19 +197,6 @@ esp_get_ip6_hdr_len (ip6_header_t * ip6)
   return len;
 }
 
-static_always_inline int
-esp_trailer_icv_overflow (vlib_node_runtime_t * node, vlib_buffer_t * b,
-                         u16 * next, u16 buffer_data_size)
-{
-  if (b->current_data + b->current_length <= buffer_data_size)
-    return 0;
-
-  b->current_length -= buffer_data_size - b->current_data;
-  b->error = node->errors[ESP_ENCRYPT_ERROR_NO_TRAILER_SPACE];
-  next[0] = ESP_ENCRYPT_NEXT_DROP;
-  return 1;
-}
-
 static_always_inline void
 esp_process_ops (vlib_main_t * vm, vlib_node_runtime_t * node,
                 vnet_crypto_op_t * ops, vlib_buffer_t * b[], u16 * nexts)
@@ -324,11 +322,12 @@ esp_encrypt_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
       if (ipsec_sa_is_set_IS_TUNNEL (sa0))
        {
          payload = vlib_buffer_get_current (b[0]);
-         next_hdr_ptr = esp_add_footer_and_icv (b[0], block_sz, icv_sz);
-         payload_len = b[0]->current_length;
-
-         if (esp_trailer_icv_overflow (node, b[0], next, buffer_data_size))
+         next_hdr_ptr = esp_add_footer_and_icv (b[0], block_sz, icv_sz,
+                                                next, node,
+                                                buffer_data_size);
+         if (!next_hdr_ptr)
            goto trace;
+         payload_len = b[0]->current_length;
 
          /* ESP header */
          hdr_len += sizeof (*esp);
@@ -387,11 +386,12 @@ esp_encrypt_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
 
          vlib_buffer_advance (b[0], ip_len);
          payload = vlib_buffer_get_current (b[0]);
-         next_hdr_ptr = esp_add_footer_and_icv (b[0], block_sz, icv_sz);
-         payload_len = b[0]->current_length;
-
-         if (esp_trailer_icv_overflow (node, b[0], next, buffer_data_size))
+         next_hdr_ptr = esp_add_footer_and_icv (b[0], block_sz, icv_sz,
+                                                next, node,
+                                                buffer_data_size);
+         if (!next_hdr_ptr)
            goto trace;
+         payload_len = b[0]->current_length;
 
          /* ESP header */
          hdr_len += sizeof (*esp);
@@ -521,7 +521,8 @@ esp_encrypt_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
                                                    sizeof (*tr));
          tr->sa_index = sa_index0;
          tr->spi = sa0->spi;
-         tr->seq = sa0->seq - 1;
+         tr->seq = sa0->seq;
+         tr->sa_seq_hi = sa0->seq_hi;
          tr->udp_encap = ipsec_sa_is_set_UDP_ENCAP (sa0);
          tr->crypto_alg = sa0->crypto_alg;
          tr->integ_alg = sa0->integ_alg;
@@ -627,6 +628,13 @@ VNET_FEATURE_INIT (esp4_encrypt_tun_feat_node, static) =
   .runs_before = VNET_FEATURES ("adj-midchain-tx"),
 };
 
+VNET_FEATURE_INIT (esp6o4_encrypt_tun_feat_node, static) =
+{
+  .arc_name = "ip6-output",
+  .node_name = "esp4-encrypt-tun",
+  .runs_before = VNET_FEATURES ("adj-midchain-tx"),
+};
+
 VNET_FEATURE_INIT (esp4_ethernet_encrypt_tun_feat_node, static) =
 {
   .arc_name = "ethernet-output",
@@ -664,6 +672,14 @@ VNET_FEATURE_INIT (esp6_encrypt_tun_feat_node, static) =
   .node_name = "esp6-encrypt-tun",
   .runs_before = VNET_FEATURES ("adj-midchain-tx"),
 };
+
+VNET_FEATURE_INIT (esp4o6_encrypt_tun_feat_node, static) =
+{
+  .arc_name = "ip4-output",
+  .node_name = "esp6-encrypt-tun",
+  .runs_before = VNET_FEATURES ("adj-midchain-tx"),
+};
+
 /* *INDENT-ON* */
 
 typedef struct