[2/5] crypto/cnxk: add ESN and antireplay support

Message ID 20220131123029.4024-3-ktejasree@marvell.com (mailing list archive)
State Accepted, archived
Delegated to: akhil goyal
Headers
Series Adding new features and improvements in cnxk crypto PMD |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Tejasree Kondoj Jan. 31, 2022, 12:30 p.m. UTC
  Adding lookaside IPsec ESN and anti-replay support
through security session update.

Signed-off-by: Tejasree Kondoj <ktejasree@marvell.com>
---
 doc/guides/cryptodevs/cnxk.rst                |  2 +
 doc/guides/rel_notes/release_22_03.rst        |  1 +
 drivers/common/cnxk/cnxk_security.c           |  3 ++
 drivers/common/cnxk/cnxk_security_ar.h        |  2 +-
 drivers/common/cnxk/roc_ie_on.h               |  2 +
 drivers/crypto/cnxk/cn10k_ipsec.c             | 36 +++++++++++++++-
 drivers/crypto/cnxk/cn9k_ipsec.c              | 43 ++++++++++++++++++-
 drivers/crypto/cnxk/cn9k_ipsec_la_ops.h       | 16 ++++++-
 .../crypto/cnxk/cnxk_cryptodev_capabilities.c |  4 ++
 9 files changed, 103 insertions(+), 6 deletions(-)
  

Patch

diff --git a/doc/guides/cryptodevs/cnxk.rst b/doc/guides/cryptodevs/cnxk.rst
index 3c585175e3..46431dd755 100644
--- a/doc/guides/cryptodevs/cnxk.rst
+++ b/doc/guides/cryptodevs/cnxk.rst
@@ -279,6 +279,8 @@  CN10XX Features supported
 
 * IPv4
 * ESP
+* ESN
+* Anti-replay
 * Tunnel mode
 * Transport mode
 * UDP Encapsulation
diff --git a/doc/guides/rel_notes/release_22_03.rst b/doc/guides/rel_notes/release_22_03.rst
index 3bc0630c7c..a992fe85f5 100644
--- a/doc/guides/rel_notes/release_22_03.rst
+++ b/doc/guides/rel_notes/release_22_03.rst
@@ -64,6 +64,7 @@  New Features
   * Added NULL cipher support in lookaside protocol (IPsec) for CN9K & CN10K.
   * Added AES-XCBC support in lookaside protocol (IPsec) for CN9K & CN10K.
   * Added AES-CMAC support in CN9K & CN10K.
+  * Added ESN and anti-replay support in lookaside protocol (IPsec) for CN10K.
 
 * **Added an API to retrieve event port id of ethdev Rx adapter.**
 
