cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

nft_set_hash.c (18588B)


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