| 2480 | } |
| 2481 | |
| 2482 | int32_t |
| 2483 | rte_hash_iterate(const struct rte_hash *h, const void **key, void **data, uint32_t *next) |
| 2484 | { |
| 2485 | uint32_t bucket_idx, idx, position; |
| 2486 | struct rte_hash_key *next_key; |
| 2487 | |
| 2488 | RETURN_IF_TRUE(((h == NULL) || (next == NULL)), -EINVAL); |
| 2489 | |
| 2490 | const uint32_t total_entries_main = h->num_buckets * |
| 2491 | RTE_HASH_BUCKET_ENTRIES; |
| 2492 | const uint32_t total_entries = total_entries_main << 1; |
| 2493 | |
| 2494 | /* Out of bounds of all buckets (both main table and ext table) */ |
| 2495 | if (*next >= total_entries_main) |
| 2496 | goto extend_table; |
| 2497 | |
| 2498 | /* Calculate bucket and index of current iterator */ |
| 2499 | bucket_idx = *next / RTE_HASH_BUCKET_ENTRIES; |
| 2500 | idx = *next % RTE_HASH_BUCKET_ENTRIES; |
| 2501 | |
| 2502 | /* If current position is empty, go to the next one */ |
| 2503 | while ((position = rte_atomic_load_explicit(&h->buckets[bucket_idx].key_idx[idx], |
| 2504 | rte_memory_order_acquire)) == EMPTY_SLOT) { |
| 2505 | (*next)++; |
| 2506 | /* End of table */ |
| 2507 | if (*next == total_entries_main) |
| 2508 | goto extend_table; |
| 2509 | bucket_idx = *next / RTE_HASH_BUCKET_ENTRIES; |
| 2510 | idx = *next % RTE_HASH_BUCKET_ENTRIES; |
| 2511 | } |
| 2512 | |
| 2513 | __hash_rw_reader_lock(h); |
| 2514 | next_key = (struct rte_hash_key *) ((char *)h->key_store + |
| 2515 | position * h->key_entry_size); |
| 2516 | /* Return key and data */ |
| 2517 | *key = next_key->key; |
| 2518 | *data = next_key->pdata; |
| 2519 | |
| 2520 | __hash_rw_reader_unlock(h); |
| 2521 | |
| 2522 | /* Increment iterator */ |
| 2523 | (*next)++; |
| 2524 | |
| 2525 | return position - 1; |
| 2526 | |
| 2527 | /* Begin to iterate extendable buckets */ |
| 2528 | extend_table: |
| 2529 | /* Out of total bound or if ext bucket feature is not enabled */ |
| 2530 | if (*next >= total_entries || !h->ext_table_support) |
| 2531 | return -ENOENT; |
| 2532 | |
| 2533 | bucket_idx = (*next - total_entries_main) / RTE_HASH_BUCKET_ENTRIES; |
| 2534 | idx = (*next - total_entries_main) % RTE_HASH_BUCKET_ENTRIES; |
| 2535 | |
| 2536 | while ((position = h->buckets_ext[bucket_idx].key_idx[idx]) == EMPTY_SLOT) { |
| 2537 | (*next)++; |
| 2538 | if (*next == total_entries) |
| 2539 | return -ENOENT; |