diff --git a/drivers/common/cnxk/cnxk_security.c b/drivers/common/cnxk/cnxk_security.c
index 035d61180a..718983d892 100644
--- a/drivers/common/cnxk/cnxk_security.c
+++ b/drivers/common/cnxk/cnxk_security.c
@@ -492,6 +492,9 @@  cnxk_ot_ipsec_outb_sa_fill(struct roc_ot_ipsec_outb_sa *sa,
 	/* ESN */
 	sa->w0.s.esn_en = !!ipsec_xfrm->options.esn;
 
+	if (ipsec_xfrm->esn.value)
+		sa->ctx.esn_val = ipsec_xfrm->esn.value - 1;
+
 	if (ipsec_xfrm->options.udp_encap) {
 		sa->w10.s.udp_src_port = 4500;
 		sa->w10.s.udp_dst_port = 4500;
diff --git a/drivers/common/cnxk/cnxk_security_ar.h b/drivers/common/cnxk/cnxk_security_ar.h
index 3ec4c296c2..deb38db0d0 100644
--- a/drivers/common/cnxk/cnxk_security_ar.h
+++ b/drivers/common/cnxk/cnxk_security_ar.h
@@ -13,7 +13,7 @@ 
 
 /* u64 array size to fit anti replay window bits */
 #define AR_WIN_ARR_SZ                                                          \
-	(PLT_ALIGN_CEIL(CNXK_ON_AR_WIN_SIZE_MAX, BITS_PER_LONG_LONG) /        \
+	(PLT_ALIGN_CEIL(CNXK_ON_AR_WIN_SIZE_MAX + 1, BITS_PER_LONG_LONG) /     \
 	 BITS_PER_LONG_LONG)
 
 #define WORD_SHIFT 6
diff --git a/drivers/common/cnxk/roc_ie_on.h b/drivers/common/cnxk/roc_ie_on.h
index aaad87243f..638b02062d 100644
--- a/drivers/common/cnxk/roc_ie_on.h
+++ b/drivers/common/cnxk/roc_ie_on.h
@@ -18,6 +18,8 @@  enum roc_ie_on_ucc_ipsec {
 	ROC_IE_ON_UCC_SUCCESS = 0,
 	ROC_IE_ON_AUTH_UNSUPPORTED = 0xB0,
 	ROC_IE_ON_ENCRYPT_UNSUPPORTED = 0xB1,
+	/* Software defined completion code for anti-replay failed packets */
+	ROC_IE_ON_SWCC_ANTI_REPLAY = 0xE7,
 };
 
 /* Helper macros */
diff --git a/drivers/crypto/cnxk/cn10k_ipsec.c b/drivers/crypto/cnxk/cn10k_ipsec.c
index 7f4ccaff99..c95c57a84d 100644
--- a/drivers/crypto/cnxk/cn10k_ipsec.c
+++ b/drivers/crypto/cnxk/cn10k_ipsec.c
@@ -239,7 +239,7 @@  cn10k_ipsec_inb_sa_create(struct roc_cpt *roc_cpt, struct roc_cpt_lf *lf,
 	}
 
 	/* Trigger CTX flush so that data is written back to DRAM */
-	roc_cpt_lf_ctx_flush(lf, in_sa, false);
+	roc_cpt_lf_ctx_flush(lf, in_sa, true);
 
 	plt_atomic_thread_fence(__ATOMIC_SEQ_CST);
 
@@ -410,6 +410,39 @@  cn10k_sec_session_stats_get(void *device, struct rte_security_session *sess,
 	return 0;
 }
 
+static int
+cn10k_sec_session_update(void *device, struct rte_security_session *sess,
+			 struct rte_security_session_conf *conf)
+{
+	struct rte_cryptodev *crypto_dev = device;
+	struct cn10k_sec_session *priv;
+	struct roc_cpt *roc_cpt;
+	struct cnxk_cpt_qp *qp;
+	struct cnxk_cpt_vf *vf;
+	int ret;
+
+	priv = get_sec_session_private_data(sess);
+	if (priv == NULL)
+		return -EINVAL;
+
+	qp = crypto_dev->data->queue_pairs[0];
+	if (qp == NULL)
+		return -EINVAL;
+
+	if (conf->ipsec.direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS)
+		return -ENOTSUP;
+
+	ret = cnxk_ipsec_xform_verify(&conf->ipsec, conf->crypto_xform);
+	if (ret)
+		return ret;
+
+	vf = crypto_dev->data->dev_private;
+	roc_cpt = &vf->cpt;
+
+	return cn10k_ipsec_outb_sa_create(roc_cpt, &qp->lf, &conf->ipsec,
+					  conf->crypto_xform, sess);
+}
+
 /* Update platform specific security ops */
 void
 cn10k_sec_ops_override(void)
@@ -419,4 +452,5 @@  cn10k_sec_ops_override(void)
 	cnxk_sec_ops.session_destroy = cn10k_sec_session_destroy;
 	cnxk_sec_ops.session_get_size = cn10k_sec_session_get_size;
 	cnxk_sec_ops.session_stats_get = cn10k_sec_session_stats_get;
+	cnxk_sec_ops.session_update = cn10k_sec_session_update;
 }
diff --git a/drivers/crypto/cnxk/cn9k_ipsec.c b/drivers/crypto/cnxk/cn9k_ipsec.c
index 9f876f75f2..f71b5101db 100644
--- a/drivers/crypto/cnxk/cn9k_ipsec.c
+++ b/drivers/crypto/cnxk/cn9k_ipsec.c
@@ -289,6 +289,11 @@  fill_ipsec_common_sa(struct rte_security_ipsec_xform *ipsec,
 	if (cipher_key_len != 0)
 		memcpy(common_sa->cipher_key, cipher_key, cipher_key_len);
 
+	if (ipsec->esn.value) {
+		common_sa->esn_low = ipsec->esn.low;
+		common_sa->esn_hi = ipsec->esn.hi;
+	}
+
 	return 0;
 }
 
@@ -330,6 +335,9 @@  cn9k_ipsec_outb_sa_create(struct cnxk_cpt_qp *qp,
 	sa->seq_lo = 1;
 	sa->seq_hi = 0;
 
+	if (ipsec->esn.value)
+		sa->esn = ipsec->esn.value;
+
 	ret = fill_ipsec_common_sa(ipsec, crypto_xform, &out_sa->common_sa);
 	if (ret)
 		return ret;
@@ -595,8 +603,8 @@  cn9k_ipsec_inb_sa_create(struct cnxk_cpt_qp *qp,
 		sa->ar.wint = sa->replay_win_sz;
 		sa->ar.base = sa->replay_win_sz;
 
-		in_sa->common_sa.esn_low = 0;
-		in_sa->common_sa.esn_hi = 0;
+		in_sa->common_sa.esn_low = sa->seq_lo;
+		in_sa->common_sa.esn_hi = sa->seq_hi;
 	}
 
 	return cn9k_cpt_enq_sa_write(
@@ -772,6 +780,36 @@  cn9k_sec_session_get_size(void *device __rte_unused)
 	return sizeof(struct cn9k_sec_session);
 }
 
+static int
+cn9k_sec_session_update(void *device, struct rte_security_session *sec_sess,
+			struct rte_security_session_conf *conf)
+{
+	struct rte_cryptodev *crypto_dev = device;
+	struct cnxk_cpt_qp *qp;
+	int ret;
+
+	qp = crypto_dev->data->queue_pairs[0];
+	if (qp == NULL) {
+		plt_err("CPT queue pairs need to be setup for updating security"
+			" session");
+		return -EPERM;
+	}
+
+	if (conf->ipsec.direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS)
+		return -ENOTSUP;
+
+	ret = cnxk_ipsec_xform_verify(&conf->ipsec, conf->crypto_xform);
+	if (ret)
+		return ret;
+
+	ret = cn9k_ipsec_xform_verify(&conf->ipsec, conf->crypto_xform);
+	if (ret)
+		return ret;
+
+	return cn9k_ipsec_outb_sa_create(qp, &conf->ipsec, conf->crypto_xform,
+					 sec_sess);
+}
+
 /* Update platform specific security ops */
 void
 cn9k_sec_ops_override(void)
@@ -780,4 +818,5 @@  cn9k_sec_ops_override(void)
 	cnxk_sec_ops.session_create = cn9k_sec_session_create;
 	cnxk_sec_ops.session_destroy = cn9k_sec_session_destroy;
 	cnxk_sec_ops.session_get_size = cn9k_sec_session_get_size;
+	cnxk_sec_ops.session_update = cn9k_sec_session_update;
 }
diff --git a/drivers/crypto/cnxk/cn9k_ipsec_la_ops.h b/drivers/crypto/cnxk/cn9k_ipsec_la_ops.h
index 9a1e217042..df89aaca4e 100644
--- a/drivers/crypto/cnxk/cn9k_ipsec_la_ops.h
+++ b/drivers/crypto/cnxk/cn9k_ipsec_la_ops.h
@@ -140,8 +140,20 @@  process_inb_sa(struct rte_crypto_op *cop, struct cn9k_ipsec_sa *sa,
 	if (sa->replay_win_sz) {
 		ret = ipsec_antireplay_check(sa, sa->replay_win_sz, m_src);
 		if (unlikely(ret)) {
-			plt_dp_err("Anti replay check failed");
-			return ret;
+			/* Use PASSTHROUGH op for failed antireplay packet */
+			inst->w4.u64 = 0;
+			inst->w4.s.opcode_major = ROC_SE_MAJOR_OP_MISC;
+			inst->w4.s.opcode_minor =
+				ROC_SE_MISC_MINOR_OP_PASSTHROUGH;
+			inst->w4.s.param1 = 1;
+			/* Send out completion code only */
+			inst->w4.s.param2 =
+				(ROC_IE_ON_SWCC_ANTI_REPLAY << 8) | 0x1;
+			inst->w4.s.dlen = 1;
+			inst->dptr = rte_pktmbuf_iova(m_src);
+			inst->rptr = inst->dptr;
+			inst->w7.u64 = sa->inst.w7;
+			return 0;
 		}
 	}
 
diff --git a/drivers/crypto/cnxk/cnxk_cryptodev_capabilities.c b/drivers/crypto/cnxk/cnxk_cryptodev_capabilities.c
index f8c007e320..04402a4b46 100644
--- a/drivers/crypto/cnxk/cnxk_cryptodev_capabilities.c
+++ b/drivers/crypto/cnxk/cnxk_cryptodev_capabilities.c
@@ -9,6 +9,7 @@ 
 
 #include "cnxk_cryptodev.h"
 #include "cnxk_cryptodev_capabilities.h"
+#include "cnxk_security_ar.h"
 
 #define CPT_CAPS_ADD(cnxk_caps, cur_pos, hw_caps, name)                        \
 	do {                                                                   \
@@ -1161,6 +1162,8 @@  cn10k_sec_caps_update(struct rte_security_capability *sec_cap)
 	sec_cap->ipsec.options.ip_csum_enable = 1;
 	sec_cap->ipsec.options.l4_csum_enable = 1;
 	sec_cap->ipsec.options.stats = 1;
+	sec_cap->ipsec.options.esn = 1;
+	sec_cap->ipsec.replay_win_sz_max = ROC_AR_WIN_SIZE_MAX;
 }
 
 static void
@@ -1171,6 +1174,7 @@  cn9k_sec_caps_update(struct rte_security_capability *sec_cap)
 		sec_cap->ipsec.options.iv_gen_disable = 1;
 #endif
 	}
+	sec_cap->ipsec.replay_win_sz_max = CNXK_ON_AR_WIN_SIZE_MAX;
 }
 
 void