crypto/ipsec_mb: introduce IPsec_mb framework
[dpdk.git] / drivers / crypto / ipsec_mb / ipsec_mb_private.h
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2021 Intel Corporation
3  */
4
5 #ifndef _IPSEC_MB_PRIVATE_H_
6 #define _IPSEC_MB_PRIVATE_H_
7
8 #include <intel-ipsec-mb.h>
9 #include <cryptodev_pmd.h>
10 #include <rte_bus_vdev.h>
11
12 #if defined(RTE_LIB_SECURITY)
13 #define IPSEC_MB_DOCSIS_SEC_ENABLED 1
14 #include <rte_security.h>
15 #include <rte_security_driver.h>
16 #endif
17
18 /* Maximum length for digest */
19 #define DIGEST_LENGTH_MAX 64
20
21 enum ipsec_mb_vector_mode {
22         IPSEC_MB_NOT_SUPPORTED = 0,
23         IPSEC_MB_SSE,
24         IPSEC_MB_AVX,
25         IPSEC_MB_AVX2,
26         IPSEC_MB_AVX512
27 };
28
29 extern enum ipsec_mb_vector_mode vector_mode;
30
31 /** IMB_MGR instances, one per thread */
32 extern RTE_DEFINE_PER_LCORE(IMB_MGR *, mb_mgr);
33
34 /** PMD LOGTYPE DRIVER, common to all PMDs */
35 extern int ipsec_mb_logtype_driver;
36 #define IPSEC_MB_LOG(level, fmt, ...)                                         \
37         rte_log(RTE_LOG_##level, ipsec_mb_logtype_driver,                     \
38                 "%s() line %u: " fmt "\n", __func__, __LINE__, ##__VA_ARGS__)
39
40 /** All supported device types */
41 enum ipsec_mb_pmd_types {
42         IPSEC_MB_N_PMD_TYPES
43 };
44
45 /** Crypto operations */
46 enum ipsec_mb_operation {
47         IPSEC_MB_OP_ENCRYPT_THEN_HASH_GEN = 0,
48         IPSEC_MB_OP_HASH_VERIFY_THEN_DECRYPT,
49         IPSEC_MB_OP_HASH_GEN_THEN_ENCRYPT,
50         IPSEC_MB_OP_DECRYPT_THEN_HASH_VERIFY,
51         IPSEC_MB_OP_ENCRYPT_ONLY,
52         IPSEC_MB_OP_DECRYPT_ONLY,
53         IPSEC_MB_OP_HASH_GEN_ONLY,
54         IPSEC_MB_OP_HASH_VERIFY_ONLY,
55         IPSEC_MB_OP_AEAD_AUTHENTICATED_DECRYPT,
56         IPSEC_MB_OP_AEAD_AUTHENTICATED_ENCRYPT,
57         IPSEC_MB_OP_NOT_SUPPORTED
58 };
59
60 /** Helper function. Gets driver ID based on PMD type */
61 static __rte_always_inline uint8_t
62 ipsec_mb_get_driver_id(__rte_unused enum ipsec_mb_pmd_types pmd_type)
63 {
64         return UINT8_MAX;
65 }
66
67 /** Common private data structure for each PMD */
68 struct ipsec_mb_dev_private {
69         enum ipsec_mb_pmd_types pmd_type;
70         /**< PMD  type */
71         uint32_t max_nb_queue_pairs;
72         /**< Max number of queue pairs supported by device */
73         __extension__ uint8_t priv[0];
74 };
75
76 /** IPSEC Multi buffer queue pair common queue pair data for all PMDs */
77 struct ipsec_mb_qp {
78         uint16_t id;
79         /**< Queue Pair Identifier */
80         char name[RTE_CRYPTODEV_NAME_MAX_LEN];
81         struct rte_ring *ingress_queue;
82         /**< Ring for placing operations ready for processing */
83         struct rte_mempool *sess_mp;
84         /**< Session Mempool */
85         struct rte_mempool *sess_mp_priv;
86         /**< Session Private Data Mempool */
87         struct rte_cryptodev_stats stats;
88         /**< Queue pair statistics */
89         enum ipsec_mb_pmd_types pmd_type;
90         /**< pmd type */
91         uint8_t digest_idx;
92         /**< Index of the next
93          * slot to be used in temp_digests,
94          * to store the digest for a given operation
95          */
96         IMB_MGR *mb_mgr;
97         /* Multi buffer manager */
98         __extension__ uint8_t additional_data[0];
99         /**< Storing PMD specific additional data */
100 };
101
102 static __rte_always_inline void *
103 ipsec_mb_get_qp_private_data(struct ipsec_mb_qp *qp)
104 {
105         return (void *)qp->additional_data;
106 }
107
108 /** Helper function. Allocates job manager */
109 static __rte_always_inline IMB_MGR *
110 alloc_init_mb_mgr(void)
111 {
112         IMB_MGR *mb_mgr = alloc_mb_mgr(0);
113
114         if (unlikely(mb_mgr == NULL)) {
115                 IPSEC_MB_LOG(ERR, "Failed to allocate IMB_MGR data\n");
116                 return NULL;
117         }
118
119         init_mb_mgr_auto(mb_mgr, NULL);
120
121         return mb_mgr;
122 }
123
124 /** Helper function. Gets per thread job manager */
125 static __rte_always_inline IMB_MGR *
126 get_per_thread_mb_mgr(void)
127 {
128         if (unlikely(RTE_PER_LCORE(mb_mgr) == NULL))
129                 RTE_PER_LCORE(mb_mgr) = alloc_init_mb_mgr();
130
131         return RTE_PER_LCORE(mb_mgr);
132 }
133
134 /** Device creation function */
135 int
136 ipsec_mb_create(struct rte_vdev_device *vdev,
137         enum ipsec_mb_pmd_types pmd_type);
138
139 /** Device remove function */
140 int
141 ipsec_mb_remove(struct rte_vdev_device *vdev);
142
143 /** Configure queue pair PMD type specific data */
144 typedef int (*ipsec_mb_queue_pair_configure_t)(struct ipsec_mb_qp *qp);
145
146 /** Configure session PMD type specific data */
147 typedef int (*ipsec_mb_session_configure_t)(IMB_MGR *mbr_mgr,
148                 void *session_private,
149                 const struct rte_crypto_sym_xform *xform);
150
151 /** Configure internals PMD type specific data */
152 typedef int (*ipsec_mb_dev_configure_t)(struct rte_cryptodev *dev);
153
154 /** Per PMD type operation and data */
155 struct ipsec_mb_internals {
156         uint8_t is_configured;
157         dequeue_pkt_burst_t dequeue_burst;
158         ipsec_mb_dev_configure_t dev_config;
159         ipsec_mb_queue_pair_configure_t queue_pair_configure;
160         ipsec_mb_session_configure_t session_configure;
161         const struct rte_cryptodev_capabilities *caps;
162         struct rte_cryptodev_ops *ops;
163         struct rte_security_ops *security_ops;
164         uint64_t feature_flags;
165         uint32_t session_priv_size;
166         uint32_t qp_priv_size;
167         uint32_t internals_priv_size;
168 };
169
170 /** Global PMD type specific data */
171 extern struct ipsec_mb_internals ipsec_mb_pmds[IPSEC_MB_N_PMD_TYPES];
172
173 int
174 ipsec_mb_config(struct rte_cryptodev *dev,
175         struct rte_cryptodev_config *config);
176
177 int
178 ipsec_mb_start(struct rte_cryptodev *dev);
179
180 void
181 ipsec_mb_stop(struct rte_cryptodev *dev);
182
183 int
184 ipsec_mb_close(struct rte_cryptodev *dev);
185
186 void
187 ipsec_mb_stats_get(struct rte_cryptodev *dev,
188                 struct rte_cryptodev_stats *stats);
189
190 void
191 ipsec_mb_stats_reset(struct rte_cryptodev *dev);
192
193 void
194 ipsec_mb_info_get(struct rte_cryptodev *dev,
195                 struct rte_cryptodev_info *dev_info);
196
197 int
198 ipsec_mb_qp_release(struct rte_cryptodev *dev, uint16_t qp_id);
199
200 int
201 ipsec_mb_qp_set_unique_name(struct rte_cryptodev *dev, struct ipsec_mb_qp *qp);
202
203 int
204 ipsec_mb_qp_setup(struct rte_cryptodev *dev, uint16_t qp_id,
205                                  const struct rte_cryptodev_qp_conf *qp_conf,
206                                  int socket_id);
207
208 /** Returns the size of the aesni multi-buffer session structure */
209 unsigned
210 ipsec_mb_sym_session_get_size(struct rte_cryptodev *dev);
211
212 /** Configure an aesni multi-buffer session from a crypto xform chain */
213 int ipsec_mb_sym_session_configure(
214         struct rte_cryptodev *dev,
215         struct rte_crypto_sym_xform *xform,
216         struct rte_cryptodev_sym_session *sess,
217         struct rte_mempool *mempool);
218
219 /** Clear the memory of session so it does not leave key material behind */
220 void
221 ipsec_mb_sym_session_clear(struct rte_cryptodev *dev,
222                                 struct rte_cryptodev_sym_session *sess);
223
224 /** Get session from op. If sessionless create a session */
225 static __rte_always_inline void *
226 ipsec_mb_get_session_private(struct ipsec_mb_qp *qp, struct rte_crypto_op *op)
227 {
228         void *sess = NULL;
229         uint32_t driver_id = ipsec_mb_get_driver_id(qp->pmd_type);
230         struct rte_crypto_sym_op *sym_op = op->sym;
231         uint8_t sess_type = op->sess_type;
232         void *_sess;
233         void *_sess_private_data = NULL;
234         struct ipsec_mb_internals *pmd_data = &ipsec_mb_pmds[qp->pmd_type];
235
236         switch (sess_type) {
237         case RTE_CRYPTO_OP_WITH_SESSION:
238                 if (likely(sym_op->session != NULL))
239                         sess = get_sym_session_private_data(sym_op->session,
240                                                             driver_id);
241         break;
242         case RTE_CRYPTO_OP_SESSIONLESS:
243                 if (!qp->sess_mp ||
244                     rte_mempool_get(qp->sess_mp, (void **)&_sess))
245                         return NULL;
246
247                 if (!qp->sess_mp_priv ||
248                     rte_mempool_get(qp->sess_mp_priv,
249                                         (void **)&_sess_private_data))
250                         return NULL;
251
252                 sess = _sess_private_data;
253                 if (unlikely(pmd_data->session_configure(qp->mb_mgr,
254                                 sess, sym_op->xform) != 0)) {
255                         rte_mempool_put(qp->sess_mp, _sess);
256                         rte_mempool_put(qp->sess_mp_priv, _sess_private_data);
257                         sess = NULL;
258                 }
259
260                 sym_op->session = (struct rte_cryptodev_sym_session *)_sess;
261                 set_sym_session_private_data(sym_op->session, driver_id,
262                                              _sess_private_data);
263         break;
264         default:
265                 IPSEC_MB_LOG(ERR, "Unrecognized session type %u", sess_type);
266         }
267
268         if (unlikely(sess == NULL))
269                 op->status = RTE_CRYPTO_OP_STATUS_INVALID_SESSION;
270
271         return sess;
272 }
273
274 #endif /* _IPSEC_MB_PRIVATE_H_ */