Skip to content

Commit 1397af5

Browse files
Florian Westphalummakynes
authored andcommitted
netfilter: conntrack: remove the percpu dying list
Its no longer needed. Entries that need event redelivery are placed on the new pernet dying list. The advantage is that there is no need to take additional spinlock on conntrack removal unless event redelivery failed or the conntrack entry was never added to the table in the first place (confirmed bit not set). The IPS_CONFIRMED bit now needs to be set as soon as the entry has been unlinked from the unconfirmed list, else the destroy function may attempt to unlink it a second time. Signed-off-by: Florian Westphal <[email protected]> Signed-off-by: Pablo Neira Ayuso <[email protected]>
1 parent 0d3cc50 commit 1397af5

File tree

4 files changed

+13
-47
lines changed

4 files changed

+13
-47
lines changed

include/net/netns/conntrack.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,6 @@ struct nf_ip_net {
9696
struct ct_pcpu {
9797
spinlock_t lock;
9898
struct hlist_nulls_head unconfirmed;
99-
struct hlist_nulls_head dying;
10099
};
101100

102101
struct netns_ct {

net/netfilter/nf_conntrack_core.c

Lines changed: 6 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -525,21 +525,6 @@ clean_from_lists(struct nf_conn *ct)
525525
nf_ct_remove_expectations(ct);
526526
}
527527

528-
/* must be called with local_bh_disable */
529-
static void nf_ct_add_to_dying_list(struct nf_conn *ct)
530-
{
531-
struct ct_pcpu *pcpu;
532-
533-
/* add this conntrack to the (per cpu) dying list */
534-
ct->cpu = smp_processor_id();
535-
pcpu = per_cpu_ptr(nf_ct_net(ct)->ct.pcpu_lists, ct->cpu);
536-
537-
spin_lock(&pcpu->lock);
538-
hlist_nulls_add_head(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode,
539-
&pcpu->dying);
540-
spin_unlock(&pcpu->lock);
541-
}
542-
543528
/* must be called with local_bh_disable */
544529
static void nf_ct_add_to_unconfirmed_list(struct nf_conn *ct)
545530
{
@@ -556,11 +541,11 @@ static void nf_ct_add_to_unconfirmed_list(struct nf_conn *ct)
556541
}
557542

558543
/* must be called with local_bh_disable */
559-
static void nf_ct_del_from_dying_or_unconfirmed_list(struct nf_conn *ct)
544+
static void nf_ct_del_from_unconfirmed_list(struct nf_conn *ct)
560545
{
561546
struct ct_pcpu *pcpu;
562547

563-
/* We overload first tuple to link into unconfirmed or dying list.*/
548+
/* We overload first tuple to link into unconfirmed list.*/
564549
pcpu = per_cpu_ptr(nf_ct_net(ct)->ct.pcpu_lists, ct->cpu);
565550

566551
spin_lock(&pcpu->lock);
@@ -648,7 +633,8 @@ void nf_ct_destroy(struct nf_conntrack *nfct)
648633
*/
649634
nf_ct_remove_expectations(ct);
650635

651-
nf_ct_del_from_dying_or_unconfirmed_list(ct);
636+
if (unlikely(!nf_ct_is_confirmed(ct)))
637+
nf_ct_del_from_unconfirmed_list(ct);
652638

653639
local_bh_enable();
654640

@@ -686,7 +672,6 @@ static void nf_ct_delete_from_lists(struct nf_conn *ct)
686672
local_bh_disable();
687673

688674
__nf_ct_delete_from_lists(ct);
689-
nf_ct_add_to_dying_list(ct);
690675

691676
local_bh_enable();
692677
}
@@ -700,8 +685,6 @@ static void nf_ct_add_to_ecache_list(struct nf_conn *ct)
700685
hlist_nulls_add_head_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode,
701686
&cnet->ecache.dying_list);
702687
spin_unlock(&cnet->ecache.dying_lock);
703-
#else
704-
nf_ct_add_to_dying_list(ct);
705688
#endif
706689
}
707690

