@@ -328,6 +328,12 @@ statistics. Per SA telemetry statistics can be enabled using
``rte_ipsec_telemetry_sa_add`` and disabled using
``rte_ipsec_telemetry_sa_del``. Note that these calls are not thread safe.
+Stateless IPsec packet processing support
+-----------------------------------------
+Support for stateless IPsec packet processing allowing use of custom
+sequence number to be used for IPsec outbound processing.
+rte_ipsec_pkt_stateless_prepare() takes as input the state parameter
+from the application and prepares the packet for IPsec processing.
Limitations
-----------
@@ -84,6 +84,12 @@ API Changes
Also, make sure to start the actual text at the margin.
=======================================================
+ * ipsec: Add support for stateless IPsec processing.
+
+ Added new API to support stateless IPsec processing.
+ The new API are ``rte_ipsec_pkr_crypto_prepare_stateless`` and
+ ``rte_ipsec_pkt_cpu_prepare_stateless`` .
+
ABI Changes
-----------
@@ -288,28 +288,22 @@ outb_pkt_xprepare(const struct rte_ipsec_sa *sa, rte_be64_t sqc,
/*
* setup/update packets and crypto ops for ESP outbound tunnel case.
*/
-uint16_t
-esp_outb_tun_prepare(const struct rte_ipsec_session *ss, struct rte_mbuf *mb[],
- struct rte_crypto_op *cop[], uint16_t num)
+static inline uint16_t
+esp_outb_tun_prepare_helper(const struct rte_ipsec_session *ss, struct rte_mbuf *mb[],
+ struct rte_crypto_op *cop[], uint16_t n, uint64_t sqn)
{
int32_t rc;
- uint32_t i, k, n;
- uint64_t sqn;
+ uint32_t i, k;
rte_be64_t sqc;
struct rte_ipsec_sa *sa;
struct rte_cryptodev_sym_session *cs;
union sym_op_data icv;
uint64_t iv[IPSEC_MAX_IV_QWORD];
- uint32_t dr[num];
+ uint32_t dr[n];
sa = ss->sa;
cs = ss->crypto.ses;
- n = num;
- sqn = esn_outb_update_sqn(sa, &n);
- if (n != num)
- rte_errno = EOVERFLOW;
-
k = 0;
for (i = 0; i != n; i++) {
@@ -339,6 +333,30 @@ esp_outb_tun_prepare(const struct rte_ipsec_session *ss, struct rte_mbuf *mb[],
return k;
}
+uint16_t
+esp_outb_tun_prepare(const struct rte_ipsec_session *ss, struct rte_mbuf *mb[],
+ struct rte_crypto_op *cop[], uint16_t num)
+{
+ uint64_t sqn;
+ uint32_t n;
+
+ n = num;
+ sqn = esn_outb_update_sqn(ss->sa, &n);
+ if (n != num)
+ rte_errno = EOVERFLOW;
+
+ return esp_outb_tun_prepare_helper(ss, mb, cop, n, sqn);
+}
+
+uint16_t
+esp_outb_tun_prepare_stateless(const struct rte_ipsec_session *ss, struct rte_mbuf *mb[],
+ struct rte_crypto_op *cop[], uint16_t num, struct rte_ipsec_state *state)
+{
+ uint64_t sqn = state->sqn;
+
+ return esp_outb_tun_prepare_helper(ss, mb, cop, num, sqn);
+}
+
/*
* setup/update packet data and metadata for ESP outbound transport case.
*/
@@ -529,33 +547,27 @@ outb_cpu_crypto_prepare(const struct rte_ipsec_sa *sa, uint32_t *pofs,
return clen;
}
-static uint16_t
-cpu_outb_pkt_prepare(const struct rte_ipsec_session *ss,
- struct rte_mbuf *mb[], uint16_t num,
- esp_outb_prepare_t prepare, uint32_t cofs_mask)
+static inline uint16_t
+cpu_outb_pkt_prepare_helper(const struct rte_ipsec_session *ss,
+ struct rte_mbuf *mb[], uint16_t n, esp_outb_prepare_t prepare,
+ uint32_t cofs_mask, uint64_t sqn)
{
int32_t rc;
- uint64_t sqn;
rte_be64_t sqc;
struct rte_ipsec_sa *sa;
- uint32_t i, k, n;
+ uint32_t i, k;
uint32_t l2, l3;
union sym_op_data icv;
- struct rte_crypto_va_iova_ptr iv[num];
- struct rte_crypto_va_iova_ptr aad[num];
- struct rte_crypto_va_iova_ptr dgst[num];
- uint32_t dr[num];
- uint32_t l4ofs[num];
- uint32_t clen[num];
- uint64_t ivbuf[num][IPSEC_MAX_IV_QWORD];
+ struct rte_crypto_va_iova_ptr iv[n];
+ struct rte_crypto_va_iova_ptr aad[n];
+ struct rte_crypto_va_iova_ptr dgst[n];
+ uint32_t dr[n];
+ uint32_t l4ofs[n];
+ uint32_t clen[n];
+ uint64_t ivbuf[n][IPSEC_MAX_IV_QWORD];
sa = ss->sa;
- n = num;
- sqn = esn_outb_update_sqn(sa, &n);
- if (n != num)
- rte_errno = EOVERFLOW;
-
for (i = 0, k = 0; i != n; i++) {
l2 = mb[i]->l2_len;
@@ -604,15 +616,40 @@ uint16_t
cpu_outb_tun_pkt_prepare(const struct rte_ipsec_session *ss,
struct rte_mbuf *mb[], uint16_t num)
{
- return cpu_outb_pkt_prepare(ss, mb, num, outb_tun_pkt_prepare, 0);
+ uint64_t sqn;
+ uint32_t n;
+
+ n = num;
+ sqn = esn_outb_update_sqn(ss->sa, &n);
+ if (n != num)
+ rte_errno = EOVERFLOW;
+
+ return cpu_outb_pkt_prepare_helper(ss, mb, n, outb_tun_pkt_prepare, 0, sqn);
+}
+
+uint16_t
+cpu_outb_tun_pkt_prepare_stateless(const struct rte_ipsec_session *ss,
+ struct rte_mbuf *mb[], uint16_t num, struct rte_ipsec_state *state)
+{
+ uint64_t sqn = state->sqn;
+
+ return cpu_outb_pkt_prepare_helper(ss, mb, num, outb_tun_pkt_prepare, 0, sqn);
}
uint16_t
cpu_outb_trs_pkt_prepare(const struct rte_ipsec_session *ss,
struct rte_mbuf *mb[], uint16_t num)
{
- return cpu_outb_pkt_prepare(ss, mb, num, outb_trs_pkt_prepare,
- UINT32_MAX);
+ uint64_t sqn;
+ uint32_t n;
+
+ n = num;
+ sqn = esn_outb_update_sqn(ss->sa, &n);
+ if (n != num)
+ rte_errno = EOVERFLOW;
+
+ return cpu_outb_pkt_prepare_helper(ss, mb, n, outb_trs_pkt_prepare,
+ UINT32_MAX, sqn);
}
/*
@@ -23,11 +23,24 @@ extern "C" {
struct rte_ipsec_session;
+/**
+ * IPsec state for stateless processing of a batch of IPsec packets.
+ */
+struct rte_ipsec_state {
+ /**
+ * 64 bit sequence number to be used for the first packet of the
+ * batch of packets.
+ */
+ uint64_t sqn;
+};
+
/**
* IPsec session specific functions that will be used to:
* - prepare - for input mbufs and given IPsec session prepare crypto ops
* that can be enqueued into the cryptodev associated with given session
* (see *rte_ipsec_pkt_crypto_prepare* below for more details).
+ * - prepare_stateless - similar to prepare, but further processing is done
+ * based on IPsec state provided by the 'state' parameter.
* - process - finalize processing of packets after crypto-dev finished
* with them or process packets that are subjects to inline IPsec offload
* (see rte_ipsec_pkt_process for more details).
@@ -42,6 +55,17 @@ struct rte_ipsec_sa_pkt_func {
struct rte_mbuf *mb[],
uint16_t num);
} prepare;
+ union {
+ uint16_t (*async)(const struct rte_ipsec_session *ss,
+ struct rte_mbuf *mb[],
+ struct rte_crypto_op *cop[],
+ uint16_t num,
+ struct rte_ipsec_state *state);
+ uint16_t (*sync)(const struct rte_ipsec_session *ss,
+ struct rte_mbuf *mb[],
+ uint16_t num,
+ struct rte_ipsec_state *state);
+ } prepare_stateless;
uint16_t (*process)(const struct rte_ipsec_session *ss,
struct rte_mbuf *mb[],
uint16_t num);
@@ -128,6 +152,66 @@ rte_ipsec_pkt_cpu_prepare(const struct rte_ipsec_session *ss,
return ss->pkt_func.prepare.sync(ss, mb, num);
}
+/**
+ * Same as *rte_ipsec_pkt_crypto_prepare*, but processing is done based on
+ * IPsec state provided by the 'state' parameter. Internal IPsec state won't
+ * be updated when this API is called.
+ *
+ * For input mbufs and given IPsec session prepare crypto ops that can be
+ * enqueued into the cryptodev associated with given session.
+ * expects that for each input packet:
+ * - l2_len, l3_len are setup correctly
+ * Note that erroneous mbufs are not freed by the function,
+ * but are placed beyond last valid mbuf in the *mb* array.
+ * It is a user responsibility to handle them further.
+ * @param ss
+ * Pointer to the *rte_ipsec_session* object the packets belong to.
+ * @param mb
+ * The address of an array of *num* pointers to *rte_mbuf* structures
+ * which contain the input packets.
+ * @param cop
+ * The address of an array of *num* pointers to the output *rte_crypto_op*
+ * structures.
+ * @param num
+ * The maximum number of packets to process.
+ * @param state
+ * The IPsec state to be used for processing current batch of packets.
+ * @return
+ * Number of successfully processed packets, with error code set in rte_errno.
+ */
+__rte_experimental
+static inline uint16_t
+rte_ipsec_pkt_crypto_prepare_stateless(const struct rte_ipsec_session *ss,
+ struct rte_mbuf *mb[], struct rte_crypto_op *cop[], uint16_t num,
+ struct rte_ipsec_state *state)
+{
+ return ss->pkt_func.prepare_stateless.async(ss, mb, cop, num, state);
+}
+
+/**
+ * Same as *rte_ipsec_pkt_crypto_prepare_stateless*, but processing is done
+ * in synchronous mode.
+ *
+ * @param ss
+ * Pointer to the *rte_ipsec_session* object the packets belong to.
+ * @param mb
+ * The address of an array of *num* pointers to *rte_mbuf* structures
+ * which contain the input packets.
+ * @param num
+ * The maximum number of packets to process.
+ * @param state
+ * The IPsec state to be used for processing current batch of packets.
+ * @return
+ * Number of successfully processed packets, with error code set in rte_errno.
+ */
+__rte_experimental
+static inline uint16_t
+rte_ipsec_pkt_cpu_prepare_stateless(const struct rte_ipsec_session *ss,
+ struct rte_mbuf *mb[], uint16_t num, struct rte_ipsec_state *state)
+{
+ return ss->pkt_func.prepare_stateless.sync(ss, mb, num, state);
+}
+
/**
* Finalise processing of packets after crypto-dev finished with them or
* process packets that are subjects to inline IPsec offload.
@@ -710,6 +710,7 @@ lksd_none_pkt_func_select(const struct rte_ipsec_sa *sa,
case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TUNLV4):
case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TUNLV6):
pf->prepare.async = esp_outb_tun_prepare;
+ pf->prepare_stateless.async = esp_outb_tun_prepare_stateless;
pf->process = (sa->sqh_len != 0) ?
esp_outb_sqh_process : pkt_flag_process;
break;
@@ -748,6 +749,7 @@ cpu_crypto_pkt_func_select(const struct rte_ipsec_sa *sa,
case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TUNLV4):
case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TUNLV6):
pf->prepare.sync = cpu_outb_tun_pkt_prepare;
+ pf->prepare_stateless.sync = cpu_outb_tun_pkt_prepare_stateless;
pf->process = (sa->sqh_len != 0) ?
esp_outb_sqh_process : pkt_flag_process;
break;
@@ -810,7 +812,7 @@ ipsec_sa_pkt_func_select(const struct rte_ipsec_session *ss,
int32_t rc;
rc = 0;
- pf[0] = (struct rte_ipsec_sa_pkt_func) { {NULL}, NULL };
+ pf[0] = (struct rte_ipsec_sa_pkt_func) { {NULL}, {NULL}, NULL };
switch (ss->type) {
case RTE_SECURITY_ACTION_TYPE_NONE:
@@ -179,6 +179,10 @@ uint16_t
esp_outb_tun_prepare(const struct rte_ipsec_session *ss, struct rte_mbuf *mb[],
struct rte_crypto_op *cop[], uint16_t num);
+uint16_t
+esp_outb_tun_prepare_stateless(const struct rte_ipsec_session *ss, struct rte_mbuf *mb[],
+ struct rte_crypto_op *cop[], uint16_t num, struct rte_ipsec_state *state);
+
uint16_t
esp_outb_trs_prepare(const struct rte_ipsec_session *ss, struct rte_mbuf *mb[],
struct rte_crypto_op *cop[], uint16_t num);
@@ -207,6 +211,10 @@ uint16_t
cpu_outb_tun_pkt_prepare(const struct rte_ipsec_session *ss,
struct rte_mbuf *mb[], uint16_t num);
uint16_t
+cpu_outb_tun_pkt_prepare_stateless(const struct rte_ipsec_session *ss,
+ struct rte_mbuf *mb[], uint16_t num, struct rte_ipsec_state *state);
+
+uint16_t
cpu_outb_trs_pkt_prepare(const struct rte_ipsec_session *ss,
struct rte_mbuf *mb[], uint16_t num);