// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 /* Copyright (c) 2018 Mellanox Technologies. All rights reserved */ #include <linux/errno.h> #include <linux/gfp.h> #include <linux/kernel.h> #include <linux/refcount.h> #include <linux/mutex.h> #include "spectrum.h" #include "spectrum_acl_tcam.h" struct mlxsw_sp_acl_bf { … }; /* Bloom filter uses a crc-16 hash over chunks of data which contain 4 key * blocks, eRP ID and region ID. In Spectrum-2 and above, region key is combined * of up to 12 key blocks, so there can be up to 3 chunks in the Bloom filter * key, depending on the actual number of key blocks used in the region. * The layout of the Bloom filter key is as follows: * * +-------------------------+------------------------+------------------------+ * | Chunk 2 Key blocks 11-8 | Chunk 1 Key blocks 7-4 | Chunk 0 Key blocks 3-0 | * +-------------------------+------------------------+------------------------+ */ #define MLXSW_BLOOM_KEY_CHUNKS … /* Spectrum-2 and Spectrum-3 chunks */ #define MLXSW_SP2_BLOOM_KEY_LEN … /* Each chunk size is 23 bytes. 18 bytes of it contain 4 key blocks, each is * 36 bits, 2 bytes which hold eRP ID and region ID, and 3 bytes of zero * padding. * The layout of each chunk is as follows: * * +---------+----------------------+-----------------------------------+ * | 3 bytes | 2 bytes | 18 bytes | * +---------+-----------+----------+-----------------------------------+ * | 183:158 | 157:148 | 147:144 | 143:0 | * +---------+-----------+----------+-----------------------------------+ * | 0 | region ID | eRP ID | 4 Key blocks (18 Bytes) | * +---------+-----------+----------+-----------------------------------+ */ #define MLXSW_SP2_BLOOM_CHUNK_PAD_BYTES … #define MLXSW_SP2_BLOOM_CHUNK_KEY_BYTES … #define MLXSW_SP2_BLOOM_KEY_CHUNK_BYTES … /* The offset of the key block within a chunk is 5 bytes as it comes after * 3 bytes of zero padding and 16 bits of region ID and eRP ID. */ #define MLXSW_SP2_BLOOM_CHUNK_KEY_OFFSET … /* This table is just the CRC of each possible byte which is used for * Spectrum-{2-3}. It is computed, Msbit first, for the Bloom filter * polynomial which is 0x8529 (1 + x^3 + x^5 + x^8 + x^10 + x^15 and * the implicit x^16). */ static const u16 mlxsw_sp2_acl_bf_crc16_tab[256] = …; /* Spectrum-4 chunks */ #define MLXSW_SP4_BLOOM_KEY_LEN … /* In Spectrum-4, there is no padding. Each chunk size is 20 bytes. * 18 bytes of it contain 4 key blocks, each is 36 bits, and 2 bytes which hold * eRP ID and region ID. * The layout of each chunk is as follows: * * +----------------------+-----------------------------------+ * | 2 bytes | 18 bytes | * +-----------+----------+-----------------------------------+ * | 157:148 | 147:144 | 143:0 | * +---------+-----------+----------+-------------------------+ * | region ID | eRP ID | 4 Key blocks (18 Bytes) | * +-----------+----------+-----------------------------------+ */ #define MLXSW_SP4_BLOOM_CHUNK_PAD_BYTES … #define MLXSW_SP4_BLOOM_CHUNK_KEY_BYTES … #define MLXSW_SP4_BLOOM_KEY_CHUNK_BYTES … /* The offset of the key block within a chunk is 2 bytes as it comes after * 16 bits of region ID and eRP ID. */ #define MLXSW_SP4_BLOOM_CHUNK_KEY_OFFSET … /* For Spectrum-4, two hash functions are used, CRC-10 and CRC-6 based. * The result is combination of the two calculations - * 6 bit column are MSB (result of CRC-6), * 10 bit row are LSB (result of CRC-10). */ /* This table is just the CRC of each possible byte which is used for * Spectrum-4. It is computed, Msbit first, for the Bloom filter * polynomial which is 0x1b (1 + x^1 + x^3 + x^4 and the implicit x^10). */ static const u16 mlxsw_sp4_acl_bf_crc10_tab[256] = …; /* This table is just the CRC of each possible byte which is used for * Spectrum-4. It is computed, Msbit first, for the Bloom filter * polynomial which is 0x2d (1 + x^2+ x^3 + x^5 and the implicit x^6). */ static const u8 mlxsw_sp4_acl_bf_crc6_tab[256] = …; /* Each chunk contains 4 key blocks. Chunk 2 uses key blocks 11-8, * and we need to populate it with 4 key blocks copied from the entry encoded * key. The original keys layout is same for Spectrum-{2,3,4}. * Since the encoded key contains a 2 bytes padding, key block 11 starts at * offset 2. block 7 that is used in chunk 1 starts at offset 20 as 4 key blocks * take 18 bytes. See 'MLXSW_SP2_AFK_BLOCK_LAYOUT' for more details. * This array defines key offsets for easy access when copying key blocks from * entry key to Bloom filter chunk. */ static const u8 chunk_key_offsets[MLXSW_BLOOM_KEY_CHUNKS] = …; static u16 mlxsw_sp2_acl_bf_crc16_byte(u16 crc, u8 c) { … } static u16 mlxsw_sp2_acl_bf_crc(const u8 *buffer, size_t len) { … } static void __mlxsw_sp_acl_bf_key_encode(struct mlxsw_sp_acl_atcam_region *aregion, struct mlxsw_sp_acl_atcam_entry *aentry, char *output, u8 *len, u8 max_chunks, u8 pad_bytes, u8 key_offset, u8 chunk_key_len, u8 chunk_len) { … } static void mlxsw_sp2_acl_bf_key_encode(struct mlxsw_sp_acl_atcam_region *aregion, struct mlxsw_sp_acl_atcam_entry *aentry, char *output, u8 *len) { … } static unsigned int mlxsw_sp2_acl_bf_index_get(struct mlxsw_sp_acl_bf *bf, struct mlxsw_sp_acl_atcam_region *aregion, struct mlxsw_sp_acl_atcam_entry *aentry) { … } static u16 mlxsw_sp4_acl_bf_crc10_byte(u16 crc, u8 c) { … } static u16 mlxsw_sp4_acl_bf_crc6_byte(u16 crc, u8 c) { … } static u16 mlxsw_sp4_acl_bf_crc(const u8 *buffer, size_t len) { … } static void right_shift_array(char *arr, u8 len, u8 shift_bits) { … } static void mlxsw_sp4_bf_key_shift_chunks(u8 chunk_count, char *output) { … } static void mlxsw_sp4_acl_bf_key_encode(struct mlxsw_sp_acl_atcam_region *aregion, struct mlxsw_sp_acl_atcam_entry *aentry, char *output, u8 *len) { … } static unsigned int mlxsw_sp4_acl_bf_index_get(struct mlxsw_sp_acl_bf *bf, struct mlxsw_sp_acl_atcam_region *aregion, struct mlxsw_sp_acl_atcam_entry *aentry) { … } static unsigned int mlxsw_sp_acl_bf_rule_count_index_get(struct mlxsw_sp_acl_bf *bf, unsigned int erp_bank, unsigned int bf_index) { … } int mlxsw_sp_acl_bf_entry_add(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_bf *bf, struct mlxsw_sp_acl_atcam_region *aregion, unsigned int erp_bank, struct mlxsw_sp_acl_atcam_entry *aentry) { … } void mlxsw_sp_acl_bf_entry_del(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_bf *bf, struct mlxsw_sp_acl_atcam_region *aregion, unsigned int erp_bank, struct mlxsw_sp_acl_atcam_entry *aentry) { … } struct mlxsw_sp_acl_bf * mlxsw_sp_acl_bf_init(struct mlxsw_sp *mlxsw_sp, unsigned int num_erp_banks) { … } void mlxsw_sp_acl_bf_fini(struct mlxsw_sp_acl_bf *bf) { … } const struct mlxsw_sp_acl_bf_ops mlxsw_sp2_acl_bf_ops = …; const struct mlxsw_sp_acl_bf_ops mlxsw_sp4_acl_bf_ops = …;