1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(C) 2021 Marvell.
5 #include <cryptodev_pmd.h>
8 #include <rte_malloc.h>
9 #include <rte_security.h>
10 #include <rte_security_driver.h>
13 #include "cn10k_ipsec.h"
14 #include "cnxk_cryptodev.h"
15 #include "cnxk_cryptodev_ops.h"
16 #include "cnxk_ipsec.h"
17 #include "cnxk_security.h"
22 ipsec_cpt_inst_w7_get(struct roc_cpt *roc_cpt, void *sa)
27 w7.s.egrp = roc_cpt->eng_grp[CPT_ENG_TYPE_IE];
29 w7.s.cptr = (uint64_t)sa;
36 cn10k_ipsec_outb_sa_create(struct roc_cpt *roc_cpt, struct roc_cpt_lf *lf,
37 struct rte_security_ipsec_xform *ipsec_xfrm,
38 struct rte_crypto_sym_xform *crypto_xfrm,
39 struct rte_security_session *sec_sess)
41 union roc_ot_ipsec_outb_param1 param1;
42 struct roc_ot_ipsec_outb_sa *sa_dptr;
43 struct cnxk_ipsec_outb_rlens rlens;
44 struct cn10k_sec_session *sess;
45 struct cn10k_ipsec_sa *sa;
46 union cpt_inst_w4 inst_w4;
50 sess = get_sec_session_private_data(sec_sess);
54 /* Allocate memory to be used as dptr for CPT ucode WRITE_SA op */
55 sa_dptr = plt_zmalloc(sizeof(struct roc_ot_ipsec_outb_sa), 8);
56 if (sa_dptr == NULL) {
57 plt_err("Couldn't allocate memory for SA dptr");
61 /* Translate security parameters to SA */
62 ret = cnxk_ot_ipsec_outb_sa_fill(sa_dptr, ipsec_xfrm, crypto_xfrm);
64 plt_err("Could not fill outbound session parameters");
68 sa->inst.w7 = ipsec_cpt_inst_w7_get(roc_cpt, out_sa);
71 /* Use IV from application in debug mode */
72 if (ipsec_xfrm->options.iv_gen_disable == 1) {
73 sa_dptr->w2.s.iv_src = ROC_IE_OT_SA_IV_SRC_FROM_SA;
74 if (crypto_xfrm->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
75 sa->iv_offset = crypto_xfrm->aead.iv.offset;
76 sa->iv_length = crypto_xfrm->aead.iv.length;
77 } else if (crypto_xfrm->type == RTE_CRYPTO_SYM_XFORM_CIPHER) {
78 sa->iv_offset = crypto_xfrm->cipher.iv.offset;
79 sa->iv_length = crypto_xfrm->cipher.iv.length;
81 sa->iv_offset = crypto_xfrm->auth.iv.offset;
82 sa->iv_length = crypto_xfrm->auth.iv.length;
86 if (ipsec_xfrm->options.iv_gen_disable != 0) {
87 plt_err("Application provided IV not supported");
93 sa->is_outbound = true;
95 /* Get Rlen calculation data */
96 ret = cnxk_ipsec_outb_rlens_get(&rlens, ipsec_xfrm, crypto_xfrm);
100 sa->max_extended_len = rlens.max_extended_len;
102 /* pre-populate CPT INST word 4 */
104 inst_w4.s.opcode_major = ROC_IE_OT_MAJOR_OP_PROCESS_OUTBOUND_IPSEC;
108 param1.s.ttl_or_hop_limit = ipsec_xfrm->options.dec_ttl;
110 /* Disable IP checksum computation by default */
111 param1.s.ip_csum_disable = ROC_IE_OT_SA_INNER_PKT_IP_CSUM_DISABLE;
113 if (ipsec_xfrm->options.ip_csum_enable) {
114 param1.s.ip_csum_disable =
115 ROC_IE_OT_SA_INNER_PKT_IP_CSUM_ENABLE;
118 /* Disable L4 checksum computation by default */
119 param1.s.l4_csum_disable = ROC_IE_OT_SA_INNER_PKT_L4_CSUM_DISABLE;
121 if (ipsec_xfrm->options.l4_csum_enable) {
122 param1.s.l4_csum_disable =
123 ROC_IE_OT_SA_INNER_PKT_L4_CSUM_ENABLE;
126 inst_w4.s.param1 = param1.u16;
128 sa->inst.w4 = inst_w4.u64;
130 if (ipsec_xfrm->options.stats == 1) {
131 /* Enable mib counters */
132 sa_dptr->w0.s.count_mib_bytes = 1;
133 sa_dptr->w0.s.count_mib_pkts = 1;
136 memset(out_sa, 0, sizeof(struct roc_ot_ipsec_outb_sa));
138 /* Copy word0 from sa_dptr to populate ctx_push_sz ctx_size fields */
139 memcpy(out_sa, sa_dptr, 8);
141 plt_atomic_thread_fence(__ATOMIC_SEQ_CST);
143 /* Write session using microcode opcode */
144 ret = roc_cpt_ctx_write(lf, sa_dptr, out_sa,
145 sizeof(struct roc_ot_ipsec_outb_sa));
147 plt_err("Could not write outbound session to hardware");
151 /* Trigger CTX flush so that data is written back to DRAM */
152 roc_cpt_lf_ctx_flush(lf, out_sa, false);
154 plt_atomic_thread_fence(__ATOMIC_SEQ_CST);
163 cn10k_ipsec_inb_sa_create(struct roc_cpt *roc_cpt, struct roc_cpt_lf *lf,
164 struct rte_security_ipsec_xform *ipsec_xfrm,
165 struct rte_crypto_sym_xform *crypto_xfrm,
166 struct rte_security_session *sec_sess)
168 union roc_ot_ipsec_inb_param1 param1;
169 struct roc_ot_ipsec_inb_sa *sa_dptr;
170 struct cn10k_sec_session *sess;
171 struct cn10k_ipsec_sa *sa;
172 union cpt_inst_w4 inst_w4;
176 sess = get_sec_session_private_data(sec_sess);
180 /* Allocate memory to be used as dptr for CPT ucode WRITE_SA op */
181 sa_dptr = plt_zmalloc(sizeof(struct roc_ot_ipsec_inb_sa), 8);
182 if (sa_dptr == NULL) {
183 plt_err("Couldn't allocate memory for SA dptr");
187 /* Translate security parameters to SA */
188 ret = cnxk_ot_ipsec_inb_sa_fill(sa_dptr, ipsec_xfrm, crypto_xfrm,
191 plt_err("Could not fill inbound session parameters");
195 sa->is_outbound = false;
196 sa->inst.w7 = ipsec_cpt_inst_w7_get(roc_cpt, in_sa);
198 /* pre-populate CPT INST word 4 */
200 inst_w4.s.opcode_major = ROC_IE_OT_MAJOR_OP_PROCESS_INBOUND_IPSEC;
204 /* Disable IP checksum verification by default */
205 param1.s.ip_csum_disable = ROC_IE_OT_SA_INNER_PKT_IP_CSUM_DISABLE;
207 if (ipsec_xfrm->options.ip_csum_enable) {
208 param1.s.ip_csum_disable =
209 ROC_IE_OT_SA_INNER_PKT_IP_CSUM_ENABLE;
212 /* Disable L4 checksum verification by default */
213 param1.s.l4_csum_disable = ROC_IE_OT_SA_INNER_PKT_L4_CSUM_DISABLE;
215 if (ipsec_xfrm->options.l4_csum_enable) {
216 param1.s.l4_csum_disable =
217 ROC_IE_OT_SA_INNER_PKT_L4_CSUM_ENABLE;
220 param1.s.esp_trailer_disable = 1;
222 inst_w4.s.param1 = param1.u16;
224 sa->inst.w4 = inst_w4.u64;
226 if (ipsec_xfrm->options.stats == 1) {
227 /* Enable mib counters */
228 sa_dptr->w0.s.count_mib_bytes = 1;
229 sa_dptr->w0.s.count_mib_pkts = 1;
232 memset(in_sa, 0, sizeof(struct roc_ot_ipsec_inb_sa));
234 /* Copy word0 from sa_dptr to populate ctx_push_sz ctx_size fields */
235 memcpy(in_sa, sa_dptr, 8);
237 plt_atomic_thread_fence(__ATOMIC_SEQ_CST);
239 /* Write session using microcode opcode */
240 ret = roc_cpt_ctx_write(lf, sa_dptr, in_sa,
241 sizeof(struct roc_ot_ipsec_inb_sa));
243 plt_err("Could not write inbound session to hardware");
247 /* Trigger CTX flush so that data is written back to DRAM */
248 roc_cpt_lf_ctx_flush(lf, in_sa, true);
250 plt_atomic_thread_fence(__ATOMIC_SEQ_CST);
259 cn10k_ipsec_session_create(void *dev,
260 struct rte_security_ipsec_xform *ipsec_xfrm,
261 struct rte_crypto_sym_xform *crypto_xfrm,
262 struct rte_security_session *sess)
264 struct rte_cryptodev *crypto_dev = dev;
265 struct roc_cpt *roc_cpt;
266 struct cnxk_cpt_vf *vf;
267 struct cnxk_cpt_qp *qp;
270 qp = crypto_dev->data->queue_pairs[0];
272 plt_err("Setup cpt queue pair before creating security session");
276 ret = cnxk_ipsec_xform_verify(ipsec_xfrm, crypto_xfrm);
280 vf = crypto_dev->data->dev_private;
283 if (ipsec_xfrm->direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS)
284 return cn10k_ipsec_inb_sa_create(roc_cpt, &qp->lf, ipsec_xfrm,
287 return cn10k_ipsec_outb_sa_create(roc_cpt, &qp->lf, ipsec_xfrm,
292 cn10k_sec_session_create(void *device, struct rte_security_session_conf *conf,
293 struct rte_security_session *sess,
294 struct rte_mempool *mempool)
296 struct cn10k_sec_session *priv;
299 if (conf->action_type != RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL)
302 if (rte_mempool_get(mempool, (void **)&priv)) {
303 plt_err("Could not allocate security session private data");
307 set_sec_session_private_data(sess, priv);
309 if (conf->protocol != RTE_SECURITY_PROTOCOL_IPSEC) {
313 ret = cn10k_ipsec_session_create(device, &conf->ipsec,
314 conf->crypto_xform, sess);
321 rte_mempool_put(mempool, priv);
322 set_sec_session_private_data(sess, NULL);
327 cn10k_sec_session_destroy(void *dev, struct rte_security_session *sec_sess)
329 struct rte_cryptodev *crypto_dev = dev;
330 union roc_ot_ipsec_sa_word2 *w2;
331 struct cn10k_sec_session *sess;
332 struct rte_mempool *sess_mp;
333 struct cn10k_ipsec_sa *sa;
334 struct cnxk_cpt_qp *qp;
335 struct roc_cpt_lf *lf;
336 void *sa_dptr = NULL;
339 sess = get_sec_session_private_data(sec_sess);
343 qp = crypto_dev->data->queue_pairs[0];
351 /* Trigger CTX flush to write dirty data back to DRAM */
352 roc_cpt_lf_ctx_flush(lf, &sa->in_sa, false);
356 if (sa->is_outbound) {
357 sa_dptr = plt_zmalloc(sizeof(struct roc_ot_ipsec_outb_sa), 8);
358 if (sa_dptr != NULL) {
359 roc_ot_ipsec_outb_sa_init(sa_dptr);
361 ret = roc_cpt_ctx_write(
362 lf, sa_dptr, &sa->out_sa,
363 sizeof(struct roc_ot_ipsec_outb_sa));
366 sa_dptr = plt_zmalloc(sizeof(struct roc_ot_ipsec_inb_sa), 8);
367 if (sa_dptr != NULL) {
368 roc_ot_ipsec_inb_sa_init(sa_dptr, false);
370 ret = roc_cpt_ctx_write(
371 lf, sa_dptr, &sa->in_sa,
372 sizeof(struct roc_ot_ipsec_inb_sa));
379 /* MC write_ctx failed. Attempt reload of CTX */
381 /* Wait for 1 ms so that flush is complete */
384 w2 = (union roc_ot_ipsec_sa_word2 *)&sa->in_sa.w2;
387 plt_atomic_thread_fence(__ATOMIC_SEQ_CST);
389 /* Trigger CTX reload to fetch new data from DRAM */
390 roc_cpt_lf_ctx_reload(lf, &sa->in_sa);
393 sess_mp = rte_mempool_from_obj(sess);
395 set_sec_session_private_data(sec_sess, NULL);
396 rte_mempool_put(sess_mp, sess);
402 cn10k_sec_session_get_size(void *device __rte_unused)
404 return sizeof(struct cn10k_sec_session);
408 cn10k_sec_session_stats_get(void *device, struct rte_security_session *sess,
409 struct rte_security_stats *stats)
411 struct rte_cryptodev *crypto_dev = device;
412 struct roc_ot_ipsec_outb_sa *out_sa;
413 struct roc_ot_ipsec_inb_sa *in_sa;
414 union roc_ot_ipsec_sa_word2 *w2;
415 struct cn10k_sec_session *priv;
416 struct cn10k_ipsec_sa *sa;
417 struct cnxk_cpt_qp *qp;
419 priv = get_sec_session_private_data(sess);
423 qp = crypto_dev->data->queue_pairs[0];
428 w2 = (union roc_ot_ipsec_sa_word2 *)&sa->in_sa.w2;
430 stats->protocol = RTE_SECURITY_PROTOCOL_IPSEC;
432 if (w2->s.dir == ROC_IE_SA_DIR_OUTBOUND) {
433 out_sa = &sa->out_sa;
434 roc_cpt_lf_ctx_flush(&qp->lf, out_sa, false);
436 stats->ipsec.opackets = out_sa->ctx.mib_pkts;
437 stats->ipsec.obytes = out_sa->ctx.mib_octs;
440 roc_cpt_lf_ctx_flush(&qp->lf, in_sa, false);
442 stats->ipsec.ipackets = in_sa->ctx.mib_pkts;
443 stats->ipsec.ibytes = in_sa->ctx.mib_octs;
450 cn10k_sec_session_update(void *device, struct rte_security_session *sess,
451 struct rte_security_session_conf *conf)
453 struct rte_cryptodev *crypto_dev = device;
454 struct cn10k_sec_session *priv;
455 struct roc_cpt *roc_cpt;
456 struct cnxk_cpt_qp *qp;
457 struct cnxk_cpt_vf *vf;
460 priv = get_sec_session_private_data(sess);
464 qp = crypto_dev->data->queue_pairs[0];
468 if (conf->ipsec.direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS)
471 ret = cnxk_ipsec_xform_verify(&conf->ipsec, conf->crypto_xform);
475 vf = crypto_dev->data->dev_private;
478 return cn10k_ipsec_outb_sa_create(roc_cpt, &qp->lf, &conf->ipsec,
479 conf->crypto_xform, sess);
482 /* Update platform specific security ops */
484 cn10k_sec_ops_override(void)
486 /* Update platform specific ops */
487 cnxk_sec_ops.session_create = cn10k_sec_session_create;
488 cnxk_sec_ops.session_destroy = cn10k_sec_session_destroy;
489 cnxk_sec_ops.session_get_size = cn10k_sec_session_get_size;
490 cnxk_sec_ops.session_stats_get = cn10k_sec_session_stats_get;
491 cnxk_sec_ops.session_update = cn10k_sec_session_update;