netfilter: nf_tables: meter: pick a set backend that supports updates
in nftables, 'meter' can be used to instantiate a hash-table at run
time:
rule add filter forward iif "internal" meter hostacct { ip saddr counter}
nft list meter ip filter hostacct
table ip filter {
meter hostacct {
type ipv4_addr
elements = { 192.168.0.1 : counter packets 8 bytes 2672, ..
because elemets get added on the fly, the kernel must chose a set
backend type that implements the ->update() function, otherwise
rule insertion fails with EOPNOTSUPP.
Therefore, skip set types that lack ->update, and also
make sure we do not discard a (bad) candidate when we did yet
find any candidate at all. This could happen when userspace prefers
low memory footprint -- the set implementation currently checked might
not be a fit at all. Make sure we pick it anyway (!bops). In
case next candidate is a better fix, it will be chosen instead.
But in case nothing else is found we at least have a non-ideal
match rather than no match at all.
Fixes: 6c03ae210c
("netfilter: nft_set_hash: add non-resizable hashtable implementation")
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
parent
36fe095606
commit
4f2921ca21
|
@ -2446,6 +2446,9 @@ EXPORT_SYMBOL_GPL(nft_unregister_set);
|
|||
|
||||
static bool nft_set_ops_candidate(const struct nft_set_ops *ops, u32 flags)
|
||||
{
|
||||
if ((flags & NFT_SET_EVAL) && !ops->update)
|
||||
return false;
|
||||
|
||||
return (flags & ops->features) == (flags & NFT_SET_FEATURES);
|
||||
}
|
||||
|
||||
|
@ -2510,7 +2513,7 @@ nft_select_set_ops(const struct nft_ctx *ctx,
|
|||
if (est.space == best.space &&
|
||||
est.lookup < best.lookup)
|
||||
break;
|
||||
} else if (est.size < best.size) {
|
||||
} else if (est.size < best.size || !bops) {
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
|
|
|
@ -674,7 +674,7 @@ static const struct nft_set_ops *
|
|||
nft_hash_select_ops(const struct nft_ctx *ctx, const struct nft_set_desc *desc,
|
||||
u32 flags)
|
||||
{
|
||||
if (desc->size && !(flags & NFT_SET_TIMEOUT)) {
|
||||
if (desc->size && !(flags & (NFT_SET_EVAL | NFT_SET_TIMEOUT))) {
|
||||
switch (desc->klen) {
|
||||
case 4:
|
||||
return &nft_hash_fast_ops;
|
||||
|
|
Loading…
Reference in New Issue