defc792aa8da62c1d8db7febad1a9a1bdaa2c636
[dpdk.git] / drivers / crypto / cnxk / cn10k_ipsec.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2021 Marvell.
3  */
4
5 #include <rte_malloc.h>
6 #include <rte_cryptodev.h>
7 #include <rte_esp.h>
8 #include <rte_ip.h>
9 #include <rte_security.h>
10 #include <rte_security_driver.h>
11 #include <rte_udp.h>
12
13 #include "cnxk_cryptodev.h"
14 #include "cnxk_ipsec.h"
15 #include "cnxk_security.h"
16 #include "cn10k_ipsec.h"
17
18 #include "roc_api.h"
19
20 static uint64_t
21 ipsec_cpt_inst_w7_get(struct roc_cpt *roc_cpt, void *sa)
22 {
23         union cpt_inst_w7 w7;
24
25         w7.u64 = 0;
26         w7.s.egrp = roc_cpt->eng_grp[CPT_ENG_TYPE_IE];
27         w7.s.ctx_val = 1;
28         w7.s.cptr = (uint64_t)sa;
29         rte_mb();
30
31         return w7.u64;
32 }
33
34 static int
35 cn10k_ipsec_outb_sa_create(struct roc_cpt *roc_cpt,
36                            struct rte_security_ipsec_xform *ipsec_xfrm,
37                            struct rte_crypto_sym_xform *crypto_xfrm,
38                            struct rte_security_session *sec_sess)
39 {
40         union roc_ot_ipsec_outb_param1 param1;
41         struct roc_ot_ipsec_outb_sa *out_sa;
42         struct cnxk_ipsec_outb_rlens rlens;
43         struct cn10k_sec_session *sess;
44         struct cn10k_ipsec_sa *sa;
45         union cpt_inst_w4 inst_w4;
46         int ret;
47
48         sess = get_sec_session_private_data(sec_sess);
49         sa = &sess->sa;
50         out_sa = &sa->out_sa;
51
52         memset(out_sa, 0, sizeof(struct roc_ot_ipsec_outb_sa));
53
54         /* Translate security parameters to SA */
55         ret = cnxk_ot_ipsec_outb_sa_fill(out_sa, ipsec_xfrm, crypto_xfrm);
56         if (ret)
57                 return ret;
58
59         sa->inst.w7 = ipsec_cpt_inst_w7_get(roc_cpt, sa);
60
61 #ifdef LA_IPSEC_DEBUG
62         /* Use IV from application in debug mode */
63         if (ipsec_xfrm->options.iv_gen_disable == 1) {
64                 out_sa->w2.s.iv_src = ROC_IE_OT_SA_IV_SRC_FROM_SA;
65                 if (crypto_xfrm->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
66                         sa->iv_offset = crypto_xfrm->aead.iv.offset;
67                         sa->iv_length = crypto_xfrm->aead.iv.length;
68                 }
69         }
70 #else
71         if (ipsec_xfrm->options.iv_gen_disable != 0) {
72                 plt_err("Application provided IV not supported");
73                 return -ENOTSUP;
74         }
75 #endif
76
77         /* Get Rlen calculation data */
78         ret = cnxk_ipsec_outb_rlens_get(&rlens, ipsec_xfrm, crypto_xfrm);
79         if (ret)
80                 return ret;
81
82         sa->max_extended_len = rlens.max_extended_len;
83
84         /* pre-populate CPT INST word 4 */
85         inst_w4.u64 = 0;
86         inst_w4.s.opcode_major = ROC_IE_OT_MAJOR_OP_PROCESS_OUTBOUND_IPSEC;
87
88         param1.u16 = 0;
89
90         /* Disable IP checksum computation by default */
91         param1.s.ip_csum_disable = ROC_IE_OT_SA_INNER_PKT_IP_CSUM_DISABLE;
92
93         if (ipsec_xfrm->options.ip_csum_enable) {
94                 param1.s.ip_csum_disable =
95                         ROC_IE_OT_SA_INNER_PKT_IP_CSUM_ENABLE;
96         }
97
98         /* Disable L4 checksum computation by default */
99         param1.s.l4_csum_disable = ROC_IE_OT_SA_INNER_PKT_L4_CSUM_DISABLE;
100
101         if (ipsec_xfrm->options.l4_csum_enable) {
102                 param1.s.l4_csum_disable =
103                         ROC_IE_OT_SA_INNER_PKT_L4_CSUM_ENABLE;
104         }
105
106         inst_w4.s.param1 = param1.u16;
107
108         sa->inst.w4 = inst_w4.u64;
109
110         return 0;
111 }
112
113 static int
114 cn10k_ipsec_inb_sa_create(struct roc_cpt *roc_cpt,
115                           struct rte_security_ipsec_xform *ipsec_xfrm,
116                           struct rte_crypto_sym_xform *crypto_xfrm,
117                           struct rte_security_session *sec_sess)
118 {
119         union roc_ot_ipsec_inb_param1 param1;
120         struct roc_ot_ipsec_inb_sa *in_sa;
121         struct cn10k_sec_session *sess;
122         struct cn10k_ipsec_sa *sa;
123         union cpt_inst_w4 inst_w4;
124         int ret;
125
126         sess = get_sec_session_private_data(sec_sess);
127         sa = &sess->sa;
128         in_sa = &sa->in_sa;
129
130         /* Translate security parameters to SA */
131         ret = cnxk_ot_ipsec_inb_sa_fill(in_sa, ipsec_xfrm, crypto_xfrm);
132         if (ret)
133                 return ret;
134
135         /* TODO add support for antireplay */
136         sa->in_sa.w0.s.ar_win = 0;
137
138         /* TODO add support for udp encap */
139
140         sa->inst.w7 = ipsec_cpt_inst_w7_get(roc_cpt, sa);
141
142         /* pre-populate CPT INST word 4 */
143         inst_w4.u64 = 0;
144         inst_w4.s.opcode_major = ROC_IE_OT_MAJOR_OP_PROCESS_INBOUND_IPSEC;
145
146         param1.u16 = 0;
147
148         /* Disable IP checksum verification by default */
149         param1.s.ip_csum_disable = ROC_IE_OT_SA_INNER_PKT_IP_CSUM_DISABLE;
150
151         if (ipsec_xfrm->options.ip_csum_enable) {
152                 param1.s.ip_csum_disable =
153                         ROC_IE_OT_SA_INNER_PKT_IP_CSUM_ENABLE;
154                 sa->ip_csum_enable = true;
155         }
156
157         /* Disable L4 checksum verification by default */
158         param1.s.l4_csum_disable = ROC_IE_OT_SA_INNER_PKT_L4_CSUM_DISABLE;
159
160         if (ipsec_xfrm->options.l4_csum_enable) {
161                 param1.s.l4_csum_disable =
162                         ROC_IE_OT_SA_INNER_PKT_L4_CSUM_ENABLE;
163         }
164
165         param1.s.esp_trailer_disable = 1;
166
167         inst_w4.s.param1 = param1.u16;
168
169         sa->inst.w4 = inst_w4.u64;
170
171         return 0;
172 }
173
174 static int
175 cn10k_ipsec_session_create(void *dev,
176                            struct rte_security_ipsec_xform *ipsec_xfrm,
177                            struct rte_crypto_sym_xform *crypto_xfrm,
178                            struct rte_security_session *sess)
179 {
180         struct rte_cryptodev *crypto_dev = dev;
181         struct roc_cpt *roc_cpt;
182         struct cnxk_cpt_vf *vf;
183         int ret;
184
185         vf = crypto_dev->data->dev_private;
186         roc_cpt = &vf->cpt;
187
188         if (crypto_dev->data->queue_pairs[0] == NULL) {
189                 plt_err("Setup cpt queue pair before creating security session");
190                 return -EPERM;
191         }
192
193         ret = cnxk_ipsec_xform_verify(ipsec_xfrm, crypto_xfrm);
194         if (ret)
195                 return ret;
196
197         if (ipsec_xfrm->direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS)
198                 return cn10k_ipsec_inb_sa_create(roc_cpt, ipsec_xfrm,
199                                                  crypto_xfrm, sess);
200         else
201                 return cn10k_ipsec_outb_sa_create(roc_cpt, ipsec_xfrm,
202                                                   crypto_xfrm, sess);
203 }
204
205 static int
206 cn10k_sec_session_create(void *device, struct rte_security_session_conf *conf,
207                          struct rte_security_session *sess,
208                          struct rte_mempool *mempool)
209 {
210         struct cn10k_sec_session *priv;
211         int ret;
212
213         if (conf->action_type != RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL)
214                 return -EINVAL;
215
216         if (rte_mempool_get(mempool, (void **)&priv)) {
217                 plt_err("Could not allocate security session private data");
218                 return -ENOMEM;
219         }
220
221         set_sec_session_private_data(sess, priv);
222
223         if (conf->protocol != RTE_SECURITY_PROTOCOL_IPSEC) {
224                 ret = -ENOTSUP;
225                 goto mempool_put;
226         }
227         ret = cn10k_ipsec_session_create(device, &conf->ipsec,
228                                          conf->crypto_xform, sess);
229         if (ret)
230                 goto mempool_put;
231
232         return 0;
233
234 mempool_put:
235         rte_mempool_put(mempool, priv);
236         set_sec_session_private_data(sess, NULL);
237         return ret;
238 }
239
240 static int
241 cn10k_sec_session_destroy(void *device __rte_unused,
242                           struct rte_security_session *sess)
243 {
244         struct cn10k_sec_session *priv;
245         struct rte_mempool *sess_mp;
246
247         priv = get_sec_session_private_data(sess);
248
249         if (priv == NULL)
250                 return 0;
251
252         sess_mp = rte_mempool_from_obj(priv);
253
254         set_sec_session_private_data(sess, NULL);
255         rte_mempool_put(sess_mp, priv);
256
257         return 0;
258 }
259
260 static unsigned int
261 cn10k_sec_session_get_size(void *device __rte_unused)
262 {
263         return sizeof(struct cn10k_sec_session);
264 }
265
266 /* Update platform specific security ops */
267 void
268 cn10k_sec_ops_override(void)
269 {
270         /* Update platform specific ops */
271         cnxk_sec_ops.session_create = cn10k_sec_session_create;
272         cnxk_sec_ops.session_destroy = cn10k_sec_session_destroy;
273         cnxk_sec_ops.session_get_size = cn10k_sec_session_get_size;
274 }