1d30ea906Sjfb8856606 /* SPDX-License-Identifier: BSD-3-Clause
2d30ea906Sjfb8856606  * Copyright(c) 2016-2017 Intel Corporation
3a9643ea8Slogwang  */
4a9643ea8Slogwang 
5a9643ea8Slogwang #include <string.h>
6a9643ea8Slogwang 
7a9643ea8Slogwang #include <rte_common.h>
8a9643ea8Slogwang #include <rte_malloc.h>
9a9643ea8Slogwang #include <rte_cryptodev_pmd.h>
10a9643ea8Slogwang 
11a9643ea8Slogwang #include "null_crypto_pmd_private.h"
12a9643ea8Slogwang 
13a9643ea8Slogwang static const struct rte_cryptodev_capabilities null_crypto_pmd_capabilities[] = {
14a9643ea8Slogwang 	{	/* NULL (AUTH) */
15a9643ea8Slogwang 		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
16a9643ea8Slogwang 		{.sym = {
17a9643ea8Slogwang 			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
18a9643ea8Slogwang 			{.auth = {
19a9643ea8Slogwang 				.algo = RTE_CRYPTO_AUTH_NULL,
20a9643ea8Slogwang 				.block_size = 1,
21a9643ea8Slogwang 				.key_size = {
22a9643ea8Slogwang 					.min = 0,
23a9643ea8Slogwang 					.max = 0,
24a9643ea8Slogwang 					.increment = 0
25a9643ea8Slogwang 				},
26a9643ea8Slogwang 				.digest_size = {
27a9643ea8Slogwang 					.min = 0,
28a9643ea8Slogwang 					.max = 0,
29a9643ea8Slogwang 					.increment = 0
30a9643ea8Slogwang 				},
312bfe3f2eSlogwang 				.iv_size = { 0 }
32a9643ea8Slogwang 			}, },
33a9643ea8Slogwang 		}, },
34a9643ea8Slogwang 	},
35a9643ea8Slogwang 	{	/* NULL (CIPHER) */
36a9643ea8Slogwang 		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
37a9643ea8Slogwang 		{.sym = {
38a9643ea8Slogwang 			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
39a9643ea8Slogwang 			{.cipher = {
40a9643ea8Slogwang 				.algo = RTE_CRYPTO_CIPHER_NULL,
41a9643ea8Slogwang 				.block_size = 1,
42a9643ea8Slogwang 				.key_size = {
43a9643ea8Slogwang 					.min = 0,
44a9643ea8Slogwang 					.max = 0,
45a9643ea8Slogwang 					.increment = 0
46a9643ea8Slogwang 				},
472bfe3f2eSlogwang 				.iv_size = { 0 }
48a9643ea8Slogwang 			}, },
49a9643ea8Slogwang 		}, }
50a9643ea8Slogwang 	},
51a9643ea8Slogwang 	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
52a9643ea8Slogwang };
53a9643ea8Slogwang 
54a9643ea8Slogwang /** Configure device */
55a9643ea8Slogwang static int
null_crypto_pmd_config(__rte_unused struct rte_cryptodev * dev,__rte_unused struct rte_cryptodev_config * config)562bfe3f2eSlogwang null_crypto_pmd_config(__rte_unused struct rte_cryptodev *dev,
572bfe3f2eSlogwang 		__rte_unused struct rte_cryptodev_config *config)
58a9643ea8Slogwang {
59a9643ea8Slogwang 	return 0;
60a9643ea8Slogwang }
61a9643ea8Slogwang 
62a9643ea8Slogwang /** Start device */
63a9643ea8Slogwang static int
null_crypto_pmd_start(__rte_unused struct rte_cryptodev * dev)64a9643ea8Slogwang null_crypto_pmd_start(__rte_unused struct rte_cryptodev *dev)
65a9643ea8Slogwang {
66a9643ea8Slogwang 	return 0;
67a9643ea8Slogwang }
68a9643ea8Slogwang 
69a9643ea8Slogwang /** Stop device */
70a9643ea8Slogwang static void
null_crypto_pmd_stop(__rte_unused struct rte_cryptodev * dev)71a9643ea8Slogwang null_crypto_pmd_stop(__rte_unused struct rte_cryptodev *dev)
72a9643ea8Slogwang {
73a9643ea8Slogwang }
74a9643ea8Slogwang 
75a9643ea8Slogwang /** Close device */
76a9643ea8Slogwang static int
null_crypto_pmd_close(__rte_unused struct rte_cryptodev * dev)77a9643ea8Slogwang null_crypto_pmd_close(__rte_unused struct rte_cryptodev *dev)
78a9643ea8Slogwang {
79a9643ea8Slogwang 	return 0;
80a9643ea8Slogwang }
81a9643ea8Slogwang 
82a9643ea8Slogwang /** Get device statistics */
83a9643ea8Slogwang static void
null_crypto_pmd_stats_get(struct rte_cryptodev * dev,struct rte_cryptodev_stats * stats)84a9643ea8Slogwang null_crypto_pmd_stats_get(struct rte_cryptodev *dev,
85a9643ea8Slogwang 		struct rte_cryptodev_stats *stats)
86a9643ea8Slogwang {
87a9643ea8Slogwang 	int qp_id;
88a9643ea8Slogwang 
89a9643ea8Slogwang 	for (qp_id = 0; qp_id < dev->data->nb_queue_pairs; qp_id++) {
90a9643ea8Slogwang 		struct null_crypto_qp *qp = dev->data->queue_pairs[qp_id];
91a9643ea8Slogwang 
92a9643ea8Slogwang 		stats->enqueued_count += qp->qp_stats.enqueued_count;
93a9643ea8Slogwang 		stats->dequeued_count += qp->qp_stats.dequeued_count;
94a9643ea8Slogwang 
95a9643ea8Slogwang 		stats->enqueue_err_count += qp->qp_stats.enqueue_err_count;
96a9643ea8Slogwang 		stats->dequeue_err_count += qp->qp_stats.dequeue_err_count;
97a9643ea8Slogwang 	}
98a9643ea8Slogwang }
99a9643ea8Slogwang 
100a9643ea8Slogwang /** Reset device statistics */
101a9643ea8Slogwang static void
null_crypto_pmd_stats_reset(struct rte_cryptodev * dev)102a9643ea8Slogwang null_crypto_pmd_stats_reset(struct rte_cryptodev *dev)
103a9643ea8Slogwang {
104a9643ea8Slogwang 	int qp_id;
105a9643ea8Slogwang 
106a9643ea8Slogwang 	for (qp_id = 0; qp_id < dev->data->nb_queue_pairs; qp_id++) {
107a9643ea8Slogwang 		struct null_crypto_qp *qp = dev->data->queue_pairs[qp_id];
108a9643ea8Slogwang 
109a9643ea8Slogwang 		memset(&qp->qp_stats, 0, sizeof(qp->qp_stats));
110a9643ea8Slogwang 	}
111a9643ea8Slogwang }
112a9643ea8Slogwang 
113a9643ea8Slogwang 
114a9643ea8Slogwang /** Get device info */
115a9643ea8Slogwang static void
null_crypto_pmd_info_get(struct rte_cryptodev * dev,struct rte_cryptodev_info * dev_info)116a9643ea8Slogwang null_crypto_pmd_info_get(struct rte_cryptodev *dev,
117a9643ea8Slogwang 		struct rte_cryptodev_info *dev_info)
118a9643ea8Slogwang {
119a9643ea8Slogwang 	struct null_crypto_private *internals = dev->data->dev_private;
120a9643ea8Slogwang 
121a9643ea8Slogwang 	if (dev_info != NULL) {
1222bfe3f2eSlogwang 		dev_info->driver_id = dev->driver_id;
123a9643ea8Slogwang 		dev_info->max_nb_queue_pairs = internals->max_nb_qpairs;
124d30ea906Sjfb8856606 		/* No limit of number of sessions */
125d30ea906Sjfb8856606 		dev_info->sym.max_nb_sessions = 0;
126a9643ea8Slogwang 		dev_info->feature_flags = dev->feature_flags;
127a9643ea8Slogwang 		dev_info->capabilities = null_crypto_pmd_capabilities;
128a9643ea8Slogwang 	}
129a9643ea8Slogwang }
130a9643ea8Slogwang 
131a9643ea8Slogwang /** Release queue pair */
132a9643ea8Slogwang static int
null_crypto_pmd_qp_release(struct rte_cryptodev * dev,uint16_t qp_id)133a9643ea8Slogwang null_crypto_pmd_qp_release(struct rte_cryptodev *dev, uint16_t qp_id)
134a9643ea8Slogwang {
135a9643ea8Slogwang 	if (dev->data->queue_pairs[qp_id] != NULL) {
1361646932aSjfb8856606 		struct null_crypto_qp *qp = dev->data->queue_pairs[qp_id];
1371646932aSjfb8856606 
1381646932aSjfb8856606 		if (qp->processed_pkts)
1391646932aSjfb8856606 			rte_ring_free(qp->processed_pkts);
1401646932aSjfb8856606 
141a9643ea8Slogwang 		rte_free(dev->data->queue_pairs[qp_id]);
142a9643ea8Slogwang 		dev->data->queue_pairs[qp_id] = NULL;
143a9643ea8Slogwang 	}
144a9643ea8Slogwang 	return 0;
145a9643ea8Slogwang }
146a9643ea8Slogwang 
147a9643ea8Slogwang /** set a unique name for the queue pair based on it's name, dev_id and qp_id */
148a9643ea8Slogwang static int
null_crypto_pmd_qp_set_unique_name(struct rte_cryptodev * dev,struct null_crypto_qp * qp)149a9643ea8Slogwang null_crypto_pmd_qp_set_unique_name(struct rte_cryptodev *dev,
150a9643ea8Slogwang 		struct null_crypto_qp *qp)
151a9643ea8Slogwang {
152a9643ea8Slogwang 	unsigned n = snprintf(qp->name, sizeof(qp->name),
153a9643ea8Slogwang 			"null_crypto_pmd_%u_qp_%u",
154a9643ea8Slogwang 			dev->data->dev_id, qp->id);
155a9643ea8Slogwang 
1562bfe3f2eSlogwang 	if (n >= sizeof(qp->name))
157a9643ea8Slogwang 		return -1;
158a9643ea8Slogwang 
159a9643ea8Slogwang 	return 0;
160a9643ea8Slogwang }
161a9643ea8Slogwang 
162a9643ea8Slogwang /** Create a ring to place process packets on */
163a9643ea8Slogwang static struct rte_ring *
null_crypto_pmd_qp_create_processed_pkts_ring(struct null_crypto_qp * qp,unsigned ring_size,int socket_id)164a9643ea8Slogwang null_crypto_pmd_qp_create_processed_pkts_ring(struct null_crypto_qp *qp,
165a9643ea8Slogwang 		unsigned ring_size, int socket_id)
166a9643ea8Slogwang {
167a9643ea8Slogwang 	struct rte_ring *r;
168a9643ea8Slogwang 
169a9643ea8Slogwang 	r = rte_ring_lookup(qp->name);
170a9643ea8Slogwang 	if (r) {
1712bfe3f2eSlogwang 		if (rte_ring_get_size(r) >= ring_size) {
172d30ea906Sjfb8856606 			NULL_LOG(INFO,
173d30ea906Sjfb8856606 					"Reusing existing ring %s for "
174d30ea906Sjfb8856606 					" processed packets", qp->name);
175a9643ea8Slogwang 			return r;
176a9643ea8Slogwang 		}
177a9643ea8Slogwang 
178d30ea906Sjfb8856606 		NULL_LOG(INFO,
179d30ea906Sjfb8856606 				"Unable to reuse existing ring %s for "
180d30ea906Sjfb8856606 				" processed packets", qp->name);
181a9643ea8Slogwang 		return NULL;
182a9643ea8Slogwang 	}
183a9643ea8Slogwang 
184a9643ea8Slogwang 	return rte_ring_create(qp->name, ring_size, socket_id,
185a9643ea8Slogwang 			RING_F_SP_ENQ | RING_F_SC_DEQ);
186a9643ea8Slogwang }
187a9643ea8Slogwang 
188a9643ea8Slogwang /** Setup a queue pair */
189a9643ea8Slogwang static int
null_crypto_pmd_qp_setup(struct rte_cryptodev * dev,uint16_t qp_id,const struct rte_cryptodev_qp_conf * qp_conf,int socket_id)190a9643ea8Slogwang null_crypto_pmd_qp_setup(struct rte_cryptodev *dev, uint16_t qp_id,
191a9643ea8Slogwang 		const struct rte_cryptodev_qp_conf *qp_conf,
192*4418919fSjohnjiang 		int socket_id)
193a9643ea8Slogwang {
194a9643ea8Slogwang 	struct null_crypto_private *internals = dev->data->dev_private;
195a9643ea8Slogwang 	struct null_crypto_qp *qp;
196a9643ea8Slogwang 	int retval;
197a9643ea8Slogwang 
198a9643ea8Slogwang 	if (qp_id >= internals->max_nb_qpairs) {
199d30ea906Sjfb8856606 		NULL_LOG(ERR, "Invalid qp_id %u, greater than maximum "
200a9643ea8Slogwang 				"number of queue pairs supported (%u).",
201a9643ea8Slogwang 				qp_id, internals->max_nb_qpairs);
202a9643ea8Slogwang 		return (-EINVAL);
203a9643ea8Slogwang 	}
204a9643ea8Slogwang 
205a9643ea8Slogwang 	/* Free memory prior to re-allocation if needed. */
206a9643ea8Slogwang 	if (dev->data->queue_pairs[qp_id] != NULL)
207a9643ea8Slogwang 		null_crypto_pmd_qp_release(dev, qp_id);
208a9643ea8Slogwang 
209a9643ea8Slogwang 	/* Allocate the queue pair data structure. */
210a9643ea8Slogwang 	qp = rte_zmalloc_socket("Null Crypto PMD Queue Pair", sizeof(*qp),
211a9643ea8Slogwang 					RTE_CACHE_LINE_SIZE, socket_id);
212a9643ea8Slogwang 	if (qp == NULL) {
213d30ea906Sjfb8856606 		NULL_LOG(ERR, "Failed to allocate queue pair memory");
214a9643ea8Slogwang 		return (-ENOMEM);
215a9643ea8Slogwang 	}
216a9643ea8Slogwang 
217a9643ea8Slogwang 	qp->id = qp_id;
218a9643ea8Slogwang 	dev->data->queue_pairs[qp_id] = qp;
219a9643ea8Slogwang 
220a9643ea8Slogwang 	retval = null_crypto_pmd_qp_set_unique_name(dev, qp);
221a9643ea8Slogwang 	if (retval) {
222d30ea906Sjfb8856606 		NULL_LOG(ERR, "Failed to create unique name for null "
223a9643ea8Slogwang 				"crypto device");
224d30ea906Sjfb8856606 
225a9643ea8Slogwang 		goto qp_setup_cleanup;
226a9643ea8Slogwang 	}
227a9643ea8Slogwang 
228a9643ea8Slogwang 	qp->processed_pkts = null_crypto_pmd_qp_create_processed_pkts_ring(qp,
229a9643ea8Slogwang 			qp_conf->nb_descriptors, socket_id);
230a9643ea8Slogwang 	if (qp->processed_pkts == NULL) {
231d30ea906Sjfb8856606 		NULL_LOG(ERR, "Failed to create unique name for null "
232a9643ea8Slogwang 				"crypto device");
233a9643ea8Slogwang 		goto qp_setup_cleanup;
234a9643ea8Slogwang 	}
235a9643ea8Slogwang 
236*4418919fSjohnjiang 	qp->sess_mp = qp_conf->mp_session;
237*4418919fSjohnjiang 	qp->sess_mp_priv = qp_conf->mp_session_private;
238a9643ea8Slogwang 
239a9643ea8Slogwang 	memset(&qp->qp_stats, 0, sizeof(qp->qp_stats));
240a9643ea8Slogwang 
241a9643ea8Slogwang 	return 0;
242a9643ea8Slogwang 
243a9643ea8Slogwang qp_setup_cleanup:
244a9643ea8Slogwang 	if (qp)
245a9643ea8Slogwang 		rte_free(qp);
246a9643ea8Slogwang 
247a9643ea8Slogwang 	return -1;
248a9643ea8Slogwang }
249a9643ea8Slogwang 
250a9643ea8Slogwang /** Returns the size of the NULL crypto session structure */
251a9643ea8Slogwang static unsigned
null_crypto_pmd_sym_session_get_size(struct rte_cryptodev * dev __rte_unused)252d30ea906Sjfb8856606 null_crypto_pmd_sym_session_get_size(struct rte_cryptodev *dev __rte_unused)
253a9643ea8Slogwang {
254a9643ea8Slogwang 	return sizeof(struct null_crypto_session);
255a9643ea8Slogwang }
256a9643ea8Slogwang 
257a9643ea8Slogwang /** Configure a null crypto session from a crypto xform chain */
2582bfe3f2eSlogwang static int
null_crypto_pmd_sym_session_configure(struct rte_cryptodev * dev __rte_unused,struct rte_crypto_sym_xform * xform,struct rte_cryptodev_sym_session * sess,struct rte_mempool * mp)259d30ea906Sjfb8856606 null_crypto_pmd_sym_session_configure(struct rte_cryptodev *dev __rte_unused,
2602bfe3f2eSlogwang 		struct rte_crypto_sym_xform *xform,
2612bfe3f2eSlogwang 		struct rte_cryptodev_sym_session *sess,
2622bfe3f2eSlogwang 		struct rte_mempool *mp)
263a9643ea8Slogwang {
2642bfe3f2eSlogwang 	void *sess_private_data;
2652bfe3f2eSlogwang 	int ret;
266a9643ea8Slogwang 
267a9643ea8Slogwang 	if (unlikely(sess == NULL)) {
268d30ea906Sjfb8856606 		NULL_LOG(ERR, "invalid session struct");
2692bfe3f2eSlogwang 		return -EINVAL;
270a9643ea8Slogwang 	}
271a9643ea8Slogwang 
2722bfe3f2eSlogwang 	if (rte_mempool_get(mp, &sess_private_data)) {
273d30ea906Sjfb8856606 		NULL_LOG(ERR,
2742bfe3f2eSlogwang 				"Couldn't get object from session mempool");
2752bfe3f2eSlogwang 		return -ENOMEM;
2762bfe3f2eSlogwang 	}
2772bfe3f2eSlogwang 
2782bfe3f2eSlogwang 	ret = null_crypto_set_session_parameters(sess_private_data, xform);
2792bfe3f2eSlogwang 	if (ret != 0) {
280d30ea906Sjfb8856606 		NULL_LOG(ERR, "failed configure session parameters");
2812bfe3f2eSlogwang 
2822bfe3f2eSlogwang 		/* Return session to mempool */
2832bfe3f2eSlogwang 		rte_mempool_put(mp, sess_private_data);
2842bfe3f2eSlogwang 		return ret;
2852bfe3f2eSlogwang 	}
2862bfe3f2eSlogwang 
287d30ea906Sjfb8856606 	set_sym_session_private_data(sess, dev->driver_id,
2882bfe3f2eSlogwang 		sess_private_data);
2892bfe3f2eSlogwang 
2902bfe3f2eSlogwang 	return 0;
291a9643ea8Slogwang }
292a9643ea8Slogwang 
293a9643ea8Slogwang /** Clear the memory of session so it doesn't leave key material behind */
294a9643ea8Slogwang static void
null_crypto_pmd_sym_session_clear(struct rte_cryptodev * dev,struct rte_cryptodev_sym_session * sess)295d30ea906Sjfb8856606 null_crypto_pmd_sym_session_clear(struct rte_cryptodev *dev,
2962bfe3f2eSlogwang 		struct rte_cryptodev_sym_session *sess)
297a9643ea8Slogwang {
2982bfe3f2eSlogwang 	uint8_t index = dev->driver_id;
299d30ea906Sjfb8856606 	void *sess_priv = get_sym_session_private_data(sess, index);
3002bfe3f2eSlogwang 
3012bfe3f2eSlogwang 	/* Zero out the whole structure */
3022bfe3f2eSlogwang 	if (sess_priv) {
3032bfe3f2eSlogwang 		memset(sess_priv, 0, sizeof(struct null_crypto_session));
3042bfe3f2eSlogwang 		struct rte_mempool *sess_mp = rte_mempool_from_obj(sess_priv);
305d30ea906Sjfb8856606 		set_sym_session_private_data(sess, index, NULL);
3062bfe3f2eSlogwang 		rte_mempool_put(sess_mp, sess_priv);
3072bfe3f2eSlogwang 	}
308a9643ea8Slogwang }
309a9643ea8Slogwang 
310d30ea906Sjfb8856606 static struct rte_cryptodev_ops pmd_ops = {
311a9643ea8Slogwang 		.dev_configure		= null_crypto_pmd_config,
312a9643ea8Slogwang 		.dev_start		= null_crypto_pmd_start,
313a9643ea8Slogwang 		.dev_stop		= null_crypto_pmd_stop,
314a9643ea8Slogwang 		.dev_close		= null_crypto_pmd_close,
315a9643ea8Slogwang 
316a9643ea8Slogwang 		.stats_get		= null_crypto_pmd_stats_get,
317a9643ea8Slogwang 		.stats_reset		= null_crypto_pmd_stats_reset,
318a9643ea8Slogwang 
319a9643ea8Slogwang 		.dev_infos_get		= null_crypto_pmd_info_get,
320a9643ea8Slogwang 
321a9643ea8Slogwang 		.queue_pair_setup	= null_crypto_pmd_qp_setup,
322a9643ea8Slogwang 		.queue_pair_release	= null_crypto_pmd_qp_release,
323a9643ea8Slogwang 
324d30ea906Sjfb8856606 		.sym_session_get_size	= null_crypto_pmd_sym_session_get_size,
325d30ea906Sjfb8856606 		.sym_session_configure	= null_crypto_pmd_sym_session_configure,
326d30ea906Sjfb8856606 		.sym_session_clear	= null_crypto_pmd_sym_session_clear
327a9643ea8Slogwang };
328a9643ea8Slogwang 
329a9643ea8Slogwang struct rte_cryptodev_ops *null_crypto_pmd_ops = &pmd_ops;
330