examples/vhost: fix use after free on drain
[dpdk.git] / drivers / crypto / octeontx2 / otx2_ipsec_po_ops.h
1
2 /* SPDX-License-Identifier: BSD-3-Clause
3  * Copyright(C) 2019 Marvell International Ltd.
4  */
5
6 #ifndef __OTX2_IPSEC_PO_OPS_H__
7 #define __OTX2_IPSEC_PO_OPS_H__
8
9 #include <rte_crypto_sym.h>
10 #include <rte_security.h>
11
12 #include "otx2_cryptodev.h"
13 #include "otx2_security.h"
14
15 static __rte_always_inline int32_t
16 otx2_ipsec_po_out_rlen_get(struct otx2_sec_session_ipsec_lp *sess,
17                            uint32_t plen)
18 {
19         uint32_t enc_payload_len;
20
21         enc_payload_len = RTE_ALIGN_CEIL(plen + sess->roundup_len,
22                         sess->roundup_byte);
23
24         return sess->partial_len + enc_payload_len;
25 }
26
27 static __rte_always_inline struct cpt_request_info *
28 alloc_request_struct(char *maddr, void *cop, int mdata_len,
29                      enum otx2_ipsec_po_mode_type mode_type)
30 {
31         struct cpt_request_info *req;
32         struct cpt_meta_info *meta;
33         uint8_t *resp_addr;
34         uintptr_t *op;
35
36         meta = (void *)RTE_PTR_ALIGN((uint8_t *)maddr, 16);
37
38         op = (uintptr_t *)meta->deq_op_info;
39         req = &meta->cpt_req;
40         resp_addr = (uint8_t *)&meta->cpt_res;
41
42         req->completion_addr = (uint64_t *)((uint8_t *)resp_addr);
43         *req->completion_addr = COMPLETION_CODE_INIT;
44         req->comp_baddr = rte_mem_virt2iova(resp_addr);
45         req->op = op;
46
47         op[0] = (uintptr_t)((uint64_t)meta | 1ull);
48         op[1] = (uintptr_t)cop;
49         op[2] = (uintptr_t)req;
50         op[3] = mdata_len;
51         op[4] = mode_type;
52
53         return req;
54 }
55
56 static __rte_always_inline int
57 process_outb_sa(struct rte_crypto_op *cop,
58                struct otx2_sec_session_ipsec_lp *sess,
59                struct cpt_qp_meta_info *m_info, void **prep_req)
60 {
61         uint32_t dlen, rlen, extend_head, extend_tail;
62         struct rte_crypto_sym_op *sym_op = cop->sym;
63         struct rte_mbuf *m_src = sym_op->m_src;
64         struct cpt_request_info *req = NULL;
65         struct otx2_ipsec_po_out_hdr *hdr;
66         struct otx2_ipsec_po_out_sa *sa;
67         int hdr_len, mdata_len, ret = 0;
68         vq_cmd_word0_t word0;
69         char *mdata, *data;
70
71         sa = &sess->out_sa;
72         hdr_len = sizeof(*hdr);
73
74         dlen = rte_pktmbuf_pkt_len(m_src) + hdr_len;
75         rlen = otx2_ipsec_po_out_rlen_get(sess, dlen - hdr_len);
76
77         extend_head = hdr_len + RTE_ETHER_HDR_LEN;
78         extend_tail = rlen - dlen;
79         mdata_len = m_info->lb_mlen + 8;
80
81         mdata = rte_pktmbuf_append(m_src, extend_tail + mdata_len);
82         if (unlikely(mdata == NULL)) {
83                 otx2_err("Not enough tail room\n");
84                 ret = -ENOMEM;
85                 goto exit;
86         }
87
88         mdata += extend_tail; /* mdata follows encrypted data */
89         req = alloc_request_struct(mdata, (void *)cop, mdata_len,
90                 sess->mode_type);
91
92         data = rte_pktmbuf_prepend(m_src, extend_head);
93         if (unlikely(data == NULL)) {
94                 otx2_err("Not enough head room\n");
95                 ret = -ENOMEM;
96                 goto exit;
97         }
98
99         /*
100          * Move the Ethernet header, to insert otx2_ipsec_po_out_hdr prior
101          * to the IP header
102          */
103         memcpy(data, data + hdr_len, RTE_ETHER_HDR_LEN);
104
105         hdr = (struct otx2_ipsec_po_out_hdr *)rte_pktmbuf_adj(m_src,
106                                                         RTE_ETHER_HDR_LEN);
107
108         memcpy(&hdr->iv[0], rte_crypto_op_ctod_offset(cop, uint8_t *,
109                 sess->iv_offset), sess->iv_length);
110
111         /* Prepare CPT instruction */
112         word0.u64 = sess->ucmd_w0;
113         word0.s.dlen = dlen;
114
115         req->ist.ei0 = word0.u64;
116         req->ist.ei1 = rte_pktmbuf_iova(m_src);
117         req->ist.ei2 = req->ist.ei1;
118
119         sa->esn_hi = sess->seq_hi;
120
121         hdr->seq = rte_cpu_to_be_32(sess->seq_lo);
122         hdr->ip_id = rte_cpu_to_be_32(sess->ip_id);
123
124         sess->ip_id++;
125         sess->esn++;
126
127 exit:
128         *prep_req = req;
129
130         return ret;
131 }
132
133 static __rte_always_inline int
134 process_inb_sa(struct rte_crypto_op *cop,
135               struct otx2_sec_session_ipsec_lp *sess,
136               struct cpt_qp_meta_info *m_info, void **prep_req)
137 {
138         struct rte_crypto_sym_op *sym_op = cop->sym;
139         struct rte_mbuf *m_src = sym_op->m_src;
140         struct cpt_request_info *req = NULL;
141         int mdata_len, ret = 0;
142         vq_cmd_word0_t word0;
143         uint32_t dlen;
144         char *mdata;
145
146         dlen = rte_pktmbuf_pkt_len(m_src);
147         mdata_len = m_info->lb_mlen + 8;
148
149         mdata = rte_pktmbuf_append(m_src, mdata_len);
150         if (unlikely(mdata == NULL)) {
151                 otx2_err("Not enough tail room\n");
152                 ret = -ENOMEM;
153                 goto exit;
154         }
155
156         req = alloc_request_struct(mdata, (void *)cop, mdata_len,
157                 sess->mode_type);
158
159         /* Prepare CPT instruction */
160         word0.u64 = sess->ucmd_w0;
161         word0.s.dlen   = dlen;
162
163         req->ist.ei0 = word0.u64;
164         req->ist.ei1 = rte_pktmbuf_iova(m_src);
165         req->ist.ei2 = req->ist.ei1;
166
167 exit:
168         *prep_req = req;
169         return ret;
170 }
171 #endif /* __OTX2_IPSEC_PO_OPS_H__ */