plugins: odp: Add support for IPsec inline operation 79/10279/3
authorSzymon Sliwa <[email protected]>
Wed, 24 Jan 2018 13:05:06 +0000 (14:05 +0100)
committerSzymon Sliwa <[email protected]>
Mon, 19 Feb 2018 16:47:48 +0000 (17:47 +0100)
To use inline mode put inline flag in the odp section
of the startup.conf file, like this:

odp {
    enable-odp-ipsec
    inline
}

Falls back to lookaside mode.

Change-Id: I1292a7254b25a15b25285773a43bae112394827d
Signed-off-by: Szymon Sliwa <[email protected]>
src/plugins/odp/ipsec/esp_encrypt_ipsec_api.c
src/plugins/odp/ipsec/ipsec.c
src/plugins/odp/node.c
src/plugins/odp/odp_packet.c
src/plugins/odp/odp_packet.h
src/vpp/conf/startup.conf

index 4753ff8..4feaa10 100644 (file)
@@ -108,6 +108,10 @@ esp_encrypt_node_fn (vlib_main_t * vm,
   odp_crypto_main_t *ocm = &odp_crypto_main;
   u32 thread_index = vlib_get_thread_index ();
 
+  vnet_main_t *vnm = vnet_get_main ();
+  odp_packet_main_t *om = odp_packet_main;
+  vnet_interface_main_t *vint_main = &vnm->interface_main;
+
   ipsec_alloc_empty_buffers (vm, im);
 
   u32 *empty_buffers = im->empty_buffers[thread_index];
@@ -135,10 +139,12 @@ esp_encrypt_node_fn (vlib_main_t * vm,
        {
          u32 bi0, next0;
          vlib_buffer_t *i_b0, *o_b0;
+         vnet_sw_interface_t *sw;
+         vnet_hw_interface_t *hw;
          u32 sa_index0;
          ipsec_sa_t *sa0;
          ip6_header_t *h6 = 0;
-         //u8 transport_mode = 0;
+         odp_packet_if_t *oif;
          sa_data_t *sa_sess_data;
          u32 flow_label;
 
@@ -201,6 +207,7 @@ esp_encrypt_node_fn (vlib_main_t * vm,
            {
              odp_packet_t pkt = odp_packet_from_vlib_buffer (i_b0);
              odp_packet_t out_pkt;
+             odp_ipsec_out_inline_param_t ipsec_inline_params;
 
              odp_ipsec_out_param_t oiopt;
              oiopt.num_sa = 1;
@@ -218,7 +225,29 @@ esp_encrypt_node_fn (vlib_main_t * vm,
 
              int ret;
 
-              if (is_async)
+             if (is_inline && next0 == ESP_ENCRYPT_NEXT_INTERFACE_OUTPUT)
+               {
+                 sw =
+                   vnet_get_sw_interface (vnm,
+                                          vnet_buffer (i_b0)->sw_if_index
+                                          [VLIB_TX]);
+                 hw = vnet_get_hw_interface (vnm, sw->hw_if_index);
+                 oif = pool_elt_at_index (om->interfaces, hw->dev_instance);
+                 ipsec_inline_params.pktio = oif->pktio;
+                 ipsec_inline_params.outer_hdr.ptr =
+                   (u8 *) & vnet_buffer (i_b0)->post_crypto.dst_mac;
+                 ipsec_inline_params.outer_hdr.len =
+                   sizeof (ethernet_header_t);
+                 ret =
+                   odp_ipsec_out_inline (&pkt, 1, &oiopt,
+                                         &ipsec_inline_params);
+                 vlib_increment_combined_counter
+                   (vint_main->combined_sw_if_counters +
+                    VNET_INTERFACE_COUNTER_TX, thread_index,
+                    vnet_buffer (i_b0)->sw_if_index[VLIB_TX], 1,
+                    i_b0->current_length);
+               }
+              else if (is_async)
                ret = odp_ipsec_out_enq (&pkt, 1, &oiopt);
              else
                ret = odp_ipsec_out (&pkt, 1, &out_pkt, &processed, &oiopt);
@@ -230,7 +259,9 @@ esp_encrypt_node_fn (vlib_main_t * vm,
                }
 
 
-             if (!is_async)
+             if (!is_async
+                 && !(is_inline
+                      && next0 == ESP_ENCRYPT_NEXT_INTERFACE_OUTPUT))
                {
                  o_b0 = vlib_buffer_from_odp_packet (out_pkt);
 
@@ -240,37 +271,38 @@ esp_encrypt_node_fn (vlib_main_t * vm,
                           (intptr_t) o_b0->data +
                           (intptr_t) odp_packet_l3_offset (out_pkt));
                  o_b0->current_length = odp_packet_len (out_pkt);
-               }
-
-           }
 
-         if (!is_async)
-           {
-             if (!sa0->is_tunnel)
-               {
-                 if (vnet_buffer (o_b0)->sw_if_index[VLIB_TX] != ~0)
+                 if (!sa0->is_tunnel)
                    {
-                     ethernet_header_t *ieh0, *oeh0;
-                     ieh0 =
-                       (ethernet_header_t *) & vnet_buffer (i_b0)->post_crypto.dst_mac;
-                     oeh0 =
-                       (ethernet_header_t *) ((uintptr_t)
-                                              vlib_buffer_get_current (o_b0)
-                                              - sizeof (ethernet_header_t));
-                     clib_memcpy (oeh0, ieh0, sizeof (ethernet_header_t));
+                     if (vnet_buffer (o_b0)->sw_if_index[VLIB_TX] != ~0)
+                       {
+                         ethernet_header_t *ieh0, *oeh0;
+                         ieh0 =
+                           (ethernet_header_t *) &
+                           vnet_buffer (i_b0)->post_crypto.dst_mac;
+                         oeh0 =
+                           (ethernet_header_t *) ((uintptr_t)
+                                                  vlib_buffer_get_current
+                                                  (o_b0) -
+                                                  sizeof
+                                                  (ethernet_header_t));
+                         clib_memcpy (oeh0, ieh0,
+                                      sizeof (ethernet_header_t));
+                       }
+
+                     o_b0->current_data -= sizeof (ethernet_header_t);
+                     o_b0->current_length += sizeof (ethernet_header_t);
                    }
-                 o_b0->current_data -= sizeof (ethernet_header_t);
-                 o_b0->current_length += sizeof (ethernet_header_t);
-               }
 
-             vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
-                                              to_next, n_left_to_next, bi0,
-                                              next0);
-           }
-         else
-           {
-             to_next -= 1;
-             n_left_to_next += 1;
+                 vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
+                                                  to_next, n_left_to_next,
+                                                  bi0, next0);
+               }
+             else
+               {
+                 to_next -= 1;
+                 n_left_to_next += 1;
+               }
            }
        trace:
          if (PREDICT_FALSE (i_b0->flags & VLIB_BUFFER_IS_TRACED))
@@ -314,7 +346,6 @@ VLIB_REGISTER_NODE (odp_ipsec_esp_encrypt_node) = {
 };
 
 VLIB_NODE_FUNCTION_MULTIARCH (odp_ipsec_esp_encrypt_node, esp_encrypt_node_fn)
-
      static uword
        esp_encrypt_post_node_fn (vlib_main_t * vm,
                                 vlib_node_runtime_t * node,
index 62a074f..f21f3fe 100644 (file)
@@ -132,6 +132,13 @@ create_odp_sa (ipsec_sa_t * sa, sa_data_t * sa_sess_data, int flow_label,
        }
     }
 
+  if (sa_params.dir == ODP_IPSEC_DIR_INBOUND && is_inline)
+    {
+      sa_params.inbound.lookup_mode = ODP_IPSEC_LOOKUP_SPI;
+      sa_params.inbound.lookup_param.ip_version =
+       (sa->is_tunnel_ip6 ? ODP_IPSEC_IPV6 : ODP_IPSEC_IPV4);
+    }
+
   sa_params.crypto.cipher_alg = ODP_CIPHER_ALG_AES_CBC;
   sa_params.crypto.cipher_key.data = sa->crypto_key;
   sa_params.crypto.cipher_key.length = sa->crypto_key_len;
@@ -380,6 +387,29 @@ ipsec_init (vlib_main_t * vm, u8 ipsec_api)
       ocm->workers[0].post_decrypt = ocm->workers[1].post_decrypt;
     }
 
+  if (ipsec_api)
+    {
+      odp_ipsec_config_t ipsec_config;
+      odp_ipsec_config_init (&ipsec_config);
+
+      if (is_inline)
+       {
+         ipsec_config.inbound_mode = ODP_IPSEC_OP_MODE_INLINE;
+         ipsec_config.outbound_mode = ODP_IPSEC_OP_MODE_INLINE;
+       }
+      else if (is_async)
+       {
+         ipsec_config.inbound_mode = ODP_IPSEC_OP_MODE_ASYNC;
+         ipsec_config.outbound_mode = ODP_IPSEC_OP_MODE_ASYNC;
+       }
+      else
+       {
+         ipsec_config.inbound_mode = ODP_IPSEC_OP_MODE_SYNC;
+         ipsec_config.outbound_mode = ODP_IPSEC_OP_MODE_SYNC;
+       }
+      odp_ipsec_config (&ipsec_config);
+    }
+
   return 0;
 }
 
