Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2024 ZTE Corporation
3 : : */
4 : :
5 : : #include "zsda_comp.h"
6 : :
7 : : #define ZLIB_HEADER_SIZE 2
8 : : #define ZLIB_TRAILER_SIZE 4
9 : : #define GZIP_HEADER_SIZE 10
10 : : #define GZIP_TRAILER_SIZE 8
11 : : #define CHECKSUM_SIZE 4
12 : :
13 : : #define POLYNOMIAL 0xEDB88320
14 : : static uint32_t crc32_table[8][256];
15 : : static int table_config;
16 : :
17 : : static void
18 : 0 : crc32_table_build(void)
19 : : {
20 [ # # ]: 0 : for (uint32_t i = 0; i < 256; i++) {
21 : : uint32_t crc = i;
22 [ # # ]: 0 : for (uint32_t j = 0; j < 8; j++)
23 [ # # ]: 0 : crc = (crc >> 1) ^ ((crc & 1) ? POLYNOMIAL : 0);
24 : 0 : crc32_table[0][i] = crc;
25 : : }
26 : :
27 [ # # ]: 0 : for (int i = 1; i < 8; i++) {
28 [ # # ]: 0 : for (uint32_t j = 0; j < 256; j++)
29 : 0 : crc32_table[i][j] = (crc32_table[i-1][j] >> 8) ^
30 : 0 : crc32_table[0][crc32_table[i-1][j] & 0xFF];
31 : : }
32 : 0 : table_config = 1;
33 : 0 : }
34 : :
35 : : static uint32_t
36 : 0 : zsda_crc32(const uint8_t *data, size_t length)
37 : : {
38 : : uint32_t crc = 0xFFFFFFFF;
39 : :
40 [ # # ]: 0 : if (!table_config)
41 : 0 : crc32_table_build();
42 : :
43 [ # # ]: 0 : while (length >= 8) {
44 : 0 : crc ^= *(const uint32_t *)data;
45 : 0 : crc = crc32_table[7][crc & 0xFF] ^
46 : 0 : crc32_table[6][(crc >> 8) & 0xFF] ^
47 : 0 : crc32_table[5][(crc >> 16) & 0xFF] ^
48 : 0 : crc32_table[4][(crc >> 24) & 0xFF] ^
49 : 0 : crc32_table[3][data[4]] ^
50 : 0 : crc32_table[2][data[5]] ^
51 : 0 : crc32_table[1][data[6]] ^
52 : 0 : crc32_table[0][data[7]];
53 : :
54 : 0 : data += 8;
55 : 0 : length -= 8;
56 : : }
57 : :
58 [ # # ]: 0 : for (size_t i = 0; i < length; i++)
59 : 0 : crc = (crc >> 8) ^ crc32_table[0][(crc ^ data[i]) & 0xFF];
60 : :
61 : 0 : return crc ^ 0xFFFFFFFF;
62 : : }
63 : :
64 : : #define MOD_ADLER 65521
65 : : #define NMAX 5552
66 : : static uint32_t
67 : : zsda_adler32(const uint8_t *buf, uint32_t len)
68 : : {
69 : : uint32_t s1 = 1;
70 : : uint32_t s2 = 0;
71 : :
72 [ # # ]: 0 : while (len > 0) {
73 : 0 : uint32_t k = (len < NMAX) ? len : NMAX;
74 : 0 : len -= k;
75 : :
76 [ # # ]: 0 : for (uint32_t i = 0; i < k; i++) {
77 : 0 : s1 += buf[i];
78 : 0 : s2 += s1;
79 : : }
80 : :
81 : 0 : s1 %= MOD_ADLER;
82 : 0 : s2 %= MOD_ADLER;
83 : :
84 : 0 : buf += k;
85 : : }
86 : :
87 : 0 : return (s2 << 16) | s1;
88 : : }
89 : :
90 : : int
91 : 0 : zsda_comp_match(const void *op_in)
92 : : {
93 : : const struct rte_comp_op *op = op_in;
94 : 0 : const struct zsda_comp_xform *xform = op->private_xform;
95 : :
96 [ # # ]: 0 : if (op->op_type != RTE_COMP_OP_STATELESS)
97 : : return 0;
98 : :
99 [ # # ]: 0 : if (xform->type != RTE_COMP_COMPRESS)
100 : 0 : return 0;
101 : :
102 : : return 1;
103 : : }
104 : :
105 : : int
106 : 0 : zsda_decomp_match(const void *op_in)
107 : : {
108 : : const struct rte_comp_op *op = op_in;
109 : 0 : const struct zsda_comp_xform *xform = op->private_xform;
110 : :
111 [ # # ]: 0 : if (op->op_type != RTE_COMP_OP_STATELESS)
112 : : return 0;
113 : :
114 [ # # ]: 0 : if (xform->type != RTE_COMP_DECOMPRESS)
115 : 0 : return 0;
116 : : return 1;
117 : : }
118 : :
119 : : static uint8_t
120 : : zsda_opcode_get(const struct zsda_comp_xform *xform)
121 : : {
122 [ # # # # ]: 0 : if (xform->type == RTE_COMP_COMPRESS) {
123 [ # # # # ]: 0 : if (xform->checksum_type == RTE_COMP_CHECKSUM_NONE ||
124 : : xform->checksum_type == RTE_COMP_CHECKSUM_CRC32)
125 : : return ZSDA_OPC_COMP_GZIP;
126 [ # # # # ]: 0 : else if (xform->checksum_type == RTE_COMP_CHECKSUM_ADLER32)
127 : : return ZSDA_OPC_COMP_ZLIB;
128 : : }
129 [ # # # # ]: 0 : if (xform->type == RTE_COMP_DECOMPRESS) {
130 [ # # # # ]: 0 : if (xform->checksum_type == RTE_COMP_CHECKSUM_CRC32 ||
131 : : xform->checksum_type == RTE_COMP_CHECKSUM_NONE)
132 : : return ZSDA_OPC_DECOMP_GZIP;
133 [ # # # # ]: 0 : else if (xform->checksum_type == RTE_COMP_CHECKSUM_ADLER32)
134 : : return ZSDA_OPC_DECOMP_ZLIB;
135 : : }
136 : :
137 : : return ZSDA_OPC_INVALID;
138 : : }
139 : :
140 : : int
141 : 0 : zsda_comp_request_build(void *op_in, const struct zsda_queue *queue,
142 : : void **op_cookies, const uint16_t new_tail)
143 : : {
144 : : struct rte_comp_op *op = op_in;
145 : 0 : struct zsda_comp_xform *xform = op->private_xform;
146 : 0 : struct zsda_wqe_comp *wqe =
147 : 0 : (struct zsda_wqe_comp *)(queue->base_addr +
148 : 0 : (new_tail * queue->msg_size));
149 : :
150 : 0 : struct zsda_op_cookie *cookie = op_cookies[new_tail];
151 : 0 : struct zsda_sgl *sgl_src = (struct zsda_sgl *)&cookie->sgl_src;
152 : 0 : struct zsda_sgl *sgl_dst = (struct zsda_sgl *)&cookie->sgl_dst;
153 : : struct comp_head_info comp_head_info;
154 : :
155 : : uint8_t opcode;
156 : : int ret;
157 : : uint32_t op_offset;
158 : : uint32_t op_src_len;
159 : : uint32_t op_dst_len;
160 : : uint32_t head_len;
161 : :
162 [ # # # # ]: 0 : if ((op->m_dst == NULL) || (op->m_dst == op->m_src)) {
163 : 0 : ZSDA_LOG(ERR, "Failed! m_dst");
164 : 0 : return -EINVAL;
165 : : }
166 : :
167 : : opcode = zsda_opcode_get(xform);
168 : : if (opcode == ZSDA_OPC_INVALID) {
169 : 0 : ZSDA_LOG(ERR, "Failed! zsda_opcode_get");
170 : 0 : return -EINVAL;
171 : : }
172 : :
173 : 0 : cookie->used = true;
174 : 0 : cookie->sid = new_tail;
175 : 0 : cookie->op = op;
176 : :
177 [ # # ]: 0 : if (opcode == ZSDA_OPC_COMP_GZIP)
178 : : head_len = GZIP_HEADER_SIZE;
179 [ # # ]: 0 : else if (opcode == ZSDA_OPC_COMP_ZLIB)
180 : : head_len = ZLIB_HEADER_SIZE;
181 : : else {
182 : 0 : ZSDA_LOG(ERR, "Comp, op_code error!");
183 : 0 : return -EINVAL;
184 : : }
185 : :
186 : 0 : comp_head_info.head_len = head_len;
187 : 0 : comp_head_info.head_phys_addr = cookie->comp_head_phys_addr;
188 : :
189 : 0 : op_offset = op->src.offset;
190 : 0 : op_src_len = op->src.length;
191 : 0 : ret = zsda_sgl_fill(op->m_src, op_offset, sgl_src,
192 : : cookie->sgl_src_phys_addr, op_src_len, NULL);
193 : :
194 : 0 : op_offset = op->dst.offset;
195 : 0 : op_dst_len = op->m_dst->pkt_len - op_offset;
196 : 0 : op_dst_len += head_len;
197 : 0 : ret |= zsda_sgl_fill(op->m_dst, op_offset, sgl_dst,
198 : : cookie->sgl_dst_phys_addr, op_dst_len,
199 : : &comp_head_info);
200 : :
201 [ # # ]: 0 : if (ret) {
202 : 0 : ZSDA_LOG(ERR, "Failed! zsda_sgl_fill");
203 : 0 : return ret;
204 : : }
205 : :
206 : : memset(wqe, 0, sizeof(struct zsda_wqe_comp));
207 : 0 : wqe->rx_length = op_src_len;
208 : 0 : wqe->tx_length = op_dst_len;
209 : 0 : wqe->valid = queue->valid;
210 : 0 : wqe->op_code = opcode;
211 : 0 : wqe->sid = cookie->sid;
212 : 0 : wqe->rx_sgl_type = WQE_ELM_TYPE_LIST;
213 : 0 : wqe->tx_sgl_type = WQE_ELM_TYPE_LIST;
214 : :
215 : 0 : wqe->rx_addr = cookie->sgl_src_phys_addr;
216 : 0 : wqe->tx_addr = cookie->sgl_dst_phys_addr;
217 : :
218 : 0 : return ret;
219 : : }
220 : :
221 : : int
222 : 0 : zsda_decomp_request_build(void *op_in, const struct zsda_queue *queue,
223 : : void **op_cookies, const uint16_t new_tail)
224 : : {
225 : : struct rte_comp_op *op = op_in;
226 : 0 : struct zsda_comp_xform *xform = op->private_xform;
227 : :
228 : 0 : struct zsda_wqe_comp *wqe =
229 : 0 : (struct zsda_wqe_comp *)(queue->base_addr +
230 : 0 : (new_tail * queue->msg_size));
231 : 0 : struct zsda_op_cookie *cookie = op_cookies[new_tail];
232 : 0 : struct zsda_sgl *sgl_src = (struct zsda_sgl *)&cookie->sgl_src;
233 : 0 : struct zsda_sgl *sgl_dst = (struct zsda_sgl *)&cookie->sgl_dst;
234 : : uint8_t opcode;
235 : : int ret;
236 : :
237 : : uint32_t op_offset;
238 : : uint32_t op_src_len;
239 : : uint32_t op_dst_len;
240 : :
241 : : uint8_t *head_data;
242 : : uint16_t head_len;
243 : : struct comp_head_info comp_head_info;
244 : 0 : uint8_t head_zlib[ZLIB_HEADER_SIZE] = {0x78, 0xDA};
245 : 0 : uint8_t head_gzip[GZIP_HEADER_SIZE] = {0x1F, 0x8B, 0x08, 0x00, 0x00,
246 : : 0x00, 0x00, 0x00, 0x00, 0x03};
247 : :
248 [ # # # # ]: 0 : if ((op->m_dst == NULL) || (op->m_dst == op->m_src)) {
249 : 0 : ZSDA_LOG(ERR, "Failed! m_dst");
250 : 0 : return -EINVAL;
251 : : }
252 : :
253 : : opcode = zsda_opcode_get(xform);
254 : : if (opcode == ZSDA_OPC_INVALID) {
255 : 0 : ZSDA_LOG(ERR, "Failed! zsda_opcode_get");
256 : 0 : return -EINVAL;
257 : : }
258 : :
259 : 0 : cookie->used = true;
260 : 0 : cookie->sid = new_tail;
261 : 0 : cookie->op = op;
262 : :
263 [ # # ]: 0 : if (opcode == ZSDA_OPC_DECOMP_GZIP) {
264 : : head_data = head_gzip;
265 : : head_len = GZIP_HEADER_SIZE;
266 [ # # ]: 0 : } else if (opcode == ZSDA_OPC_DECOMP_ZLIB) {
267 : : head_data = head_zlib;
268 : : head_len = ZLIB_HEADER_SIZE;
269 : : } else {
270 : 0 : ZSDA_LOG(ERR, "Comp, op_code error!");
271 : 0 : return -EINVAL;
272 : : }
273 : :
274 : 0 : op_offset = op->src.offset;
275 : 0 : op_src_len = op->src.length;
276 : 0 : op_src_len += head_len;
277 : 0 : comp_head_info.head_len = head_len;
278 : 0 : comp_head_info.head_phys_addr = cookie->comp_head_phys_addr;
279 : 0 : cookie->decomp_no_tail = true;
280 [ # # ]: 0 : for (int i = 0; i < head_len; i++)
281 : 0 : cookie->comp_head[i] = head_data[i];
282 : :
283 : 0 : ret = zsda_sgl_fill(op->m_src, op_offset, sgl_src,
284 : : cookie->sgl_src_phys_addr, op_src_len,
285 : : &comp_head_info);
286 : :
287 : 0 : op_offset = op->dst.offset;
288 : 0 : op_dst_len = op->m_dst->pkt_len - op_offset;
289 : 0 : ret |= zsda_sgl_fill(op->m_dst, op_offset, sgl_dst,
290 : : cookie->sgl_dst_phys_addr, op_dst_len, NULL);
291 : :
292 [ # # ]: 0 : if (ret) {
293 : 0 : ZSDA_LOG(ERR, "Failed! zsda_sgl_fill");
294 : 0 : return ret;
295 : : }
296 : :
297 : : memset(wqe, 0, sizeof(struct zsda_wqe_comp));
298 : :
299 : 0 : wqe->rx_length = op_src_len;
300 : 0 : wqe->tx_length = op_dst_len;
301 : 0 : wqe->valid = queue->valid;
302 : 0 : wqe->op_code = opcode;
303 : 0 : wqe->sid = cookie->sid;
304 : 0 : wqe->rx_sgl_type = WQE_ELM_TYPE_LIST;
305 : 0 : wqe->tx_sgl_type = WQE_ELM_TYPE_LIST;
306 : 0 : wqe->rx_addr = cookie->sgl_src_phys_addr;
307 : 0 : wqe->tx_addr = cookie->sgl_dst_phys_addr;
308 : :
309 : 0 : return ret;
310 : : }
311 : :
312 : : static uint32_t
313 : 0 : zsda_chksum_read(uint8_t *data_addr, uint8_t op_code, uint32_t produced)
314 : : {
315 : : uint8_t *chk_addr;
316 : : uint32_t chksum = 0;
317 : : int i = 0;
318 : :
319 [ # # ]: 0 : if (op_code == ZSDA_OPC_COMP_ZLIB) {
320 : 0 : chk_addr = data_addr + produced - ZLIB_TRAILER_SIZE;
321 [ # # ]: 0 : for (i = 0; i < CHECKSUM_SIZE; i++) {
322 : 0 : chksum = chksum << 8;
323 : 0 : chksum |= (*(chk_addr + i));
324 : : }
325 [ # # ]: 0 : } else if (op_code == ZSDA_OPC_COMP_GZIP) {
326 : 0 : chk_addr = data_addr + produced - GZIP_TRAILER_SIZE;
327 [ # # ]: 0 : for (i = 0; i < CHECKSUM_SIZE; i++)
328 : 0 : chksum |= (*(chk_addr + i) << (i * 8));
329 : : }
330 : :
331 : 0 : return chksum;
332 : : }
333 : :
334 : : int
335 : 0 : zsda_comp_callback(void *cookie_in, struct zsda_cqe *cqe)
336 : : {
337 : : struct zsda_op_cookie *tmp_cookie = cookie_in;
338 : 0 : struct rte_comp_op *tmp_op = tmp_cookie->op;
339 : 0 : uint8_t *data_addr =
340 : 0 : (uint8_t *)tmp_op->m_dst->buf_addr + tmp_op->m_dst->data_off;
341 : : uint32_t chksum = 0;
342 : : uint16_t head_len;
343 : : uint16_t tail_len;
344 : :
345 [ # # # # : 0 : if (tmp_cookie->decomp_no_tail && CQE_ERR0_RIGHT(cqe->err0))
# # ]
346 : 0 : cqe->err0 = 0x0000;
347 : :
348 [ # # # # ]: 0 : if (!(CQE_ERR0(cqe->err0) || CQE_ERR1(cqe->err1)))
349 : 0 : tmp_op->status = RTE_COMP_OP_STATUS_SUCCESS;
350 : : else {
351 : 0 : tmp_op->status = RTE_COMP_OP_STATUS_ERROR;
352 : 0 : return ZSDA_FAILED;
353 : : }
354 : :
355 : : /* handle chksum */
356 : 0 : tmp_op->produced = cqe->tx_real_length;
357 [ # # ]: 0 : if (cqe->op_code == ZSDA_OPC_COMP_ZLIB) {
358 : : head_len = ZLIB_HEADER_SIZE;
359 : : tail_len = ZLIB_TRAILER_SIZE;
360 : 0 : chksum = zsda_chksum_read(data_addr, cqe->op_code,
361 : : tmp_op->produced - head_len);
362 : : }
363 [ # # ]: 0 : if (cqe->op_code == ZSDA_OPC_COMP_GZIP) {
364 : : head_len = GZIP_HEADER_SIZE;
365 : : tail_len = GZIP_TRAILER_SIZE;
366 : 0 : chksum = zsda_chksum_read(data_addr, cqe->op_code,
367 : : tmp_op->produced - head_len);
368 [ # # ]: 0 : } else if (cqe->op_code == ZSDA_OPC_DECOMP_ZLIB) {
369 : : head_len = ZLIB_HEADER_SIZE;
370 : : tail_len = ZLIB_TRAILER_SIZE;
371 : : chksum = zsda_adler32(data_addr, tmp_op->produced);
372 [ # # ]: 0 : } else if (cqe->op_code == ZSDA_OPC_DECOMP_GZIP) {
373 : : head_len = GZIP_HEADER_SIZE;
374 : : tail_len = GZIP_TRAILER_SIZE;
375 : 0 : chksum = zsda_crc32(data_addr, tmp_op->produced);
376 : : }
377 : 0 : tmp_op->output_chksum = chksum;
378 : :
379 [ # # ]: 0 : if (cqe->op_code == ZSDA_OPC_COMP_ZLIB ||
380 : : cqe->op_code == ZSDA_OPC_COMP_GZIP) {
381 : : /* remove tail data*/
382 : : rte_pktmbuf_trim(tmp_op->m_dst, GZIP_TRAILER_SIZE);
383 : : /* remove head and tail length */
384 : 0 : tmp_op->produced = tmp_op->produced - (head_len + tail_len);
385 : : }
386 : :
387 : : return ZSDA_SUCCESS;
388 : : }
|