Revert "ipsec: Use the new tunnel API types to add flow label and TTL copy"
[vpp.git] / src / vnet / ipsec / ah_encrypt.c
index 1620f87..a4c3491 100644 (file)
 #include <vnet/ipsec/ipsec.h>
 #include <vnet/ipsec/esp.h>
 #include <vnet/ipsec/ah.h>
+#include <vnet/tunnel/tunnel_dp.h>
 
 #define foreach_ah_encrypt_next \
-  _ (DROP, "error-drop")            \
-  _ (IP4_LOOKUP, "ip4-lookup")      \
-  _ (IP6_LOOKUP, "ip6-lookup")      \
+  _ (DROP, "error-drop")                           \
+  _ (HANDOFF, "handoff")                           \
   _ (INTERFACE_OUTPUT, "interface-output")
 
 
@@ -75,8 +75,8 @@ format_ah_encrypt_trace (u8 * s, va_list * args)
   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
   ah_encrypt_trace_t *t = va_arg (*args, ah_encrypt_trace_t *);
 
-  s = format (s, "ah: sa-index %d spi %u seq %u:%u integrity %U",
-             t->sa_index, t->spi, t->seq_hi, t->seq_lo,
+  s = format (s, "ah: sa-index %d spi %u (0x%08x) seq %u:%u integrity %U",
+             t->sa_index, t->spi, t->spi, t->seq_hi, t->seq_lo,
              format_ipsec_integ_alg, t->integ_alg);
   return s;
 }
