All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] nft hash set expansion fixes
@ 2015-02-10  0:48 Josh Hunt
  2015-02-10  0:48 ` [PATCH 1/3] rhashtable: require max_shift definition Josh Hunt
                   ` (2 more replies)
  0 siblings, 3 replies; 11+ messages in thread
From: Josh Hunt @ 2015-02-10  0:48 UTC (permalink / raw)
  To: Pablo Neira Ayuso, Patrick McHardy, Thomas Graf
  Cc: netfilter-devel, netdev, Daniel Borkmann, Josh Hunt

This patchset resolves some issues I've come across while investigating nft hash
sets.

The first patch requires users of rhashtable to define a max_shift as suggested
by Daniel Borkmann and Thomas Graf. One side-effect of not setting max_shift is
that tables are not allowed to expand. I was observing this behavior with nft
hash sets prior to these changes.

The next patch implements this requirement for nft hash sets using desc->size as
the max_shift if it's provided by the user. If not, it falls back to a newly
defined default of 1024 elements. This value is somewhat arbitrary, but seems
like a reasonable default to me.

I used 'size' above for max_shift because it appears to be used as a ceiling for
the number of elements in a set in nft_add_set_elem(). It's also used in the
estimate fn. Prior to the next patch 'size' was also being used as the nelem_hint
to pass to rhashtable_init(). This seems incorrect since nelem_hint is meant to
provide a hint for how many hash buckets to initially allocate.

Instead of using 'size' for nelem_hint, the final patch introduces a new set
parameter named 'init_size'. If this approach is acceptable I can provide the
userspace patches to fully implement the new parameter.

The patchset is against net-next.

Josh Hunt (3):
  rhashtable: require max_shift definition
  nft_hash: define max_shift rhashtable param
  nft_hash: introduce init_size set parameter

 include/net/netfilter/nf_tables.h        |    4 +++-
 include/uapi/linux/netfilter/nf_tables.h |    2 ++
 lib/rhashtable.c                         |    3 ++-
 net/netfilter/nf_tables_api.c            |    4 ++++
 net/netfilter/nft_hash.c                 |    7 ++++++-
 5 files changed, 17 insertions(+), 3 deletions(-)

-- 
1.7.9.5

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 1/3] rhashtable: require max_shift definition
  2015-02-10  0:48 [PATCH 0/3] nft hash set expansion fixes Josh Hunt
@ 2015-02-10  0:48 ` Josh Hunt
  2015-02-10  0:58   ` Thomas Graf
  2015-02-10  0:48 ` [PATCH 2/3] nft_hash: define max_shift rhashtable param Josh Hunt
  2015-02-10  0:48 ` [PATCH 3/3] nft_hash: introduce init_size set parameter Josh Hunt
  2 siblings, 1 reply; 11+ messages in thread
From: Josh Hunt @ 2015-02-10  0:48 UTC (permalink / raw)
  To: Pablo Neira Ayuso, Patrick McHardy, Thomas Graf
  Cc: netfilter-devel, netdev, Daniel Borkmann, Josh Hunt

Force rhashtable users to define a max_shift value. This places a ceiling
on how large the table can grow.

Signed-off-by: Josh Hunt <johunt@akamai.com>
---
 lib/rhashtable.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/lib/rhashtable.c b/lib/rhashtable.c
