Regards,
Bala
On 21 March 2017 at 19:47, Petri Savolainen <[email protected]> wrote:
>
> 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 <[email protected]>
> ---
> include/odp/api/spec/ipsec.h | 348
> ++++++++++++++++++++++++++++++++++++---
> include/odp/api/spec/packet_io.h | 32 ++++
> 2 files changed, 355 insertions(+), 25 deletions(-)
>
> diff --git a/include/odp/api/spec/ipsec.h b/include/odp/api/spec/ipsec.h
> index e951e49..23d02cf 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 {
> @@ -77,9 +111,113 @@ typedef struct odp_ipsec_inbound_config_t {
> uint32_t max;
> } spi;
>
> + /** 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 in IPSEC payload
> + *
> + * Select header parsing level after inbound processing. Packet
> headers
> + * in IPSEC payload must be parsed (at least) up to this level.
> + * Default value is ODP_IPSEC_LAYER_NONE.
> + *
> + * Note that IPSec payload is never a L2 packet (ODP_IPSEC_LAYER_L2
> + * equals ODP_IPSEC_LAYER_NONE). In transport mode, IPSEC payload
> + * starts after IP header (ODP_IPSEC_LAYER_L3 equals
> + * 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 {
> @@ -102,6 +240,24 @@ 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 inline classification (ODP_IPSEC_DEST_CLS) for
> resulting
> + * inbound packets.
> + *
> + * 0: Inline classification of resulting packets is not supported
> + * 1: Inline classification of resulting packets is supported
> + * 2: Inline classification of resulting packets is supported and
> + * preferred
> + */
> + uint8_t cls_inline;
> +
> /** Soft expiry limit in seconds support
> *
> * 0: Limit is not supported
> @@ -128,12 +284,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 */
> @@ -142,6 +305,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;
>
> /**
> @@ -381,11 +547,29 @@ typedef enum odp_ipsec_lookup_mode_t {
> ODP_IPSEC_LOOKUP_DISABLED = 0,
>
> /** Inbound SA lookup is enabled. Used SPI values must be unique. */
> - ODP_IPSEC_LOOKUP_IN_UNIQUE_SA
> + ODP_IPSEC_LOOKUP_IN_UNIQUE_SPI,
> +
> + /** Inbound SA lookup is enabled. Lookup matches both SPI and
> + * destination IP address. Used SPI values must be unique. */
> + ODP_IPSEC_LOOKUP_IN_DSTADDR_UNIQUE_SPI
>
> } odp_ipsec_lookup_mode_t;
odp_ipsec_lookup_mode_t is not added either in odp_ipsec_config() or
in odp_ipsec_capability().
I believe this should be added in both these struct?
>
>
> /**
> + * Result event destination
> + */
> +typedef enum odp_ipsec_dest_mode_t {
> + /** Destination for IPSEC result events is a queue. */
> + ODP_IPSEC_DEST_QUEUE = 0,
> +
> + /** Destination for IPSEC result events is the classifier.
> + * IPSEC capability 'cls_inline' determines if inline classification
> + * is supported. */
> + ODP_IPSEC_DEST_CLS
> +
> +} odp_ipsec_dest_mode_t;
Should'nt we add a dest_mode ODP_IPSEC_DEST_PKTIO for outbound inline
when the packet is sent out through interface directly.
>
> +
> +/**
> * IPSEC Security Association (SA) parameters
> */
> typedef struct odp_ipsec_sa_param_t {
> @@ -426,6 +610,17 @@ 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_IN_DSTADDR_UNIQUE_SPI lookup mode. */
> + struct {
> + /* v4 or v6 */
> + 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
> @@ -434,13 +629,32 @@ typedef struct odp_ipsec_sa_param_t {
> */
> uint32_t mtu;
>
> + /** Select where IPSEC result events are sent
> + *
> + * Asynchronous and inline modes generate result events. Select where
> + * those events are sent. Inbound SAs may choose between a queue or
> + * the classifier. Outbound SAs must define a queue always.
> + * The default value is ODP_IPSEC_DEST_QUEUE.
> + */
> + odp_ipsec_dest_mode_t dest_mode;
> +
> /** Destination queue for IPSEC events
> *
> - * Operations in asynchronous mode enqueue resulting events into
> l- * 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 'dest_mode' is
> + * ODP_IPSEC_DEST_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.
> @@ -673,6 +887,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;
>
> /**
> @@ -727,6 +953,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 {
> @@ -752,6 +1007,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;
>
> /**
> @@ -773,18 +1045,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:
> + * meta-data 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 meta-data for parse results and error checks depend on
> + * configuration (selected parse and error check levels).
> */
> odp_packet_t *pkt;
>
> @@ -915,10 +1183,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
> @@ -928,6 +1196,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)
> @@ -940,10 +1213,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
> @@ -953,6 +1226,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)
> @@ -963,6 +1239,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;
>
> /**
> --
> 2.8.1
>