IPSEC; dpdk backend for tunnel interface encryption
[vpp.git] / src / plugins / dpdk / ipsec / esp_encrypt.c
index 25815d9..45a6257 100644 (file)
@@ -110,7 +110,7 @@ format_esp_encrypt_trace (u8 * s, va_list * args)
 always_inline uword
 dpdk_esp_encrypt_inline (vlib_main_t * vm,
                         vlib_node_runtime_t * node,
-                        vlib_frame_t * from_frame, int is_ip6)
+                        vlib_frame_t * from_frame, int is_ip6, int is_tun)
 {
   u32 n_left_from, *from, *to_next, next_index, thread_index;
   ipsec_main_t *im = &ipsec_main;
@@ -155,8 +155,8 @@ dpdk_esp_encrypt_inline (vlib_main_t * vm,
       while (n_left_from > 0 && n_left_to_next > 0)
        {
          clib_error_t *error;
-         u32 bi0;
-         vlib_buffer_t *b0 = 0;
+         u32 bi0, bi1;
+         vlib_buffer_t *b0, *b1;
          u32 sa_index0;
          ip4_and_esp_header_t *ih0, *oh0 = 0;
          ip6_and_esp_header_t *ih6_0, *oh6_0 = 0;
@@ -169,7 +169,7 @@ dpdk_esp_encrypt_inline (vlib_main_t * vm,
          u8 trunc_size;
          u16 rewrite_len;
          u16 udp_encap_adv = 0;
-         struct rte_mbuf *mb0 = 0;
+         struct rte_mbuf *mb0;
          struct rte_crypto_op *op;
          u16 res_idx;
 
@@ -188,6 +188,16 @@ dpdk_esp_encrypt_inline (vlib_main_t * vm,
          /* mb0 */
          CLIB_PREFETCH (mb0, CLIB_CACHE_LINE_BYTES, STORE);
 
+         if (n_left_from > 1)
+           {
+             bi1 = from[1];
+             b1 = vlib_get_buffer (vm, bi1);
+
+             CLIB_PREFETCH (b1, CLIB_CACHE_LINE_BYTES, LOAD);
+             CLIB_PREFETCH (b1->data - CLIB_CACHE_LINE_BYTES,
+                            CLIB_CACHE_LINE_BYTES, STORE);
+           }
+
          op = ops[0];
          ops += 1;
          ASSERT (op->status == RTE_CRYPTO_OP_STATUS_NOT_PROCESSED);
@@ -200,7 +210,16 @@ dpdk_esp_encrypt_inline (vlib_main_t * vm,
            sizeof (op[0]) + sizeof (op[0].sym[0]) + sizeof (priv[0]);
          CLIB_PREFETCH (op, op_len, STORE);
 
-         sa_index0 = vnet_buffer (b0)->ipsec.sad_index;
+         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));
+           }
+         else
+           sa_index0 = vnet_buffer (b0)->ipsec.sad_index;
 
          if (sa_index0 != last_sa_index)
            {
@@ -513,7 +532,7 @@ dpdk_esp_encrypt_inline (vlib_main_t * vm,
              aad[1] = clib_host_to_net_u32 (sa0->seq);
 
              /* aad[3] should always be 0 */
-             if (PREDICT_FALSE (ipsec_sa_is_set_USE_EXTENDED_SEQ_NUM (sa0)))
+             if (PREDICT_FALSE (ipsec_sa_is_set_USE_ESN (sa0)))
                aad[2] = clib_host_to_net_u32 (sa0->seq_hi);
              else
                aad[2] = 0;
@@ -522,7 +541,7 @@ dpdk_esp_encrypt_inline (vlib_main_t * vm,
            {
              auth_len =
                vlib_buffer_get_tail (b0) - ((u8 *) esp0) - trunc_size;
-             if (ipsec_sa_is_set_USE_EXTENDED_SEQ_NUM (sa0))
+             if (ipsec_sa_is_set_USE_ESN (sa0))
                {
                  u32 *_digest = (u32 *) digest;
                  _digest[0] = clib_host_to_net_u32 (sa0->seq_hi);
@@ -576,7 +595,7 @@ VLIB_NODE_FN (dpdk_esp4_encrypt_node) (vlib_main_t * vm,
                                       vlib_node_runtime_t * node,
                                       vlib_frame_t * from_frame)
 {
-  return dpdk_esp_encrypt_inline (vm, node, from_frame, 0 /*is_ip6 */ );
+  return dpdk_esp_encrypt_inline (vm, node, from_frame, 0 /*is_ip6 */ , 0);
 }
 
 /* *INDENT-OFF* */
@@ -599,7 +618,7 @@ VLIB_NODE_FN (dpdk_esp6_encrypt_node) (vlib_main_t * vm,
                                       vlib_node_runtime_t * node,
                                       vlib_frame_t * from_frame)
 {
-  return dpdk_esp_encrypt_inline (vm, node, from_frame, 1 /*is_ip6 */ );
+  return dpdk_esp_encrypt_inline (vm, node, from_frame, 1 /*is_ip6 */ , 0);
 }
 
 /* *INDENT-OFF* */
@@ -618,6 +637,66 @@ VLIB_REGISTER_NODE (dpdk_esp6_encrypt_node) = {
 };
 /* *INDENT-ON* */
 
+VLIB_NODE_FN (dpdk_esp4_encrypt_tun_node) (vlib_main_t * vm,
+                                          vlib_node_runtime_t * node,
+                                          vlib_frame_t * from_frame)
+{
+  return dpdk_esp_encrypt_inline (vm, node, from_frame, 0 /*is_ip6 */ , 1);
+}
+
+/* *INDENT-OFF* */
+VLIB_REGISTER_NODE (dpdk_esp4_encrypt_tun_node) = {
+  .name = "dpdk-esp4-encrypt-tun",
+  .flags = VLIB_NODE_FLAG_IS_OUTPUT,
+  .vector_size = sizeof (u32),
+  .format_trace = format_esp_encrypt_trace,
+  .n_errors = ARRAY_LEN (esp_encrypt_error_strings),
+  .error_strings = esp_encrypt_error_strings,
+  .n_next_nodes = 1,
+  .next_nodes =
+    {
+      [ESP_ENCRYPT_NEXT_DROP] = "error-drop",
+    }
+};
+
+VNET_FEATURE_INIT (dpdk_esp4_encrypt_tun_feat_node, static) =
+{
+  .arc_name = "ip4-output",
+  .node_name = "dpdk-esp4-encrypt-tun",
+  .runs_before = VNET_FEATURES ("adj-midchain-tx"),
+};
+/* *INDENT-ON* */
+
+VLIB_NODE_FN (dpdk_esp6_encrypt_tun_node) (vlib_main_t * vm,
+                                          vlib_node_runtime_t * node,
+                                          vlib_frame_t * from_frame)
+{
+  return dpdk_esp_encrypt_inline (vm, node, from_frame, 1 /*is_ip6 */ , 1);
+}
+
+/* *INDENT-OFF* */
+VLIB_REGISTER_NODE (dpdk_esp6_encrypt_tun_node) = {
+  .name = "dpdk-esp6-encrypt-tun",
+  .flags = VLIB_NODE_FLAG_IS_OUTPUT,
+  .vector_size = sizeof (u32),
+  .format_trace = format_esp_encrypt_trace,
+  .n_errors = ARRAY_LEN (esp_encrypt_error_strings),
+  .error_strings = esp_encrypt_error_strings,
+  .n_next_nodes = 1,
+  .next_nodes =
+    {
+      [ESP_ENCRYPT_NEXT_DROP] = "error-drop",
+    }
+};
+
+VNET_FEATURE_INIT (dpdk_esp6_encrypt_tun_feat_node, static) =
+{
+  .arc_name = "ip6-output",
+  .node_name = "dpdk-esp6-encrypt-tun",
+  .runs_before = VNET_FEATURES ("adj-midchain-tx"),
+};
+/* *INDENT-ON* */
+
 /*
  * fd.io coding-style-patch-verification: ON
  *