Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause 2 : : * Copyright(c) 2017-2020 Intel Corporation 3 : : */ 4 : : 5 : : #include <stddef.h> 6 : : #include <stdint.h> 7 : : 8 : : #include <eal_export.h> 9 : : #include <rte_cpuflags.h> 10 : : #include <rte_common.h> 11 : : #include <rte_net_crc.h> 12 : : #include <rte_vect.h> 13 : : #include <rte_malloc.h> 14 : : 15 : : #include "net_crc.h" 16 : : 17 : : /** CRC polynomials */ 18 : : #define CRC32_ETH_POLYNOMIAL 0x04c11db7UL 19 : : #define CRC16_CCITT_POLYNOMIAL 0x1021U 20 : : 21 : : #define CRC_LUT_SIZE 256 22 : : 23 : : /* crc tables */ 24 : : static uint32_t crc32_eth_lut[CRC_LUT_SIZE]; 25 : : static uint32_t crc16_ccitt_lut[CRC_LUT_SIZE]; 26 : : 27 : : static uint32_t 28 : : rte_crc16_ccitt_handler(const uint8_t *data, uint32_t data_len); 29 : : 30 : : static uint32_t 31 : : rte_crc32_eth_handler(const uint8_t *data, uint32_t data_len); 32 : : 33 : : typedef uint32_t 34 : : (*rte_net_crc_handler)(const uint8_t *data, uint32_t data_len); 35 : : 36 : : struct rte_net_crc { 37 : : enum rte_net_crc_alg alg; 38 : : enum rte_net_crc_type type; 39 : : }; 40 : : 41 : : static struct { 42 : : rte_net_crc_handler f[RTE_NET_CRC_REQS]; 43 : : } handlers[RTE_NET_CRC_AVX512 + 1]; 44 : : 45 : : /* Scalar handling */ 46 : : 47 : : /** 48 : : * Reflect the bits about the middle 49 : : * 50 : : * @param val 51 : : * value to be reflected 52 : : * 53 : : * @return 54 : : * reflected value 55 : : */ 56 : : static uint32_t 57 : : reflect_32bits(uint32_t val) 58 : : { 59 : : uint32_t i, res = 0; 60 : : 61 [ + + + + ]: 8549376 : for (i = 0; i < 32; i++) 62 [ + + + + ]: 8290304 : if ((val & (1U << i)) != 0) 63 : 2072576 : res |= (uint32_t)(1U << (31 - i)); 64 : : 65 : : return res; 66 : : } 67 : : 68 : : static void 69 : 506 : crc32_eth_init_lut(uint32_t poly, 70 : : uint32_t *lut) 71 : : { 72 : : uint32_t i, j; 73 : : 74 [ + + ]: 130042 : for (i = 0; i < CRC_LUT_SIZE; i++) { 75 : : uint32_t crc = reflect_32bits(i); 76 : : 77 [ + + ]: 1165824 : for (j = 0; j < 8; j++) { 78 [ + + ]: 1036288 : if (crc & 0x80000000L) 79 : 518144 : crc = (crc << 1) ^ poly; 80 : : else 81 : 518144 : crc <<= 1; 82 : : } 83 : 259072 : lut[i] = reflect_32bits(crc); 84 : : } 85 : 506 : } 86 : : 87 : : static __rte_always_inline uint32_t 88 : : crc32_eth_calc_lut(const uint8_t *data, 89 : : uint32_t data_len, 90 : : uint32_t crc, 91 : : const uint32_t *lut) 92 : : { 93 [ + + + + ]: 3888 : while (data_len--) 94 : 3876 : crc = lut[(crc ^ *data++) & 0xffL] ^ (crc >> 8); 95 : : 96 : : return crc; 97 : : } 98 : : 99 : : static void 100 : 253 : rte_net_crc_scalar_init(void) 101 : : { 102 : : /* 32-bit crc init */ 103 : 253 : crc32_eth_init_lut(CRC32_ETH_POLYNOMIAL, crc32_eth_lut); 104 : : 105 : : /* 16-bit CRC init */ 106 : 253 : crc32_eth_init_lut(CRC16_CCITT_POLYNOMIAL << 16, crc16_ccitt_lut); 107 : 253 : } 108 : : 109 : : static inline uint32_t 110 : 6 : rte_crc16_ccitt_handler(const uint8_t *data, uint32_t data_len) 111 : : { 112 : : /* return 16-bit CRC value */ 113 : 6 : return (uint16_t)~crc32_eth_calc_lut(data, 114 : : data_len, 115 : : 0xffff, 116 : : crc16_ccitt_lut); 117 : : } 118 : : 119 : : static inline uint32_t 120 : 6 : rte_crc32_eth_handler(const uint8_t *data, uint32_t data_len) 121 : : { 122 : : /* return 32-bit CRC value */ 123 : 6 : return ~crc32_eth_calc_lut(data, 124 : : data_len, 125 : : 0xffffffffUL, 126 : : crc32_eth_lut); 127 : : } 128 : : 129 : : /* AVX512/VPCLMULQDQ handling */ 130 : : 131 : : #define AVX512_VPCLMULQDQ_CPU_SUPPORTED ( \ 132 : : rte_cpu_get_flag_enabled(RTE_CPUFLAG_AVX512F) && \ 133 : : rte_cpu_get_flag_enabled(RTE_CPUFLAG_AVX512BW) && \ 134 : : rte_cpu_get_flag_enabled(RTE_CPUFLAG_AVX512DQ) && \ 135 : : rte_cpu_get_flag_enabled(RTE_CPUFLAG_AVX512VL) && \ 136 : : rte_cpu_get_flag_enabled(RTE_CPUFLAG_PCLMULQDQ) && \ 137 : : rte_cpu_get_flag_enabled(RTE_CPUFLAG_VPCLMULQDQ) \ 138 : : ) 139 : : 140 : : static void 141 : 253 : avx512_vpclmulqdq_init(void) 142 : : { 143 : : #ifdef CC_AVX512_SUPPORT 144 [ + - + - : 253 : if (AVX512_VPCLMULQDQ_CPU_SUPPORTED) + - + - + - - + ] 145 : 0 : rte_net_crc_avx512_init(); 146 : : #endif 147 : 253 : } 148 : : 149 : : /* SSE4.2/PCLMULQDQ handling */ 150 : : 151 : : #define SSE42_PCLMULQDQ_CPU_SUPPORTED \ 152 : : rte_cpu_get_flag_enabled(RTE_CPUFLAG_PCLMULQDQ) 153 : : 154 : : static void 155 : 253 : sse42_pclmulqdq_init(void) 156 : : { 157 : : #ifdef RTE_ARCH_X86_64 158 [ + - ]: 253 : if (SSE42_PCLMULQDQ_CPU_SUPPORTED) 159 : 253 : rte_net_crc_sse42_init(); 160 : : #endif 161 : 253 : } 162 : : 163 : : /* NEON/PMULL handling */ 164 : : 165 : : #define NEON_PMULL_CPU_SUPPORTED \ 166 : : rte_cpu_get_flag_enabled(RTE_CPUFLAG_PMULL) 167 : : 168 : : static void 169 : : neon_pmull_init(void) 170 : : { 171 : : #ifdef CC_ARM64_NEON_PMULL_SUPPORT 172 : : if (NEON_PMULL_CPU_SUPPORTED) 173 : : rte_net_crc_neon_init(); 174 : : #endif 175 : : } 176 : : 177 : : static void 178 : 506 : handlers_init(enum rte_net_crc_alg alg) 179 : : { 180 : 759 : handlers[alg].f[RTE_NET_CRC16_CCITT] = rte_crc16_ccitt_handler; 181 : 759 : handlers[alg].f[RTE_NET_CRC32_ETH] = rte_crc32_eth_handler; 182 : : 183 [ + + - ]: 506 : switch (alg) { 184 : 253 : case RTE_NET_CRC_AVX512: 185 : : #ifdef CC_AVX512_SUPPORT 186 [ + - + - : 253 : if (AVX512_VPCLMULQDQ_CPU_SUPPORTED) { + - + - + - - + ] 187 : 0 : handlers[alg].f[RTE_NET_CRC16_CCITT] = rte_crc16_ccitt_avx512_handler; 188 : 0 : handlers[alg].f[RTE_NET_CRC32_ETH] = rte_crc32_eth_avx512_handler; 189 : 0 : break; 190 : : } 191 : : #endif 192 : : /* fall-through */ 193 : : case RTE_NET_CRC_SSE42: 194 : : #ifdef RTE_ARCH_X86_64 195 [ + - ]: 506 : if (SSE42_PCLMULQDQ_CPU_SUPPORTED) { 196 : 506 : handlers[alg].f[RTE_NET_CRC16_CCITT] = rte_crc16_ccitt_sse42_handler; 197 : 506 : handlers[alg].f[RTE_NET_CRC32_ETH] = rte_crc32_eth_sse42_handler; 198 : : } 199 : : #endif 200 : : break; 201 : : case RTE_NET_CRC_NEON: 202 : : #ifdef CC_ARM64_NEON_PMULL_SUPPORT 203 : : if (NEON_PMULL_CPU_SUPPORTED) { 204 : : handlers[alg].f[RTE_NET_CRC16_CCITT] = rte_crc16_ccitt_neon_handler; 205 : : handlers[alg].f[RTE_NET_CRC32_ETH] = rte_crc32_eth_neon_handler; 206 : : break; 207 : : } 208 : : #endif 209 : : /* fall-through */ 210 : : case RTE_NET_CRC_SCALAR: 211 : : /* fall-through */ 212 : : default: 213 : : break; 214 : : } 215 : 506 : } 216 : : 217 : : /* Public API */ 218 : : 219 : : RTE_EXPORT_SYMBOL(rte_net_crc_set_alg) 220 : 24 : struct rte_net_crc *rte_net_crc_set_alg(enum rte_net_crc_alg alg, enum rte_net_crc_type type) 221 : : { 222 : : uint16_t max_simd_bitwidth; 223 : : struct rte_net_crc *crc; 224 : : 225 : 24 : crc = rte_zmalloc(NULL, sizeof(struct rte_net_crc), 0); 226 [ + - ]: 24 : if (crc == NULL) 227 : : return NULL; 228 : 24 : max_simd_bitwidth = rte_vect_get_max_simd_bitwidth(); 229 : 24 : crc->type = type; 230 : 24 : crc->alg = RTE_NET_CRC_SCALAR; 231 : : 232 [ + + + + ]: 24 : switch (alg) { 233 : 6 : case RTE_NET_CRC_AVX512: 234 [ - + ]: 6 : if (max_simd_bitwidth >= RTE_VECT_SIMD_512) { 235 : 0 : crc->alg = RTE_NET_CRC_AVX512; 236 : 0 : return crc; 237 : : } 238 : : /* fall-through */ 239 : : case RTE_NET_CRC_SSE42: 240 [ + - ]: 12 : if (max_simd_bitwidth >= RTE_VECT_SIMD_128) { 241 : 12 : crc->alg = RTE_NET_CRC_SSE42; 242 : 12 : return crc; 243 : : } 244 : : break; 245 : 6 : case RTE_NET_CRC_NEON: 246 [ + - ]: 6 : if (max_simd_bitwidth >= RTE_VECT_SIMD_128) { 247 : 6 : crc->alg = RTE_NET_CRC_NEON; 248 : 6 : return crc; 249 : : } 250 : : break; 251 : : case RTE_NET_CRC_SCALAR: 252 : : /* fall-through */ 253 : : default: 254 : : break; 255 : : } 256 : : return crc; 257 : : } 258 : : 259 : : RTE_EXPORT_SYMBOL(rte_net_crc_free) 260 : 24 : void rte_net_crc_free(struct rte_net_crc *crc) 261 : : { 262 : 24 : rte_free(crc); 263 : 24 : } 264 : : 265 : : RTE_EXPORT_SYMBOL(rte_net_crc_calc) 266 : 24 : uint32_t rte_net_crc_calc(const struct rte_net_crc *ctx, const void *data, const uint32_t data_len) 267 : : { 268 : 24 : return handlers[ctx->alg].f[ctx->type](data, data_len); 269 : : } 270 : : 271 : : /* Call initialisation helpers for all crc algorithm handlers */ 272 : 253 : RTE_INIT(rte_net_crc_init) 273 : : { 274 : 253 : rte_net_crc_scalar_init(); 275 : 253 : sse42_pclmulqdq_init(); 276 : 253 : avx512_vpclmulqdq_init(); 277 : : neon_pmull_init(); 278 : : handlers_init(RTE_NET_CRC_SCALAR); 279 : : handlers_init(RTE_NET_CRC_NEON); 280 : 253 : handlers_init(RTE_NET_CRC_SSE42); 281 : 253 : handlers_init(RTE_NET_CRC_AVX512); 282 : 253 : }