bcmbloom.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. /*
  2. * Bloom filter support
  3. *
  4. * Portions of this code are copyright (c) 2020 Cypress Semiconductor Corporation
  5. *
  6. * Copyright (C) 1999-2020, Broadcom Corporation
  7. *
  8. * Unless you and Broadcom execute a separate written software license
  9. * agreement governing use of this software, this software is licensed to you
  10. * under the terms of the GNU General Public License version 2 (the "GPL"),
  11. * available at http://www.broadcom.com/licenses/GPLv2.php, with the
  12. * following added to such license:
  13. *
  14. * As a special exception, the copyright holders of this software give you
  15. * permission to link this software with independent modules, and to copy and
  16. * distribute the resulting executable under terms of your choice, provided that
  17. * you also meet, for each linked independent module, the terms and conditions of
  18. * the license of that module. An independent module is a module which is not
  19. * derived from this software. The special exception does not apply to any
  20. * modifications of the software.
  21. *
  22. * Notwithstanding the above, under no circumstances may you combine this
  23. * software in any way with any other Broadcom software provided under a license
  24. * other than the GPL, without Broadcom's express prior written consent.
  25. *
  26. *
  27. * <<Broadcom-WL-IPTag/Open:>>
  28. *
  29. * $Id$
  30. */
  31. #include <typedefs.h>
  32. #include <bcmdefs.h>
  33. #include <stdarg.h>
  34. #ifdef BCMDRIVER
  35. #include <osl.h>
  36. #include <bcmutils.h>
  37. #else /* !BCMDRIVER */
  38. #include <stdio.h>
  39. #include <string.h>
  40. #ifndef ASSERT
  41. #define ASSERT(exp)
  42. #endif // endif
  43. #endif /* !BCMDRIVER */
  44. #include <bcmutils.h>
  45. #include <bcmbloom.h>
  46. #define BLOOM_BIT_LEN(_x) ((_x) << 3)
  47. struct bcm_bloom_filter {
  48. void *cb_ctx;
  49. uint max_hash;
  50. bcm_bloom_hash_t *hash; /* array of hash functions */
  51. uint filter_size; /* in bytes */
  52. uint8 *filter; /* can be NULL for validate only */
  53. };
  54. /* public interface */
  55. int
  56. bcm_bloom_create(bcm_bloom_alloc_t alloc_cb,
  57. bcm_bloom_free_t free_cb, void *cb_ctx, uint max_hash,
  58. uint filter_size, bcm_bloom_filter_t **bloom)
  59. {
  60. int err = BCME_OK;
  61. bcm_bloom_filter_t *bp = NULL;
  62. if (!bloom || !alloc_cb || (max_hash == 0)) {
  63. err = BCME_BADARG;
  64. goto done;
  65. }
  66. bp = (*alloc_cb)(cb_ctx, sizeof(*bp));
  67. if (!bp) {
  68. err = BCME_NOMEM;
  69. goto done;
  70. }
  71. memset(bp, 0, sizeof(*bp));
  72. bp->cb_ctx = cb_ctx;
  73. bp->max_hash = max_hash;
  74. bp->hash = (*alloc_cb)(cb_ctx, sizeof(*bp->hash) * max_hash);
  75. memset(bp->hash, 0, sizeof(*bp->hash) * max_hash);
  76. if (!bp->hash) {
  77. err = BCME_NOMEM;
  78. goto done;
  79. }
  80. if (filter_size > 0) {
  81. bp->filter = (*alloc_cb)(cb_ctx, filter_size);
  82. if (!bp->filter) {
  83. err = BCME_NOMEM;
  84. goto done;
  85. }
  86. bp->filter_size = filter_size;
  87. memset(bp->filter, 0, filter_size);
  88. }
  89. *bloom = bp;
  90. done:
  91. if (err != BCME_OK)
  92. bcm_bloom_destroy(&bp, free_cb);
  93. return err;
  94. }
  95. int
  96. bcm_bloom_destroy(bcm_bloom_filter_t **bloom, bcm_bloom_free_t free_cb)
  97. {
  98. int err = BCME_OK;
  99. bcm_bloom_filter_t *bp;
  100. if (!bloom || !*bloom || !free_cb)
  101. goto done;
  102. bp = *bloom;
  103. *bloom = NULL;
  104. if (bp->filter)
  105. (*free_cb)(bp->cb_ctx, bp->filter, bp->filter_size);
  106. if (bp->hash)
  107. (*free_cb)(bp->cb_ctx, bp->hash,
  108. sizeof(*bp->hash) * bp->max_hash);
  109. (*free_cb)(bp->cb_ctx, bp, sizeof(*bp));
  110. done:
  111. return err;
  112. }
  113. int
  114. bcm_bloom_add_hash(bcm_bloom_filter_t *bp, bcm_bloom_hash_t hash, uint *idx)
  115. {
  116. uint i;
  117. if (!bp || !hash || !idx)
  118. return BCME_BADARG;
  119. for (i = 0; i < bp->max_hash; ++i) {
  120. if (bp->hash[i] == NULL)
  121. break;
  122. }
  123. if (i >= bp->max_hash)
  124. return BCME_NORESOURCE;
  125. bp->hash[i] = hash;
  126. *idx = i;
  127. return BCME_OK;
  128. }
  129. int
  130. bcm_bloom_remove_hash(bcm_bloom_filter_t *bp, uint idx)
  131. {
  132. if (!bp)
  133. return BCME_BADARG;
  134. if (idx >= bp->max_hash)
  135. return BCME_NOTFOUND;
  136. bp->hash[idx] = NULL;
  137. return BCME_OK;
  138. }
  139. bool
  140. bcm_bloom_is_member(bcm_bloom_filter_t *bp,
  141. const uint8 *tag, uint tag_len, const uint8 *buf, uint buf_len)
  142. {
  143. uint i;
  144. int err = BCME_OK;
  145. if (!tag || (tag_len == 0)) /* empty tag is always a member */
  146. goto done;
  147. /* use internal buffer if none was specified */
  148. if (!buf || (buf_len == 0)) {
  149. if (!bp->filter) /* every one is a member of empty filter */
  150. goto done;
  151. buf = bp->filter;
  152. buf_len = bp->filter_size;
  153. }
  154. for (i = 0; i < bp->max_hash; ++i) {
  155. uint pos;
  156. if (!bp->hash[i])
  157. continue;
  158. pos = (*bp->hash[i])(bp->cb_ctx, i, tag, tag_len);
  159. /* all bits must be set for a match */
  160. CLANG_DIAGNOSTIC_PUSH_SUPPRESS_CAST()
  161. if (isclr(buf, pos % BLOOM_BIT_LEN(buf_len))) {
  162. CLANG_DIAGNOSTIC_POP()
  163. err = BCME_NOTFOUND;
  164. break;
  165. }
  166. }
  167. done:
  168. return err;
  169. }
  170. int
  171. bcm_bloom_add_member(bcm_bloom_filter_t *bp, const uint8 *tag, uint tag_len)
  172. {
  173. uint i;
  174. if (!bp || !tag || (tag_len == 0))
  175. return BCME_BADARG;
  176. if (!bp->filter) /* validate only */
  177. return BCME_UNSUPPORTED;
  178. for (i = 0; i < bp->max_hash; ++i) {
  179. uint pos;
  180. if (!bp->hash[i])
  181. continue;
  182. pos = (*bp->hash[i])(bp->cb_ctx, i, tag, tag_len);
  183. setbit(bp->filter, pos % BLOOM_BIT_LEN(bp->filter_size));
  184. }
  185. return BCME_OK;
  186. }
  187. int bcm_bloom_get_filter_data(bcm_bloom_filter_t *bp,
  188. uint buf_size, uint8 *buf, uint *buf_len)
  189. {
  190. if (!bp)
  191. return BCME_BADARG;
  192. if (buf_len)
  193. *buf_len = bp->filter_size;
  194. if (buf_size < bp->filter_size)
  195. return BCME_BUFTOOSHORT;
  196. if (bp->filter && bp->filter_size)
  197. memcpy(buf, bp->filter, bp->filter_size);
  198. return BCME_OK;
  199. }