[dpdk-dev] [RFC 0/7] ipsec inline

Boris Pismenny borisp at mellanox.com
Wed Jul 12 16:08:06 CEST 2017


Hi Declan,

> Hey Boris, we've been working on v2 of the RFC based on the feedback you
> and others gave on our original , but as what we were going to propose
> is largely inline with your proposal here, with one or 2 exceptions,
> mainly on the IPsec SA management elements, I'll just comment here
> instead of sending another RFC.
> 
> We agree the rte_flow based approach as proposed here is the more
> flexible approach and should work better with futures devices which
> could offer support for other protocols as well as full protocol offload.

That's great.

> 
> The main difference to your proposal below and what we are considering
> is that we would like to introduce the idea of a port based rte_security
> API which would support a generic API for security protocol
> configuration, I can see MACsec, IPsec, DTLS all working easily under
> this approach.
> 
> struct rte_security_session *
> rte_security_session_create(uint8_t port_id,
> 		struct rte_security_sess_conf *sess_conf);
> 
> 
> The session create function will return a opaque security session which
> would be used in the security flow action programming. The session
> configuration will contain the security protocol specific information,
> in IPsec case the SA parameter as well as the crypto xforms.
> 
> /** IPsec Security Session Configuration */
> struct rte_security_conf_ipsec_sa {
> 	unsigned int spi;
> 	/**< SA security parameter index */

When not using full protocol offload. What does this field mean?

> 
> 	enum rte_security_conf_ipsec_sa_dir {
> 		RTE_SECURITY_IPSEC_SA_DIR_INGRESS,
> 		RTE_SECURITY_IPSEC_SA_DIR_EGRESS
> 	} direction;
> 	/**< IPsec SA direction - ingress / egress */
> 
> 	enum rte_security_conf_ipsec_sa_mode {
> 		RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT,
> 		RTE_SECURITY_IPSEC_SA_MODE_TUNNEL
> 	} mode;
> 	/**< IPsec SA Mode - transport/tunnel */
> 
> 	enum rte_security_conf_ipsec_sa_protocol {
> 		RTE_SECURITY_IPSEC_SA_PROTO_AH,
> 		RTE_SECURITY_IPSEC_SA_PROTO_ESP
> 	} proto;
> 	/**< IPsec SA Protocol - AH/ESP */
> 
> 	struct ipaddr src_ip;	/**< Source IP */
> 	struct ipaddr dst_ip;	/**< Destination IP */

When not using full protocol offload, and when not using tunnel mode.
What do these fields mean?

I think we need a separate rte_security_conf_ipsec_sa for full proto offload
and maybe a separate one for tunnel/transport mode as well to avoid redundant
fields.
Moreover, we could split full protocol offload into 2 steps - encap/decap
and crypto. rte_create_flow already supports using multiple actions.

> };
> 
> /**
>   * Security Session Configuration
>   */
> struct rte_security_sess_conf {
> 	enum {
> 		RTE_SECURITY_SESS_INLINE_CRYPTO,
> 		RTE_SECURITY_SESS_FULL_PROTO_OFFLOAD
> 	} action_type;
> 
> 	enum rte_security_sess_conf_type {
> 		SEC_CONF_DTLS,
> 		SEC_CONF_IPSEC,
> 		SEC_CONF_MACSEC
> 
> 	} type;
> 	/**< Type of security session to be configured */
> 
> 	struct {
> 		struct rte_security_conf_dtls dtls;
> 		struct rte_security_conf_ipsec_sa ipsec_sa;
> 		struct rte_security_conf_macsec macsec;
> 	};
> 	/* Configuration parameters for security session */
> 
> 	struct rte_crypto_sym_xform *xform;
> 	/**< Symmetric Crypto Transform Chain */

> };
> 
> The APIs would be introduced in the same manner as the flow and traffic
> management API as a plug-able component into a ethdev, and would provide
> the abstraction to configure security protocols state (IPsec SA, DTLS
> record etc.) and then the flow action would be a security flow action
> instead of the crypto flow action as proposed below.
> 
> This gives a flexible approach to future extension to other protocols
> and modes (crypto vs full offload) and also addresses an issue raised on
> the our previous RFC regarding polluting the crypto namespace with
> security protocol specific information. One other issue with putting the
> protocol information into a crypto transform is that we won't have any
> crypto devices which support them.
> 
> 

