nft_set_hash.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2008-2014 Patrick McHardy <kaber@trash.net>
  4. *
  5. * Development of this code funded by Astaro AG (http://www.astaro.com/)
  6. */
  7. #include <linux/kernel.h>
  8. #include <linux/init.h>
  9. #include <linux/module.h>
  10. #include <linux/list.h>
  11. #include <linux/log2.h>
  12. #include <linux/jhash.h>
  13. #include <linux/netlink.h>
  14. #include <linux/workqueue.h>
  15. #include <linux/rhashtable.h>
  16. #include <linux/netfilter.h>
  17. #include <linux/netfilter/nf_tables.h>
  18. #include <net/netfilter/nf_tables_core.h>
  19. /* We target a hash table size of 4, element hint is 75% of final size */
  20. #define NFT_RHASH_ELEMENT_HINT 3
  21. struct nft_rhash {
  22. struct rhashtable ht;
  23. struct delayed_work gc_work;
  24. };
  25. struct nft_rhash_elem {
  26. struct rhash_head node;
  27. struct nft_set_ext ext;
  28. };
  29. struct nft_rhash_cmp_arg {
  30. const struct nft_set *set;
  31. const u32 *key;
  32. u8 genmask;
  33. };
  34. static inline u32 nft_rhash_key(const void *data, u32 len, u32 seed)
  35. {
  36. const struct nft_rhash_cmp_arg *arg = data;
  37. return jhash(arg->key, len, seed);
  38. }
  39. static inline u32 nft_rhash_obj(const void *data, u32 len, u32 seed)
  40. {
  41. const struct nft_rhash_elem *he = data;
  42. return jhash(nft_set_ext_key(&he->ext), len, seed);
  43. }
  44. static inline int nft_rhash_cmp(struct rhashtable_compare_arg *arg,
  45. const void *ptr)
  46. {
  47. const struct nft_rhash_cmp_arg *x = arg->key;
  48. const struct nft_rhash_elem *he = ptr;
  49. if (memcmp(nft_set_ext_key(&he->ext), x->key, x->set->klen))
  50. return 1;
  51. if (nft_set_elem_expired(&he->ext))
  52. return 1;
  53. if (!nft_set_elem_active(&he->ext, x->genmask))
  54. return 1;
  55. return 0;
  56. }
  57. static const struct rhashtable_params nft_rhash_params = {
  58. .head_offset = offsetof(struct nft_rhash_elem, node),
  59. .hashfn = nft_rhash_key,
  60. .obj_hashfn = nft_rhash_obj,
  61. .obj_cmpfn = nft_rhash_cmp,
  62. .automatic_shrinking = true,
  63. };
  64. static bool nft_rhash_lookup(const struct net *net, const struct nft_set *set,
  65. const u32 *key, const struct nft_set_ext **ext)
  66. {
  67. struct nft_rhash *priv = nft_set_priv(set);
  68. const struct nft_rhash_elem *he;
  69. struct nft_rhash_cmp_arg arg = {
  70. .genmask = nft_genmask_cur(net),
  71. .set = set,
  72. .key = key,
  73. };
  74. he = rhashtable_lookup(&priv->ht, &arg, nft_rhash_params);
  75. if (he != NULL)
  76. *ext = &he->ext;
  77. return !!he;
  78. }
  79. static void *nft_rhash_get(const struct net *net, const struct nft_set *set,
  80. const struct nft_set_elem *elem, unsigned int flags)
  81. {
  82. struct nft_rhash *priv = nft_set_priv(set);
  83. struct nft_rhash_elem *he;
  84. struct nft_rhash_cmp_arg arg = {
  85. .genmask = nft_genmask_cur(net),
  86. .set = set,
  87. .key = elem->key.val.data,
  88. };
  89. he = rhashtable_lookup(&priv->ht, &arg, nft_rhash_params);
  90. if (he != NULL)
  91. return he;
  92. return ERR_PTR(-ENOENT);
  93. }
  94. static bool nft_rhash_update(struct nft_set *set, const u32 *key,
  95. void *(*new)(struct nft_set *,
  96. const struct nft_expr *,
  97. struct nft_regs *regs),
  98. const struct nft_expr *expr,
  99. struct nft_regs *regs,
  100. const struct nft_set_ext **ext)
  101. {
  102. struct nft_rhash *priv = nft_set_priv(set);
  103. struct nft_rhash_elem *he, *prev;
  104. struct nft_rhash_cmp_arg arg = {
  105. .genmask = NFT_GENMASK_ANY,
  106. .set = set,
  107. .key = key,
  108. };
  109. he = rhashtable_lookup(&priv->ht, &arg, nft_rhash_params);
  110. if (he != NULL)
  111. goto out;
  112. he = new(set, expr, regs);
  113. if (he == NULL)
  114. goto err1;
  115. prev = rhashtable_lookup_get_insert_key(&priv->ht, &arg, &he->node,
  116. nft_rhash_params);
  117. if (IS_ERR(prev))
  118. goto err2;
  119. /* Another cpu may race to insert the element with the same key */
  120. if (prev) {
  121. nft_set_elem_destroy(set, he, true);
  122. he = prev;
  123. }
  124. out:
  125. *ext = &he->ext;
  126. return true;
  127. err2:
  128. nft_set_elem_destroy(set, he, true);
  129. err1:
  130. return false;
  131. }
  132. static int nft_rhash_insert(const struct net *net, const struct nft_set *set,
  133. const struct nft_set_elem *elem,
  134. struct nft_set_ext **ext)
  135. {
  136. struct nft_rhash *priv = nft_set_priv(set);
  137. struct nft_rhash_elem *he = elem->priv;
  138. struct nft_rhash_cmp_arg arg = {
  139. .genmask = nft_genmask_next(net),
  140. .set = set,
  141. .key = elem->key.val.data,
  142. };
  143. struct nft_rhash_elem *prev;
  144. prev = rhashtable_lookup_get_insert_key(&priv->ht, &arg, &he->node,
  145. nft_rhash_params);
  146. if (IS_ERR(prev))
  147. return PTR_ERR(prev);
  148. if (prev) {
  149. *ext = &prev->ext;
  150. return -EEXIST;
  151. }
  152. return 0;
  153. }
  154. static void nft_rhash_activate(const struct net *net, const struct nft_set *set,
  155. const struct nft_set_elem *elem)
  156. {
  157. struct nft_rhash_elem *he = elem->priv;
  158. nft_set_elem_change_active(net, set, &he->ext);
  159. nft_set_elem_clear_busy(&he->ext);
  160. }
  161. static bool nft_rhash_flush(const struct net *net,
  162. const struct nft_set *set, void *priv)
  163. {
  164. struct nft_rhash_elem *he = priv;
  165. if (!nft_set_elem_mark_busy(&he->ext) ||
  166. !nft_is_active(net, &he->ext)) {
  167. nft_set_elem_change_active(net, set, &he->ext);
  168. return true;
  169. }
  170. return false;
  171. }
  172. static void *nft_rhash_deactivate(const struct net *net,
  173. const struct nft_set *set,
  174. const struct nft_set_elem *elem)
  175. {
  176. struct nft_rhash *priv = nft_set_priv(set);
  177. struct nft_rhash_elem *he;
  178. struct nft_rhash_cmp_arg arg = {
  179. .genmask = nft_genmask_next(net),
  180. .set = set,
  181. .key = elem->key.val.data,
  182. };
  183. rcu_read_lock();
  184. he = rhashtable_lookup(&priv->ht, &arg, nft_rhash_params);
  185. if (he != NULL &&
  186. !nft_rhash_flush(net, set, he))
  187. he = NULL;
  188. rcu_read_unlock();
  189. return he;
  190. }
  191. static void nft_rhash_remove(const struct net *net,
  192. const struct nft_set *set,
  193. const struct nft_set_elem *elem)
  194. {
  195. struct nft_rhash *priv = nft_set_priv(set);
  196. struct nft_rhash_elem *he = elem->priv;
  197. rhashtable_remove_fast(&priv->ht, &he->node, nft_rhash_params);
  198. }
  199. static bool nft_rhash_delete(const struct nft_set *set,
  200. const u32 *key)
  201. {
  202. struct nft_rhash *priv = nft_set_priv(set);
  203. struct nft_rhash_cmp_arg arg = {
  204. .genmask = NFT_GENMASK_ANY,
  205. .set = set,
  206. .key = key,
  207. };
  208. struct nft_rhash_elem *he;
  209. he = rhashtable_lookup(&priv->ht, &arg, nft_rhash_params);
  210. if (he == NULL)
  211. return false;
  212. return rhashtable_remove_fast(&priv->ht, &he->node, nft_rhash_params) == 0;
  213. }
  214. static void nft_rhash_walk(const struct nft_ctx *ctx, struct nft_set *set,
  215. struct nft_set_iter *iter)
  216. {
  217. struct nft_rhash *priv = nft_set_priv(set);
  218. struct nft_rhash_elem *he;
  219. struct rhashtable_iter hti;
  220. struct nft_set_elem elem;
  221. rhashtable_walk_enter(&priv->ht, &hti);
  222. rhashtable_walk_start(&hti);
  223. while ((he = rhashtable_walk_next(&hti))) {
  224. if (IS_ERR(he)) {
  225. if (PTR_ERR(he) != -EAGAIN) {
  226. iter->err = PTR_ERR(he);
  227. break;
  228. }
  229. continue;
  230. }
  231. if (iter->count < iter->skip)
  232. goto cont;
  233. if (nft_set_elem_expired(&he->ext))
  234. goto cont;
  235. if (!nft_set_elem_active(&he->ext, iter->genmask))
  236. goto cont;
  237. elem.priv = he;
  238. iter->err = iter->fn(ctx, set, iter, &elem);
  239. if (iter->err < 0)
  240. break;
  241. cont:
  242. iter->count++;
  243. }
  244. rhashtable_walk_stop(&hti);
  245. rhashtable_walk_exit(&hti);
  246. }
  247. static void nft_rhash_gc(struct work_struct *work)
  248. {
  249. struct nft_set *set;
  250. struct nft_rhash_elem *he;
  251. struct nft_rhash *priv;
  252. struct nft_set_gc_batch *gcb = NULL;
  253. struct rhashtable_iter hti;
  254. priv = container_of(work, struct nft_rhash, gc_work.work);
  255. set = nft_set_container_of(priv);
  256. rhashtable_walk_enter(&priv->ht, &hti);
  257. rhashtable_walk_start(&hti);
  258. while ((he = rhashtable_walk_next(&hti))) {
  259. if (IS_ERR(he)) {
  260. if (PTR_ERR(he) != -EAGAIN)
  261. break;
  262. continue;
  263. }
  264. if (nft_set_ext_exists(&he->ext, NFT_SET_EXT_EXPR)) {
  265. struct nft_expr *expr = nft_set_ext_expr(&he->ext);
  266. if (expr->ops->gc &&
  267. expr->ops->gc(read_pnet(&set->net), expr))
  268. goto gc;
  269. }
  270. if (!nft_set_elem_expired(&he->ext))
  271. continue;
  272. gc:
  273. if (nft_set_elem_mark_busy(&he->ext))
  274. continue;
  275. gcb = nft_set_gc_batch_check(set, gcb, GFP_ATOMIC);
  276. if (gcb == NULL)
  277. break;
  278. rhashtable_remove_fast(&priv->ht, &he->node, nft_rhash_params);
  279. atomic_dec(&set->nelems);
  280. nft_set_gc_batch_add(gcb, he);
  281. }
  282. rhashtable_walk_stop(&hti);
  283. rhashtable_walk_exit(&hti);
  284. nft_set_gc_batch_complete(gcb);
  285. queue_delayed_work(system_power_efficient_wq, &priv->gc_work,
  286. nft_set_gc_interval(set));
  287. }
  288. static u64 nft_rhash_privsize(const struct nlattr * const nla[],
  289. const struct nft_set_desc *desc)
  290. {
  291. return sizeof(struct nft_rhash);
  292. }
  293. static void nft_rhash_gc_init(const struct nft_set *set)
  294. {
  295. struct nft_rhash *priv = nft_set_priv(set);
  296. queue_delayed_work(system_power_efficient_wq, &priv->gc_work,
  297. nft_set_gc_interval(set));
  298. }
  299. static int nft_rhash_init(const struct nft_set *set,
  300. const struct nft_set_desc *desc,
  301. const struct nlattr * const tb[])
  302. {
  303. struct nft_rhash *priv = nft_set_priv(set);
  304. struct rhashtable_params params = nft_rhash_params;
  305. int err;
  306. params.nelem_hint = desc->size ?: NFT_RHASH_ELEMENT_HINT;
  307. params.key_len = set->klen;
  308. err = rhashtable_init(&priv->ht, &params);
  309. if (err < 0)
  310. return err;
  311. INIT_DEFERRABLE_WORK(&priv->gc_work, nft_rhash_gc);
  312. if (set->flags & NFT_SET_TIMEOUT)
  313. nft_rhash_gc_init(set);
  314. return 0;
  315. }
  316. static void nft_rhash_elem_destroy(void *ptr, void *arg)
  317. {
  318. nft_set_elem_destroy(arg, ptr, true);
  319. }
  320. static void nft_rhash_destroy(const struct nft_set *set)
  321. {
  322. struct nft_rhash *priv = nft_set_priv(set);
  323. cancel_delayed_work_sync(&priv->gc_work);
  324. rcu_barrier();
  325. rhashtable_free_and_destroy(&priv->ht, nft_rhash_elem_destroy,
  326. (void *)set);
  327. }
  328. /* Number of buckets is stored in u32, so cap our result to 1U<<31 */
  329. #define NFT_MAX_BUCKETS (1U << 31)
  330. static u32 nft_hash_buckets(u32 size)
  331. {
  332. u64 val = div_u64((u64)size * 4, 3);
  333. if (val >= NFT_MAX_BUCKETS)
  334. return NFT_MAX_BUCKETS;
  335. return roundup_pow_of_two(val);
  336. }
  337. static bool nft_rhash_estimate(const struct nft_set_desc *desc, u32 features,
  338. struct nft_set_estimate *est)
  339. {
  340. est->size = ~0;
  341. est->lookup = NFT_SET_CLASS_O_1;
  342. est->space = NFT_SET_CLASS_O_N;
  343. return true;
  344. }
  345. struct nft_hash {
  346. u32 seed;
  347. u32 buckets;
  348. struct hlist_head table[];
  349. };
  350. struct nft_hash_elem {
  351. struct hlist_node node;
  352. struct nft_set_ext ext;
  353. };
  354. static bool nft_hash_lookup(const struct net *net, const struct nft_set *set,
  355. const u32 *key, const struct nft_set_ext **ext)
  356. {
  357. struct nft_hash *priv = nft_set_priv(set);
  358. u8 genmask = nft_genmask_cur(net);
  359. const struct nft_hash_elem *he;
  360. u32 hash;
  361. hash = jhash(key, set->klen, priv->seed);
  362. hash = reciprocal_scale(hash, priv->buckets);
  363. hlist_for_each_entry_rcu(he, &priv->table[hash], node) {
  364. if (!memcmp(nft_set_ext_key(&he->ext), key, set->klen) &&
  365. nft_set_elem_active(&he->ext, genmask)) {
  366. *ext = &he->ext;
  367. return true;
  368. }
  369. }
  370. return false;
  371. }
  372. static void *nft_hash_get(const struct net *net, const struct nft_set *set,
  373. const struct nft_set_elem *elem, unsigned int flags)
  374. {
  375. struct nft_hash *priv = nft_set_priv(set);
  376. u8 genmask = nft_genmask_cur(net);
  377. struct nft_hash_elem *he;
  378. u32 hash;
  379. hash = jhash(elem->key.val.data, set->klen, priv->seed);
  380. hash = reciprocal_scale(hash, priv->buckets);
  381. hlist_for_each_entry_rcu(he, &priv->table[hash], node) {
  382. if (!memcmp(nft_set_ext_key(&he->ext), elem->key.val.data, set->klen) &&
  383. nft_set_elem_active(&he->ext, genmask))
  384. return he;
  385. }
  386. return ERR_PTR(-ENOENT);
  387. }
  388. static bool nft_hash_lookup_fast(const struct net *net,
  389. const struct nft_set *set,
  390. const u32 *key, const struct nft_set_ext **ext)
  391. {
  392. struct nft_hash *priv = nft_set_priv(set);
  393. u8 genmask = nft_genmask_cur(net);
  394. const struct nft_hash_elem *he;
  395. u32 hash, k1, k2;
  396. k1 = *key;
  397. hash = jhash_1word(k1, priv->seed);
  398. hash = reciprocal_scale(hash, priv->buckets);
  399. hlist_for_each_entry_rcu(he, &priv->table[hash], node) {
  400. k2 = *(u32 *)nft_set_ext_key(&he->ext)->data;
  401. if (k1 == k2 &&
  402. nft_set_elem_active(&he->ext, genmask)) {
  403. *ext = &he->ext;
  404. return true;
  405. }
  406. }
  407. return false;
  408. }
  409. static u32 nft_jhash(const struct nft_set *set, const struct nft_hash *priv,
  410. const struct nft_set_ext *ext)
  411. {
  412. const struct nft_data *key = nft_set_ext_key(ext);
  413. u32 hash, k1;
  414. if (set->klen == 4) {
  415. k1 = *(u32 *)key;
  416. hash = jhash_1word(k1, priv->seed);
  417. } else {
  418. hash = jhash(key, set->klen, priv->seed);
  419. }
  420. hash = reciprocal_scale(hash, priv->buckets);
  421. return hash;
  422. }
  423. static int nft_hash_insert(const struct net *net, const struct nft_set *set,
  424. const struct nft_set_elem *elem,
  425. struct nft_set_ext **ext)
  426. {
  427. struct nft_hash_elem *this = elem->priv, *he;
  428. struct nft_hash *priv = nft_set_priv(set);
  429. u8 genmask = nft_genmask_next(net);
  430. u32 hash;
  431. hash = nft_jhash(set, priv, &this->ext);
  432. hlist_for_each_entry(he, &priv->table[hash], node) {
  433. if (!memcmp(nft_set_ext_key(&this->ext),
  434. nft_set_ext_key(&he->ext), set->klen) &&
  435. nft_set_elem_active(&he->ext, genmask)) {
  436. *ext = &he->ext;
  437. return -EEXIST;
  438. }
  439. }
  440. hlist_add_head_rcu(&this->node, &priv->table[hash]);
  441. return 0;
  442. }
  443. static void nft_hash_activate(const struct net *net, const struct nft_set *set,
  444. const struct nft_set_elem *elem)
  445. {
  446. struct nft_hash_elem *he = elem->priv;
  447. nft_set_elem_change_active(net, set, &he->ext);
  448. }
  449. static bool nft_hash_flush(const struct net *net,
  450. const struct nft_set *set, void *priv)
  451. {
  452. struct nft_hash_elem *he = priv;
  453. nft_set_elem_change_active(net, set, &he->ext);
  454. return true;
  455. }
  456. static void *nft_hash_deactivate(const struct net *net,
  457. const struct nft_set *set,
  458. const struct nft_set_elem *elem)
  459. {
  460. struct nft_hash *priv = nft_set_priv(set);
  461. struct nft_hash_elem *this = elem->priv, *he;
  462. u8 genmask = nft_genmask_next(net);
  463. u32 hash;
  464. hash = nft_jhash(set, priv, &this->ext);
  465. hlist_for_each_entry(he, &priv->table[hash], node) {
  466. if (!memcmp(nft_set_ext_key(&he->ext), &elem->key.val,
  467. set->klen) &&
  468. nft_set_elem_active(&he->ext, genmask)) {
  469. nft_set_elem_change_active(net, set, &he->ext);
  470. return he;
  471. }
  472. }
  473. return NULL;
  474. }
  475. static void nft_hash_remove(const struct net *net,
  476. const struct nft_set *set,
  477. const struct nft_set_elem *elem)
  478. {
  479. struct nft_hash_elem *he = elem->priv;
  480. hlist_del_rcu(&he->node);
  481. }
  482. static void nft_hash_walk(const struct nft_ctx *ctx, struct nft_set *set,
  483. struct nft_set_iter *iter)
  484. {
  485. struct nft_hash *priv = nft_set_priv(set);
  486. struct nft_hash_elem *he;
  487. struct nft_set_elem elem;
  488. int i;
  489. for (i = 0; i < priv->buckets; i++) {
  490. hlist_for_each_entry_rcu(he, &priv->table[i], node) {
  491. if (iter->count < iter->skip)
  492. goto cont;
  493. if (!nft_set_elem_active(&he->ext, iter->genmask))
  494. goto cont;
  495. elem.priv = he;
  496. iter->err = iter->fn(ctx, set, iter, &elem);
  497. if (iter->err < 0)
  498. return;
  499. cont:
  500. iter->count++;
  501. }
  502. }
  503. }
  504. static u64 nft_hash_privsize(const struct nlattr * const nla[],
  505. const struct nft_set_desc *desc)
  506. {
  507. return sizeof(struct nft_hash) +
  508. (u64)nft_hash_buckets(desc->size) * sizeof(struct hlist_head);
  509. }
  510. static int nft_hash_init(const struct nft_set *set,
  511. const struct nft_set_desc *desc,
  512. const struct nlattr * const tb[])
  513. {
  514. struct nft_hash *priv = nft_set_priv(set);
  515. priv->buckets = nft_hash_buckets(desc->size);
  516. get_random_bytes(&priv->seed, sizeof(priv->seed));
  517. return 0;
  518. }
  519. static void nft_hash_destroy(const struct nft_set *set)
  520. {
  521. struct nft_hash *priv = nft_set_priv(set);
  522. struct nft_hash_elem *he;
  523. struct hlist_node *next;
  524. int i;
  525. for (i = 0; i < priv->buckets; i++) {
  526. hlist_for_each_entry_safe(he, next, &priv->table[i], node) {
  527. hlist_del_rcu(&he->node);
  528. nft_set_elem_destroy(set, he, true);
  529. }
  530. }
  531. }
  532. static bool nft_hash_estimate(const struct nft_set_desc *desc, u32 features,
  533. struct nft_set_estimate *est)
  534. {
  535. if (!desc->size)
  536. return false;
  537. if (desc->klen == 4)
  538. return false;
  539. est->size = sizeof(struct nft_hash) +
  540. (u64)nft_hash_buckets(desc->size) * sizeof(struct hlist_head) +
  541. (u64)desc->size * sizeof(struct nft_hash_elem);
  542. est->lookup = NFT_SET_CLASS_O_1;
  543. est->space = NFT_SET_CLASS_O_N;
  544. return true;
  545. }
  546. static bool nft_hash_fast_estimate(const struct nft_set_desc *desc, u32 features,
  547. struct nft_set_estimate *est)
  548. {
  549. if (!desc->size)
  550. return false;
  551. if (desc->klen != 4)
  552. return false;
  553. est->size = sizeof(struct nft_hash) +
  554. (u64)nft_hash_buckets(desc->size) * sizeof(struct hlist_head) +
  555. (u64)desc->size * sizeof(struct nft_hash_elem);
  556. est->lookup = NFT_SET_CLASS_O_1;
  557. est->space = NFT_SET_CLASS_O_N;
  558. return true;
  559. }
  560. const struct nft_set_type nft_set_rhash_type = {
  561. .features = NFT_SET_MAP | NFT_SET_OBJECT |
  562. NFT_SET_TIMEOUT | NFT_SET_EVAL,
  563. .ops = {
  564. .privsize = nft_rhash_privsize,
  565. .elemsize = offsetof(struct nft_rhash_elem, ext),
  566. .estimate = nft_rhash_estimate,
  567. .init = nft_rhash_init,
  568. .gc_init = nft_rhash_gc_init,
  569. .destroy = nft_rhash_destroy,
  570. .insert = nft_rhash_insert,
  571. .activate = nft_rhash_activate,
  572. .deactivate = nft_rhash_deactivate,
  573. .flush = nft_rhash_flush,
  574. .remove = nft_rhash_remove,
  575. .lookup = nft_rhash_lookup,
  576. .update = nft_rhash_update,
  577. .delete = nft_rhash_delete,
  578. .walk = nft_rhash_walk,
  579. .get = nft_rhash_get,
  580. },
  581. };
  582. const struct nft_set_type nft_set_hash_type = {
  583. .features = NFT_SET_MAP | NFT_SET_OBJECT,
  584. .ops = {
  585. .privsize = nft_hash_privsize,
  586. .elemsize = offsetof(struct nft_hash_elem, ext),
  587. .estimate = nft_hash_estimate,
  588. .init = nft_hash_init,
  589. .destroy = nft_hash_destroy,
  590. .insert = nft_hash_insert,
  591. .activate = nft_hash_activate,
  592. .deactivate = nft_hash_deactivate,
  593. .flush = nft_hash_flush,
  594. .remove = nft_hash_remove,
  595. .lookup = nft_hash_lookup,
  596. .walk = nft_hash_walk,
  597. .get = nft_hash_get,
  598. },
  599. };
  600. const struct nft_set_type nft_set_hash_fast_type = {
  601. .features = NFT_SET_MAP | NFT_SET_OBJECT,
  602. .ops = {
  603. .privsize = nft_hash_privsize,
  604. .elemsize = offsetof(struct nft_hash_elem, ext),
  605. .estimate = nft_hash_fast_estimate,
  606. .init = nft_hash_init,
  607. .destroy = nft_hash_destroy,
  608. .insert = nft_hash_insert,
  609. .activate = nft_hash_activate,
  610. .deactivate = nft_hash_deactivate,
  611. .flush = nft_hash_flush,
  612. .remove = nft_hash_remove,
  613. .lookup = nft_hash_lookup_fast,
  614. .walk = nft_hash_walk,
  615. .get = nft_hash_get,
  616. },
  617. };