Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2020 Intel Corporation
3 : : */
4 : : #include <string.h>
5 : : #include <stdio.h>
6 : : #include <errno.h>
7 : :
8 : : #include <eal_export.h>
9 : : #include <rte_common.h>
10 : : #include <rte_prefetch.h>
11 : : #include <rte_jhash.h>
12 : : #include <rte_hash_crc.h>
13 : :
14 : : #include "rte_swx_keycmp.h"
15 : : #include "rte_swx_table_em.h"
16 : :
17 : : #define CHECK(condition, err_code) \
18 : : do { \
19 : : if (!(condition)) \
20 : : return -(err_code); \
21 : : } while (0)
22 : :
23 : : #ifndef RTE_SWX_TABLE_EM_USE_HUGE_PAGES
24 : : #define RTE_SWX_TABLE_EM_USE_HUGE_PAGES 1
25 : : #endif
26 : :
27 : : #if RTE_SWX_TABLE_EM_USE_HUGE_PAGES
28 : :
29 : : #include <rte_malloc.h>
30 : :
31 : : static void *
32 : : env_malloc(size_t size, size_t alignment, int numa_node)
33 : : {
34 : 0 : return rte_zmalloc_socket(NULL, size, alignment, numa_node);
35 : : }
36 : :
37 : : static void
38 : : env_free(void *start, size_t size __rte_unused)
39 : : {
40 : 0 : rte_free(start);
41 : 0 : }
42 : :
43 : : #else
44 : :
45 : : #include <numa.h>
46 : :
47 : : static void *
48 : : env_malloc(size_t size, size_t alignment __rte_unused, int numa_node)
49 : : {
50 : : return numa_alloc_onnode(size, numa_node);
51 : : }
52 : :
53 : : static void
54 : : env_free(void *start, size_t size)
55 : : {
56 : : numa_free(start, size);
57 : : }
58 : :
59 : : #endif
60 : :
61 : : static void
62 : : keycpy(void *dst, void *src, uint32_t n_bytes)
63 : : {
64 : 0 : memcpy(dst, src, n_bytes);
65 : : }
66 : :
67 : : #define KEYS_PER_BUCKET 4
68 : :
69 : : struct bucket_extension {
70 : : struct bucket_extension *next;
71 : : uint16_t sig[KEYS_PER_BUCKET];
72 : : uint32_t key_id[KEYS_PER_BUCKET];
73 : : };
74 : :
75 : : struct table {
76 : : /* Input parameters */
77 : : struct rte_swx_table_params params;
78 : :
79 : : /* Internal. */
80 : : uint32_t key_size_shl;
81 : : uint32_t data_size_shl;
82 : : uint32_t n_buckets;
83 : : uint32_t n_buckets_ext;
84 : : uint32_t key_stack_tos;
85 : : uint32_t bkt_ext_stack_tos;
86 : : uint64_t total_size;
87 : : rte_swx_keycmp_func_t keycmp_func;
88 : :
89 : : /* Memory arrays. */
90 : : struct bucket_extension *buckets;
91 : : struct bucket_extension *buckets_ext;
92 : : uint8_t *keys;
93 : : uint32_t *key_stack;
94 : : uint32_t *bkt_ext_stack;
95 : : uint8_t *data;
96 : : };
97 : :
98 : : static inline uint8_t *
99 : : table_key(struct table *t, uint32_t key_id)
100 : : {
101 : 0 : return &t->keys[(uint64_t)key_id << t->key_size_shl];
102 : : }
103 : :
104 : : static inline uint64_t *
105 : : table_key_data(struct table *t, uint32_t key_id)
106 : : {
107 : 0 : return (uint64_t *)&t->data[(uint64_t)key_id << t->data_size_shl];
108 : : }
109 : :
110 : : static inline int
111 : : bkt_is_empty(struct bucket_extension *bkt)
112 : : {
113 : 0 : return (!bkt->sig[0] && !bkt->sig[1] && !bkt->sig[2] && !bkt->sig[3]) ? 1 : 0;
114 : : }
115 : :
116 : : /* Return:
117 : : * 0 = Bucket key position is NOT empty;
118 : : * 1 = Bucket key position is empty.
119 : : */
120 : : static inline int
121 : : bkt_key_is_empty(struct bucket_extension *bkt, uint32_t bkt_pos)
122 : : {
123 : 0 : return bkt->sig[bkt_pos] ? 0 : 1;
124 : : }
125 : :
126 : : /* Return: 0 = Keys are NOT equal; 1 = Keys are equal. */
127 : : static inline int
128 : : bkt_keycmp(struct table *t,
129 : : struct bucket_extension *bkt,
130 : : uint8_t *input_key,
131 : : uint32_t bkt_pos,
132 : : uint32_t input_sig)
133 : : {
134 : : uint32_t bkt_key_id;
135 : : uint8_t *bkt_key;
136 : :
137 : : /* Key signature comparison. */
138 [ # # ]: 0 : if (input_sig != bkt->sig[bkt_pos])
139 : : return 0;
140 : :
141 : : /* Key comparison. */
142 : 0 : bkt_key_id = bkt->key_id[bkt_pos];
143 : : bkt_key = table_key(t, bkt_key_id);
144 : 0 : return t->keycmp_func(bkt_key, input_key, t->params.key_size);
145 : : }
146 : :
147 : : static inline void
148 : 0 : bkt_key_install(struct table *t,
149 : : struct bucket_extension *bkt,
150 : : struct rte_swx_table_entry *input,
151 : : uint32_t bkt_pos,
152 : : uint32_t bkt_key_id,
153 : : uint32_t input_sig)
154 : : {
155 : : uint8_t *bkt_key;
156 : : uint64_t *bkt_data;
157 : :
158 : : /* Key signature. */
159 : 0 : bkt->sig[bkt_pos] = (uint16_t)input_sig;
160 : :
161 : : /* Key. */
162 : 0 : bkt->key_id[bkt_pos] = bkt_key_id;
163 : : bkt_key = table_key(t, bkt_key_id);
164 [ # # ]: 0 : keycpy(bkt_key, input->key, t->params.key_size);
165 : :
166 : : /* Key data. */
167 : : bkt_data = table_key_data(t, bkt_key_id);
168 : 0 : bkt_data[0] = input->action_id;
169 [ # # # # ]: 0 : if (t->params.action_data_size && input->action_data)
170 : 0 : memcpy(&bkt_data[1], input->action_data, t->params.action_data_size);
171 : 0 : }
172 : :
173 : : static inline void
174 : 0 : bkt_key_data_update(struct table *t,
175 : : struct bucket_extension *bkt,
176 : : struct rte_swx_table_entry *input,
177 : : uint32_t bkt_pos)
178 : : {
179 : : uint32_t bkt_key_id;
180 : : uint64_t *bkt_data;
181 : :
182 : : /* Key. */
183 : 0 : bkt_key_id = bkt->key_id[bkt_pos];
184 : :
185 : : /* Key data. */
186 : : bkt_data = table_key_data(t, bkt_key_id);
187 : 0 : bkt_data[0] = input->action_id;
188 [ # # # # ]: 0 : if (t->params.action_data_size && input->action_data)
189 : 0 : memcpy(&bkt_data[1], input->action_data, t->params.action_data_size);
190 : 0 : }
191 : :
192 : : #define CL RTE_CACHE_LINE_ROUNDUP
193 : :
194 : : static int
195 : 0 : __table_create(struct table **table,
196 : : uint64_t *memory_footprint,
197 : : struct rte_swx_table_params *params,
198 : : const char *args __rte_unused,
199 : : int numa_node)
200 : : {
201 : : struct table *t;
202 : : uint8_t *memory;
203 : : size_t table_meta_sz, bucket_sz, bucket_ext_sz, key_sz,
204 : : key_stack_sz, bkt_ext_stack_sz, data_sz, total_size;
205 : : size_t bucket_offset, bucket_ext_offset, key_offset,
206 : : key_stack_offset, bkt_ext_stack_offset, data_offset;
207 : : uint32_t key_size, key_data_size, n_buckets, n_buckets_ext, i;
208 : :
209 : : /* Check input arguments. */
210 [ # # ]: 0 : CHECK(params, EINVAL);
211 [ # # ]: 0 : CHECK(params->match_type == RTE_SWX_TABLE_MATCH_EXACT, EINVAL);
212 [ # # ]: 0 : CHECK(params->key_size, EINVAL);
213 : :
214 [ # # ]: 0 : if (params->key_mask0) {
215 [ # # ]: 0 : for (i = 0; i < params->key_size; i++)
216 [ # # ]: 0 : if (params->key_mask0[i] != 0xFF)
217 : : break;
218 : :
219 [ # # ]: 0 : CHECK(i == params->key_size, EINVAL);
220 : : }
221 : :
222 [ # # ]: 0 : CHECK(params->n_keys_max, EINVAL);
223 : :
224 : : /* Memory allocation. */
225 [ # # ]: 0 : key_size = rte_align64pow2(params->key_size);
226 : 0 : key_data_size = rte_align64pow2(params->action_data_size + 8);
227 : 0 : n_buckets = rte_align64pow2((params->n_keys_max + KEYS_PER_BUCKET - 1) / KEYS_PER_BUCKET);
228 : : n_buckets_ext = n_buckets;
229 : :
230 : : table_meta_sz = CL(sizeof(struct table));
231 : 0 : bucket_sz = CL(n_buckets * sizeof(struct bucket_extension));
232 : : bucket_ext_sz = CL(n_buckets_ext * sizeof(struct bucket_extension));
233 : 0 : key_sz = CL(params->n_keys_max * key_size);
234 : 0 : key_stack_sz = CL(params->n_keys_max * sizeof(uint32_t));
235 : 0 : bkt_ext_stack_sz = CL(n_buckets_ext * sizeof(uint32_t));
236 : 0 : data_sz = CL(params->n_keys_max * key_data_size);
237 : 0 : total_size = table_meta_sz + bucket_sz + bucket_ext_sz +
238 : 0 : key_sz + key_stack_sz + bkt_ext_stack_sz + data_sz;
239 : :
240 : : bucket_offset = table_meta_sz;
241 : : bucket_ext_offset = bucket_offset + bucket_sz;
242 : : key_offset = bucket_ext_offset + bucket_ext_sz;
243 : : key_stack_offset = key_offset + key_sz;
244 : : bkt_ext_stack_offset = key_stack_offset + key_stack_sz;
245 : : data_offset = bkt_ext_stack_offset + bkt_ext_stack_sz;
246 : :
247 [ # # ]: 0 : if (!table) {
248 [ # # ]: 0 : if (memory_footprint)
249 : 0 : *memory_footprint = total_size;
250 : 0 : return 0;
251 : : }
252 : :
253 : : memory = env_malloc(total_size, RTE_CACHE_LINE_SIZE, numa_node);
254 [ # # ]: 0 : CHECK(memory, ENOMEM);
255 : : memset(memory, 0, total_size);
256 : :
257 : : /* Initialization. */
258 : : t = (struct table *)memory;
259 [ # # ]: 0 : memcpy(&t->params, params, sizeof(*params));
260 : 0 : t->params.key_mask0 = NULL;
261 [ # # ]: 0 : if (!params->hash_func)
262 : 0 : t->params.hash_func = rte_hash_crc;
263 : :
264 : 0 : t->key_size_shl = rte_ctz32(key_size);
265 : 0 : t->data_size_shl = rte_ctz32(key_data_size);
266 : 0 : t->n_buckets = n_buckets;
267 : 0 : t->n_buckets_ext = n_buckets_ext;
268 : 0 : t->total_size = total_size;
269 : 0 : t->keycmp_func = rte_swx_keycmp_func_get(params->key_size);
270 : :
271 : 0 : t->buckets = (struct bucket_extension *)&memory[bucket_offset];
272 : 0 : t->buckets_ext = (struct bucket_extension *)&memory[bucket_ext_offset];
273 : 0 : t->keys = &memory[key_offset];
274 : 0 : t->key_stack = (uint32_t *)&memory[key_stack_offset];
275 : 0 : t->bkt_ext_stack = (uint32_t *)&memory[bkt_ext_stack_offset];
276 : 0 : t->data = &memory[data_offset];
277 : :
278 [ # # ]: 0 : for (i = 0; i < t->params.n_keys_max; i++)
279 : 0 : t->key_stack[i] = t->params.n_keys_max - 1 - i;
280 : 0 : t->key_stack_tos = t->params.n_keys_max;
281 : :
282 [ # # ]: 0 : for (i = 0; i < n_buckets_ext; i++)
283 : 0 : t->bkt_ext_stack[i] = n_buckets_ext - 1 - i;
284 : 0 : t->bkt_ext_stack_tos = n_buckets_ext;
285 : :
286 : 0 : *table = t;
287 : 0 : return 0;
288 : : }
289 : :
290 : : static void
291 : 0 : table_free(void *table)
292 : : {
293 : : struct table *t = table;
294 : :
295 [ # # # # ]: 0 : if (!t)
296 : : return;
297 : :
298 : : env_free(t, t->total_size);
299 : : }
300 : :
301 : : static int
302 : 0 : table_add(void *table, struct rte_swx_table_entry *entry)
303 : : {
304 : : struct table *t = table;
305 : : struct bucket_extension *bkt0, *bkt, *bkt_prev;
306 : : uint32_t input_sig, bkt_id, i;
307 : :
308 [ # # ]: 0 : CHECK(t, EINVAL);
309 [ # # ]: 0 : CHECK(entry, EINVAL);
310 [ # # ]: 0 : CHECK(entry->key, EINVAL);
311 : :
312 : 0 : input_sig = t->params.hash_func(entry->key, t->params.key_size, 0);
313 : 0 : bkt_id = input_sig & (t->n_buckets - 1);
314 : 0 : bkt0 = &t->buckets[bkt_id];
315 : 0 : input_sig = (input_sig >> 16) | 1;
316 : :
317 : : /* Key is present in the bucket. */
318 [ # # ]: 0 : for (bkt = bkt0; bkt; bkt = bkt->next)
319 [ # # ]: 0 : for (i = 0; i < KEYS_PER_BUCKET; i++)
320 [ # # # # ]: 0 : if (bkt_keycmp(t, bkt, entry->key, i, input_sig)) {
321 : 0 : bkt_key_data_update(t, bkt, entry, i);
322 : 0 : return 0;
323 : : }
324 : :
325 : : /* Key is not present in the bucket. Bucket not full. */
326 [ # # ]: 0 : for (bkt = bkt0, bkt_prev = NULL; bkt; bkt_prev = bkt, bkt = bkt->next)
327 [ # # ]: 0 : for (i = 0; i < KEYS_PER_BUCKET; i++)
328 [ # # ]: 0 : if (bkt_key_is_empty(bkt, i)) {
329 : : uint32_t new_bkt_key_id;
330 : :
331 : : /* Allocate new key & install. */
332 [ # # ]: 0 : CHECK(t->key_stack_tos, ENOSPC);
333 : 0 : new_bkt_key_id = t->key_stack[--t->key_stack_tos];
334 : 0 : bkt_key_install(t, bkt, entry, i, new_bkt_key_id, input_sig);
335 : 0 : return 0;
336 : : }
337 : :
338 : : /* Bucket full: extend bucket. */
339 [ # # # # ]: 0 : if (t->bkt_ext_stack_tos && t->key_stack_tos) {
340 : : struct bucket_extension *new_bkt;
341 : : uint32_t new_bkt_id, new_bkt_key_id;
342 : :
343 : : /* Allocate new bucket extension & install. */
344 : 0 : new_bkt_id = t->bkt_ext_stack[--t->bkt_ext_stack_tos];
345 : 0 : new_bkt = &t->buckets_ext[new_bkt_id];
346 : : memset(new_bkt, 0, sizeof(*new_bkt));
347 : 0 : bkt_prev->next = new_bkt;
348 : :
349 : : /* Allocate new key & install. */
350 : 0 : new_bkt_key_id = t->key_stack[--t->key_stack_tos];
351 : 0 : bkt_key_install(t, new_bkt, entry, 0, new_bkt_key_id, input_sig);
352 : 0 : return 0;
353 : : }
354 : :
355 : : CHECK(0, ENOSPC);
356 : : }
357 : :
358 : : static int
359 : 0 : table_del(void *table, struct rte_swx_table_entry *entry)
360 : : {
361 : : struct table *t = table;
362 : : struct bucket_extension *bkt0, *bkt, *bkt_prev;
363 : : uint32_t input_sig, bkt_id, i;
364 : :
365 [ # # ]: 0 : CHECK(t, EINVAL);
366 [ # # ]: 0 : CHECK(entry, EINVAL);
367 [ # # ]: 0 : CHECK(entry->key, EINVAL);
368 : :
369 : 0 : input_sig = t->params.hash_func(entry->key, t->params.key_size, 0);
370 : 0 : bkt_id = input_sig & (t->n_buckets - 1);
371 : 0 : bkt0 = &t->buckets[bkt_id];
372 : 0 : input_sig = (input_sig >> 16) | 1;
373 : :
374 : : /* Key is present in the bucket. */
375 [ # # ]: 0 : for (bkt = bkt0, bkt_prev = NULL; bkt; bkt_prev = bkt, bkt = bkt->next)
376 [ # # ]: 0 : for (i = 0; i < KEYS_PER_BUCKET; i++)
377 [ # # # # ]: 0 : if (bkt_keycmp(t, bkt, entry->key, i, input_sig)) {
378 : : /* Key free. */
379 : 0 : bkt->sig[i] = 0;
380 : 0 : t->key_stack[t->key_stack_tos++] = bkt->key_id[i];
381 : :
382 : : /* Bucket extension free if empty and not the 1st in bucket. */
383 [ # # # # ]: 0 : if (bkt_prev && bkt_is_empty(bkt)) {
384 : 0 : bkt_prev->next = bkt->next;
385 : 0 : bkt_id = bkt - t->buckets_ext;
386 : 0 : t->bkt_ext_stack[t->bkt_ext_stack_tos++] = bkt_id;
387 : : }
388 : :
389 : 0 : return 0;
390 : : }
391 : :
392 : : return 0;
393 : : }
394 : :
395 : : static uint64_t
396 : 0 : table_mailbox_size_get_unoptimized(void)
397 : : {
398 : 0 : return 0;
399 : : }
400 : :
401 : : static int
402 : 0 : table_lookup_unoptimized(void *table,
403 : : void *mailbox __rte_unused,
404 : : uint8_t **key,
405 : : uint64_t *action_id,
406 : : uint8_t **action_data,
407 : : size_t *entry_id,
408 : : int *hit)
409 : : {
410 : : struct table *t = table;
411 : : struct bucket_extension *bkt0, *bkt;
412 : : uint8_t *input_key;
413 : : uint32_t input_sig, bkt_id, i;
414 : :
415 : 0 : input_key = &(*key)[t->params.key_offset];
416 : :
417 : 0 : input_sig = t->params.hash_func(input_key, t->params.key_size, 0);
418 : 0 : bkt_id = input_sig & (t->n_buckets - 1);
419 : 0 : bkt0 = &t->buckets[bkt_id];
420 : 0 : input_sig = (input_sig >> 16) | 1;
421 : :
422 : : /* Key is present in the bucket. */
423 [ # # ]: 0 : for (bkt = bkt0; bkt; bkt = bkt->next)
424 [ # # ]: 0 : for (i = 0; i < KEYS_PER_BUCKET; i++)
425 [ # # ]: 0 : if (bkt_keycmp(t, bkt, input_key, i, input_sig)) {
426 : : uint32_t bkt_key_id;
427 : : uint64_t *bkt_data;
428 : :
429 : : /* Key. */
430 : 0 : bkt_key_id = bkt->key_id[i];
431 : :
432 : : /* Key data. */
433 : : bkt_data = table_key_data(t, bkt_key_id);
434 : 0 : *action_id = bkt_data[0];
435 : 0 : *action_data = (uint8_t *)&bkt_data[1];
436 : 0 : *entry_id = bkt_key_id;
437 : 0 : *hit = 1;
438 : 0 : return 1;
439 : : }
440 : :
441 : 0 : *hit = 0;
442 : 0 : return 1;
443 : : }
444 : :
445 : : struct mailbox {
446 : : struct bucket_extension *bkt;
447 : : uint32_t input_sig;
448 : : uint32_t bkt_key_id;
449 : : uint32_t sig_match;
450 : : uint32_t sig_match_many;
451 : : int state;
452 : : };
453 : :
454 : : static uint64_t
455 : 0 : table_mailbox_size_get(void)
456 : : {
457 : 0 : return sizeof(struct mailbox);
458 : : }
459 : :
460 : : /*
461 : : * mask = match bitmask
462 : : * match = at least one match
463 : : * match_many = more than one match
464 : : * match_pos = position of first match
465 : : *
466 : : *+------+-------+------------+-----------+
467 : : *| mask | match | match_many | match_pos |
468 : : *+------+-------+------------+-----------+
469 : : *| 0000 | 0 | 0 | 00 |
470 : : *| 0001 | 1 | 0 | 00 |
471 : : *| 0010 | 1 | 0 | 01 |
472 : : *| 0011 | 1 | 1 | 00 |
473 : : *+------+-------+------------+-----------+
474 : : *| 0100 | 1 | 0 | 10 |
475 : : *| 0101 | 1 | 1 | 00 |
476 : : *| 0110 | 1 | 1 | 01 |
477 : : *| 0111 | 1 | 1 | 00 |
478 : : *+------+-------+------------+-----------+
479 : : *| 1000 | 1 | 0 | 11 |
480 : : *| 1001 | 1 | 1 | 00 |
481 : : *| 1010 | 1 | 1 | 01 |
482 : : *| 1011 | 1 | 1 | 00 |
483 : : *+------+-------+------------+-----------+
484 : : *| 1100 | 1 | 1 | 10 |
485 : : *| 1101 | 1 | 1 | 00 |
486 : : *| 1110 | 1 | 1 | 01 |
487 : : *| 1111 | 1 | 1 | 00 |
488 : : *+------+-------+------------+-----------+
489 : : *
490 : : * match = 1111_1111_1111_1110 = 0xFFFE
491 : : * match_many = 1111_1110_1110_1000 = 0xFEE8
492 : : * match_pos = 0001_0010_0001_0011__0001_0010_0001_0000 = 0x12131210
493 : : */
494 : :
495 : : #define LUT_MATCH 0xFFFE
496 : : #define LUT_MATCH_MANY 0xFEE8
497 : : #define LUT_MATCH_POS 0x12131210
498 : :
499 : : static int
500 : 0 : table_lookup(void *table,
501 : : void *mailbox,
502 : : uint8_t **key,
503 : : uint64_t *action_id,
504 : : uint8_t **action_data,
505 : : size_t *entry_id,
506 : : int *hit)
507 : : {
508 : : struct table *t = table;
509 : : struct mailbox *m = mailbox;
510 : :
511 [ # # # # ]: 0 : switch (m->state) {
512 : 0 : case 0: {
513 : 0 : uint8_t *input_key = &(*key)[t->params.key_offset];
514 : : struct bucket_extension *bkt;
515 : : uint32_t input_sig, bkt_id;
516 : :
517 : 0 : input_sig = t->params.hash_func(input_key, t->params.key_size, 0);
518 : 0 : bkt_id = input_sig & (t->n_buckets - 1);
519 : 0 : bkt = &t->buckets[bkt_id];
520 : : rte_prefetch0(bkt);
521 : :
522 : 0 : m->bkt = bkt;
523 : 0 : m->input_sig = (input_sig >> 16) | 1;
524 : 0 : m->state++;
525 : 0 : return 0;
526 : : }
527 : :
528 : 0 : case 1: {
529 : 0 : struct bucket_extension *bkt = m->bkt;
530 : 0 : uint32_t input_sig = m->input_sig;
531 : : uint32_t bkt_sig0, bkt_sig1, bkt_sig2, bkt_sig3;
532 : : uint32_t mask0 = 0, mask1 = 0, mask2 = 0, mask3 = 0, mask_all;
533 : : uint32_t sig_match = LUT_MATCH;
534 : : uint32_t sig_match_many = LUT_MATCH_MANY;
535 : : uint32_t sig_match_pos = LUT_MATCH_POS;
536 : : uint32_t bkt_key_id;
537 : :
538 : 0 : bkt_sig0 = input_sig ^ bkt->sig[0];
539 [ # # ]: 0 : if (!bkt_sig0)
540 : : mask0 = 1 << 0;
541 : :
542 : 0 : bkt_sig1 = input_sig ^ bkt->sig[1];
543 [ # # ]: 0 : if (!bkt_sig1)
544 : : mask1 = 1 << 1;
545 : :
546 : 0 : bkt_sig2 = input_sig ^ bkt->sig[2];
547 [ # # ]: 0 : if (!bkt_sig2)
548 : : mask2 = 1 << 2;
549 : :
550 : 0 : bkt_sig3 = input_sig ^ bkt->sig[3];
551 [ # # ]: 0 : if (!bkt_sig3)
552 : : mask3 = 1 << 3;
553 : :
554 : 0 : mask_all = (mask0 | mask1) | (mask2 | mask3);
555 : 0 : sig_match = (sig_match >> mask_all) & 1;
556 : 0 : sig_match_many = (sig_match_many >> mask_all) & 1;
557 : 0 : sig_match_pos = (sig_match_pos >> (mask_all << 1)) & 3;
558 : :
559 : 0 : bkt_key_id = bkt->key_id[sig_match_pos];
560 : : rte_prefetch0(table_key(t, bkt_key_id));
561 : : rte_prefetch0(table_key_data(t, bkt_key_id));
562 : :
563 : 0 : m->bkt_key_id = bkt_key_id;
564 : 0 : m->sig_match = sig_match;
565 : 0 : m->sig_match_many = sig_match_many;
566 : 0 : m->state++;
567 : 0 : return 0;
568 : : }
569 : :
570 : 0 : case 2: {
571 : 0 : uint8_t *input_key = &(*key)[t->params.key_offset];
572 : 0 : struct bucket_extension *bkt = m->bkt;
573 : 0 : uint32_t bkt_key_id = m->bkt_key_id;
574 : : uint8_t *bkt_key = table_key(t, bkt_key_id);
575 : : uint64_t *bkt_data = table_key_data(t, bkt_key_id);
576 : : uint32_t lkp_hit;
577 : :
578 : 0 : lkp_hit = t->keycmp_func(bkt_key, input_key, t->params.key_size);
579 : 0 : lkp_hit &= m->sig_match;
580 : 0 : *action_id = bkt_data[0];
581 : 0 : *action_data = (uint8_t *)&bkt_data[1];
582 : 0 : *entry_id = bkt_key_id;
583 : 0 : *hit = lkp_hit;
584 : :
585 : 0 : m->state = 0;
586 : :
587 [ # # # # : 0 : if (!lkp_hit && (m->sig_match_many || bkt->next))
# # ]
588 : 0 : return table_lookup_unoptimized(t,
589 : : m,
590 : : key,
591 : : action_id,
592 : : action_data,
593 : : entry_id,
594 : : hit);
595 : :
596 : : return 1;
597 : : }
598 : :
599 : : default:
600 : : return 0;
601 : : }
602 : : }
603 : :
604 : : static void *
605 : 0 : table_create(struct rte_swx_table_params *params,
606 : : struct rte_swx_table_entry_list *entries,
607 : : const char *args,
608 : : int numa_node)
609 : : {
610 : : struct table *t;
611 : : struct rte_swx_table_entry *entry;
612 : : int status;
613 : :
614 : : /* Table create. */
615 : 0 : status = __table_create(&t, NULL, params, args, numa_node);
616 [ # # ]: 0 : if (status)
617 : : return NULL;
618 : :
619 : : /* Table add entries. */
620 [ # # ]: 0 : if (!entries)
621 : 0 : return t;
622 : :
623 [ # # ]: 0 : TAILQ_FOREACH(entry, entries, node) {
624 : : int status;
625 : :
626 : 0 : status = table_add(t, entry);
627 [ # # ]: 0 : if (status) {
628 : : table_free(t);
629 : 0 : return NULL;
630 : : }
631 : : }
632 : :
633 : 0 : return t;
634 : : }
635 : :
636 : : static uint64_t
637 : 0 : table_footprint(struct rte_swx_table_params *params,
638 : : struct rte_swx_table_entry_list *entries __rte_unused,
639 : : const char *args)
640 : : {
641 : : uint64_t memory_footprint;
642 : : int status;
643 : :
644 : 0 : status = __table_create(NULL, &memory_footprint, params, args, 0);
645 [ # # ]: 0 : if (status)
646 : : return 0;
647 : :
648 : 0 : return memory_footprint;
649 : : }
650 : :
651 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_table_exact_match_unoptimized_ops, 20.11)
652 : : struct rte_swx_table_ops rte_swx_table_exact_match_unoptimized_ops = {
653 : : .footprint_get = table_footprint,
654 : : .mailbox_size_get = table_mailbox_size_get_unoptimized,
655 : : .create = table_create,
656 : : .add = table_add,
657 : : .del = table_del,
658 : : .lkp = table_lookup_unoptimized,
659 : : .free = table_free,
660 : : };
661 : :
662 : : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_swx_table_exact_match_ops, 20.11)
663 : : struct rte_swx_table_ops rte_swx_table_exact_match_ops = {
664 : : .footprint_get = table_footprint,
665 : : .mailbox_size_get = table_mailbox_size_get,
666 : : .create = table_create,
667 : : .add = table_add,
668 : : .del = table_del,
669 : : .lkp = table_lookup,
670 : : .free = table_free,
671 : : };
|