@@ -995,7 +978,6 @@ static void __nf_conntrack_insert_prepare(struct nf_conn *ct)
995978
struct nf_conn_tstamp *tstamp;
996979

997980
refcount_inc(&ct->ct_general.use);
998-
ct->status |= IPS_CONFIRMED;
999981

1000982
/* set conntrack timestamp, if enabled. */
1001983
tstamp = nf_conn_tstamp_find(ct);
@@ -1024,7 +1006,6 @@ static int __nf_ct_resolve_clash(struct sk_buff *skb,
10241006
nf_conntrack_get(&ct->ct_general);
10251007

10261008
nf_ct_acct_merge(ct, ctinfo, loser_ct);
1027-
nf_ct_add_to_dying_list(loser_ct);
10281009
nf_ct_put(loser_ct);
10291010
nf_ct_set(skb, ct, ctinfo);
10301011

@@ -1157,7 +1138,6 @@ nf_ct_resolve_clash(struct sk_buff *skb, struct nf_conntrack_tuple_hash *h,
11571138
return ret;
11581139

11591140
drop:
1160-
nf_ct_add_to_dying_list(loser_ct);
11611141
NF_CT_STAT_INC(net, drop);
11621142
NF_CT_STAT_INC(net, insert_failed);
11631143
return NF_DROP;
@@ -1224,10 +1204,10 @@ __nf_conntrack_confirm(struct sk_buff *skb)
12241204
* user context, else we insert an already 'dead' hash, blocking
12251205
* further use of that particular connection -JM.
12261206
*/
1227-
nf_ct_del_from_dying_or_unconfirmed_list(ct);
1207+
nf_ct_del_from_unconfirmed_list(ct);
1208+
ct->status |= IPS_CONFIRMED;
12281209

12291210
if (unlikely(nf_ct_is_dying(ct))) {
1230-
nf_ct_add_to_dying_list(ct);
12311211
NF_CT_STAT_INC(net, insert_failed);
12321212
goto dying;
12331213
}
@@ -1251,7 +1231,6 @@ __nf_conntrack_confirm(struct sk_buff *skb)
12511231
goto out;
12521232
if (chainlen++ > max_chainlen) {
12531233
chaintoolong:
1254-
nf_ct_add_to_dying_list(ct);
12551234
NF_CT_STAT_INC(net, chaintoolong);
12561235
NF_CT_STAT_INC(net, insert_failed);
12571236
ret = NF_DROP;
@@ -2800,7 +2779,6 @@ void nf_conntrack_init_end(void)
28002779
* We need to use special "null" values, not used in hash table
28012780
*/
28022781
#define UNCONFIRMED_NULLS_VAL ((1<<30)+0)
2803-
#define DYING_NULLS_VAL ((1<<30)+1)
28042782

28052783
int nf_conntrack_init_net(struct net *net)
28062784
{
@@ -2821,7 +2799,6 @@ int nf_conntrack_init_net(struct net *net)
28212799

28222800
spin_lock_init(&pcpu->lock);
28232801
INIT_HLIST_NULLS_HEAD(&pcpu->unconfirmed, UNCONFIRMED_NULLS_VAL);
2824-
INIT_HLIST_NULLS_HEAD(&pcpu->dying, DYING_NULLS_VAL);
28252802
}
28262803

28272804
net->ct.stat = alloc_percpu(struct ip_conntrack_stat);

net/netfilter/nf_conntrack_ecache.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,6 @@ static enum retry_state ecache_work_evict_list(struct nf_conntrack_net *cnet)
9494
hlist_nulls_for_each_entry_safe(h, n, &evicted_list, hnnode) {
9595
struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h);
9696

97-
hlist_nulls_add_fake(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode);
9897
hlist_nulls_del_rcu(&ct->tuplehash[IP_CT_DIR_REPLY].hnnode);
9998
nf_ct_put(ct);
10099

net/netfilter/nf_conntrack_netlink.c

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ struct ctnetlink_list_dump_ctx {
6262
struct nf_conn *last;
6363
unsigned int cpu;
6464
bool done;
65-
bool retrans_done;
6665
};
6766

6867
static int ctnetlink_dump_tuples_proto(struct sk_buff *skb,
@@ -1751,13 +1750,12 @@ static int ctnetlink_dump_one_entry(struct sk_buff *skb,
17511750
}
17521751

17531752
static int
1754-
ctnetlink_dump_list(struct sk_buff *skb, struct netlink_callback *cb, bool dying)
1753+
ctnetlink_dump_unconfirmed(struct sk_buff *skb, struct netlink_callback *cb)
17551754
{
17561755
struct ctnetlink_list_dump_ctx *ctx = (void *)cb->ctx;
17571756
struct nf_conn *ct, *last;
17581757
struct nf_conntrack_tuple_hash *h;
17591758
struct hlist_nulls_node *n;
1760-
struct hlist_nulls_head *list;
17611759
struct net *net = sock_net(skb->sk);
17621760
int res, cpu;
17631761

@@ -1774,12 +1772,11 @@ ctnetlink_dump_list(struct sk_buff *skb, struct netlink_callback *cb, bool dying
17741772

17751773
pcpu = per_cpu_ptr(net->ct.pcpu_lists, cpu);
17761774
spin_lock_bh(&pcpu->lock);
1777-
list = dying ? &pcpu->dying : &pcpu->unconfirmed;
17781775
restart:
1779-
hlist_nulls_for_each_entry(h, n, list, hnnode) {
1776+
hlist_nulls_for_each_entry(h, n, &pcpu->unconfirmed, hnnode) {
17801777
ct = nf_ct_tuplehash_to_ctrack(h);
17811778

1782-
res = ctnetlink_dump_one_entry(skb, cb, ct, dying);
1779+
res = ctnetlink_dump_one_entry(skb, cb, ct, false);
17831780
if (res < 0) {
17841781
ctx->cpu = cpu;
17851782
spin_unlock_bh(&pcpu->lock);
@@ -1812,8 +1809,8 @@ ctnetlink_dump_dying(struct sk_buff *skb, struct netlink_callback *cb)
18121809
struct hlist_nulls_node *n;
18131810
#endif
18141811

1815-
if (ctx->retrans_done)
1816-
return ctnetlink_dump_list(skb, cb, true);
1812+
if (ctx->done)
1813+
return 0;
18171814

18181815
ctx->last = NULL;
18191816

@@ -1842,10 +1839,10 @@ ctnetlink_dump_dying(struct sk_buff *skb, struct netlink_callback *cb)
18421839

18431840
spin_unlock_bh(&ecache_net->dying_lock);
18441841
#endif
1842+
ctx->done = true;
18451843
nf_ct_put(last);
1846-
ctx->retrans_done = true;
18471844

1848-
return ctnetlink_dump_list(skb, cb, true);
1845+
return skb->len;
18491846
}
18501847

18511848
static int ctnetlink_get_ct_dying(struct sk_buff *skb,
@@ -1863,12 +1860,6 @@ static int ctnetlink_get_ct_dying(struct sk_buff *skb,
18631860
return -EOPNOTSUPP;
18641861
}
18651862

1866-
static int
1867-
ctnetlink_dump_unconfirmed(struct sk_buff *skb, struct netlink_callback *cb)
1868-
{
1869-
return ctnetlink_dump_list(skb, cb, false);
1870-
}
1871-
18721863
static int ctnetlink_get_ct_unconfirmed(struct sk_buff *skb,
18731864
const struct nfnl_info *info,
18741865
const struct nlattr * const cda[])

0 commit comments

Comments
 (0)