Skip to content

Commit bb89abe

Browse files
Florian Westphalummakynes
authored andcommitted
netfilter: conntrack: split resolve_clash function
Followup patch will need a helper function with the 'clashing entries refer to the identical tuple in both directions' resolution logic. This patch will add another resolve_clash helper where loser_ct must not be added to the dying list because it will be inserted into the table. Therefore this also moves the stat counters and dying-list insertion of the losing ct. Signed-off-by: Florian Westphal <[email protected]> Signed-off-by: Pablo Neira Ayuso <[email protected]>
1 parent b1b3255 commit bb89abe

File tree

1 file changed

+41
-17
lines changed

1 file changed

+41
-17
lines changed

net/netfilter/nf_conntrack_core.c

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -907,6 +907,39 @@ static void __nf_conntrack_insert_prepare(struct nf_conn *ct)
907907
tstamp->start = ktime_get_real_ns();
908908
}
909909

910+
static int __nf_ct_resolve_clash(struct sk_buff *skb,
911+
struct nf_conntrack_tuple_hash *h)
912+
{
913+
/* This is the conntrack entry already in hashes that won race. */
914+
struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h);
915+
enum ip_conntrack_info ctinfo;
916+
struct nf_conn *loser_ct;
917+
918+
loser_ct = nf_ct_get(skb, &ctinfo);
919+
920+
if (nf_ct_is_dying(ct))
921+
return NF_DROP;
922+
923+
if (!atomic_inc_not_zero(&ct->ct_general.use))
924+
return NF_DROP;
925+
926+
if (((ct->status & IPS_NAT_DONE_MASK) == 0) ||
927+
nf_ct_match(ct, loser_ct)) {
928+
struct net *net = nf_ct_net(ct);
929+
930+
nf_ct_acct_merge(ct, ctinfo, loser_ct);
931+
nf_ct_add_to_dying_list(loser_ct);
932+
nf_conntrack_put(&loser_ct->ct_general);
933+
nf_ct_set(skb, ct, ctinfo);
934+
935+
NF_CT_STAT_INC(net, insert_failed);
936+
return NF_ACCEPT;
937+
}
938+
939+
nf_ct_put(ct);
940+
return NF_DROP;
941+
}
942+
910943
/**
911944
* nf_ct_resolve_clash - attempt to handle clash without packet drop
912945
*
@@ -941,31 +974,23 @@ nf_ct_resolve_clash(struct sk_buff *skb, struct nf_conntrack_tuple_hash *h)
941974
enum ip_conntrack_info ctinfo;
942975
struct nf_conn *loser_ct;
943976
struct net *net;
977+
int ret;
944978

945979
loser_ct = nf_ct_get(skb, &ctinfo);
980+
net = nf_ct_net(loser_ct);
946981

947982
l4proto = nf_ct_l4proto_find(nf_ct_protonum(ct));
948983
if (!l4proto->allow_clash)
949984
goto drop;
950985

951-
if (nf_ct_is_dying(ct))
952-
goto drop;
953-
954-
if (!atomic_inc_not_zero(&ct->ct_general.use))
955-
goto drop;
956-
957-
if (((ct->status & IPS_NAT_DONE_MASK) == 0) ||
958-
nf_ct_match(ct, loser_ct)) {
959-
nf_ct_acct_merge(ct, ctinfo, loser_ct);
960-
nf_conntrack_put(&loser_ct->ct_general);
961-
nf_ct_set(skb, ct, ctinfo);
962-
return NF_ACCEPT;
963-
}
986+
ret = __nf_ct_resolve_clash(skb, h);
987+
if (ret == NF_ACCEPT)
988+
return ret;
964989

965-
nf_ct_put(ct);
966990
drop:
967-
net = nf_ct_net(loser_ct);
991+
nf_ct_add_to_dying_list(loser_ct);
968992
NF_CT_STAT_INC(net, drop);
993+
NF_CT_STAT_INC(net, insert_failed);
969994
return NF_DROP;
970995
}
971996

@@ -1034,6 +1059,7 @@ __nf_conntrack_confirm(struct sk_buff *skb)
10341059

10351060
if (unlikely(nf_ct_is_dying(ct))) {
10361061
nf_ct_add_to_dying_list(ct);
1062+
NF_CT_STAT_INC(net, insert_failed);
10371063
goto dying;
10381064
}
10391065

@@ -1075,11 +1101,9 @@ __nf_conntrack_confirm(struct sk_buff *skb)
10751101
return NF_ACCEPT;
10761102

10771103
out:
1078-
nf_ct_add_to_dying_list(ct);
10791104
ret = nf_ct_resolve_clash(skb, h);
10801105
dying:
10811106
nf_conntrack_double_unlock(hash, reply_hash);
1082-
NF_CT_STAT_INC(net, insert_failed);
10831107
local_bh_enable();
10841108
return ret;
10851109
}

0 commit comments

Comments
 (0)