@@ -112,12 +112,13 @@ typedef struct
 {
   union
   {
+    /* Variable fields in the IP header not covered by the AH
+     * integrity check */
     struct
     {
       u8 hop_limit;
       u32 ip_version_traffic_class_and_flow_label;
     };
-
     struct
     {
       u8 ttl;
@@ -183,6 +184,21 @@ ah_encrypt_inline (vlib_main_t * vm,
       pd->sa_index = current_sa_index;
       next[0] = AH_ENCRYPT_NEXT_DROP;
 
+      if (PREDICT_FALSE (~0 == sa0->thread_index))
+       {
+         /* this is the first packet to use this SA, claim the SA
+          * for this thread. this could happen simultaneously on
+          * another thread */
+         clib_atomic_cmp_and_swap (&sa0->thread_index, ~0,
+                                   ipsec_sa_assign_thread (thread_index));
+       }
+
+      if (PREDICT_TRUE (thread_index != sa0->thread_index))
+       {
+         next[0] = AH_ENCRYPT_NEXT_HANDOFF;
+         goto next;
+       }
+
       if (PREDICT_FALSE (esp_seq_advance (sa0)))
        {
          b[0]->error = node->errors[AH_ENCRYPT_ERROR_SEQ_CYCLED];
@@ -195,8 +211,6 @@ ah_encrypt_inline (vlib_main_t * vm,
 
       ssize_t adv;
       ih0 = vlib_buffer_get_current (b[0]);
-      pd->ttl = ih0->ip4.ttl;
-      pd->tos = ih0->ip4.tos;
 
       if (PREDICT_TRUE (ipsec_sa_is_set_IS_TUNNEL (sa0)))
        {
@@ -216,12 +230,12 @@ ah_encrypt_inline (vlib_main_t * vm,
       /* transport mode save the eth header before it is overwritten */
       if (PREDICT_FALSE (!ipsec_sa_is_set_IS_TUNNEL (sa0)))
        {
-         ethernet_header_t *ieh0 = (ethernet_header_t *)
-           ((u8 *) vlib_buffer_get_current (b[0]) -
-            sizeof (ethernet_header_t));
-         ethernet_header_t *oeh0 =
-           (ethernet_header_t *) ((u8 *) ieh0 + (adv - icv_size));
-         clib_memcpy_fast (oeh0, ieh0, sizeof (ethernet_header_t));
+         const u32 l2_len = vnet_buffer (b[0])->ip.save_rewrite_length;
+         u8 *l2_hdr_in = (u8 *) vlib_buffer_get_current (b[0]) - l2_len;
+
+         u8 *l2_hdr_out = l2_hdr_in + adv - icv_size;
+
+         clib_memcpy_le32 (l2_hdr_out, l2_hdr_in, l2_len);
        }
 
       vlib_buffer_advance (b[0], adv - icv_size);
@@ -232,10 +246,20 @@ ah_encrypt_inline (vlib_main_t * vm,
          ip_hdr_size = sizeof (ip6_header_t);
          oh6_0 = vlib_buffer_get_current (b[0]);
          pd->current_data = b[0]->current_data;
-
          pd->hop_limit = ih6_0->ip6.hop_limit;
-         pd->ip_version_traffic_class_and_flow_label =
+
+         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);
+
+         tunnel_encap_fixup_6o6 (sa0->tunnel_flags,
+                                 &ih6_0->ip6, &oh6_0->ip6);
+
+         pd->ip_version_traffic_class_and_flow_label =
+           oh6_0->ip6.ip_version_traffic_class_and_flow_label;
+         oh6_0->ip6.ip_version_traffic_class_and_flow_label = 0;
+
          if (PREDICT_TRUE (ipsec_sa_is_set_IS_TUNNEL (sa0)))
            {
              next_hdr_type = IP_PROTOCOL_IPV6;
@@ -261,8 +285,24 @@ ah_encrypt_inline (vlib_main_t * vm,
        {
          ip_hdr_size = sizeof (ip4_header_t);
          oh0 = vlib_buffer_get_current (b[0]);
-         clib_memset (oh0, 0, sizeof (ip4_and_ah_header_t));
+         pd->ttl = ih0->ip4.ttl;
+
+         if (sa0->dscp)
+           pd->tos = sa0->dscp << 2;
+         else
+           {
+             pd->tos = ih0->ip4.tos;
+             if (!
+                 (sa0->tunnel_flags &
+                  TUNNEL_ENCAP_DECAP_FLAG_ENCAP_COPY_DSCP))
+               pd->tos &= 0x3;
+             if (!
+                 (sa0->tunnel_flags &
+                  TUNNEL_ENCAP_DECAP_FLAG_ENCAP_COPY_ECN))
+               pd->tos &= 0xfc;
+           }
          pd->current_data = b[0]->current_data;
+         clib_memset (oh0, 0, sizeof (ip4_and_ah_header_t));
 
          if (PREDICT_TRUE (ipsec_sa_is_set_IS_TUNNEL (sa0)))
            {
@@ -292,11 +332,10 @@ ah_encrypt_inline (vlib_main_t * vm,
        {
          clib_memcpy_fast (&oh0->ip4.address_pair,
                            &sa0->ip4_hdr.address_pair,
-                           sizeof (ip4_address_t));
+                           sizeof (ip4_address_pair_t));
 
-         next[0] = sa0->dpo[IPSEC_PROTOCOL_AH].dpoi_next_node;
-         vnet_buffer (b[0])->ip.adj_index[VLIB_TX] =
-           sa0->dpo[IPSEC_PROTOCOL_AH].dpoi_index;
+         next[0] = sa0->dpo.dpoi_next_node;
+         vnet_buffer (b[0])->ip.adj_index[VLIB_TX] = sa0->dpo.dpoi_index;
        }
       else if (is_ip6 && ipsec_sa_is_set_IS_TUNNEL (sa0) &&
               ipsec_sa_is_set_IS_TUNNEL_V6 (sa0))
@@ -304,9 +343,8 @@ ah_encrypt_inline (vlib_main_t * vm,
          clib_memcpy_fast (&oh6_0->ip6.src_address,
                            &sa0->ip6_hdr.src_address,
                            sizeof (ip6_address_t) * 2);
-         next[0] = sa0->dpo[IPSEC_PROTOCOL_AH].dpoi_next_node;
-         vnet_buffer (b[0])->ip.adj_index[VLIB_TX] =
-           sa0->dpo[IPSEC_PROTOCOL_AH].dpoi_index;
+         next[0] = sa0->dpo.dpoi_next_node;
+         vnet_buffer (b[0])->ip.adj_index[VLIB_TX] = sa0->dpo.dpoi_index;
        }
 
       if (PREDICT_TRUE (sa0->integ_op_id))
@@ -422,9 +460,9 @@ VLIB_REGISTER_NODE (ah4_encrypt_node) = {
 
   .n_next_nodes = AH_ENCRYPT_N_NEXT,
   .next_nodes = {
-#define _(s,n) [AH_ENCRYPT_NEXT_##s] = n,
-    foreach_ah_encrypt_next
-#undef _
+    [AH_ENCRYPT_NEXT_DROP] = "ip4-drop",
+    [AH_ENCRYPT_NEXT_HANDOFF] = "ah4-encrypt-handoff",
+    [AH_ENCRYPT_NEXT_INTERFACE_OUTPUT] = "interface-output",
   },
 };
 /* *INDENT-ON* */
@@ -448,9 +486,9 @@ VLIB_REGISTER_NODE (ah6_encrypt_node) = {
 
   .n_next_nodes = AH_ENCRYPT_N_NEXT,
   .next_nodes = {
-#define _(s,n) [AH_ENCRYPT_NEXT_##s] = n,
-    foreach_ah_encrypt_next
-#undef _
+    [AH_ENCRYPT_NEXT_DROP] = "ip6-drop",
+    [AH_ENCRYPT_NEXT_HANDOFF] = "ah6-encrypt-handoff",
+    [AH_ENCRYPT_NEXT_INTERFACE_OUTPUT] = "interface-output",
   },
 };
 /* *INDENT-ON* */