Skip to content

Commit aac14d5

Browse files
author
Florian Westphal
committed
netfilter: nft_set_pipapo: shrink data structures
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 Reviewed-by: Stefano Brivio <[email protected]> Signed-off-by: Florian Westphal <[email protected]>
1 parent 07ace0b commit aac14d5

File tree

2 files changed

+51
-40
lines changed

2 files changed

+51
-40
lines changed

net/netfilter/nft_set_pipapo.c

Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -359,11 +359,13 @@
359359
*
360360
* Return: -1 on no match, bit position on 'match_only', 0 otherwise.
361361
*/
362-
int pipapo_refill(unsigned long *map, int len, int rules, unsigned long *dst,
362+
int pipapo_refill(unsigned long *map, unsigned int len, unsigned int rules,
363+
unsigned long *dst,
363364
const union nft_pipapo_map_bucket *mt, bool match_only)
364365
{
365366
unsigned long bitset;
366-
int k, ret = -1;
367+
unsigned int k;
368+
int ret = -1;
367369

368370
for (k = 0; k < len; k++) {
369371
bitset = map[k];
@@ -631,13 +633,17 @@ nft_pipapo_get(const struct net *net, const struct nft_set *set,
631633
*
632634
* Return: 0 on success, -ENOMEM on allocation failure.
633635
*/
634-
static int pipapo_resize(struct nft_pipapo_field *f, int old_rules, int rules)
636+
static int pipapo_resize(struct nft_pipapo_field *f,
637+
unsigned int old_rules, unsigned int rules)
635638
{
636639
long *new_lt = NULL, *new_p, *old_lt = f->lt, *old_p;
637640
union nft_pipapo_map_bucket *new_mt, *old_mt = f->mt;
638-
size_t new_bucket_size, copy;
641+
unsigned int new_bucket_size, copy;
639642
int group, bucket;
640643

644+
if (rules >= NFT_PIPAPO_RULE0_MAX)
645+
return -ENOSPC;
646+
641647
new_bucket_size = DIV_ROUND_UP(rules, BITS_PER_LONG);
642648
#ifdef NFT_PIPAPO_ALIGN
643649
new_bucket_size = roundup(new_bucket_size,
@@ -690,7 +696,7 @@ static int pipapo_resize(struct nft_pipapo_field *f, int old_rules, int rules)
690696

691697
if (new_lt) {
692698
f->bsize = new_bucket_size;
693-
NFT_PIPAPO_LT_ASSIGN(f, new_lt);
699+
f->lt = new_lt;
694700
kvfree(old_lt);
695701
}
696702

@@ -847,8 +853,8 @@ static void pipapo_lt_8b_to_4b(int old_groups, int bsize,
847853
*/
848854
static void pipapo_lt_bits_adjust(struct nft_pipapo_field *f)
849855
{
856+
unsigned int groups, bb;
850857
unsigned long *new_lt;
851-
int groups, bb;
852858
size_t lt_size;
853859

854860
lt_size = f->groups * NFT_PIPAPO_BUCKETS(f->bb) * f->bsize *
@@ -898,7 +904,7 @@ static void pipapo_lt_bits_adjust(struct nft_pipapo_field *f)
898904
f->groups = groups;
899905
f->bb = bb;
900906
kvfree(f->lt);
901-
NFT_PIPAPO_LT_ASSIGN(f, new_lt);
907+
f->lt = new_lt;
902908
}
903909

904910
/**
@@ -915,7 +921,7 @@ static void pipapo_lt_bits_adjust(struct nft_pipapo_field *f)
915921
static int pipapo_insert(struct nft_pipapo_field *f, const uint8_t *k,
916922
int mask_bits)
917923
{
918-
int rule = f->rules, group, ret, bit_offset = 0;
924+
unsigned int rule = f->rules, group, ret, bit_offset = 0;
919925

920926
ret = pipapo_resize(f, f->rules, f->rules + 1);
921927
if (ret)
@@ -1255,8 +1261,14 @@ static int nft_pipapo_insert(const struct net *net, const struct nft_set *set,
12551261
/* Validate */
12561262
start_p = start;
12571263
end_p = end;
1264+
1265+
/* some helpers return -1, or 0 >= for valid rule pos,
1266+
* so we cannot support more than INT_MAX rules at this time.
1267+
*/
1268+
BUILD_BUG_ON(NFT_PIPAPO_RULE0_MAX > INT_MAX);
1269+
12581270
nft_pipapo_for_each_field(f, i, m) {
1259-
if (f->rules >= (unsigned long)NFT_PIPAPO_RULE0_MAX)
1271+
if (f->rules >= NFT_PIPAPO_RULE0_MAX)
12601272
return -ENOSPC;
12611273

12621274
if (memcmp(start_p, end_p,
@@ -1362,7 +1374,7 @@ static struct nft_pipapo_match *pipapo_clone(struct nft_pipapo_match *old)
13621374
if (!new_lt)
13631375
goto out_lt;
13641376

1365-
NFT_PIPAPO_LT_ASSIGN(dst, new_lt);
1377+
dst->lt = new_lt;
13661378

13671379
memcpy(NFT_PIPAPO_LT_ALIGN(new_lt),
13681380
NFT_PIPAPO_LT_ALIGN(src->lt),
@@ -1433,10 +1445,10 @@ static struct nft_pipapo_match *pipapo_clone(struct nft_pipapo_match *old)
14331445
*
14341446
* Return: Number of rules that originated from the same entry as @first.
14351447
*/
1436-
static int pipapo_rules_same_key(struct nft_pipapo_field *f, int first)
1448+
static unsigned int pipapo_rules_same_key(struct nft_pipapo_field *f, unsigned int first)
14371449
{
14381450
struct nft_pipapo_elem *e = NULL; /* Keep gcc happy */
1439-
int r;
1451+
unsigned int r;
14401452

14411453
for (r = first; r < f->rules; r++) {
14421454
if (r != first && e != f->mt[r].e)
@@ -1489,8 +1501,9 @@ static int pipapo_rules_same_key(struct nft_pipapo_field *f, int first)
14891501
* 0 1 2
14901502
* element pointers: 0x42 0x42 0x44
14911503
*/
1492-
static void pipapo_unmap(union nft_pipapo_map_bucket *mt, int rules,
1493-
int start, int n, int to_offset, bool is_last)
1504+
static void pipapo_unmap(union nft_pipapo_map_bucket *mt, unsigned int rules,
1505+
unsigned int start, unsigned int n,
1506+
unsigned int to_offset, bool is_last)
14941507
{
14951508
int i;
14961509

@@ -1596,8 +1609,8 @@ static void pipapo_gc(struct nft_set *set, struct nft_pipapo_match *m)
15961609
{
15971610
struct nft_pipapo *priv = nft_set_priv(set);
15981611
struct net *net = read_pnet(&set->net);
1612+
unsigned int rules_f0, first_rule = 0;
15991613
u64 tstamp = nft_net_tstamp(net);
1600-
int rules_f0, first_rule = 0;
16011614
struct nft_pipapo_elem *e;
16021615
struct nft_trans_gc *gc;
16031616

@@ -1608,7 +1621,7 @@ static void pipapo_gc(struct nft_set *set, struct nft_pipapo_match *m)
16081621
while ((rules_f0 = pipapo_rules_same_key(m->f, first_rule))) {
16091622
union nft_pipapo_map_bucket rulemap[NFT_PIPAPO_MAX_FIELDS];
16101623
const struct nft_pipapo_field *f;
1611-
int i, start, rules_fx;
1624+
unsigned int i, start, rules_fx;
16121625

16131626
start = first_rule;
16141627
rules_fx = rules_f0;
@@ -1986,7 +1999,7 @@ static void nft_pipapo_remove(const struct net *net, const struct nft_set *set,
19861999
{
19872000
struct nft_pipapo *priv = nft_set_priv(set);
19882001
struct nft_pipapo_match *m = priv->clone;
1989-
int rules_f0, first_rule = 0;
2002+
unsigned int rules_f0, first_rule = 0;
19902003
struct nft_pipapo_elem *e;
19912004
const u8 *data;
19922005

@@ -2051,7 +2064,7 @@ static void nft_pipapo_walk(const struct nft_ctx *ctx, struct nft_set *set,
20512064
struct net *net = read_pnet(&set->net);
20522065
const struct nft_pipapo_match *m;
20532066
const struct nft_pipapo_field *f;
2054-
int i, r;
2067+
unsigned int i, r;
20552068

20562069
rcu_read_lock();
20572070
if (iter->genmask == nft_genmask_cur(net))
@@ -2155,6 +2168,9 @@ static int nft_pipapo_init(const struct nft_set *set,
21552168

21562169
field_count = desc->field_count ? : 1;
21572170

2171+
BUILD_BUG_ON(NFT_PIPAPO_MAX_FIELDS > 255);
2172+
BUILD_BUG_ON(NFT_PIPAPO_MAX_FIELDS != NFT_REG32_COUNT);
2173+
21582174
if (field_count > NFT_PIPAPO_MAX_FIELDS)
21592175
return -EINVAL;
21602176

@@ -2176,7 +2192,11 @@ static int nft_pipapo_init(const struct nft_set *set,
21762192
rcu_head_init(&m->rcu);
21772193

21782194
nft_pipapo_for_each_field(f, i, m) {
2179-
int len = desc->field_len[i] ? : set->klen;
2195+
unsigned int len = desc->field_len[i] ? : set->klen;
2196+
2197+
/* f->groups is u8 */
2198+
BUILD_BUG_ON((NFT_PIPAPO_MAX_BYTES *
2199+
BITS_PER_BYTE / NFT_PIPAPO_GROUP_BITS_LARGE_SET) >= 256);
21802200

21812201
f->bb = NFT_PIPAPO_GROUP_BITS_INIT;
21822202
f->groups = len * NFT_PIPAPO_GROUPS_PER_BYTE(f);
@@ -2185,7 +2205,7 @@ static int nft_pipapo_init(const struct nft_set *set,
21852205

21862206
f->bsize = 0;
21872207
f->rules = 0;
2188-
NFT_PIPAPO_LT_ASSIGN(f, NULL);
2208+
f->lt = NULL;
21892209
f->mt = NULL;
21902210
}
21912211

@@ -2221,7 +2241,7 @@ static void nft_set_pipapo_match_destroy(const struct nft_ctx *ctx,
22212241
struct nft_pipapo_match *m)
22222242
{
22232243
struct nft_pipapo_field *f;
2224-
int i, r;
2244+
unsigned int i, r;
22252245

22262246
for (i = 0, f = m->f; i < m->field_count - 1; i++, f++)
22272247
;

net/netfilter/nft_set_pipapo.h

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -70,15 +70,9 @@
7070
#define NFT_PIPAPO_ALIGN_HEADROOM \
7171
(NFT_PIPAPO_ALIGN - ARCH_KMALLOC_MINALIGN)
7272
#define NFT_PIPAPO_LT_ALIGN(lt) (PTR_ALIGN((lt), NFT_PIPAPO_ALIGN))
73-
#define NFT_PIPAPO_LT_ASSIGN(field, x) \
74-
do { \
75-
(field)->lt_aligned = NFT_PIPAPO_LT_ALIGN(x); \
76-
(field)->lt = (x); \
77-
} while (0)
7873
#else
7974
#define NFT_PIPAPO_ALIGN_HEADROOM 0
8075
#define NFT_PIPAPO_LT_ALIGN(lt) (lt)
81-
#define NFT_PIPAPO_LT_ASSIGN(field, x) ((field)->lt = (x))
8276
#endif /* NFT_PIPAPO_ALIGN */
8377

8478
#define nft_pipapo_for_each_field(field, index, match) \
@@ -110,22 +104,18 @@ union nft_pipapo_map_bucket {
110104

111105
/**
112106
* struct nft_pipapo_field - Lookup, mapping tables and related data for a field
113-
* @groups: Amount of bit groups
114107
* @rules: Number of inserted rules
115108
* @bsize: Size of each bucket in lookup table, in longs
109+
* @groups: Amount of bit groups
116110
* @bb: Number of bits grouped together in lookup table buckets
117111
* @lt: Lookup table: 'groups' rows of buckets
118-
* @lt_aligned: Version of @lt aligned to NFT_PIPAPO_ALIGN bytes
119112
* @mt: Mapping table: one bucket per rule
120113
*/
121114
struct nft_pipapo_field {
122-
int groups;
123-
unsigned long rules;
124-
size_t bsize;
125-
int bb;
126-
#ifdef NFT_PIPAPO_ALIGN
127-
unsigned long *lt_aligned;
128-
#endif
115+
unsigned int rules;
116+
unsigned int bsize;
117+
u8 groups;
118+
u8 bb;
129119
unsigned long *lt;
130120
union nft_pipapo_map_bucket *mt;
131121
};
@@ -145,15 +135,15 @@ struct nft_pipapo_scratch {
145135
/**
146136
* struct nft_pipapo_match - Data used for lookup and matching
147137
* @field_count: Amount of fields in set
148-
* @scratch: Preallocated per-CPU maps for partial matching results
149138
* @bsize_max: Maximum lookup table bucket size of all fields, in longs
139+
* @scratch: Preallocated per-CPU maps for partial matching results
150140
* @rcu: Matching data is swapped on commits
151141
* @f: Fields, with lookup and mapping tables
152142
*/
153143
struct nft_pipapo_match {
154-
int field_count;
144+
u8 field_count;
145+
unsigned int bsize_max;
155146
struct nft_pipapo_scratch * __percpu *scratch;
156-
size_t bsize_max;
157147
struct rcu_head rcu;
158148
struct nft_pipapo_field f[] __counted_by(field_count);
159149
};
@@ -186,7 +176,8 @@ struct nft_pipapo_elem {
186176
struct nft_set_ext ext;
187177
};
188178

189-
int pipapo_refill(unsigned long *map, int len, int rules, unsigned long *dst,
179+
int pipapo_refill(unsigned long *map, unsigned int len, unsigned int rules,
180+
unsigned long *dst,
190181
const union nft_pipapo_map_bucket *mt, bool match_only);
191182

192183
/**

0 commit comments

Comments
 (0)