]> git.proxmox.com Git - ceph.git/blame - ceph/src/seastar/dpdk/lib/librte_net/rte_net_crc.c
import 15.2.0 Octopus source
[ceph.git] / ceph / src / seastar / dpdk / lib / librte_net / rte_net_crc.c
CommitLineData
9f95a23c
TL
1/* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2017 Intel Corporation
11fdf7f2
TL
3 */
4
5#include <stddef.h>
6#include <string.h>
7#include <stdint.h>
8
9#include <rte_cpuflags.h>
10#include <rte_common.h>
11#include <rte_net_crc.h>
12
9f95a23c 13#if defined(RTE_ARCH_X86_64) && defined(RTE_MACHINE_CPUFLAG_PCLMULQDQ)
11fdf7f2 14#define X86_64_SSE42_PCLMULQDQ 1
9f95a23c
TL
15#elif defined(RTE_ARCH_ARM64) && defined(RTE_MACHINE_CPUFLAG_PMULL)
16#define ARM64_NEON_PMULL 1
11fdf7f2
TL
17#endif
18
19#ifdef X86_64_SSE42_PCLMULQDQ
20#include <net_crc_sse.h>
9f95a23c
TL
21#elif defined ARM64_NEON_PMULL
22#include <net_crc_neon.h>
11fdf7f2
TL
23#endif
24
25/* crc tables */
26static uint32_t crc32_eth_lut[CRC_LUT_SIZE];
27static uint32_t crc16_ccitt_lut[CRC_LUT_SIZE];
28
29static uint32_t
30rte_crc16_ccitt_handler(const uint8_t *data, uint32_t data_len);
31
32static uint32_t
33rte_crc32_eth_handler(const uint8_t *data, uint32_t data_len);
34
35typedef uint32_t
36(*rte_net_crc_handler)(const uint8_t *data, uint32_t data_len);
37
38static rte_net_crc_handler *handlers;
39
40static rte_net_crc_handler handlers_scalar[] = {
41 [RTE_NET_CRC16_CCITT] = rte_crc16_ccitt_handler,
42 [RTE_NET_CRC32_ETH] = rte_crc32_eth_handler,
43};
44
45#ifdef X86_64_SSE42_PCLMULQDQ
46static rte_net_crc_handler handlers_sse42[] = {
47 [RTE_NET_CRC16_CCITT] = rte_crc16_ccitt_sse42_handler,
48 [RTE_NET_CRC32_ETH] = rte_crc32_eth_sse42_handler,
49};
9f95a23c
TL
50#elif defined ARM64_NEON_PMULL
51static rte_net_crc_handler handlers_neon[] = {
52 [RTE_NET_CRC16_CCITT] = rte_crc16_ccitt_neon_handler,
53 [RTE_NET_CRC32_ETH] = rte_crc32_eth_neon_handler,
54};
11fdf7f2
TL
55#endif
56
57/**
58 * Reflect the bits about the middle
59 *
60 * @param val
61 * value to be reflected
62 *
63 * @return
64 * reflected value
65 */
66static uint32_t
67reflect_32bits(uint32_t val)
68{
69 uint32_t i, res = 0;
70
71 for (i = 0; i < 32; i++)
9f95a23c
TL
72 if ((val & (1U << i)) != 0)
73 res |= (uint32_t)(1U << (31 - i));
11fdf7f2
TL
74
75 return res;
76}
77
78static void
79crc32_eth_init_lut(uint32_t poly,
80 uint32_t *lut)
81{
82 uint32_t i, j;
83
84 for (i = 0; i < CRC_LUT_SIZE; i++) {
85 uint32_t crc = reflect_32bits(i);
86
87 for (j = 0; j < 8; j++) {
88 if (crc & 0x80000000L)
89 crc = (crc << 1) ^ poly;
90 else
91 crc <<= 1;
92 }
93 lut[i] = reflect_32bits(crc);
94 }
95}
96
9f95a23c 97static __rte_always_inline uint32_t
11fdf7f2
TL
98crc32_eth_calc_lut(const uint8_t *data,
99 uint32_t data_len,
100 uint32_t crc,
101 const uint32_t *lut)
102{
103 while (data_len--)
104 crc = lut[(crc ^ *data++) & 0xffL] ^ (crc >> 8);
105
106 return crc;
107}
108
109static void
110rte_net_crc_scalar_init(void)
111{
112 /* 32-bit crc init */
113 crc32_eth_init_lut(CRC32_ETH_POLYNOMIAL, crc32_eth_lut);
114
115 /* 16-bit CRC init */
116 crc32_eth_init_lut(CRC16_CCITT_POLYNOMIAL << 16, crc16_ccitt_lut);
117}
118
119static inline uint32_t
120rte_crc16_ccitt_handler(const uint8_t *data, uint32_t data_len)
121{
122 /* return 16-bit CRC value */
123 return (uint16_t)~crc32_eth_calc_lut(data,
124 data_len,
125 0xffff,
126 crc16_ccitt_lut);
127}
128
129static inline uint32_t
130rte_crc32_eth_handler(const uint8_t *data, uint32_t data_len)
131{
132 /* return 32-bit CRC value */
133 return ~crc32_eth_calc_lut(data,
134 data_len,
135 0xffffffffUL,
136 crc32_eth_lut);
137}
138
139void
140rte_net_crc_set_alg(enum rte_net_crc_alg alg)
141{
142 switch (alg) {
11fdf7f2 143#ifdef X86_64_SSE42_PCLMULQDQ
9f95a23c 144 case RTE_NET_CRC_SSE42:
11fdf7f2 145 handlers = handlers_sse42;
11fdf7f2 146 break;
9f95a23c
TL
147#elif defined ARM64_NEON_PMULL
148 /* fall-through */
149 case RTE_NET_CRC_NEON:
150 if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_PMULL)) {
151 handlers = handlers_neon;
152 break;
153 }
154#endif
155 /* fall-through */
11fdf7f2 156 case RTE_NET_CRC_SCALAR:
9f95a23c 157 /* fall-through */
11fdf7f2
TL
158 default:
159 handlers = handlers_scalar;
160 break;
161 }
162}
163
164uint32_t
165rte_net_crc_calc(const void *data,
166 uint32_t data_len,
167 enum rte_net_crc_type type)
168{
169 uint32_t ret;
170 rte_net_crc_handler f_handle;
171
172 f_handle = handlers[type];
173 ret = f_handle(data, data_len);
174
175 return ret;
176}
177
178/* Select highest available crc algorithm as default one */
9f95a23c 179RTE_INIT(rte_net_crc_init)
11fdf7f2
TL
180{
181 enum rte_net_crc_alg alg = RTE_NET_CRC_SCALAR;
182
183 rte_net_crc_scalar_init();
184
185#ifdef X86_64_SSE42_PCLMULQDQ
9f95a23c
TL
186 alg = RTE_NET_CRC_SSE42;
187 rte_net_crc_sse42_init();
188#elif defined ARM64_NEON_PMULL
189 if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_PMULL)) {
190 alg = RTE_NET_CRC_NEON;
191 rte_net_crc_neon_init();
192 }
11fdf7f2
TL
193#endif
194
195 rte_net_crc_set_alg(alg);
196}