Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netfilter: allow exp not to be removed in nf_ct_find_expectation

Currently nf_conntrack_in() calling nf_ct_find_expectation() will
remove the exp from the hash table. However, in some scenario, we
expect the exp not to be removed when the created ct will not be
confirmed, like in OVS and TC conntrack in the following patches.

This patch allows exp not to be removed by setting IPS_CONFIRMED
in the status of the tmpl.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
Acked-by: Aaron Conole <aconole@redhat.com>
Acked-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

authored by

Xin Long and committed by
Paolo Abeni
4914109a 03b123de

+6 -4
+1 -1
include/net/netfilter/nf_conntrack_expect.h
··· 100 100 struct nf_conntrack_expect * 101 101 nf_ct_find_expectation(struct net *net, 102 102 const struct nf_conntrack_zone *zone, 103 - const struct nf_conntrack_tuple *tuple); 103 + const struct nf_conntrack_tuple *tuple, bool unlink); 104 104 105 105 void nf_ct_unlink_expect_report(struct nf_conntrack_expect *exp, 106 106 u32 portid, int report);
+1 -1
net/netfilter/nf_conntrack_core.c
··· 1756 1756 cnet = nf_ct_pernet(net); 1757 1757 if (cnet->expect_count) { 1758 1758 spin_lock_bh(&nf_conntrack_expect_lock); 1759 - exp = nf_ct_find_expectation(net, zone, tuple); 1759 + exp = nf_ct_find_expectation(net, zone, tuple, !tmpl || nf_ct_is_confirmed(tmpl)); 1760 1760 if (exp) { 1761 1761 /* Welcome, Mr. Bond. We've been expecting you... */ 1762 1762 __set_bit(IPS_EXPECTED_BIT, &ct->status);
+2 -2
net/netfilter/nf_conntrack_expect.c
··· 171 171 struct nf_conntrack_expect * 172 172 nf_ct_find_expectation(struct net *net, 173 173 const struct nf_conntrack_zone *zone, 174 - const struct nf_conntrack_tuple *tuple) 174 + const struct nf_conntrack_tuple *tuple, bool unlink) 175 175 { 176 176 struct nf_conntrack_net *cnet = nf_ct_pernet(net); 177 177 struct nf_conntrack_expect *i, *exp = NULL; ··· 211 211 !refcount_inc_not_zero(&exp->master->ct_general.use))) 212 212 return NULL; 213 213 214 - if (exp->flags & NF_CT_EXPECT_PERMANENT) { 214 + if (exp->flags & NF_CT_EXPECT_PERMANENT || !unlink) { 215 215 refcount_inc(&exp->use); 216 216 return exp; 217 217 } else if (del_timer(&exp->timeout)) {
+2
net/netfilter/nft_ct.c
··· 262 262 regs->verdict.code = NF_DROP; 263 263 return; 264 264 } 265 + __set_bit(IPS_CONFIRMED_BIT, &ct->status); 265 266 } 266 267 267 268 nf_ct_set(skb, ct, IP_CT_NEW); ··· 369 368 return false; 370 369 } 371 370 371 + __set_bit(IPS_CONFIRMED_BIT, &tmp->status); 372 372 per_cpu(nft_ct_pcpu_template, cpu) = tmp; 373 373 } 374 374