@@ -14,6 +14,213 @@ struct mlxsw_sp_acl_bf {
1414 refcount_t refcnt [0 ];
1515};
1616
17+ /* Bloom filter uses a crc-16 hash over chunks of data which contain 4 key
18+ * blocks, eRP ID and region ID. In Spectrum-2, region key is combined of up to
19+ * 12 key blocks, so there can be up to 3 chunks in the Bloom filter key,
20+ * depending on the actual number of key blocks used in the region.
21+ * The layout of the Bloom filter key is as follows:
22+ *
23+ * +-------------------------+------------------------+------------------------+
24+ * | Chunk 2 Key blocks 11-8 | Chunk 1 Key blocks 7-4 | Chunk 0 Key blocks 3-0 |
25+ * +-------------------------+------------------------+------------------------+
26+ */
27+ #define MLXSW_BLOOM_KEY_CHUNKS 3
28+ #define MLXSW_BLOOM_KEY_LEN 69
29+
30+ /* Each chunk size is 23 bytes. 18 bytes of it contain 4 key blocks, each is
31+ * 36 bits, 2 bytes which hold eRP ID and region ID, and 3 bytes of zero
32+ * padding.
33+ * The layout of each chunk is as follows:
34+ *
35+ * +---------+----------------------+-----------------------------------+
36+ * | 3 bytes | 2 bytes | 18 bytes |
37+ * +---------+-----------+----------+-----------------------------------+
38+ * | 183:158 | 157:148 | 147:144 | 143:0 |
39+ * +---------+-----------+----------+-----------------------------------+
40+ * | 0 | region ID | eRP ID | 4 Key blocks (18 Bytes) |
41+ * +---------+-----------+----------+-----------------------------------+
42+ */
43+ #define MLXSW_BLOOM_CHUNK_PAD_BYTES 3
44+ #define MLXSW_BLOOM_CHUNK_KEY_BYTES 18
45+ #define MLXSW_BLOOM_KEY_CHUNK_BYTES 23
46+
47+ /* The offset of the key block within a chunk is 5 bytes as it comes after
48+ * 3 bytes of zero padding and 16 bits of region ID and eRP ID.
49+ */
50+ #define MLXSW_BLOOM_CHUNK_KEY_OFFSET 5
51+
52+ /* Each chunk contains 4 key blocks. Chunk 2 uses key blocks 11-8,
53+ * and we need to populate it with 4 key blocks copied from the entry encoded
54+ * key. Since the encoded key contains a padding, key block 11 starts at offset
55+ * 2. block 7 that is used in chunk 1 starts at offset 20 as 4 key blocks take
56+ * 18 bytes.
57+ * This array defines key offsets for easy access when copying key blocks from
58+ * entry key to Bloom filter chunk.
59+ */
60+ static const u8 chunk_key_offsets [MLXSW_BLOOM_KEY_CHUNKS ] = {2 , 20 , 38 };
61+
62+ /* This table is just the CRC of each possible byte. It is
63+ * computed, Msbit first, for the Bloom filter polynomial
64+ * which is 0x8529 (1 + x^3 + x^5 + x^8 + x^10 + x^15 and
65+ * the implicit x^16).
66+ */
67+ static const u16 mlxsw_sp_acl_bf_crc_tab [256 ] = {
68+ 0x0000 , 0x8529 , 0x8f7b , 0x0a52 , 0x9bdf , 0x1ef6 , 0x14a4 , 0x918d ,
69+ 0xb297 , 0x37be , 0x3dec , 0xb8c5 , 0x2948 , 0xac61 , 0xa633 , 0x231a ,
70+ 0xe007 , 0x652e , 0x6f7c , 0xea55 , 0x7bd8 , 0xfef1 , 0xf4a3 , 0x718a ,
71+ 0x5290 , 0xd7b9 , 0xddeb , 0x58c2 , 0xc94f , 0x4c66 , 0x4634 , 0xc31d ,
72+ 0x4527 , 0xc00e , 0xca5c , 0x4f75 , 0xdef8 , 0x5bd1 , 0x5183 , 0xd4aa ,
73+ 0xf7b0 , 0x7299 , 0x78cb , 0xfde2 , 0x6c6f , 0xe946 , 0xe314 , 0x663d ,
74+ 0xa520 , 0x2009 , 0x2a5b , 0xaf72 , 0x3eff , 0xbbd6 , 0xb184 , 0x34ad ,
75+ 0x17b7 , 0x929e , 0x98cc , 0x1de5 , 0x8c68 , 0x0941 , 0x0313 , 0x863a ,
76+ 0x8a4e , 0x0f67 , 0x0535 , 0x801c , 0x1191 , 0x94b8 , 0x9eea , 0x1bc3 ,
77+ 0x38d9 , 0xbdf0 , 0xb7a2 , 0x328b , 0xa306 , 0x262f , 0x2c7d , 0xa954 ,
78+ 0x6a49 , 0xef60 , 0xe532 , 0x601b , 0xf196 , 0x74bf , 0x7eed , 0xfbc4 ,
79+ 0xd8de , 0x5df7 , 0x57a5 , 0xd28c , 0x4301 , 0xc628 , 0xcc7a , 0x4953 ,
80+ 0xcf69 , 0x4a40 , 0x4012 , 0xc53b , 0x54b6 , 0xd19f , 0xdbcd , 0x5ee4 ,
81+ 0x7dfe , 0xf8d7 , 0xf285 , 0x77ac , 0xe621 , 0x6308 , 0x695a , 0xec73 ,
82+ 0x2f6e , 0xaa47 , 0xa015 , 0x253c , 0xb4b1 , 0x3198 , 0x3bca , 0xbee3 ,
83+ 0x9df9 , 0x18d0 , 0x1282 , 0x97ab , 0x0626 , 0x830f , 0x895d , 0x0c74 ,
84+ 0x91b5 , 0x149c , 0x1ece , 0x9be7 , 0x0a6a , 0x8f43 , 0x8511 , 0x0038 ,
85+ 0x2322 , 0xa60b , 0xac59 , 0x2970 , 0xb8fd , 0x3dd4 , 0x3786 , 0xb2af ,
86+ 0x71b2 , 0xf49b , 0xfec9 , 0x7be0 , 0xea6d , 0x6f44 , 0x6516 , 0xe03f ,
87+ 0xc325 , 0x460c , 0x4c5e , 0xc977 , 0x58fa , 0xddd3 , 0xd781 , 0x52a8 ,
88+ 0xd492 , 0x51bb , 0x5be9 , 0xdec0 , 0x4f4d , 0xca64 , 0xc036 , 0x451f ,
89+ 0x6605 , 0xe32c , 0xe97e , 0x6c57 , 0xfdda , 0x78f3 , 0x72a1 , 0xf788 ,
90+ 0x3495 , 0xb1bc , 0xbbee , 0x3ec7 , 0xaf4a , 0x2a63 , 0x2031 , 0xa518 ,
91+ 0x8602 , 0x032b , 0x0979 , 0x8c50 , 0x1ddd , 0x98f4 , 0x92a6 , 0x178f ,
92+ 0x1bfb , 0x9ed2 , 0x9480 , 0x11a9 , 0x8024 , 0x050d , 0x0f5f , 0x8a76 ,
93+ 0xa96c , 0x2c45 , 0x2617 , 0xa33e , 0x32b3 , 0xb79a , 0xbdc8 , 0x38e1 ,
94+ 0xfbfc , 0x7ed5 , 0x7487 , 0xf1ae , 0x6023 , 0xe50a , 0xef58 , 0x6a71 ,
95+ 0x496b , 0xcc42 , 0xc610 , 0x4339 , 0xd2b4 , 0x579d , 0x5dcf , 0xd8e6 ,
96+ 0x5edc , 0xdbf5 , 0xd1a7 , 0x548e , 0xc503 , 0x402a , 0x4a78 , 0xcf51 ,
97+ 0xec4b , 0x6962 , 0x6330 , 0xe619 , 0x7794 , 0xf2bd , 0xf8ef , 0x7dc6 ,
98+ 0xbedb , 0x3bf2 , 0x31a0 , 0xb489 , 0x2504 , 0xa02d , 0xaa7f , 0x2f56 ,
99+ 0x0c4c , 0x8965 , 0x8337 , 0x061e , 0x9793 , 0x12ba , 0x18e8 , 0x9dc1 ,
100+ };
101+
102+ static u16 mlxsw_sp_acl_bf_crc_byte (u16 crc , u8 c )
103+ {
104+ return (crc << 8 ) ^ mlxsw_sp_acl_bf_crc_tab [(crc >> 8 ) ^ c ];
105+ }
106+
107+ static u16 mlxsw_sp_acl_bf_crc (const u8 * buffer , size_t len )
108+ {
109+ u16 crc = 0 ;
110+
111+ while (len -- )
112+ crc = mlxsw_sp_acl_bf_crc_byte (crc , * buffer ++ );
113+ return crc ;
114+ }
115+
116+ static void
117+ mlxsw_sp_acl_bf_key_encode (struct mlxsw_sp_acl_atcam_region * aregion ,
118+ struct mlxsw_sp_acl_atcam_entry * aentry ,
119+ char * output , u8 * len )
120+ {
121+ struct mlxsw_afk_key_info * key_info = aregion -> region -> key_info ;
122+ u8 chunk_index , chunk_count , block_count ;
123+ char * chunk = output ;
124+ __be16 erp_region_id ;
125+
126+ block_count = mlxsw_afk_key_info_blocks_count_get (key_info );
127+ chunk_count = 1 + ((block_count - 1 ) >> 2 );
128+ erp_region_id = cpu_to_be16 (aentry -> ht_key .erp_id |
129+ (aregion -> region -> id << 4 ));
130+ for (chunk_index = MLXSW_BLOOM_KEY_CHUNKS - chunk_count ;
131+ chunk_index < MLXSW_BLOOM_KEY_CHUNKS ; chunk_index ++ ) {
132+ memset (chunk , 0 , MLXSW_BLOOM_CHUNK_PAD_BYTES );
133+ memcpy (chunk + MLXSW_BLOOM_CHUNK_PAD_BYTES , & erp_region_id ,
134+ sizeof (erp_region_id ));
135+ memcpy (chunk + MLXSW_BLOOM_CHUNK_KEY_OFFSET ,
136+ & aentry -> ht_key .enc_key [chunk_key_offsets [chunk_index ]],
137+ MLXSW_BLOOM_CHUNK_KEY_BYTES );
138+ chunk += MLXSW_BLOOM_KEY_CHUNK_BYTES ;
139+ }
140+ * len = chunk_count * MLXSW_BLOOM_KEY_CHUNK_BYTES ;
141+ }
142+
143+ static unsigned int
144+ mlxsw_sp_acl_bf_rule_count_index_get (struct mlxsw_sp_acl_bf * bf ,
145+ unsigned int erp_bank ,
146+ unsigned int bf_index )
147+ {
148+ return erp_bank * bf -> bank_size + bf_index ;
149+ }
150+
151+ static unsigned int
152+ mlxsw_sp_acl_bf_index_get (struct mlxsw_sp_acl_bf * bf ,
153+ struct mlxsw_sp_acl_atcam_region * aregion ,
154+ struct mlxsw_sp_acl_atcam_entry * aentry )
155+ {
156+ char bf_key [MLXSW_BLOOM_KEY_LEN ];
157+ u8 bf_size ;
158+
159+ mlxsw_sp_acl_bf_key_encode (aregion , aentry , bf_key , & bf_size );
160+ return mlxsw_sp_acl_bf_crc (bf_key , bf_size );
161+ }
162+
163+ int
164+ mlxsw_sp_acl_bf_entry_add (struct mlxsw_sp * mlxsw_sp ,
165+ struct mlxsw_sp_acl_bf * bf ,
166+ struct mlxsw_sp_acl_atcam_region * aregion ,
167+ unsigned int erp_bank ,
168+ struct mlxsw_sp_acl_atcam_entry * aentry )
169+ {
170+ unsigned int rule_index ;
171+ char * peabfe_pl ;
172+ u16 bf_index ;
173+ int err ;
174+
175+ bf_index = mlxsw_sp_acl_bf_index_get (bf , aregion , aentry );
176+ rule_index = mlxsw_sp_acl_bf_rule_count_index_get (bf , erp_bank ,
177+ bf_index );
178+
179+ if (refcount_inc_not_zero (& bf -> refcnt [rule_index ]))
180+ return 0 ;
181+
182+ peabfe_pl = kmalloc (MLXSW_REG_PEABFE_LEN , GFP_KERNEL );
183+ if (!peabfe_pl )
184+ return - ENOMEM ;
185+
186+ mlxsw_reg_peabfe_pack (peabfe_pl );
187+ mlxsw_reg_peabfe_rec_pack (peabfe_pl , 0 , 1 , erp_bank , bf_index );
188+ err = mlxsw_reg_write (mlxsw_sp -> core , MLXSW_REG (peabfe ), peabfe_pl );
189+ kfree (peabfe_pl );
190+ if (err )
191+ return err ;
192+
193+ refcount_set (& bf -> refcnt [rule_index ], 1 );
194+ return 0 ;
195+ }
196+
197+ void
198+ mlxsw_sp_acl_bf_entry_del (struct mlxsw_sp * mlxsw_sp ,
199+ struct mlxsw_sp_acl_bf * bf ,
200+ struct mlxsw_sp_acl_atcam_region * aregion ,
201+ unsigned int erp_bank ,
202+ struct mlxsw_sp_acl_atcam_entry * aentry )
203+ {
204+ unsigned int rule_index ;
205+ char * peabfe_pl ;
206+ u16 bf_index ;
207+
208+ bf_index = mlxsw_sp_acl_bf_index_get (bf , aregion , aentry );
209+ rule_index = mlxsw_sp_acl_bf_rule_count_index_get (bf , erp_bank ,
210+ bf_index );
211+
212+ if (refcount_dec_and_test (& bf -> refcnt [rule_index ])) {
213+ peabfe_pl = kmalloc (MLXSW_REG_PEABFE_LEN , GFP_KERNEL );
214+ if (!peabfe_pl )
215+ return ;
216+
217+ mlxsw_reg_peabfe_pack (peabfe_pl );
218+ mlxsw_reg_peabfe_rec_pack (peabfe_pl , 0 , 0 , erp_bank , bf_index );
219+ mlxsw_reg_write (mlxsw_sp -> core , MLXSW_REG (peabfe ), peabfe_pl );
220+ kfree (peabfe_pl );
221+ }
222+ }
223+
17224struct mlxsw_sp_acl_bf *
18225mlxsw_sp_acl_bf_init (struct mlxsw_sp * mlxsw_sp , unsigned int num_erp_banks )
19226{
0 commit comments