ipsec: bind an SA to a worker
[vpp.git] / src / vnet / ipsec / esp_decrypt.c
index 986ac94..a56a784 100644 (file)
@@ -27,7 +27,8 @@
 #define foreach_esp_decrypt_next                \
 _(DROP, "error-drop")                           \
 _(IP4_INPUT, "ip4-input-no-checksum")           \
-_(IP6_INPUT, "ip6-input")
+_(IP6_INPUT, "ip6-input")                       \
+_(HANDOFF, "handoff")
 
 #define _(v, s) ESP_DECRYPT_NEXT_##v,
 typedef enum
@@ -47,7 +48,8 @@ typedef enum
  _(RUNT, "undersized packet")                                   \
  _(CHAINED_BUFFER, "chained buffers (packet dropped)")          \
  _(OVERSIZED_HEADER, "buffer with oversized header (dropped)")  \
- _(NO_TAIL_SPACE, "no enough buffer tail space (dropped)")
+ _(NO_TAIL_SPACE, "no enough buffer tail space (dropped)")      \
+ _(TUN_NO_PROTO, "no tunnel protocol")                          \
 
 
 typedef enum
@@ -176,6 +178,21 @@ esp_decrypt_inline (vlib_main_t * vm,
          cpd.sa_index = current_sa_index;
        }
 
+      if (PREDICT_FALSE (~0 == sa0->decrypt_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->decrypt_thread_index, ~0,
+                                   ipsec_sa_assign_thread (thread_index));
+       }
+
+      if (PREDICT_TRUE (thread_index != sa0->decrypt_thread_index))
+       {
+         next[0] = ESP_DECRYPT_NEXT_HANDOFF;
+         goto next;
+       }
+
       /* store packet data for next round for easier prefetch */
       pd->sa_data = cpd.sa_data;
       pd->current_data = b[0]->current_data;
@@ -497,8 +514,11 @@ esp_decrypt_inline (vlib_main_t * vm,
                                                     &ip4->dst_address) ||
                          !ip46_address_is_equal_v4 (&itp->itp_tun.dst,
                                                     &ip4->src_address))
-                       next[0] = ESP_DECRYPT_NEXT_DROP;
-
+                       {
+                         next[0] = ESP_DECRYPT_NEXT_DROP;
+                         b[0]->error =
+                           node->errors[ESP_DECRYPT_ERROR_TUN_NO_PROTO];
+                       }
                    }
                  else if (f->next_header == IP_PROTOCOL_IPV6)
                    {
@@ -510,7 +530,11 @@ esp_decrypt_inline (vlib_main_t * vm,
                                                     &ip6->dst_address) ||
                          !ip46_address_is_equal_v6 (&itp->itp_tun.dst,
                                                     &ip6->src_address))
-                       next[0] = ESP_DECRYPT_NEXT_DROP;
+                       {
+                         next[0] = ESP_DECRYPT_NEXT_DROP;
+                         b[0]->error =
+                           node->errors[ESP_DECRYPT_ERROR_TUN_NO_PROTO];
+                       }
                    }
                }
            }
@@ -587,9 +611,10 @@ VLIB_REGISTER_NODE (esp4_decrypt_node) = {
 
   .n_next_nodes = ESP_DECRYPT_N_NEXT,
   .next_nodes = {
-#define _(s,n) [ESP_DECRYPT_NEXT_##s] = n,
-    foreach_esp_decrypt_next
-#undef _
+    [ESP_DECRYPT_NEXT_DROP] = "ip4-drop",
+    [ESP_DECRYPT_NEXT_IP4_INPUT] = "ip4-input-no-checksum",
+    [ESP_DECRYPT_NEXT_IP6_INPUT] = "ip6-input",
+    [ESP_DECRYPT_NEXT_HANDOFF] = "esp4-decrypt-handoff",
   },
 };
 
@@ -604,9 +629,10 @@ VLIB_REGISTER_NODE (esp6_decrypt_node) = {
 
   .n_next_nodes = ESP_DECRYPT_N_NEXT,
   .next_nodes = {
-#define _(s,n) [ESP_DECRYPT_NEXT_##s] = n,
-    foreach_esp_decrypt_next
-#undef _
+    [ESP_DECRYPT_NEXT_DROP] = "ip6-drop",
+    [ESP_DECRYPT_NEXT_IP4_INPUT] = "ip4-input-no-checksum",
+    [ESP_DECRYPT_NEXT_IP6_INPUT] = "ip6-input",
+    [ESP_DECRYPT_NEXT_HANDOFF]=  "esp6-decrypt-handoff",
   },
 };
 
@@ -615,15 +641,14 @@ VLIB_REGISTER_NODE (esp4_decrypt_tun_node) = {
   .vector_size = sizeof (u32),
   .format_trace = format_esp_decrypt_trace,
   .type = VLIB_NODE_TYPE_INTERNAL,
-
   .n_errors = ARRAY_LEN(esp_decrypt_error_strings),
   .error_strings = esp_decrypt_error_strings,
-
   .n_next_nodes = ESP_DECRYPT_N_NEXT,
   .next_nodes = {
-#define _(s,n) [ESP_DECRYPT_NEXT_##s] = n,
-    foreach_esp_decrypt_next
-#undef _
+    [ESP_DECRYPT_NEXT_DROP] = "ip4-drop",
+    [ESP_DECRYPT_NEXT_IP4_INPUT] = "ip4-input-no-checksum",
+    [ESP_DECRYPT_NEXT_IP6_INPUT] = "ip6-input",
+    [ESP_DECRYPT_NEXT_HANDOFF] = "esp4-decrypt-handoff",
   },
 };
 
@@ -632,15 +657,14 @@ VLIB_REGISTER_NODE (esp6_decrypt_tun_node) = {
   .vector_size = sizeof (u32),
   .format_trace = format_esp_decrypt_trace,
   .type = VLIB_NODE_TYPE_INTERNAL,
-
   .n_errors = ARRAY_LEN(esp_decrypt_error_strings),
   .error_strings = esp_decrypt_error_strings,
-
   .n_next_nodes = ESP_DECRYPT_N_NEXT,
   .next_nodes = {
-#define _(s,n) [ESP_DECRYPT_NEXT_##s] = n,
-    foreach_esp_decrypt_next
-#undef _
+    [ESP_DECRYPT_NEXT_DROP] = "ip6-drop",
+    [ESP_DECRYPT_NEXT_IP4_INPUT] = "ip4-input-no-checksum",
+    [ESP_DECRYPT_NEXT_IP6_INPUT] = "ip6-input",
+    [ESP_DECRYPT_NEXT_HANDOFF]=  "esp6-decrypt-handoff",
   },
 };
 /* *INDENT-ON* */