xref: /dpdk/lib/ipsec/misc.h (revision daa02b5cddbb8e11b31d41e2bf7bb1ae64dcae2f)
199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
299a2dd95SBruce Richardson  * Copyright(c) 2018-2020 Intel Corporation
399a2dd95SBruce Richardson  */
499a2dd95SBruce Richardson 
599a2dd95SBruce Richardson #ifndef _MISC_H_
699a2dd95SBruce Richardson #define _MISC_H_
799a2dd95SBruce Richardson 
899a2dd95SBruce Richardson /**
999a2dd95SBruce Richardson  * @file misc.h
1099a2dd95SBruce Richardson  * Contains miscellaneous functions/structures/macros used internally
1199a2dd95SBruce Richardson  * by ipsec library.
1299a2dd95SBruce Richardson  */
1399a2dd95SBruce Richardson 
1499a2dd95SBruce Richardson /*
1599a2dd95SBruce Richardson  * Move bad (unprocessed) mbufs beyond the good (processed) ones.
1699a2dd95SBruce Richardson  * bad_idx[] contains the indexes of bad mbufs inside the mb[].
1799a2dd95SBruce Richardson  */
1899a2dd95SBruce Richardson static inline void
move_bad_mbufs(struct rte_mbuf * mb[],const uint32_t bad_idx[],uint32_t nb_mb,uint32_t nb_bad)1999a2dd95SBruce Richardson move_bad_mbufs(struct rte_mbuf *mb[], const uint32_t bad_idx[], uint32_t nb_mb,
2099a2dd95SBruce Richardson 	uint32_t nb_bad)
2199a2dd95SBruce Richardson {
2299a2dd95SBruce Richardson 	uint32_t i, j, k;
2399a2dd95SBruce Richardson 	struct rte_mbuf *drb[nb_bad];
2499a2dd95SBruce Richardson 
2599a2dd95SBruce Richardson 	j = 0;
2699a2dd95SBruce Richardson 	k = 0;
2799a2dd95SBruce Richardson 
2899a2dd95SBruce Richardson 	/* copy bad ones into a temp place */
2999a2dd95SBruce Richardson 	for (i = 0; i != nb_mb; i++) {
3099a2dd95SBruce Richardson 		if (j != nb_bad && i == bad_idx[j])
3199a2dd95SBruce Richardson 			drb[j++] = mb[i];
3299a2dd95SBruce Richardson 		else
3399a2dd95SBruce Richardson 			mb[k++] = mb[i];
3499a2dd95SBruce Richardson 	}
3599a2dd95SBruce Richardson 
3699a2dd95SBruce Richardson 	/* copy bad ones after the good ones */
3799a2dd95SBruce Richardson 	for (i = 0; i != nb_bad; i++)
3899a2dd95SBruce Richardson 		mb[k + i] = drb[i];
3999a2dd95SBruce Richardson }
4099a2dd95SBruce Richardson 
4199a2dd95SBruce Richardson /*
4299a2dd95SBruce Richardson  * Find packet's segment for the specified offset.
4399a2dd95SBruce Richardson  * ofs - at input should contain required offset, at output would contain
4499a2dd95SBruce Richardson  * offset value within the segment.
4599a2dd95SBruce Richardson  */
4699a2dd95SBruce Richardson static inline struct rte_mbuf *
mbuf_get_seg_ofs(struct rte_mbuf * mb,uint32_t * ofs)4799a2dd95SBruce Richardson mbuf_get_seg_ofs(struct rte_mbuf *mb, uint32_t *ofs)
4899a2dd95SBruce Richardson {
4999a2dd95SBruce Richardson 	uint32_t k, n, plen;
5099a2dd95SBruce Richardson 	struct rte_mbuf *ms;
5199a2dd95SBruce Richardson 
5299a2dd95SBruce Richardson 	plen = mb->pkt_len;
5399a2dd95SBruce Richardson 	n = *ofs;
5499a2dd95SBruce Richardson 
5599a2dd95SBruce Richardson 	if (n == plen) {
5699a2dd95SBruce Richardson 		ms = rte_pktmbuf_lastseg(mb);
5799a2dd95SBruce Richardson 		n = n + rte_pktmbuf_data_len(ms) - plen;
5899a2dd95SBruce Richardson 	} else {
5999a2dd95SBruce Richardson 		ms = mb;
6099a2dd95SBruce Richardson 		for (k = rte_pktmbuf_data_len(ms); n >= k;
6199a2dd95SBruce Richardson 				k = rte_pktmbuf_data_len(ms)) {
6299a2dd95SBruce Richardson 			ms = ms->next;
6399a2dd95SBruce Richardson 			n -= k;
6499a2dd95SBruce Richardson 		}
6599a2dd95SBruce Richardson 	}
6699a2dd95SBruce Richardson 
6799a2dd95SBruce Richardson 	*ofs = n;
6899a2dd95SBruce Richardson 	return ms;
6999a2dd95SBruce Richardson }
7099a2dd95SBruce Richardson 
7199a2dd95SBruce Richardson /*
7299a2dd95SBruce Richardson  * Trim multi-segment packet at the specified offset, and free
7399a2dd95SBruce Richardson  * all unused segments.
7499a2dd95SBruce Richardson  * mb - input packet
7599a2dd95SBruce Richardson  * ms - segment where to cut
7699a2dd95SBruce Richardson  * ofs - offset within the *ms*
7799a2dd95SBruce Richardson  * len - length to cut (from given offset to the end of the packet)
7899a2dd95SBruce Richardson  * Can be used in conjunction with mbuf_get_seg_ofs():
7999a2dd95SBruce Richardson  * ofs = new_len;
8099a2dd95SBruce Richardson  * ms = mbuf_get_seg_ofs(mb, &ofs);
8199a2dd95SBruce Richardson  * mbuf_cut_seg_ofs(mb, ms, ofs, mb->pkt_len - new_len);
8299a2dd95SBruce Richardson  */
8399a2dd95SBruce Richardson static inline void
mbuf_cut_seg_ofs(struct rte_mbuf * mb,struct rte_mbuf * ms,uint32_t ofs,uint32_t len)8499a2dd95SBruce Richardson mbuf_cut_seg_ofs(struct rte_mbuf *mb, struct rte_mbuf *ms, uint32_t ofs,
8599a2dd95SBruce Richardson 	uint32_t len)
8699a2dd95SBruce Richardson {
8799a2dd95SBruce Richardson 	uint32_t n, slen;
8899a2dd95SBruce Richardson 	struct rte_mbuf *mn;
8999a2dd95SBruce Richardson 
9099a2dd95SBruce Richardson 	slen = ms->data_len;
9199a2dd95SBruce Richardson 	ms->data_len = ofs;
9299a2dd95SBruce Richardson 
9399a2dd95SBruce Richardson 	/* tail spawns through multiple segments */
9499a2dd95SBruce Richardson 	if (slen < ofs + len) {
9599a2dd95SBruce Richardson 		mn = ms->next;
9699a2dd95SBruce Richardson 		ms->next = NULL;
9799a2dd95SBruce Richardson 		for (n = 0; mn != NULL; n++) {
9899a2dd95SBruce Richardson 			ms = mn->next;
9999a2dd95SBruce Richardson 			rte_pktmbuf_free_seg(mn);
10099a2dd95SBruce Richardson 			mn = ms;
10199a2dd95SBruce Richardson 		}
10299a2dd95SBruce Richardson 		mb->nb_segs -= n;
10399a2dd95SBruce Richardson 	}
10499a2dd95SBruce Richardson 
10599a2dd95SBruce Richardson 	mb->pkt_len -= len;
10699a2dd95SBruce Richardson }
10799a2dd95SBruce Richardson 
10899a2dd95SBruce Richardson /*
10999a2dd95SBruce Richardson  * process packets using sync crypto engine.
11099a2dd95SBruce Richardson  * expects *num* to be greater than zero.
11199a2dd95SBruce Richardson  */
11299a2dd95SBruce Richardson static inline void
cpu_crypto_bulk(const struct rte_ipsec_session * ss,union rte_crypto_sym_ofs ofs,struct rte_mbuf * mb[],struct rte_crypto_va_iova_ptr iv[],struct rte_crypto_va_iova_ptr aad[],struct rte_crypto_va_iova_ptr dgst[],uint32_t l4ofs[],uint32_t clen[],uint32_t num)11399a2dd95SBruce Richardson cpu_crypto_bulk(const struct rte_ipsec_session *ss,
11499a2dd95SBruce Richardson 	union rte_crypto_sym_ofs ofs, struct rte_mbuf *mb[],
11599a2dd95SBruce Richardson 	struct rte_crypto_va_iova_ptr iv[],
11699a2dd95SBruce Richardson 	struct rte_crypto_va_iova_ptr aad[],
11799a2dd95SBruce Richardson 	struct rte_crypto_va_iova_ptr dgst[], uint32_t l4ofs[],
11899a2dd95SBruce Richardson 	uint32_t clen[], uint32_t num)
11999a2dd95SBruce Richardson {
12099a2dd95SBruce Richardson 	uint32_t i, j, n;
12199a2dd95SBruce Richardson 	int32_t vcnt, vofs;
12299a2dd95SBruce Richardson 	int32_t st[num];
12399a2dd95SBruce Richardson 	struct rte_crypto_sgl vecpkt[num];
12499a2dd95SBruce Richardson 	struct rte_crypto_vec vec[UINT8_MAX];
12599a2dd95SBruce Richardson 	struct rte_crypto_sym_vec symvec;
12699a2dd95SBruce Richardson 
12799a2dd95SBruce Richardson 	const uint32_t vnum = RTE_DIM(vec);
12899a2dd95SBruce Richardson 
12999a2dd95SBruce Richardson 	j = 0, n = 0;
13099a2dd95SBruce Richardson 	vofs = 0;
13199a2dd95SBruce Richardson 	for (i = 0; i != num; i++) {
13299a2dd95SBruce Richardson 
13399a2dd95SBruce Richardson 		vcnt = rte_crypto_mbuf_to_vec(mb[i], l4ofs[i], clen[i],
13499a2dd95SBruce Richardson 			&vec[vofs], vnum - vofs);
13599a2dd95SBruce Richardson 
13699a2dd95SBruce Richardson 		/* not enough space in vec[] to hold all segments */
13799a2dd95SBruce Richardson 		if (vcnt < 0) {
13899a2dd95SBruce Richardson 			/* fill the request structure */
13910488d59SHemant Agrawal 			symvec.src_sgl = &vecpkt[j];
14099a2dd95SBruce Richardson 			symvec.iv = &iv[j];
14199a2dd95SBruce Richardson 			symvec.digest = &dgst[j];
14299a2dd95SBruce Richardson 			symvec.aad = &aad[j];
14399a2dd95SBruce Richardson 			symvec.status = &st[j];
14499a2dd95SBruce Richardson 			symvec.num = i - j;
14599a2dd95SBruce Richardson 
14699a2dd95SBruce Richardson 			/* flush vec array and try again */
14799a2dd95SBruce Richardson 			n += rte_cryptodev_sym_cpu_crypto_process(
14899a2dd95SBruce Richardson 				ss->crypto.dev_id, ss->crypto.ses, ofs,
14999a2dd95SBruce Richardson 				&symvec);
15099a2dd95SBruce Richardson 			vofs = 0;
15199a2dd95SBruce Richardson 			vcnt = rte_crypto_mbuf_to_vec(mb[i], l4ofs[i], clen[i],
15299a2dd95SBruce Richardson 				vec, vnum);
15399a2dd95SBruce Richardson 			RTE_ASSERT(vcnt > 0);
15499a2dd95SBruce Richardson 			j = i;
15599a2dd95SBruce Richardson 		}
15699a2dd95SBruce Richardson 
15799a2dd95SBruce Richardson 		vecpkt[i].vec = &vec[vofs];
15899a2dd95SBruce Richardson 		vecpkt[i].num = vcnt;
15999a2dd95SBruce Richardson 		vofs += vcnt;
16099a2dd95SBruce Richardson 	}
16199a2dd95SBruce Richardson 
16299a2dd95SBruce Richardson 	/* fill the request structure */
16310488d59SHemant Agrawal 	symvec.src_sgl = &vecpkt[j];
16499a2dd95SBruce Richardson 	symvec.iv = &iv[j];
16599a2dd95SBruce Richardson 	symvec.aad = &aad[j];
16699a2dd95SBruce Richardson 	symvec.digest = &dgst[j];
16799a2dd95SBruce Richardson 	symvec.status = &st[j];
16899a2dd95SBruce Richardson 	symvec.num = i - j;
16999a2dd95SBruce Richardson 
17099a2dd95SBruce Richardson 	n += rte_cryptodev_sym_cpu_crypto_process(ss->crypto.dev_id,
17199a2dd95SBruce Richardson 		ss->crypto.ses, ofs, &symvec);
17299a2dd95SBruce Richardson 
17399a2dd95SBruce Richardson 	j = num - n;
17499a2dd95SBruce Richardson 	for (i = 0; j != 0 && i != num; i++) {
17599a2dd95SBruce Richardson 		if (st[i] != 0) {
176*daa02b5cSOlivier Matz 			mb[i]->ol_flags |= RTE_MBUF_F_RX_SEC_OFFLOAD_FAILED;
17799a2dd95SBruce Richardson 			j--;
17899a2dd95SBruce Richardson 		}
17999a2dd95SBruce Richardson 	}
18099a2dd95SBruce Richardson }
18199a2dd95SBruce Richardson 
18299a2dd95SBruce Richardson #endif /* _MISC_H_ */
183