index e0b468a..322aeb7 100755 (executable)
@@ -177,6 +177,8 @@ odp_adjust_buffer (vlib_buffer_t * buf, odp_packet_t pkt,
 {
   buf->current_length = odp_packet_len (pkt);
   buf->current_data = 0;
+  buf->current_data = (int) ((intptr_t) odp_packet_data (pkt) -
+                            (intptr_t) buf->data);
   buf->total_length_not_including_first_buffer = 0;
   buf->flags = VLIB_BUFFER_TOTAL_LENGTH_VALID;
   buf->free_list_index = VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX;
@@ -355,8 +357,9 @@ odp_packet_device_input_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
          else
            next0 = odp_rx_next_from_etype (pkt, b0);
 
-         if (next0 != VNET_DEVICE_INPUT_NEXT_ETHERNET_INPUT)
-           vlib_buffer_advance (b0, sizeof (ethernet_header_t));
+         b0->current_data = (int) ((intptr_t) odp_packet_data (pkt) -
+                                   (intptr_t) b0->data);
+         vlib_buffer_advance (b0, sizeof (ethernet_header_t));
 
          /* trace */
          ODP_TRACE_BUFFER (n_trace, b0, next0, vm, node, oif);
index 7f5f05c..29b2ef0 100755 (executable)
@@ -26,6 +26,7 @@ odp_crypto_main_t odp_crypto_main;
 u8 enable_odp_crypto;
 u8 ipsec_api;
 u8 is_async;
+u8 is_inline;
 
 static u32
 odp_packet_eth_flag_change (vnet_main_t * vnm, vnet_hw_interface_t * hi,
@@ -437,9 +438,13 @@ odp_config (vlib_main_t * vm, unformat_input_t * input)
          ipsec_api = 1;
        }
       else if (unformat (input, "async"))
-        {
-          is_async = 1;
-        }
+       {
+         is_async = 1;
+       }
+      else if (unformat (input, "inline"))
+       {
+         is_inline = 1;
+       }
       else if (unformat (input, "%s", &param))
        {
          clib_warning ("%s: Unknown option %s\n", __func__, param);
index e840947..ac98415 100755 (executable)
@@ -83,6 +83,7 @@ extern odp_if_mode_t def_if_mode;
 extern u8 enable_odp_crypto;
 extern u8 ipsec_api;
 extern u8 is_async;
+extern u8 is_inline;
 
 u32 odp_packet_create_if (vlib_main_t * vm, u8 * host_if_name,
                          u8 * hw_addr_set, u32 * sw_if_index,
index 8b05286..3d4f7c3 100644 (file)
@@ -138,6 +138,9 @@ cpu {
 
        ## To use asynchronous mode of the crypto/ipsec operations
        # async
+
+       ## To use inline mode of ipsec
+       # inline
 # }
 
 # Adjusting the plugin path depending on where the VPP plugins are: