net/ixgbe/base: fix infinite recursion on PCIe link down
[dpdk.git] / lib / librte_ipsec / misc.h
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
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 *
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
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
113 cpu_crypto_bulk(const struct rte_ipsec_session *ss,
114         union rte_crypto_sym_ofs ofs, struct rte_mbuf *mb[],
115         void *iv[], void *aad[], void *dgst[], uint32_t l4ofs[],
116         uint32_t clen[], uint32_t num)
117 {
118         uint32_t i, j, n;
119         int32_t vcnt, vofs;
120         int32_t st[num];
121         struct rte_crypto_sgl vecpkt[num];
122         struct rte_crypto_vec vec[UINT8_MAX];
123         struct rte_crypto_sym_vec symvec;
124
125         const uint32_t vnum = RTE_DIM(vec);
126
127         j = 0, n = 0;
128         vofs = 0;
129         for (i = 0; i != num; i++) {
130
131                 vcnt = rte_crypto_mbuf_to_vec(mb[i], l4ofs[i], clen[i],
132                         &vec[vofs], vnum - vofs);
133
134                 /* not enough space in vec[] to hold all segments */
135                 if (vcnt < 0) {
136                         /* fill the request structure */
137                         symvec.sgl = &vecpkt[j];
138                         symvec.iv = &iv[j];
139                         symvec.aad = &aad[j];
140                         symvec.digest = &dgst[j];
141                         symvec.status = &st[j];
142                         symvec.num = i - j;
143
144                         /* flush vec array and try again */
145                         n += rte_cryptodev_sym_cpu_crypto_process(
146                                 ss->crypto.dev_id, ss->crypto.ses, ofs,
147                                 &symvec);
148                         vofs = 0;
149                         vcnt = rte_crypto_mbuf_to_vec(mb[i], l4ofs[i], clen[i],
150                                 vec, vnum);
151                         RTE_ASSERT(vcnt > 0);
152                         j = i;
153                 }
154
155                 vecpkt[i].vec = &vec[vofs];
156                 vecpkt[i].num = vcnt;
157                 vofs += vcnt;
158         }
159
160         /* fill the request structure */
161         symvec.sgl = &vecpkt[j];
162         symvec.iv = &iv[j];
163         symvec.aad = &aad[j];
164         symvec.digest = &dgst[j];
165         symvec.status = &st[j];
166         symvec.num = i - j;
167
168         n += rte_cryptodev_sym_cpu_crypto_process(ss->crypto.dev_id,
169                 ss->crypto.ses, ofs, &symvec);
170
171         j = num - n;
172         for (i = 0; j != 0 && i != num; i++) {
173                 if (st[i] != 0) {
174                         mb[i]->ol_flags |= PKT_RX_SEC_OFFLOAD_FAILED;
175                         j--;
176                 }
177         }
178 }
179
180 #endif /* _MISC_H_ */