index 9cc4c4a..f1bdfb0 100644
--- a/lib/rhashtable.c
+++ b/lib/rhashtable.c
@@ -1077,7 +1077,8 @@ int rhashtable_init(struct rhashtable *ht, struct rhashtable_params *params)
 	size = HASH_DEFAULT_SIZE;
 
 	if ((params->key_len && !params->hashfn) ||
-	    (!params->key_len && !params->obj_hashfn))
+	    (!params->key_len && !params->obj_hashfn) ||
+	    (!params->max_shift))
 		return -EINVAL;
 
 	if (params->nulls_base && params->nulls_base < (1U << RHT_BASE_SHIFT))
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 2/3] nft_hash: define max_shift rhashtable param
  2015-02-10  0:48 [PATCH 0/3] nft hash set expansion fixes Josh Hunt
  2015-02-10  0:48 ` [PATCH 1/3] rhashtable: require max_shift definition Josh Hunt
@ 2015-02-10  0:48 ` Josh Hunt
  2015-02-10  0:48 ` [PATCH 3/3] nft_hash: introduce init_size set parameter Josh Hunt
  2 siblings, 0 replies; 11+ messages in thread
From: Josh Hunt @ 2015-02-10  0:48 UTC (permalink / raw)
  To: Pablo Neira Ayuso, Patrick McHardy, Thomas Graf
  Cc: netfilter-devel, netdev, Daniel Borkmann, Josh Hunt

Starting with commit "rhashtable: require max_shift definition" all users of
rhashtable must define a max_shift value to set an upper bound the table can
grow to. nft sets presently use nft_set_desc.size to enforce a limit on the size
a set can grow. Use this value to also set the ceiling for rhashtables.

If a user doesn't define a size it will fall back to a newly defined default of
10 (1024 elements.)

Signed-off-by: Josh Hunt <johunt@akamai.com>
---
 net/netfilter/nft_hash.c |    5 +++++
 1 file changed, 5 insertions(+)

diff --git a/net/netfilter/nft_hash.c b/net/netfilter/nft_hash.c
index 61e6c40..08ec179 100644
--- a/net/netfilter/nft_hash.c
+++ b/net/netfilter/nft_hash.c
@@ -23,6 +23,9 @@
 /* We target a hash table size of 4, element hint is 75% of final size */
 #define NFT_HASH_ELEMENT_HINT 3
 
+/* Default max number of elements if user doesn't specify a size */
+#define NFT_HASH_MAX_ELEMENTS 10
+
 struct nft_hash_elem {
 	struct rhash_head		node;
 	struct nft_data			key;
@@ -194,6 +197,8 @@ static int nft_hash_init(const struct nft_set *set,
 		.hashfn = jhash,
 		.grow_decision = rht_grow_above_75,
 		.shrink_decision = rht_shrink_below_30,
+		.max_shift = desc->size ?
+			roundup_pow_of_two(desc->size) : NFT_HASH_MAX_ELEMENTS,
 	};
 
 	return rhashtable_init(priv, &params);
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 3/3] nft_hash: introduce init_size set parameter
  2015-02-10  0:48 [PATCH 0/3] nft hash set expansion fixes Josh Hunt
  2015-02-10  0:48 ` [PATCH 1/3] rhashtable: require max_shift definition Josh Hunt
  2015-02-10  0:48 ` [PATCH 2/3] nft_hash: define max_shift rhashtable param Josh Hunt
@ 2015-02-10  0:48 ` Josh Hunt
  2 siblings, 0 replies; 11+ messages in thread
From: Josh Hunt @ 2015-02-10  0:48 UTC (permalink / raw)
  To: Pablo Neira Ayuso, Patrick McHardy, Thomas Graf
  Cc: netfilter-devel, netdev, Daniel Borkmann, Josh Hunt

Currently nft_hash is using desc->size to both set a ceiling on the number of
entries a set can have, and as the nelem_hint for rhashtable. This not correct
since nelem_hint defines the # of initial buckets for the set to use. It is not
used to enforce a maximum size on the table. That's done through max_shift.

This creates a new parameter 'init_size' to pass as the nelem_hint to rhashtable
as the # of buckets you would like to initialize the table with.

