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(ROC_NIX_INL_OT_IPSEC_OUTB_HW_SZ, 0);
56 if (sa_dptr == NULL) {
57 plt_err("Couldn't allocate memory for SA dptr");
61 memset(sa_dptr, 0, sizeof(struct roc_ot_ipsec_outb_sa));
63 /* Translate security parameters to SA */
64 ret = cnxk_ot_ipsec_outb_sa_fill(sa_dptr, ipsec_xfrm, crypto_xfrm);
66 plt_err("Could not fill outbound session parameters");
70 sa->inst.w7 = ipsec_cpt_inst_w7_get(roc_cpt, sa);
73 /* Use IV from application in debug mode */
74 if (ipsec_xfrm->options.iv_gen_disable == 1) {
75 sa_dptr->w2.s.iv_src = ROC_IE_OT_SA_IV_SRC_FROM_SA;
76 if (crypto_xfrm->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
77 sa->iv_offset = crypto_xfrm->aead.iv.offset;
78 sa->iv_length = crypto_xfrm->aead.iv.length;
80 sa->iv_offset = crypto_xfrm->cipher.iv.offset;
81 sa->iv_length = crypto_xfrm->cipher.iv.length;
85 if (ipsec_xfrm->options.iv_gen_disable != 0) {
86 plt_err("Application provided IV not supported");
92 /* Get Rlen calculation data */
93 ret = cnxk_ipsec_outb_rlens_get(&rlens, ipsec_xfrm, crypto_xfrm);
97 sa->max_extended_len = rlens.max_extended_len;
99 /* pre-populate CPT INST word 4 */
101 inst_w4.s.opcode_major = ROC_IE_OT_MAJOR_OP_PROCESS_OUTBOUND_IPSEC;
105 /* Disable IP checksum computation by default */
106 param1.s.ip_csum_disable = ROC_IE_OT_SA_INNER_PKT_IP_CSUM_DISABLE;
108 if (ipsec_xfrm->options.ip_csum_enable) {
109 param1.s.ip_csum_disable =
110 ROC_IE_OT_SA_INNER_PKT_IP_CSUM_ENABLE;
113 /* Disable L4 checksum computation by default */
114 param1.s.l4_csum_disable = ROC_IE_OT_SA_INNER_PKT_L4_CSUM_DISABLE;
116 if (ipsec_xfrm->options.l4_csum_enable) {
117 param1.s.l4_csum_disable =
118 ROC_IE_OT_SA_INNER_PKT_L4_CSUM_ENABLE;
121 inst_w4.s.param1 = param1.u16;
123 sa->inst.w4 = inst_w4.u64;
125 memset(out_sa, 0, sizeof(struct roc_ot_ipsec_outb_sa));
127 /* Copy word0 from sa_dptr to populate ctx_push_sz ctx_size fields */
128 memcpy(out_sa, sa_dptr, 8);
130 /* Write session using microcode opcode */
131 ret = roc_cpt_ctx_write(lf, sa_dptr, out_sa,
132 ROC_NIX_INL_OT_IPSEC_OUTB_HW_SZ);
134 plt_err("Could not write outbound session to hardware");
138 /* Trigger CTX flush to write dirty data back to DRAM */
139 roc_cpt_lf_ctx_flush(lf, out_sa, false);
148 cn10k_ipsec_inb_sa_create(struct roc_cpt *roc_cpt, struct roc_cpt_lf *lf,
149 struct rte_security_ipsec_xform *ipsec_xfrm,
150 struct rte_crypto_sym_xform *crypto_xfrm,
151 struct rte_security_session *sec_sess)
153 union roc_ot_ipsec_inb_param1 param1;
154 struct roc_ot_ipsec_inb_sa *sa_dptr;
155 struct cn10k_sec_session *sess;
156 struct cn10k_ipsec_sa *sa;
157 union cpt_inst_w4 inst_w4;
161 sess = get_sec_session_private_data(sec_sess);
165 /* Allocate memory to be used as dptr for CPT ucode WRITE_SA op */
166 sa_dptr = plt_zmalloc(ROC_NIX_INL_OT_IPSEC_INB_HW_SZ, 0);
167 if (sa_dptr == NULL) {
168 plt_err("Couldn't allocate memory for SA dptr");
172 memset(sa_dptr, 0, sizeof(struct roc_ot_ipsec_inb_sa));
174 /* Translate security parameters to SA */
175 ret = cnxk_ot_ipsec_inb_sa_fill(sa_dptr, ipsec_xfrm, crypto_xfrm);
177 plt_err("Could not fill inbound session parameters");
181 sa->inst.w7 = ipsec_cpt_inst_w7_get(roc_cpt, sa);
183 /* pre-populate CPT INST word 4 */
185 inst_w4.s.opcode_major = ROC_IE_OT_MAJOR_OP_PROCESS_INBOUND_IPSEC;
189 /* Disable IP checksum verification by default */
190 param1.s.ip_csum_disable = ROC_IE_OT_SA_INNER_PKT_IP_CSUM_DISABLE;
192 if (ipsec_xfrm->options.ip_csum_enable) {
193 param1.s.ip_csum_disable =
194 ROC_IE_OT_SA_INNER_PKT_IP_CSUM_ENABLE;
195 sa->ip_csum_enable = true;
198 /* Disable L4 checksum verification by default */
199 param1.s.l4_csum_disable = ROC_IE_OT_SA_INNER_PKT_L4_CSUM_DISABLE;
201 if (ipsec_xfrm->options.l4_csum_enable) {
202 param1.s.l4_csum_disable =
203 ROC_IE_OT_SA_INNER_PKT_L4_CSUM_ENABLE;
206 param1.s.esp_trailer_disable = 1;
208 inst_w4.s.param1 = param1.u16;
210 sa->inst.w4 = inst_w4.u64;
212 memset(in_sa, 0, sizeof(struct roc_ot_ipsec_inb_sa));
214 /* Copy word0 from sa_dptr to populate ctx_push_sz ctx_size fields */
215 memcpy(in_sa, sa_dptr, 8);
217 /* Write session using microcode opcode */
218 ret = roc_cpt_ctx_write(lf, sa_dptr, in_sa,
219 ROC_NIX_INL_OT_IPSEC_INB_HW_SZ);
221 plt_err("Could not write inbound session to hardware");
225 /* Trigger CTX flush to write dirty data back to DRAM */
226 roc_cpt_lf_ctx_flush(lf, in_sa, false);
235 cn10k_ipsec_session_create(void *dev,
236 struct rte_security_ipsec_xform *ipsec_xfrm,
237 struct rte_crypto_sym_xform *crypto_xfrm,
238 struct rte_security_session *sess)
240 struct rte_cryptodev *crypto_dev = dev;
241 struct roc_cpt *roc_cpt;
242 struct cnxk_cpt_vf *vf;
243 struct cnxk_cpt_qp *qp;
246 qp = crypto_dev->data->queue_pairs[0];
248 plt_err("Setup cpt queue pair before creating security session");
252 ret = cnxk_ipsec_xform_verify(ipsec_xfrm, crypto_xfrm);
256 vf = crypto_dev->data->dev_private;
259 if (ipsec_xfrm->direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS)
260 return cn10k_ipsec_inb_sa_create(roc_cpt, &qp->lf, ipsec_xfrm,
263 return cn10k_ipsec_outb_sa_create(roc_cpt, &qp->lf, ipsec_xfrm,
268 cn10k_sec_session_create(void *device, struct rte_security_session_conf *conf,
269 struct rte_security_session *sess,
270 struct rte_mempool *mempool)
272 struct cn10k_sec_session *priv;
275 if (conf->action_type != RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL)
278 if (rte_mempool_get(mempool, (void **)&priv)) {
279 plt_err("Could not allocate security session private data");
283 set_sec_session_private_data(sess, priv);
285 if (conf->protocol != RTE_SECURITY_PROTOCOL_IPSEC) {
289 ret = cn10k_ipsec_session_create(device, &conf->ipsec,
290 conf->crypto_xform, sess);
297 rte_mempool_put(mempool, priv);
298 set_sec_session_private_data(sess, NULL);
303 cn10k_sec_session_destroy(void *device __rte_unused,
304 struct rte_security_session *sess)
306 struct cn10k_sec_session *priv;
307 struct rte_mempool *sess_mp;
309 priv = get_sec_session_private_data(sess);
314 sess_mp = rte_mempool_from_obj(priv);
316 set_sec_session_private_data(sess, NULL);
317 rte_mempool_put(sess_mp, priv);
323 cn10k_sec_session_get_size(void *device __rte_unused)
325 return sizeof(struct cn10k_sec_session);
328 /* Update platform specific security ops */
330 cn10k_sec_ops_override(void)
332 /* Update platform specific ops */
333 cnxk_sec_ops.session_create = cn10k_sec_session_create;
334 cnxk_sec_ops.session_destroy = cn10k_sec_session_destroy;
335 cnxk_sec_ops.session_get_size = cn10k_sec_session_get_size;