diff options
author | Patrick McHardy <kaber@trash.net> | 2015-04-05 14:41:08 +0200 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2015-04-08 16:58:27 +0200 |
commit | 22fe54d5fefcfa98c58cc2f4607dd26d9648b3f5 (patch) | |
tree | 153c791a6efb2c0eb7aca4baecb84cb76199b706 /net/netfilter/nft_hash.c | |
parent | 11113e190bf0ad73086884f87efccc994ff28b3d (diff) | |
download | op-kernel-dev-22fe54d5fefcfa98c58cc2f4607dd26d9648b3f5.zip op-kernel-dev-22fe54d5fefcfa98c58cc2f4607dd26d9648b3f5.tar.gz |
netfilter: nf_tables: add support for dynamic set updates
Add a new "dynset" expression for dynamic set updates.
A new set op ->update() is added which, for non existant elements,
invokes an initialization callback and inserts the new element.
For both new or existing elements the extenstion pointer is returned
to the caller to optionally perform timer updates or other actions.
Element removal is not supported so far, however that seems to be a
rather exotic need and can be added later on.
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net/netfilter/nft_hash.c')
-rw-r--r-- | net/netfilter/nft_hash.c | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/net/netfilter/nft_hash.c b/net/netfilter/nft_hash.c index c74e2bf..bc23806 100644 --- a/net/netfilter/nft_hash.c +++ b/net/netfilter/nft_hash.c @@ -90,6 +90,42 @@ static bool nft_hash_lookup(const struct nft_set *set, return !!he; } +static bool nft_hash_update(struct nft_set *set, const struct nft_data *key, + void *(*new)(struct nft_set *, + const struct nft_expr *, + struct nft_data []), + const struct nft_expr *expr, + struct nft_data data[], + const struct nft_set_ext **ext) +{ + struct nft_hash *priv = nft_set_priv(set); + struct nft_hash_elem *he; + struct nft_hash_cmp_arg arg = { + .genmask = NFT_GENMASK_ANY, + .set = set, + .key = key, + }; + + he = rhashtable_lookup_fast(&priv->ht, &arg, nft_hash_params); + if (he != NULL) + goto out; + + he = new(set, expr, data); + if (he == NULL) + goto err1; + if (rhashtable_lookup_insert_key(&priv->ht, &arg, &he->node, + nft_hash_params)) + goto err2; +out: + *ext = &he->ext; + return true; + +err2: + nft_set_elem_destroy(set, he); +err1: + return false; +} + static int nft_hash_insert(const struct nft_set *set, const struct nft_set_elem *elem) { @@ -335,6 +371,7 @@ static struct nft_set_ops nft_hash_ops __read_mostly = { .deactivate = nft_hash_deactivate, .remove = nft_hash_remove, .lookup = nft_hash_lookup, + .update = nft_hash_update, .walk = nft_hash_walk, .features = NFT_SET_MAP | NFT_SET_TIMEOUT, .owner = THIS_MODULE, |