xref: /dpdk/lib/ipsec/misc.h (revision daa02b5cddbb8e11b31d41e2bf7bb1ae64dcae2f)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018-2020 Intel Corporation
3  */
4 
5 #ifndef _MISC_H_
6 #define _MISC_H_
7 
8 /**
9  * @file misc.h
10  * Contains miscellaneous functions/structures/macros used internally
11  * by ipsec library.
12  */
13 
14 /*
15  * Move bad (unprocessed) mbufs beyond the good (processed) ones.
16  * bad_idx[] contains the indexes of bad mbufs inside the mb[].
17  */
18 static inline void
move_bad_mbufs(struct rte_mbuf * mb[],const uint32_t bad_idx[],uint32_t nb_mb,uint32_t nb_bad)19 move_bad_mbufs(struct rte_mbuf *mb[], const uint32_t bad_idx[], uint32_t nb_mb,
20 	uint32_t nb_bad)
21 {
22 	uint32_t i, j, k;
23 	struct rte_mbuf *drb[nb_bad];
24 
25 	j = 0;
26 	k = 0;
27 
28 	/* copy bad ones into a temp place */
29 	for (i = 0; i != nb_mb; i++) {
30 		if (j != nb_bad && i == bad_idx[j])
31 			drb[j++] = mb[i];
32 		else
33 			mb[k++] = mb[i];
34 	}
35 
36 	/* copy bad ones after the good ones */
37 	for (i = 0; i != nb_bad; i++)
38 		mb[k + i] = drb[i];
39 }
40 
41 /*
42  * Find packet's segment for the specified offset.
43  * ofs - at input should contain required offset, at output would contain
44  * offset value within the segment.
45  */
46 static inline struct rte_mbuf *
mbuf_get_seg_ofs(struct rte_mbuf * mb,uint32_t * ofs)47 mbuf_get_seg_ofs(struct rte_mbuf *mb, uint32_t *ofs)
48 {
49 	uint32_t k, n, plen;
50 	struct rte_mbuf *ms;
51 
52 	plen = mb->pkt_len;
53 	n = *ofs;
54 
55 	if (n == plen) {
56 		ms = rte_pktmbuf_lastseg(mb);
57 		n = n + rte_pktmbuf_data_len(ms) - plen;
58 	} else {
59 		ms = mb;
60 		for (k = rte_pktmbuf_data_len(ms); n >= k;
61 				k = rte_pktmbuf_data_len(ms)) {
62 			ms = ms->next;
63 			n -= k;
64 		}
65 	}
66 
67 	*ofs = n;
68 	return ms;
69 }
70 
71 /*
72  * Trim multi-segment packet at the specified offset, and free
73  * all unused segments.
74  * mb - input packet
75  * ms - segment where to cut
76  * ofs - offset within the *ms*
77  * len - length to cut (from given offset to the end of the packet)
78  * Can be used in conjunction with mbuf_get_seg_ofs():
79  * ofs = new_len;
80  * ms = mbuf_get_seg_ofs(mb, &ofs);
81  * mbuf_cut_seg_ofs(mb, ms, ofs, mb->pkt_len - new_len);
82  */
83 static inline void
mbuf_cut_seg_ofs(struct rte_mbuf * mb,struct rte_mbuf * ms,uint32_t ofs,uint32_t len)84 mbuf_cut_seg_ofs(struct rte_mbuf *mb, struct rte_mbuf *ms, uint32_t ofs,
85 	uint32_t len)
86 {
87 	uint32_t n, slen;
88 	struct rte_mbuf *mn;
89 
90 	slen = ms->data_len;
91 	ms->data_len = ofs;
92 
93 	/* tail spawns through multiple segments */
94 	if (slen < ofs + len) {
95 		mn = ms->next;
96 		ms->next = NULL;
97 		for (n = 0; mn != NULL; n++) {
98 			ms = mn->next;
99 			rte_pktmbuf_free_seg(mn);
100 			mn = ms;
101 		}
102 		mb->nb_segs -= n;
103 	}
104 
105 	mb->pkt_len -= len;
106 }
107 
108 /*
109  * process packets using sync crypto engine.
110  * expects *num* to be greater than zero.
111  */
112 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)113 cpu_crypto_bulk(const struct rte_ipsec_session *ss,
114 	union rte_crypto_sym_ofs ofs, struct rte_mbuf *mb[],
115 	struct rte_crypto_va_iova_ptr iv[],
116 	struct rte_crypto_va_iova_ptr aad[],
117 	struct rte_crypto_va_iova_ptr dgst[], uint32_t l4ofs[],
118 	uint32_t clen[], uint32_t num)
119 {
120 	uint32_t i, j, n;
121 	int32_t vcnt, vofs;
122 	int32_t st[num];
123 	struct rte_crypto_sgl vecpkt[num];
124 	struct rte_crypto_vec vec[UINT8_MAX];
125 	struct rte_crypto_sym_vec symvec;
126 
127 	const uint32_t vnum = RTE_DIM(vec);
128 
129 	j = 0, n = 0;
130 	vofs = 0;
131 	for (i = 0; i != num; i++) {
132 
133 		vcnt = rte_crypto_mbuf_to_vec(mb[i], l4ofs[i], clen[i],
134 			&vec[vofs], vnum - vofs);
135 
136 		/* not enough space in vec[] to hold all segments */
137 		if (vcnt < 0) {
138 			/* fill the request structure */
139 			symvec.src_sgl = &vecpkt[j];
140 			symvec.iv = &iv[j];
141 			symvec.digest = &dgst[j];
142 			symvec.aad = &aad[j];
143 			symvec.status = &st[j];
144 			symvec.num = i - j;
145 
146 			/* flush vec array and try again */
147 			n += rte_cryptodev_sym_cpu_crypto_process(
148 				ss->crypto.dev_id, ss->crypto.ses, ofs,
149 				&symvec);
150 			vofs = 0;
151 			vcnt = rte_crypto_mbuf_to_vec(mb[i], l4ofs[i], clen[i],
152 				vec, vnum);
153 			RTE_ASSERT(vcnt > 0);
154 			j = i;
155 		}
156 
157 		vecpkt[i].vec = &vec[vofs];
158 		vecpkt[i].num = vcnt;
159 		vofs += vcnt;
160 	}
161 
162 	/* fill the request structure */
163 	symvec.src_sgl = &vecpkt[j];
164 	symvec.iv = &iv[j];
165 	symvec.aad = &aad[j];
166 	symvec.digest = &dgst[j];
167 	symvec.status = &st[j];
168 	symvec.num = i - j;
169 
170 	n += rte_cryptodev_sym_cpu_crypto_process(ss->crypto.dev_id,
171 		ss->crypto.ses, ofs, &symvec);
172 
173 	j = num - n;
174 	for (i = 0; j != 0 && i != num; i++) {
175 		if (st[i] != 0) {
176 			mb[i]->ol_flags |= RTE_MBUF_F_RX_SEC_OFFLOAD_FAILED;
177 			j--;
178 		}
179 	}
180 }
181 
182 #endif /* _MISC_H_ */
183