We agree that it makes sense to use opaque handles for the crypto session.

The main advantage as you've mentioned below is less overhead during
updates. However, the update problem is relevant for all rte_flow_action
and crypto is not special in that sense. It would be possible to generalize
the rte_security_sess_* api to something like rte_flow_action_sess_*.

Some examples that are not related to crypto where it would be useful:
- encap/decap: add a flow to be encap/decap using specific parameters
or update the tunnel parameters.
- rss: add a flow to go through rss using specific hash or update the hash
key.

> 
> > 1. Inline crypto processing
> > 1.1. Device Capabilities:
> >     o DEV_RX_OFFLOAD_IPSEC_CRYPTO            - device support inline ipsec
> >     decryption offload.
> >     o DEV_TX_OFFLOAD_IPSEC_CRYPTO_HW_TRAILER - device support inline
> ipsec
> >     encrypted offload, ipsec trailer is added by hardware.
> >     o DEV_TX_OFFLOAD_IPSEC_CRYPTO_TSO        - device support inline ipsec
> >     encrypted offload within segment large packets, ipsec trailer is added by
> >     hardware to each segment.
> >
> > 1.2. Configuration API:
> >     We will modify steering API in order to add IPsec transform actions.
> >
> >     o Definition of ESP header:
> >
> >     struct esp_hdr {
> >         int32_t spi;  /**< Security Parameters Index */
> >         uint32_t seq;  /**< packet sequence number */
> >     } __attribute__((__packed__));
> >
> >     o New flow item:
> >
> >     enum rte_flow_item_type {
> >         ...
> >
> >         /**
> >          * Matches a ESP header.
> >          *
> >          * See struct rte_flow_item_esp.
> >          */
> >         RTE_FLOW_ITEM_TYPE_ESP,
> >     };
> >
> >     struct rte_flow_item_esp {
> >         struct esp_hdr hdr; /**< ESP header definition. */
> >     };
> >
> >     struct rte_flow_item_esp {
> >         static const struct rte_flow_item_esp rte_flow_item_esp_mask = {
> >         .hdr = {
> >             .spi = 0xffffffff,
> >         },
> >     };
> >
> >     o New ipsec transform:
> >     struct rte_crypto_ipsec_xform {
> >         enum rte_crypto_cipher_operation op;
> >         enum rte_crypto_cipher_algorithm algo;
> >
> >         struct {
> >             uint8_t *data;    /**< pointer to key data */
> >             size_t length;    /**< key length in bytes */
> >         } key;
> >
> >         uint32_t salt; /* salt for this security association */
> >     };
> >
> >     /** Crypto transformation types */
> >     enum rte_crypto_sym_xform_type {
> >         ...
> >         RTE_CRYPTO_SYM_XFORM_CIPHER,    /**< Cipher xform  */
> >         RTE_CRYPTO_SYM_XFORM_IPSEC,        /**< IPsec xform  */
> >     };
> >
> >     struct rte_crypto_sym_xform {
> >         ...
> >         struct rte_crypto_ipsec_xform ipsec;
> >         /**< IPsec xform */
> >     };
> >
> As mentioned above I think it would be better to keep the security
> protocol specific information separate to the crypto APIs
> 
> >
> >     o New flow action:
> >
> >     enum rte_flow_action_type {
> >         ...
> >
> >         /**
> >          * Encrypts or decrypts packets matching this flow. Must be either egress
> >          * or ingress, but not both.
> >          *
> >          * See struct rte_flow_action_crypto.
> >          */
> >         RTE_FLOW_ACTION_TYPE_CRYPTO,
> >     };
> >
> >     struct rte_flow_action_crypto {
> >         struct rte_crypto_sym_xform xform; /* applied crypto transform */
> >     };
> >
> >
> >  Configuration Path
> >          |
> > +--------|--------+
> > |    Add/Remove   |
> > |     IPsec SA    |   <------ Build crypto flow action of ipsec transform
> > |        |        |
> > |--------|--------|
> >          |
> > +--------V--------+
> > |   Flow API      |
> > +--------|--------+
> >          |
> > +--------V--------+
> > |                 |
> > |     NIC PMD     |   <------ Add/Remove SA to/from hw context
> > |                 |
> > +--------|--------+
> >          |
> > +--------|--------+
> > |  HW ACCELERATED |
> > |        NIC      |
> > |                 |
> > +--------|--------+
> >
> > o Add/Delete SA flow:
> >     To add a new inline SA construct a rte_flow_item for Ethernet + IP + ESP
> >     using the SA selectors and the rte_crypto_ipsec_xform as the
> rte_flow_action.
> >     Note that any rte_flow_items may be empty, which means it is not checked.
> >
> >     In its most basic form, IPsec flow specification is as follows:
> > +-------+     +----------+    +--------+    +-----+
> > |  Eth  | ->  |   IP4/6  | -> |   ESP  | -> | END |
> > +-------+     +----------+    +--------+    +-----+
> >
> >     However, the API can represent, IPsec crypto offload with any
> encapsulation:
> >
> > +-------+            +--------+    +-----+
> > |  Eth  | ->  ... -> |   ESP  | -> | END |
> > +-------+            +--------+    +-----+
> >
> For egress I think we need to support creating multiple flows using the
> same crypto action, i.e. multiple plaintext flows to a single IPsec SA.
> I think having the security_sess action would make this much easier than
> having to match crypto transform chains within the PMD to see if the
> action SA is the same as an existing one.
> 
> Also it will be difficult to update the tunnel state if there isn't as
> separate API for configuration.
> 

I agree. As I've said above, this is true for all rte_flow_action.

> > 1.3. Data Path Processing:
> >
> > 1.3.1. mbuf Changes
> >     o New rx mbuf offload flags to indicate that a packet has gone through
> >     inline crypto processing on to the NIC PMD and the result of this processing.
> >     On failure, packets should be dropped.
> >     /**
> >      * Mask of bits used to determine the status of RX IPsec crypto.
> >      * - PKT_RX_IPSEC_CRYPTO_UNKNOWN     : no information about the RX
> IPsec crypto
> >      * - PKT_RX_IPSEC_CRYPTO �           : decryption and authentication were
> performed
> >      * - PKT_RX_IPSEC_CRYPTO_FAILED      : ipsec processing failed
> >      */
> >     #define PKT_RX_IPSEC_CRYPTO_UNKNOWN         0
> This doesn't make sense to me, it's implicit in the flag below not being
> set?
> 

This is similar to PKT_RX_IP_CKSUM_UNKNOWN and it appears here to
make things more clear to the reader.

> >     #define PKT_RX_IPSEC_CRYPTO                 (1ULL << 18)
> >     #define PKT_RX_IPSEC_CRYPTO_FAILED          (1ULL << 19)
> >
> >     o New tx mbuf offload flags to indicate that a packet requires IPsec inline
> >     crypto processing and trailer construction on the NIC PMD.
> >
> I know Thomas raised a concern of having to add multiple crypto flags
> for different protocol. If we go with the security session model, then
> PKT_RX_SECURITY & PKT_RX_SECURITY_FAILED flag would be sufficient to
> support all security protocols I think, especially if we added a generic
> field for security_session_id in the mbuf which could be populated in
> the rx_burst function.
> 
> >     /**
> >      * Offload the IPsec encryption with software provided trailer.
> >      * This flag must be set by the application to enable this
> >      * offload feature for a packet to be transmitted.
> >      */
> >     #define PKT_TX_IPSEC_CRYPTO        (1ULL << 42)
> >
> >     /**
> >        * Offload the IPsec encryption and trailer construction. This flag must
> >        * be set by the application to enable this offload feature for a packet
> >        * to be transmitted.
> >        */
> >       #define PKT_TX_IPSEC_CRYPTO_HW_TRAILER     (1ULL << 43)
> 
> Would the hw trailer not be implicit by the device you are using, or do
> you think that there may be a case when some flows would have this set
> and some wouldn't?
> 

What do you mean by "implicit by the device"?

The IPsec trailer would be constructed by the device for packets which set this flag.
Some devices might require the user to provide the trailer of the ESP packet.

Doesn't your device require that?

Users of these devices could use the PKT_TX_IPSEC_CRYPTO alone to indicate
that software provides the trailer and expects inline crypto offload.


More information about the dev mailing list