diff mbox series

[API-NEXT,v4,2/3] api: ipsec: add inline IPSEC support

Message ID 1490869785-16657-2-git-send-email-petri.savolainen@linaro.org
State Accepted
Commit 4caae92593e353802b8894959fe658c09763eaf8
Headers show
Series [API-NEXT,v4,1/3] api: ipsec: extend lookaside API | expand

Commit Message

Petri Savolainen March 30, 2017, 10:29 a.m. UTC
Added support for inline IPSEC processing on packet input and
output. Inline mode IPSEC and traffic manager cannot be enabled
(currently) on the same pktio interface.

Signed-off-by: Petri Savolainen <petri.savolainen@linaro.org>

---
 include/odp/api/spec/ipsec.h     | 355 ++++++++++++++++++++++++++++++++++++---
 include/odp/api/spec/packet_io.h |  32 ++++
 2 files changed, 360 insertions(+), 27 deletions(-)

-- 
2.8.1
diff mbox series

Patch

diff --git a/include/odp/api/spec/ipsec.h b/include/odp/api/spec/ipsec.h
index 118363e..b3dc0ca 100644
--- a/include/odp/api/spec/ipsec.h
+++ b/include/odp/api/spec/ipsec.h
@@ -19,6 +19,8 @@  extern "C" {
 #endif
 
 #include <odp/api/crypto.h>
+#include <odp/api/packet_io.h>
+#include <odp/api/classification.h>
 
 /** @defgroup odp_ipsec ODP IPSEC
  *  Operations of IPSEC API.
@@ -51,11 +53,43 @@  typedef enum odp_ipsec_op_mode_t {
 	  * Application uses asynchronous IPSEC operations,
 	  * which return results via events.
 	  */
-	ODP_IPSEC_OP_MODE_ASYNC
+	ODP_IPSEC_OP_MODE_ASYNC,
+
+	/** Inline IPSEC operation
+	  *
+	  * Packet input/output is connected directly to IPSEC inbound/outbound
+	  * processing. Application uses asynchronous or inline IPSEC
+	  * operations.
+	  */
+	ODP_IPSEC_OP_MODE_INLINE,
+
+	/** IPSEC is disabled in inbound / outbound direction */
+	ODP_IPSEC_OP_MODE_DISABLED
 
 } odp_ipsec_op_mode_t;
 
 /**
+ * Protocol layers in IPSEC configuration
+ */
+typedef enum odp_ipsec_proto_layer_t {
+	/** No layers */
+	ODP_IPSEC_LAYER_NONE = 0,
+
+	/** Layer L2 protocols (Ethernet, VLAN, etc) */
+	ODP_IPSEC_LAYER_L2,
+
+	/** Layer L3 protocols (IPv4, IPv6, ICMP, IPSEC, etc) */
+	ODP_IPSEC_LAYER_L3,
+
+	/** Layer L4 protocols (UDP, TCP, SCTP) */
+	ODP_IPSEC_LAYER_L4,
+
+	/** All layers */
+	ODP_IPSEC_LAYER_ALL
+
+} odp_ipsec_proto_layer_t;
+
+/**
  * Configuration options for IPSEC inbound processing
  */
 typedef struct odp_ipsec_inbound_config_t {
@@ -88,9 +122,110 @@  typedef struct odp_ipsec_inbound_config_t {
 
 	} lookup;
 
+	/** Retain outer headers
+	 *
+	 *  Select up to which protocol layer (at least) outer headers are
+	 *  retained in inbound inline processing. Default value is
+	 *  ODP_IPSEC_LAYER_NONE.
+	 *
+	 *  ODP_IPSEC_LAYER_NONE: Application does not require any outer
+	 *                        headers to be retained.
+	 *
+	 *  ODP_IPSEC_LAYER_L2:   Retain headers up to layer 2.
+	 *
+	 *  ODP_IPSEC_LAYER_L3:   Retain headers up to layer 3, otherwise the
+	 *                        same as ODP_IPSEC_LAYER_ALL.
+	 *
+	 *  ODP_IPSEC_LAYER_L4:   Retain headers up to layer 4, otherwise the
+	 *                        same as ODP_IPSEC_LAYER_ALL.
+	 *
+	 *  ODP_IPSEC_LAYER_ALL:  In tunnel mode, all headers before IPSEC are
+	 *                        retained. In transport mode, all headers
+	 *                        before IP (carrying IPSEC) are retained.
+	 *
+	 */
+	odp_ipsec_proto_layer_t retain_outer;
+
+	/** Parse packet headers after IPSEC transformation
+	 *
+	 *  Select header parsing level after inbound processing. Headers of the
+	 *  resulting packet must be parsed (at least) up to this level. Parsing
+	 *  starts from IP (layer 3). Each successfully transformed packet has
+	 *  a valid value for L3 offset regardless of the parse configuration.
+	 *  Default value is ODP_IPSEC_LAYER_NONE.
+	 */
+	odp_ipsec_proto_layer_t parse;
+
+	/** Flags to control IPSEC payload data checks up to the selected parse
+	 *  level. */
+	union {
+		struct {
+			/** Check IPv4 header checksum in IPSEC payload.
+			 *  Default value is 0. */
+			uint32_t ipv4_chksum   : 1;
+
+			/** Check UDP checksum in IPSEC payload.
+			 *  Default value is 0. */
+			uint32_t udp_chksum    : 1;
+
+			/** Check TCP checksum in IPSEC payload.
+			 *  Default value is 0. */
+			uint32_t tcp_chksum    : 1;
+
+			/** Check SCTP checksum in IPSEC payload.
+			 *  Default value is 0. */
+			uint32_t sctp_chksum   : 1;
+		} check;
+
+		/** All bits of the bit field structure
+		  *
+		  * This field can be used to set/clear all flags, or bitwise
+		  * operations over the entire structure. */
+		uint32_t all_check;
+	};
+
 } odp_ipsec_inbound_config_t;
 
 /**
+ * Configuration options for IPSEC outbound processing
+ */
+typedef struct odp_ipsec_outbound_config_t {
+	/** Flags to control L3/L4 checksum insertion as part of outbound
+	 *  packet processing. Packet must have set with valid L3/L4 offsets.
+	 *  Checksum configuration is ignored for packets that checksum cannot
+	 *  be computed for (e.g. IPv4 fragments). Application may use a packet
+	 *  metadata flag to disable checksum insertion per packet bases.
+	 */
+	union {
+		struct {
+			/** Insert IPv4 header checksum on the payload packet
+			 *  before IPSEC transformation. Default value is 0. */
+			uint32_t inner_ipv4   : 1;
+
+			/** Insert UDP header checksum on the payload packet
+			 *  before IPSEC transformation. Default value is 0. */
+			uint32_t inner_udp    : 1;
+
+			/** Insert TCP header checksum on the payload packet
+			 *  before IPSEC transformation. Default value is 0. */
+			uint32_t inner_tcp    : 1;
+
+			/** Insert SCTP header checksum on the payload packet
+			 *  before IPSEC transformation. Default value is 0. */
+			uint32_t inner_sctp   : 1;
+
+		} chksum;
+
+		/** All bits of the bit field structure
+		  *
+		  * This field can be used to set/clear all flags, or bitwise
+		  * operations over the entire structure. */
+		uint32_t all_chksum;
+	};
+
+} odp_ipsec_outbound_config_t;
+
+/**
  * IPSEC capability
  */
 typedef struct odp_ipsec_capability_t {
@@ -113,6 +248,23 @@  typedef struct odp_ipsec_capability_t {
 	 */
 	uint8_t op_mode_async;
 
+	/** Inline IPSEC operation mode (ODP_IPSEC_OP_MODE_INLINE) support
+	 *
+	 *  0: Inline IPSEC operation is not supported
+	 *  1: Inline IPSEC operation is supported
+	 *  2: Inline IPSEC operation is supported and preferred
+	 */
+	uint8_t op_mode_inline;
+
+	/** Support of pipelined classification (ODP_IPSEC_PIPELINE_CLS) of
+	 *  resulting inbound packets.
+	 *
+	 *  0: Classification of resulting packets is not supported
+	 *  1: Classification of resulting packets is supported
+	 *  2: Classification of resulting packets is supported and preferred
+	 */
+	uint8_t pipeline_cls;
+
 	/** Soft expiry limit in seconds support
 	 *
 	 *  0: Limit is not supported
@@ -139,12 +291,19 @@  typedef struct odp_ipsec_capability_t {
  * IPSEC configuration options
  */
 typedef struct odp_ipsec_config_t {
-	/** IPSEC operation mode. Application selects which mode (sync or async)
-	 *  will be used for IPSEC operations.
+	/** Inbound IPSEC operation mode. Application selects which mode
+	 *  will be used for inbound IPSEC operations.
 	 *
 	 *  @see odp_ipsec_in(), odp_ipsec_in_enq()
 	 */
-	odp_ipsec_op_mode_t op_mode;
+	odp_ipsec_op_mode_t inbound_mode;
+
+	/** Outbound IPSEC operation mode. Application selects which mode
+	 *  will be used for outbound IPSEC operations.
+	 *
+	 *  @see odp_ipsec_out(), odp_ipsec_out_enq(), odp_ipsec_out_inline()
+	 */
+	odp_ipsec_op_mode_t outbound_mode;
 
 	/** Maximum number of IPSEC SAs that application will use
 	 * simultaneously */
@@ -153,6 +312,9 @@  typedef struct odp_ipsec_config_t {
 	/** IPSEC inbound processing configuration */
 	odp_ipsec_inbound_config_t inbound;
 
+	/** IPSEC outbound processing configuration */
+	odp_ipsec_outbound_config_t outbound;
+
 } odp_ipsec_config_t;
 
 /**
@@ -392,13 +554,35 @@  typedef enum odp_ipsec_lookup_mode_t {
 	ODP_IPSEC_LOOKUP_DISABLED = 0,
 
 	/** Inbound SA lookup is enabled. Lookup matches only SPI value.
-	 *  SA lookup failure status (error.sa_lookup) is reported through
+	 *  In inline mode, a lookup miss directs the packet back to normal
+	 *  packet input interface processing. In other modes, the SA lookup
+	 *  failure status (error.sa_lookup) is reported through
 	 *  odp_ipsec_packet_result_t. */
-	ODP_IPSEC_LOOKUP_SPI
+	ODP_IPSEC_LOOKUP_SPI,
+
+	/** Inbound SA lookup is enabled. Lookup matches both SPI value and
+	  * destination IP address. Functionality is otherwise identical to
+	  * ODP_IPSEC_LOOKUP_SPI. */
+	ODP_IPSEC_LOOKUP_DSTADDR_SPI
 
 } odp_ipsec_lookup_mode_t;
 
 /**
+ * Result event pipeline configuration
+ */
+typedef enum odp_ipsec_pipeline_t {
+	/** Do not pipeline */
+	ODP_IPSEC_PIPELINE_NONE = 0,
+
+	/** Send IPSEC result events to the classifier.
+	 *
+	 *  IPSEC capability 'pipeline_cls' determines if pipelined
+	 *  classification is supported. */
+	ODP_IPSEC_PIPELINE_CLS
+
+} odp_ipsec_pipeline_t;
+
+/**
  * IPSEC Security Association (SA) parameters
  */
 typedef struct odp_ipsec_sa_param_t {
@@ -439,6 +623,21 @@  typedef struct odp_ipsec_sa_param_t {
 	/** SPI value */
 	uint32_t spi;
 
+	/** Additional inbound SA lookup parameters. Values are considered
+	 *  only in ODP_IPSEC_LOOKUP_DSTADDR_SPI lookup mode. */
+	struct {
+		/** Select IP version
+		 *
+		 *  4:   IPv4
+		 *  6:   IPv6
+		 */
+		uint8_t ip_version;
+
+		/** IP destination address (NETWORK ENDIAN) */
+		void    *dst_addr;
+
+	} lookup_param;
+
 	/** MTU for outbound IP fragmentation offload
 	 *
 	 *  This is the maximum length of IP packets that outbound IPSEC
@@ -447,13 +646,31 @@  typedef struct odp_ipsec_sa_param_t {
 	 */
 	uint32_t mtu;
 
+	/** Select pipelined destination for IPSEC result events
+	 *
+	 *  Asynchronous and inline modes generate result events. Select where
+	 *  those events are sent. Inbound SAs may choose to use pipelined
+	 *  classification. The default value is ODP_IPSEC_PIPELINE_NONE.
+	 */
+	odp_ipsec_pipeline_t pipeline;
+
 	/** Destination queue for IPSEC events
 	 *
-	 *  Operations in asynchronous mode enqueue resulting events into
-	 *  this queue.
+	 *  Operations in asynchronous or inline mode enqueue resulting events
+	 *  into this queue.
 	 */
 	odp_queue_t dest_queue;
 
+	/** Classifier destination CoS for IPSEC result events
+	 *
+	 *  Result events for successfully decapsulated packets are sent to
+	 *  classification through this CoS. Other result events are sent to
+	 *  'dest_queue'. This field is considered only when 'pipeline' is
+	 *  ODP_IPSEC_PIPELINE_CLS. The CoS must not be shared between any pktio
+	 *  interface default CoS.
+	 */
+	odp_cos_t dest_cos;
+
 	/** User defined SA context pointer
 	 *
 	 *  User defined context pointer associated with the SA.
@@ -686,6 +903,18 @@  typedef struct odp_ipsec_op_status_t {
 		uint32_t all_error;
 	};
 
+	union {
+		/** Status flags */
+		struct {
+			/** Packet was processed in inline mode */
+			uint32_t inline_mode      : 1;
+
+		} flag;
+
+		/** All flag bits */
+		uint32_t all_flag;
+	};
+
 } odp_ipsec_op_status_t;
 
 /**
@@ -715,7 +944,7 @@  typedef struct odp_ipsec_op_param_t {
 
 	/** Pointer to an array of packets
 	 *
-	 *  Each packet must have a valid value for these meta-data:
+	 *  Each packet must have a valid value for these metadata:
 	 *  * L3 offset: Offset to the first byte of the (outmost) IP header
 	 *  * L4 offset: For inbound direction, when udp_encap is enabled -
 	 *               offset to the first byte of the encapsulating UDP
@@ -740,6 +969,35 @@  typedef struct odp_ipsec_op_param_t {
 } odp_ipsec_op_param_t;
 
 /**
+ * Outbound inline IPSEC operation parameters
+ */
+typedef struct odp_ipsec_inline_op_param_t {
+	/** Packet output interface for inline output operation
+	 *
+	 *  Outbound inline IPSEC operation uses this packet IO interface to
+	 *  output the packet after a successful IPSEC transformation. The pktio
+	 *  must have been configured to operate in inline IPSEC mode.
+	 */
+	odp_pktio_t pktio;
+
+	/** Outer headers for inline output operation
+	 *
+	 *  Outbound inline IPSEC operation uses this information to prepend
+	 *  outer headers to the IPSEC packet before sending it out.
+	 */
+	struct {
+		/** Points to first byte of outer headers to be copied in
+		 *  front of the outgoing IPSEC packet. Implementation copies
+		 *  the headers during odp_ipsec_out_inline() call. */
+		uint8_t *ptr;
+
+		/** Outer header length in bytes */
+		uint32_t len;
+	} outer_hdr;
+
+} odp_ipsec_inline_op_param_t;
+
+/**
  * IPSEC operation result for a packet
  */
 typedef struct odp_ipsec_packet_result_t {
@@ -765,6 +1023,23 @@  typedef struct odp_ipsec_packet_result_t {
 	 */
 	odp_ipsec_sa_t sa;
 
+	/** Packet outer header status before inbound inline processing.
+	 *  This is valid only when status.flag.inline_mode is set.
+	 */
+	struct {
+		/** Points to the first byte of retained outer headers. These
+		 *  headers are stored in a contiquous, per packet,
+		 *  implementation specific memory space. Since the memory space
+		 *  may overlap with e.g. packet head/tailroom, the content
+		 *  becomes invalid if packet data storage is modified in
+		 *  anyway. The memory space may not be sharable to other
+		 *  threads. */
+		uint8_t *ptr;
+
+		/** Outer header length in bytes */
+		uint32_t len;
+	} outer_hdr;
+
 } odp_ipsec_packet_result_t;
 
 /**
@@ -786,18 +1061,14 @@  typedef struct odp_ipsec_op_result_t {
 	 *  at least 'num_pkt' elements.
 	 *
 	 *  Each successfully transformed packet has a valid value for these
-	 *  meta-data:
+	 *  metadata regardless of the inner packet parse configuration.
+	 *  (odp_ipsec_inbound_config_t):
 	 *  * L3 offset: Offset to the first byte of the (outmost) IP header
-	 *  * L4 offset: Offset to the first byte of the valid and known L4
-	 *               header (immediately following the IP header).
-	 *  * Various flags about L3 and L4 layers:
-	 *               has_l3, has_l4, has_ipv4, has_ipv6, has_ipfrag,
-	 *               has_ipsec, has_udp, has_tcp, etc depending on
-	 *               the resulted packet format
+	 *  * pktio:     For inbound inline IPSEC processed packets, original
+	 *               packet input interface
 	 *
-	 * @see odp_packet_l3_offset(), odp_packet_l4_offset(),
-	 *      odp_packet_has_ipv4(), odp_packet_has_ipv6(),
-	 *      odp_packet_has_ipfrag(), odp_packet_has_ipsec()
+	 *  Other metadata for parse results and error checks depend on
+	 *  configuration (selected parse and error check levels).
 	 */
 	odp_packet_t *pkt;
 
@@ -928,10 +1199,10 @@  int odp_ipsec_out(const odp_ipsec_op_param_t *input,
 /**
  * Inbound asynchronous IPSEC operation
  *
- * This operation does inbound IPSEC processing in asynchronous mode
- * (ODP_IPSEC_OP_MODE_ASYNC). It processes packets otherwise identically to
- * odp_ipsec_in(), but outputs all results through one or more
- * ODP_EVENT_IPSEC_RESULT events with the following ordering considerations.
+ * This operation does inbound IPSEC processing in asynchronous mode. It
+ * processes packets otherwise identically to odp_ipsec_in(), but outputs all
+ * results through one or more ODP_EVENT_IPSEC_RESULT events with the following
+ * ordering considerations.
  *
  * Asynchronous mode maintains (operation input) packet order per SA when
  * application calls the operation within an ordered or atomic scheduler context
@@ -941,6 +1212,11 @@  int odp_ipsec_out(const odp_ipsec_op_param_t *input,
  * events for the same SA are enqueued in order, and packet handles (for the
  * same SA) are stored in order within an event.
  *
+ * The function may be used also in inline processing mode, e.g. for IPSEC
+ * packets for which inline processing is not possible. Packets for the same SA
+ * may be processed simultaneously in both modes (initiated by this function
+ * and inline operation).
+ *
  * @param         input   Operation input parameters
  *
  * @return Number of input packets consumed (0 ... input.num_pkt)
@@ -953,10 +1229,10 @@  int odp_ipsec_in_enq(const odp_ipsec_op_param_t *input);
 /**
  * Outbound asynchronous IPSEC operation
  *
- * This operation does outbound IPSEC processing in asynchronous mode
- * (ODP_IPSEC_OP_MODE_ASYNC). It processes packets otherwise identically to
- * odp_ipsec_out(), but outputs all results through one or more
- * ODP_EVENT_IPSEC_RESULT events with the following ordering considerations.
+ * This operation does outbound IPSEC processing in asynchronous mode. It
+ * processes packets otherwise identically to odp_ipsec_out(), but outputs all
+ * results through one or more ODP_EVENT_IPSEC_RESULT events with the following
+ * ordering considerations.
  *
  * Asynchronous mode maintains (operation input) packet order per SA when
  * application calls the operation within an ordered or atomic scheduler context
@@ -966,6 +1242,9 @@  int odp_ipsec_in_enq(const odp_ipsec_op_param_t *input);
  * events for the same SA are enqueued in order, and packet handles (for the
  * same SA) are stored in order within an event.
  *
+ * The function may be used also in inline processing mode, e.g. for IPSEC
+ * packets for which inline processing is not possible.
+ *
  * @param         input   Operation input parameters
  *
  * @return Number of input packets consumed (0 ... input.num_pkt)
@@ -976,6 +1255,28 @@  int odp_ipsec_in_enq(const odp_ipsec_op_param_t *input);
 int odp_ipsec_out_enq(const odp_ipsec_op_param_t *input);
 
 /**
+ * Outbound inline IPSEC operation
+ *
+ * This operation does outbound inline IPSEC processing for the packets. It's
+ * otherwise identical to odp_ipsec_out_enq(), but outputs all successfully
+ * transformed packets to the specified output interface, instead of generating
+ * result events for those.
+ *
+ * Inline operation parameters are defined per packet. The array of parameters
+ * must have 'op_param.num_pkt' elements and is pointed to by 'inline_param'.
+ *
+ * @param         op_param      Operation parameters
+ * @param         inline_param  Outbound inline operation specific parameters
+ *
+ * @return Number of packets consumed (0 ... op_param.num_pkt)
+ * @retval <0     On failure
+ *
+ * @see odp_ipsec_out_enq()
+ */
+int odp_ipsec_out_inline(const odp_ipsec_op_param_t *op_param,
+			 const odp_ipsec_inline_op_param_t *inline_param);
+
+/**
  * Get IPSEC results from an ODP_EVENT_IPSEC_RESULT event
  *
  * Copies IPSEC operation results from an event. The event must be of
diff --git a/include/odp/api/spec/packet_io.h b/include/odp/api/spec/packet_io.h
index cec1f22..8802089 100644
--- a/include/odp/api/spec/packet_io.h
+++ b/include/odp/api/spec/packet_io.h
@@ -407,6 +407,38 @@  typedef struct odp_pktio_config_t {
 	 * interface capability before enabling the same. */
 	odp_bool_t enable_loop;
 
+	/** Inbound IPSEC inlined with packet input
+	 *
+	 *  Enable/disable inline inbound IPSEC operation. When enabled packet
+	 *  input directs all IPSEC packets automatically to IPSEC inbound
+	 *  processing. IPSEC configuration is done through the IPSEC API.
+	 *  Packets that are not (recognized as) IPSEC are processed
+	 *  according to the packet input configuration.
+	 *
+	 *  0: Disable inbound IPSEC inline operation (default)
+	 *  1: Enable inbound IPSEC inline operation
+	 *
+	 *  @see odp_ipsec_config(), odp_ipsec_sa_create()
+	 */
+	odp_bool_t inbound_ipsec;
+
+	/** Outbound IPSEC inlined with packet output
+	 *
+	 *  Enable/disable inline outbound IPSEC operation. When enabled IPSEC
+	 *  outbound processing can send outgoing IPSEC packets directly
+	 *  to the pktio interface for output. IPSEC configuration is done
+	 *  through the IPSEC API.
+	 *
+	 *  Outbound IPSEC inline operation cannot be combined with traffic
+	 *  manager (ODP_PKTOUT_MODE_TM).
+	 *
+	 *  0: Disable outbound IPSEC inline operation (default)
+	 *  1: Enable outbound IPSEC inline operation
+	 *
+	 *  @see odp_ipsec_config(), odp_ipsec_sa_create()
+	 */
+	odp_bool_t outbound_ipsec;
+
 } odp_pktio_config_t;
 
 /**