bpf_arena_htab.h 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
  2. /* Copyright (c) 2024 Meta Platforms, Inc. and affiliates. */
  3. #pragma once
  4. #include <errno.h>
  5. #include "bpf_arena_alloc.h"
  6. #include "bpf_arena_list.h"
  7. struct htab_bucket {
  8. struct arena_list_head head;
  9. };
  10. typedef struct htab_bucket __arena htab_bucket_t;
  11. struct htab {
  12. htab_bucket_t *buckets;
  13. int n_buckets;
  14. };
  15. typedef struct htab __arena htab_t;
  16. static inline htab_bucket_t *__select_bucket(htab_t *htab, __u32 hash)
  17. {
  18. htab_bucket_t *b = htab->buckets;
  19. cast_kern(b);
  20. return &b[hash & (htab->n_buckets - 1)];
  21. }
  22. static inline arena_list_head_t *select_bucket(htab_t *htab, __u32 hash)
  23. {
  24. return &__select_bucket(htab, hash)->head;
  25. }
  26. struct hashtab_elem {
  27. int hash;
  28. int key;
  29. int value;
  30. struct arena_list_node hash_node;
  31. };
  32. typedef struct hashtab_elem __arena hashtab_elem_t;
  33. static hashtab_elem_t *lookup_elem_raw(arena_list_head_t *head, __u32 hash, int key)
  34. {
  35. hashtab_elem_t *l;
  36. list_for_each_entry(l, head, hash_node)
  37. if (l->hash == hash && l->key == key)
  38. return l;
  39. return NULL;
  40. }
  41. static int htab_hash(int key)
  42. {
  43. return key;
  44. }
  45. __weak int htab_lookup_elem(htab_t *htab __arg_arena, int key)
  46. {
  47. hashtab_elem_t *l_old;
  48. arena_list_head_t *head;
  49. cast_kern(htab);
  50. head = select_bucket(htab, key);
  51. l_old = lookup_elem_raw(head, htab_hash(key), key);
  52. if (l_old)
  53. return l_old->value;
  54. return 0;
  55. }
  56. __weak int htab_update_elem(htab_t *htab __arg_arena, int key, int value)
  57. {
  58. hashtab_elem_t *l_new = NULL, *l_old;
  59. arena_list_head_t *head;
  60. cast_kern(htab);
  61. head = select_bucket(htab, key);
  62. l_old = lookup_elem_raw(head, htab_hash(key), key);
  63. l_new = bpf_alloc(sizeof(*l_new));
  64. if (!l_new)
  65. return -ENOMEM;
  66. l_new->key = key;
  67. l_new->hash = htab_hash(key);
  68. l_new->value = value;
  69. list_add_head(&l_new->hash_node, head);
  70. if (l_old) {
  71. list_del(&l_old->hash_node);
  72. bpf_free(l_old);
  73. }
  74. return 0;
  75. }
  76. void htab_init(htab_t *htab)
  77. {
  78. void __arena *buckets = bpf_arena_alloc_pages(&arena, NULL, 2, NUMA_NO_NODE, 0);
  79. cast_user(buckets);
  80. htab->buckets = buckets;
  81. htab->n_buckets = 2 * PAGE_SIZE / sizeof(struct htab_bucket);
  82. }