From: Stefano Brivio <sbrivio@redhat.com>
To: Florian Westphal <fw@strlen.de>
Cc: <netfilter-devel@vger.kernel.org>
Subject: Re: [PATCH nf-next 3/4] netfilter: nft_set_pipapo: shrink data structures
Date: Tue, 13 Feb 2024 14:17:02 +0100 [thread overview]
Message-ID: <20240213141702.6c55e57d@elisabeth> (raw)
In-Reply-To: <20240212100202.10116-4-fw@strlen.de>
On Mon, 12 Feb 2024 11:01:52 +0100
Florian Westphal <fw@strlen.de> wrote:
> The set uses a mix of 'int', 'unsigned int', and size_t.
>
> The rule count limit is NFT_PIPAPO_RULE0_MAX, which cannot
> exceed INT_MAX (a few helpers use 'int' as return type).
>
> Add a compile-time assertion for this.
>
> Replace size_t usage in structs with unsigned int or u8 where
> the stored values are smaller.
>
> Replace signed-int arguments for lengths with 'unsigned int'
> where possible.
>
> Last, remove lt_aligned member: its set but never read.
>
> struct nft_pipapo_match 40 bytes -> 32 bytes
> struct nft_pipapo_field 56 bytes -> 32 bytes
>
> Signed-off-by: Florian Westphal <fw@strlen.de>
> ---
> net/netfilter/nft_set_pipapo.c | 60 ++++++++++++++++++++++------------
> net/netfilter/nft_set_pipapo.h | 29 ++++++----------
> 2 files changed, 49 insertions(+), 40 deletions(-)
>
> diff --git a/net/netfilter/nft_set_pipapo.c b/net/netfilter/nft_set_pipapo.c
> index 6a79ec98de86..a0ddf24a8052 100644
> --- a/net/netfilter/nft_set_pipapo.c
> +++ b/net/netfilter/nft_set_pipapo.c
> @@ -359,11 +359,13 @@
> *
> * Return: -1 on no match, bit position on 'match_only', 0 otherwise.
> */
> -int pipapo_refill(unsigned long *map, int len, int rules, unsigned long *dst,
> +int pipapo_refill(unsigned long *map, unsigned int len, unsigned int rules,
> + unsigned long *dst,
> const union nft_pipapo_map_bucket *mt, bool match_only)
> {
> unsigned long bitset;
> - int k, ret = -1;
> + unsigned int k;
> + int ret = -1;
>
> for (k = 0; k < len; k++) {
> bitset = map[k];
> @@ -632,13 +634,16 @@ nft_pipapo_get(const struct net *net, const struct nft_set *set,
> *
> * Return: 0 on success, -ENOMEM on allocation failure.
> */
> -static int pipapo_resize(struct nft_pipapo_field *f, int old_rules, int rules)
> +static int pipapo_resize(struct nft_pipapo_field *f, unsigned int old_rules, unsigned int rules)
Nit:
static int pipapo_resize(struct nft_pipapo_field *f,
unsigned int old_rules, unsigned int rules)
without losing readability.
> {
> long *new_lt = NULL, *new_p, *old_lt = f->lt, *old_p;
> union nft_pipapo_map_bucket *new_mt, *old_mt = f->mt;
> - size_t new_bucket_size, copy;
> + unsigned int new_bucket_size, copy;
> int group, bucket;
>
> + if (rules >= NFT_PIPAPO_RULE0_MAX)
> + return -ENOSPC;
> +
> new_bucket_size = DIV_ROUND_UP(rules, BITS_PER_LONG);
> #ifdef NFT_PIPAPO_ALIGN
> new_bucket_size = roundup(new_bucket_size,
> @@ -691,7 +696,7 @@ static int pipapo_resize(struct nft_pipapo_field *f, int old_rules, int rules)
>
> if (new_lt) {
> f->bsize = new_bucket_size;
> - NFT_PIPAPO_LT_ASSIGN(f, new_lt);
> + f->lt = new_lt;
> kvfree(old_lt);
> }
>
> @@ -848,8 +853,8 @@ static void pipapo_lt_8b_to_4b(int old_groups, int bsize,
> */
> static void pipapo_lt_bits_adjust(struct nft_pipapo_field *f)
> {
> + unsigned int groups, bb;
> unsigned long *new_lt;
> - int groups, bb;
> size_t lt_size;
>
> lt_size = f->groups * NFT_PIPAPO_BUCKETS(f->bb) * f->bsize *
> @@ -899,7 +904,7 @@ static void pipapo_lt_bits_adjust(struct nft_pipapo_field *f)
> f->groups = groups;
> f->bb = bb;
> kvfree(f->lt);
> - NFT_PIPAPO_LT_ASSIGN(f, new_lt);
> + f->lt = new_lt;
> }
>
> /**
> @@ -916,7 +921,7 @@ static void pipapo_lt_bits_adjust(struct nft_pipapo_field *f)
> static int pipapo_insert(struct nft_pipapo_field *f, const uint8_t *k,
> int mask_bits)
> {
> - int rule = f->rules, group, ret, bit_offset = 0;
> + unsigned int rule = f->rules, group, ret, bit_offset = 0;
>
> ret = pipapo_resize(f, f->rules, f->rules + 1);
> if (ret)
> @@ -1256,8 +1261,14 @@ static int nft_pipapo_insert(const struct net *net, const struct nft_set *set,
> /* Validate */
> start_p = start;
> end_p = end;
> +
> + /* some helpers return -1, or 0 >= for valid rule pos,
> + * so we cannot support more than INT_MAX rules at this time.
> + */
> + BUILD_BUG_ON(NFT_PIPAPO_RULE0_MAX > INT_MAX);
> +
> nft_pipapo_for_each_field(f, i, m) {
> - if (f->rules >= (unsigned long)NFT_PIPAPO_RULE0_MAX)
> + if (f->rules >= NFT_PIPAPO_RULE0_MAX)
> return -ENOSPC;
>
> if (memcmp(start_p, end_p,
> @@ -1363,7 +1374,7 @@ static struct nft_pipapo_match *pipapo_clone(struct nft_pipapo_match *old)
> if (!new_lt)
> goto out_lt;
>
> - NFT_PIPAPO_LT_ASSIGN(dst, new_lt);
> + dst->lt = new_lt;
>
> memcpy(NFT_PIPAPO_LT_ALIGN(new_lt),
> NFT_PIPAPO_LT_ALIGN(src->lt),
> @@ -1433,10 +1444,10 @@ static struct nft_pipapo_match *pipapo_clone(struct nft_pipapo_match *old)
> *
> * Return: Number of rules that originated from the same entry as @first.
> */
> -static int pipapo_rules_same_key(struct nft_pipapo_field *f, int first)
> +static unsigned int pipapo_rules_same_key(struct nft_pipapo_field *f, unsigned int first)
> {
> struct nft_pipapo_elem *e = NULL; /* Keep gcc happy */
> - int r;
> + unsigned int r;
>
> for (r = first; r < f->rules; r++) {
> if (r != first && e != f->mt[r].e)
> @@ -1489,8 +1500,8 @@ static int pipapo_rules_same_key(struct nft_pipapo_field *f, int first)
> * 0 1 2
> * element pointers: 0x42 0x42 0x44
> */
> -static void pipapo_unmap(union nft_pipapo_map_bucket *mt, int rules,
> - int start, int n, int to_offset, bool is_last)
> +static void pipapo_unmap(union nft_pipapo_map_bucket *mt, unsigned int rules,
> + unsigned int start, unsigned int n, unsigned int to_offset, bool is_last)
Same here,
static void pipapo_unmap(union nft_pipapo_map_bucket *mt, unsigned int rules,
unsigned int start, unsigned int n,
unsigned int to_offset, bool is_last)
?
> {
> int i;
>
> @@ -1596,8 +1607,8 @@ static void pipapo_gc(struct nft_set *set, struct nft_pipapo_match *m)
> {
> struct nft_pipapo *priv = nft_set_priv(set);
> struct net *net = read_pnet(&set->net);
> + unsigned int rules_f0, first_rule = 0;
> u64 tstamp = nft_net_tstamp(net);
> - int rules_f0, first_rule = 0;
> struct nft_pipapo_elem *e;
> struct nft_trans_gc *gc;
>
> @@ -1608,7 +1619,7 @@ static void pipapo_gc(struct nft_set *set, struct nft_pipapo_match *m)
> while ((rules_f0 = pipapo_rules_same_key(m->f, first_rule))) {
> union nft_pipapo_map_bucket rulemap[NFT_PIPAPO_MAX_FIELDS];
> const struct nft_pipapo_field *f;
> - int i, start, rules_fx;
> + unsigned int i, start, rules_fx;
>
> start = first_rule;
> rules_fx = rules_f0;
> @@ -1986,7 +1997,7 @@ static void nft_pipapo_remove(const struct net *net, const struct nft_set *set,
> {
> struct nft_pipapo *priv = nft_set_priv(set);
> struct nft_pipapo_match *m = priv->clone;
> - int rules_f0, first_rule = 0;
> + unsigned int rules_f0, first_rule = 0;
> struct nft_pipapo_elem *e;
> const u8 *data;
>
> @@ -2051,7 +2062,7 @@ static void nft_pipapo_walk(const struct nft_ctx *ctx, struct nft_set *set,
> struct net *net = read_pnet(&set->net);
> const struct nft_pipapo_match *m;
> const struct nft_pipapo_field *f;
> - int i, r;
> + unsigned int i, r;
>
> rcu_read_lock();
> if (iter->genmask == nft_genmask_cur(net))
> @@ -2155,6 +2166,9 @@ static int nft_pipapo_init(const struct nft_set *set,
>
> field_count = desc->field_count ? : 1;
>
> + BUILD_BUG_ON(NFT_PIPAPO_MAX_FIELDS > 255);
> + BUILD_BUG_ON(NFT_PIPAPO_MAX_FIELDS != NFT_REG32_COUNT);
> +
> if (field_count > NFT_PIPAPO_MAX_FIELDS)
> return -EINVAL;
>
> @@ -2176,7 +2190,11 @@ static int nft_pipapo_init(const struct nft_set *set,
> rcu_head_init(&m->rcu);
>
> nft_pipapo_for_each_field(f, i, m) {
> - int len = desc->field_len[i] ? : set->klen;
> + unsigned int len = desc->field_len[i] ? : set->klen;
> +
> + /* f->groups is u8 */
> + BUILD_BUG_ON((NFT_PIPAPO_MAX_BYTES *
> + BITS_PER_BYTE / NFT_PIPAPO_GROUP_BITS_LARGE_SET) >= 256);
>
> f->bb = NFT_PIPAPO_GROUP_BITS_INIT;
> f->groups = len * NFT_PIPAPO_GROUPS_PER_BYTE(f);
> @@ -2185,7 +2203,7 @@ static int nft_pipapo_init(const struct nft_set *set,
>
> f->bsize = 0;
> f->rules = 0;
> - NFT_PIPAPO_LT_ASSIGN(f, NULL);
> + f->lt = NULL;
> f->mt = NULL;
> }
>
> @@ -2221,7 +2239,7 @@ static void nft_set_pipapo_match_destroy(const struct nft_ctx *ctx,
> struct nft_pipapo_match *m)
> {
> struct nft_pipapo_field *f;
> - int i, r;
> + unsigned int i, r;
>
> for (i = 0, f = m->f; i < m->field_count - 1; i++, f++)
> ;
> diff --git a/net/netfilter/nft_set_pipapo.h b/net/netfilter/nft_set_pipapo.h
> index 90d22d691afc..8d9486ae0c01 100644
> --- a/net/netfilter/nft_set_pipapo.h
> +++ b/net/netfilter/nft_set_pipapo.h
> @@ -70,15 +70,9 @@
> #define NFT_PIPAPO_ALIGN_HEADROOM \
> (NFT_PIPAPO_ALIGN - ARCH_KMALLOC_MINALIGN)
> #define NFT_PIPAPO_LT_ALIGN(lt) (PTR_ALIGN((lt), NFT_PIPAPO_ALIGN))
> -#define NFT_PIPAPO_LT_ASSIGN(field, x) \
> - do { \
> - (field)->lt_aligned = NFT_PIPAPO_LT_ALIGN(x); \
> - (field)->lt = (x); \
> - } while (0)
> #else
> #define NFT_PIPAPO_ALIGN_HEADROOM 0
> #define NFT_PIPAPO_LT_ALIGN(lt) (lt)
> -#define NFT_PIPAPO_LT_ASSIGN(field, x) ((field)->lt = (x))
> #endif /* NFT_PIPAPO_ALIGN */
>
> #define nft_pipapo_for_each_field(field, index, match) \
> @@ -110,22 +104,18 @@ union nft_pipapo_map_bucket {
>
> /**
> * struct nft_pipapo_field - Lookup, mapping tables and related data for a field
> - * @groups: Amount of bit groups
> * @rules: Number of inserted rules
> * @bsize: Size of each bucket in lookup table, in longs
> + * @groups: Amount of bit groups
> * @bb: Number of bits grouped together in lookup table buckets
> * @lt: Lookup table: 'groups' rows of buckets
> - * @lt_aligned: Version of @lt aligned to NFT_PIPAPO_ALIGN bytes
> * @mt: Mapping table: one bucket per rule
> */
> struct nft_pipapo_field {
> - int groups;
> - unsigned long rules;
> - size_t bsize;
> - int bb;
> -#ifdef NFT_PIPAPO_ALIGN
> - unsigned long *lt_aligned;
> -#endif
> + unsigned int rules;
> + unsigned int bsize;
> + u8 groups;
> + u8 bb;
> unsigned long *lt;
> union nft_pipapo_map_bucket *mt;
> };
> @@ -145,15 +135,15 @@ struct nft_pipapo_scratch {
> /**
> * struct nft_pipapo_match - Data used for lookup and matching
> * @field_count Amount of fields in set
> - * @scratch: Preallocated per-CPU maps for partial matching results
> * @bsize_max: Maximum lookup table bucket size of all fields, in longs
> + * @scratch: Preallocated per-CPU maps for partial matching results
> * @rcu Matching data is swapped on commits
> * @f: Fields, with lookup and mapping tables
> */
> struct nft_pipapo_match {
> - int field_count;
> + u8 field_count;
> + unsigned int bsize_max;
> struct nft_pipapo_scratch * __percpu *scratch;
> - size_t bsize_max;
> struct rcu_head rcu;
> struct nft_pipapo_field f[] __counted_by(field_count);
> };
> @@ -186,7 +176,8 @@ struct nft_pipapo_elem {
> struct nft_set_ext ext;
> };
>
> -int pipapo_refill(unsigned long *map, int len, int rules, unsigned long *dst,
> +int pipapo_refill(unsigned long *map, unsigned int len, unsigned int rules,
> + unsigned long *dst,
> const union nft_pipapo_map_bucket *mt, bool match_only);
>
> /**
--
Stefano
next prev parent reply other threads:[~2024-02-13 13:18 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-02-12 10:01 [PATCH nf-next 0/4] netfilter: nft_set_pipapo: speed up bulk element insertions Florian Westphal
2024-02-12 10:01 ` [PATCH nf-next 1/4] netfilter: nft_set_pipapo: constify lookup fn args where possible Florian Westphal
2024-02-13 7:19 ` Stefano Brivio
2024-02-12 10:01 ` [PATCH nf-next 2/4] netfilter: nft_set_pipapo: do not rely on ZERO_SIZE_PTR Florian Westphal
2024-02-13 7:20 ` Stefano Brivio
2024-02-13 11:09 ` Florian Westphal
2024-02-12 10:01 ` [PATCH nf-next 3/4] netfilter: nft_set_pipapo: shrink data structures Florian Westphal
2024-02-13 13:17 ` Stefano Brivio [this message]
2024-02-12 10:01 ` [PATCH nf-next 4/4] netfilter: nft_set_pipapo: speed up bulk element insertions Florian Westphal
2024-02-13 13:17 ` Stefano Brivio
2024-02-13 13:29 ` Florian Westphal
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240213141702.6c55e57d@elisabeth \
--to=sbrivio@redhat.com \
--cc=fw@strlen.de \
--cc=netfilter-devel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).