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