Signed-off-by: Josh Hunt <johunt@akamai.com>
---
 include/net/netfilter/nf_tables.h        |    4 +++-
 include/uapi/linux/netfilter/nf_tables.h |    2 ++
 net/netfilter/nf_tables_api.c            |    4 ++++
 net/netfilter/nft_hash.c                 |    2 +-
 4 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index 9eaaa78..2c9130d 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -153,12 +153,14 @@ struct nft_set_iter {
  *
  *	@klen: key length
  *	@dlen: data length
- *	@size: number of set elements
+ *	@size: max number of set elements
+ *	@init_size: initial set size
  */
 struct nft_set_desc {
 	unsigned int		klen;
 	unsigned int		dlen;
 	unsigned int		size;
+	unsigned int		init_size;
 };
 
 /**
diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
index 832bc46..63e53eb 100644
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -230,10 +230,12 @@ enum nft_set_policies {
  * enum nft_set_desc_attributes - set element description
  *
  * @NFTA_SET_DESC_SIZE: number of elements in set (NLA_U32)
+ * @NFTA_SET_DESC_INIT_SIZE: initial set size (NLA_U32)
  */
 enum nft_set_desc_attributes {
 	NFTA_SET_DESC_UNSPEC,
 	NFTA_SET_DESC_SIZE,
+	NFTA_SET_DESC_INIT_SIZE,
 	__NFTA_SET_DESC_MAX
 };
 #define NFTA_SET_DESC_MAX	(__NFTA_SET_DESC_MAX - 1)
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 199fd0f..275f41b 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -2211,6 +2211,7 @@ static const struct nla_policy nft_set_policy[NFTA_SET_MAX + 1] = {
 
 static const struct nla_policy nft_set_desc_policy[NFTA_SET_DESC_MAX + 1] = {
 	[NFTA_SET_DESC_SIZE]		= { .type = NLA_U32 },
+	[NFTA_SET_DESC_INIT_SIZE]	= { .type = NLA_U32 },
 };
 
 static int nft_ctx_init_from_setattr(struct nft_ctx *ctx,
@@ -2552,6 +2553,9 @@ static int nf_tables_set_desc_parse(const struct nft_ctx *ctx,
 	if (da[NFTA_SET_DESC_SIZE] != NULL)
 		desc->size = ntohl(nla_get_be32(da[NFTA_SET_DESC_SIZE]));
 
+	if (da[NFTA_SET_DESC_INIT_SIZE] != NULL)
+		desc->init_size = ntohl(nla_get_be32(da[NFTA_SET_DESC_INIT_SIZE]));
+
 	return 0;
 }
 
diff --git a/net/netfilter/nft_hash.c b/net/netfilter/nft_hash.c
index 08ec179..e03d1c6 100644
--- a/net/netfilter/nft_hash.c
+++ b/net/netfilter/nft_hash.c
@@ -190,7 +190,7 @@ static int nft_hash_init(const struct nft_set *set,
 {
 	struct rhashtable *priv = nft_set_priv(set);
 	struct rhashtable_params params = {
-		.nelem_hint = desc->size ? : NFT_HASH_ELEMENT_HINT,
+		.nelem_hint = desc->init_size ? : NFT_HASH_ELEMENT_HINT,
 		.head_offset = offsetof(struct nft_hash_elem, node),
 		.key_offset = offsetof(struct nft_hash_elem, key),
 		.key_len = set->klen,
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH 1/3] rhashtable: require max_shift definition
  2015-02-10  0:48 ` [PATCH 1/3] rhashtable: require max_shift definition Josh Hunt
@ 2015-02-10  0:58   ` Thomas Graf
  2015-02-10  8:30     ` Daniel Borkmann
  0 siblings, 1 reply; 11+ messages in thread
From: Thomas Graf @ 2015-02-10  0:58 UTC (permalink / raw)
  To: Josh Hunt
  Cc: Pablo Neira Ayuso, Patrick McHardy, netfilter-devel, netdev,
	Daniel Borkmann

On 02/09/15 at 07:48pm, Josh Hunt wrote:
>  	if ((params->key_len && !params->hashfn) ||
> -	    (!params->key_len && !params->obj_hashfn))
> +	    (!params->key_len && !params->obj_hashfn) ||
> +	    (!params->max_shift))
>  		return -EINVAL;

You can drop the parenthesis around the new max_shift check.

Other than that:

Acked-by: Thomas Graf <tgraf@suug.ch>

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 1/3] rhashtable: require max_shift definition
  2015-02-10  0:58   ` Thomas Graf
@ 2015-02-10  8:30     ` Daniel Borkmann
  2015-02-10 15:56       ` Josh Hunt
  0 siblings, 1 reply; 11+ messages in thread
From: Daniel Borkmann @ 2015-02-10  8:30 UTC (permalink / raw)
  To: Thomas Graf
  Cc: Josh Hunt, Pablo Neira Ayuso, Patrick McHardy, netfilter-devel,
	netdev

On 02/10/2015 01:58 AM, Thomas Graf wrote:
> On 02/09/15 at 07:48pm, Josh Hunt wrote:
>>   	if ((params->key_len && !params->hashfn) ||
>> -	    (!params->key_len && !params->obj_hashfn))
>> +	    (!params->key_len && !params->obj_hashfn) ||
>> +	    (!params->max_shift))
>>   		return -EINVAL;
>
> You can drop the parenthesis around the new max_shift check.

Also, I think the test should be expanded to check if there's
a grow_decision given and only in that case require max_shift
to be non-zero, otherwise we would require users who don't
want to expand their table to give a upper expansion limit.

Thanks,
Daniel

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 1/3] rhashtable: require max_shift definition
  2015-02-10  8:30     ` Daniel Borkmann
@ 2015-02-10 15:56       ` Josh Hunt
  2015-02-10 17:06         ` Daniel Borkmann
  0 siblings, 1 reply; 11+ messages in thread
From: Josh Hunt @ 2015-02-10 15:56 UTC (permalink / raw)
  To: Daniel Borkmann, Thomas Graf
  Cc: Pablo Neira Ayuso, Patrick McHardy, netfilter-devel, netdev

On 02/10/2015 02:30 AM, Daniel Borkmann wrote:
> On 02/10/2015 01:58 AM, Thomas Graf wrote:
>> On 02/09/15 at 07:48pm, Josh Hunt wrote:
>>>       if ((params->key_len && !params->hashfn) ||
>>> -        (!params->key_len && !params->obj_hashfn))
>>> +        (!params->key_len && !params->obj_hashfn) ||
>>> +        (!params->max_shift))
>>>           return -EINVAL;
>>
>> You can drop the parenthesis around the new max_shift check.
>
> Also, I think the test should be expanded to check if there's
> a grow_decision given and only in that case require max_shift
> to be non-zero, otherwise we would require users who don't
> want to expand their table to give a upper expansion limit.

This is a good point. I'll make this change.

max_shift restricts the # of buckets, but should there be an optional 
parameter, maxelems, to set a ceiling on the # of elements in a table 
also? If not, I believe users will be able to add an "unlimited" # of 
entries to the existing buckets, whether or not a grow_decision fn is 
defined.

Josh

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 1/3] rhashtable: require max_shift definition
  2015-02-10 15:56       ` Josh Hunt
@ 2015-02-10 17:06         ` Daniel Borkmann
  2015-02-10 17:22           ` Thomas Graf
  0 siblings, 1 reply; 11+ messages in thread
From: Daniel Borkmann @ 2015-02-10 17:06 UTC (permalink / raw)
  To: Josh Hunt
  Cc: Thomas Graf, Pablo Neira Ayuso, Patrick McHardy, netfilter-devel,
	netdev

On 02/10/2015 04:56 PM, Josh Hunt wrote:
> On 02/10/2015 02:30 AM, Daniel Borkmann wrote:
>> On 02/10/2015 01:58 AM, Thomas Graf wrote:
>>> On 02/09/15 at 07:48pm, Josh Hunt wrote:
>>>>       if ((params->key_len && !params->hashfn) ||
>>>> -        (!params->key_len && !params->obj_hashfn))
>>>> +        (!params->key_len && !params->obj_hashfn) ||
>>>> +        (!params->max_shift))
>>>>           return -EINVAL;
>>>
>>> You can drop the parenthesis around the new max_shift check.
>>
>> Also, I think the test should be expanded to check if there's
>> a grow_decision given and only in that case require max_shift
>> to be non-zero, otherwise we would require users who don't
>> want to expand their table to give a upper expansion limit.
>
> This is a good point. I'll make this change.
>
> max_shift restricts the # of buckets, but should there be an optional parameter, maxelems, to set a ceiling on the # of elements in a table also? If not, I believe users will be able to add an "unlimited" # of entries to the existing buckets, whether or not a grow_decision fn is defined.

Hm, given that min_shift/max_shift are parameters that directly
concern internals of rhashtable i.e. are tightly coupled to expand
and shrink functionality, I'd say that depending on the use case,
a maxelem limit should rather be handled outside of it, if it's
truly an issue/concern.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 1/3] rhashtable: require max_shift definition
  2015-02-10 17:06         ` Daniel Borkmann
@ 2015-02-10 17:22           ` Thomas Graf
  2015-02-10 17:44             ` Patrick McHardy
  0 siblings, 1 reply; 11+ messages in thread
From: Thomas Graf @ 2015-02-10 17:22 UTC (permalink / raw)
  To: Daniel Borkmann
  Cc: Josh Hunt, Pablo Neira Ayuso, Patrick McHardy, netfilter-devel,
	netdev

On 02/10/15 at 06:06pm, Daniel Borkmann wrote:
> Hm, given that min_shift/max_shift are parameters that directly
> concern internals of rhashtable i.e. are tightly coupled to expand
> and shrink functionality, I'd say that depending on the use case,
> a maxelem limit should rather be handled outside of it, if it's
> truly an issue/concern.

Agreed, Netlink already uses the atomic counter of rhashtable to
enforce  upper limit of table entries:

        err = -ENOMEM;
        if (BITS_PER_LONG > 32 &&
            unlikely(atomic_read(&table->hash.nelems) >= UINT_MAX))
                goto err;

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 1/3] rhashtable: require max_shift definition
  2015-02-10 17:22           ` Thomas Graf
@ 2015-02-10 17:44             ` Patrick McHardy
  2015-02-10 21:18               ` Josh Hunt
  0 siblings, 1 reply; 11+ messages in thread
From: Patrick McHardy @ 2015-02-10 17:44 UTC (permalink / raw)
  To: Thomas Graf, Daniel Borkmann
  Cc: Josh Hunt, Pablo Neira Ayuso, netfilter-devel, netdev

Am 10. Februar 2015 18:22:41 MEZ, schrieb Thomas Graf <tgraf@suug.ch>:
>On 02/10/15 at 06:06pm, Daniel Borkmann wrote:
>> Hm, given that min_shift/max_shift are parameters that directly
>> concern internals of rhashtable i.e. are tightly coupled to expand
>> and shrink functionality, I'd say that depending on the use case,
>> a maxelem limit should rather be handled outside of it, if it's
>> truly an issue/concern.
>
>Agreed, Netlink already uses the atomic counter of rhashtable to
>enforce  upper limit of table entries:
>
>        err = -ENOMEM;
>        if (BITS_PER_LONG > 32 &&
>            unlikely(atomic_read(&table->hash.nelems) >= UINT_MAX))
>                goto err;

I would tend to agree with Pablo, now we're handling half (shift) internally and half (max) externally, using internal values.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 1/3] rhashtable: require max_shift definition
  2015-02-10 17:44             ` Patrick McHardy
@ 2015-02-10 21:18               ` Josh Hunt
  0 siblings, 0 replies; 11+ messages in thread
From: Josh Hunt @ 2015-02-10 21:18 UTC (permalink / raw)
  To: Patrick McHardy, Thomas Graf, Daniel Borkmann
  Cc: Pablo Neira Ayuso, netfilter-devel, netdev

On 02/10/2015 11:44 AM, Patrick McHardy wrote:
> Am 10. Februar 2015 18:22:41 MEZ, schrieb Thomas Graf <tgraf@suug.ch>:
>> On 02/10/15 at 06:06pm, Daniel Borkmann wrote:
>>> Hm, given that min_shift/max_shift are parameters that directly
>>> concern internals of rhashtable i.e. are tightly coupled to expand
>>> and shrink functionality, I'd say that depending on the use case,
>>> a maxelem limit should rather be handled outside of it, if it's
>>> truly an issue/concern.
>>
>> Agreed, Netlink already uses the atomic counter of rhashtable to
>> enforce  upper limit of table entries:
>>
>>         err = -ENOMEM;
>>         if (BITS_PER_LONG > 32 &&
>>             unlikely(atomic_read(&table->hash.nelems) >= UINT_MAX))
>>                 goto err;
>
> I would tend to agree with Pablo, now we're handling half (shift) internally and half (max) externally, using internal values.

OK. Thanks for all the feedback. I will send a v2 once the other 2 
patches get reviewed.

Thanks
Josh

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2015-02-10 21:18 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-02-10  0:48 [PATCH 0/3] nft hash set expansion fixes Josh Hunt
2015-02-10  0:48 ` [PATCH 1/3] rhashtable: require max_shift definition Josh Hunt
2015-02-10  0:58   ` Thomas Graf
2015-02-10  8:30     ` Daniel Borkmann
2015-02-10 15:56       ` Josh Hunt
2015-02-10 17:06         ` Daniel Borkmann
2015-02-10 17:22           ` Thomas Graf
2015-02-10 17:44             ` Patrick McHardy
2015-02-10 21:18               ` Josh Hunt
2015-02-10  0:48 ` [PATCH 2/3] nft_hash: define max_shift rhashtable param Josh Hunt
2015-02-10  0:48 ` [PATCH 3/3] nft_hash: introduce init_size set parameter Josh Hunt

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.