Skip to content

Commit 976afca

Browse files
YiHungWeiummakynes
authored andcommitted
netfilter: nf_conncount: Early exit in nf_conncount_lookup() and cleanup
This patch is originally from Florian Westphal. This patch does the following three tasks. It applies the same early exit technique for nf_conncount_lookup(). Since now we keep the number of connections in 'struct nf_conncount_list', we no longer need to return the count in nf_conncount_lookup(). Moreover, we expose the garbage collection function nf_conncount_gc_list() for nft_connlimit. Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com> Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
1 parent cb2b36f commit 976afca

File tree

3 files changed

+33
-25
lines changed

3 files changed

+33
-25
lines changed

include/net/netfilter/nf_conntrack_count.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,20 @@ unsigned int nf_conncount_count(struct net *net,
2121
const struct nf_conntrack_tuple *tuple,
2222
const struct nf_conntrack_zone *zone);
2323

24-
unsigned int nf_conncount_lookup(struct net *net, struct nf_conncount_list *list,
25-
const struct nf_conntrack_tuple *tuple,
26-
const struct nf_conntrack_zone *zone,
27-
bool *addit);
24+
void nf_conncount_lookup(struct net *net, struct nf_conncount_list *list,
25+
const struct nf_conntrack_tuple *tuple,
26+
const struct nf_conntrack_zone *zone,
27+
bool *addit);
2828

2929
void nf_conncount_list_init(struct nf_conncount_list *list);
3030

3131
bool nf_conncount_add(struct nf_conncount_list *list,
3232
const struct nf_conntrack_tuple *tuple,
3333
const struct nf_conntrack_zone *zone);
3434

35+
void nf_conncount_gc_list(struct net *net,
36+
struct nf_conncount_list *list);
37+
3538
void nf_conncount_cache_free(struct nf_conncount_list *list);
3639

3740
#endif

net/netfilter/nf_conncount.c

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -144,35 +144,38 @@ find_or_evict(struct net *net, struct nf_conncount_list *list,
144144
return ERR_PTR(-EAGAIN);
145145
}
146146

147-
unsigned int nf_conncount_lookup(struct net *net,
148-
struct nf_conncount_list *list,
149-
const struct nf_conntrack_tuple *tuple,
150-
const struct nf_conntrack_zone *zone,
151-
bool *addit)
147+
void nf_conncount_lookup(struct net *net,
148+
struct nf_conncount_list *list,
149+
const struct nf_conntrack_tuple *tuple,
150+
const struct nf_conntrack_zone *zone,
151+
bool *addit)
152152
{
153153
const struct nf_conntrack_tuple_hash *found;
154154
struct nf_conncount_tuple *conn, *conn_n;
155155
struct nf_conn *found_ct;
156-
unsigned int length = 0;
156+
unsigned int collect = 0;
157157

158+
/* best effort only */
158159
*addit = tuple ? true : false;
159160

160161
/* check the saved connections */
161162
list_for_each_entry_safe(conn, conn_n, &list->head, node) {
163+
if (collect > CONNCOUNT_GC_MAX_NODES)
164+
break;
165+
162166
found = find_or_evict(net, list, conn);
163167
if (IS_ERR(found)) {
164168
/* Not found, but might be about to be confirmed */
165169
if (PTR_ERR(found) == -EAGAIN) {
166-
length++;
167170
if (!tuple)
168171
continue;
169172

170173
if (nf_ct_tuple_equal(&conn->tuple, tuple) &&
171174
nf_ct_zone_id(&conn->zone, conn->zone.dir) ==
172175
nf_ct_zone_id(zone, zone->dir))
173176
*addit = false;
174-
}
175-
177+
} else if (PTR_ERR(found) == -ENOENT)
178+
collect++;
176179
continue;
177180
}
178181

@@ -181,9 +184,10 @@ unsigned int nf_conncount_lookup(struct net *net,
181184
if (tuple && nf_ct_tuple_equal(&conn->tuple, tuple) &&
182185
nf_ct_zone_equal(found_ct, zone, zone->dir)) {
183186
/*
184-
* Just to be sure we have it only once in the list.
185187
* We should not see tuples twice unless someone hooks
186188
* this into a table without "-p tcp --syn".
189+
*
190+
* Attempt to avoid a re-add in this case.
187191
*/
188192
*addit = false;
189193
} else if (already_closed(found_ct)) {
@@ -193,14 +197,12 @@ unsigned int nf_conncount_lookup(struct net *net,
193197
*/
194198
nf_ct_put(found_ct);
195199
conn_free(list, conn);
200+
collect++;
196201
continue;
197202
}
198203

199204
nf_ct_put(found_ct);
200-
length++;
201205
}
202-
203-
return length;
204206
}
205207
EXPORT_SYMBOL_GPL(nf_conncount_lookup);
206208

@@ -211,8 +213,8 @@ void nf_conncount_list_init(struct nf_conncount_list *list)
211213
}
212214
EXPORT_SYMBOL_GPL(nf_conncount_list_init);
213215

214-
static void nf_conncount_gc_list(struct net *net,
215-
struct nf_conncount_list *list)
216+
void nf_conncount_gc_list(struct net *net,
217+
struct nf_conncount_list *list)
216218
{
217219
const struct nf_conntrack_tuple_hash *found;
218220
struct nf_conncount_tuple *conn, *conn_n;
@@ -244,6 +246,7 @@ static void nf_conncount_gc_list(struct net *net,
244246
return;
245247
}
246248
}
249+
EXPORT_SYMBOL_GPL(nf_conncount_gc_list);
247250

248251
static void tree_nodes_free(struct rb_root *root,
249252
struct nf_conncount_rb *gc_nodes[],
@@ -291,8 +294,9 @@ count_tree(struct net *net, struct rb_root *root,
291294
/* same source network -> be counted! */
292295
unsigned int count;
293296

294-
count = nf_conncount_lookup(net, &rbconn->list, tuple,
295-
zone, &addit);
297+
nf_conncount_lookup(net, &rbconn->list, tuple, zone,
298+
&addit);
299+
count = rbconn->list.count;
296300

297301
tree_nodes_free(root, gc_nodes, gc_count);
298302
if (!addit)

net/netfilter/nft_connlimit.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,9 @@ static inline void nft_connlimit_do_eval(struct nft_connlimit *priv,
4646
}
4747

4848
spin_lock_bh(&priv->lock);
49-
count = nf_conncount_lookup(nft_net(pkt), &priv->list, tuple_ptr, zone,
50-
&addit);
49+
nf_conncount_lookup(nft_net(pkt), &priv->list, tuple_ptr, zone,
50+
&addit);
51+
count = priv->list.count;
5152

5253
if (!addit)
5354
goto out;
@@ -231,10 +232,10 @@ static void nft_connlimit_destroy_clone(const struct nft_ctx *ctx,
231232
static bool nft_connlimit_gc(struct net *net, const struct nft_expr *expr)
232233
{
233234
struct nft_connlimit *priv = nft_expr_priv(expr);
234-
bool addit, ret;
235+
bool ret;
235236

236237
spin_lock_bh(&priv->lock);
237-
nf_conncount_lookup(net, &priv->list, NULL, &nf_ct_zone_dflt, &addit);
238+
nf_conncount_gc_list(net, &priv->list);
238239

239240
ret = list_empty(&priv->list.head);
240241
spin_unlock_bh(&priv->lock);

0 commit comments

Comments
 (0)