Commit 4914109a authored by Xin Long's avatar Xin Long Committed by Paolo Abeni

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: default avatarXin Long <lucien.xin@gmail.com>
Acked-by: default avatarAaron Conole <aconole@redhat.com>
Acked-by: default avatarFlorian Westphal <fw@strlen.de>
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent 03b123de
...@@ -100,7 +100,7 @@ nf_ct_expect_find_get(struct net *net, ...@@ -100,7 +100,7 @@ nf_ct_expect_find_get(struct net *net,
struct nf_conntrack_expect * struct nf_conntrack_expect *
nf_ct_find_expectation(struct net *net, nf_ct_find_expectation(struct net *net,
const struct nf_conntrack_zone *zone, const struct nf_conntrack_zone *zone,
const struct nf_conntrack_tuple *tuple); const struct nf_conntrack_tuple *tuple, bool unlink);
void nf_ct_unlink_expect_report(struct nf_conntrack_expect *exp, void nf_ct_unlink_expect_report(struct nf_conntrack_expect *exp,
u32 portid, int report); u32 portid, int report);
......
...@@ -1756,7 +1756,7 @@ init_conntrack(struct net *net, struct nf_conn *tmpl, ...@@ -1756,7 +1756,7 @@ init_conntrack(struct net *net, struct nf_conn *tmpl,
cnet = nf_ct_pernet(net); cnet = nf_ct_pernet(net);
if (cnet->expect_count) { if (cnet->expect_count) {
spin_lock_bh(&nf_conntrack_expect_lock); spin_lock_bh(&nf_conntrack_expect_lock);
exp = nf_ct_find_expectation(net, zone, tuple); exp = nf_ct_find_expectation(net, zone, tuple, !tmpl || nf_ct_is_confirmed(tmpl));
if (exp) { if (exp) {
/* Welcome, Mr. Bond. We've been expecting you... */ /* Welcome, Mr. Bond. We've been expecting you... */
__set_bit(IPS_EXPECTED_BIT, &ct->status); __set_bit(IPS_EXPECTED_BIT, &ct->status);
......
...@@ -171,7 +171,7 @@ EXPORT_SYMBOL_GPL(nf_ct_expect_find_get); ...@@ -171,7 +171,7 @@ EXPORT_SYMBOL_GPL(nf_ct_expect_find_get);
struct nf_conntrack_expect * struct nf_conntrack_expect *
nf_ct_find_expectation(struct net *net, nf_ct_find_expectation(struct net *net,
const struct nf_conntrack_zone *zone, const struct nf_conntrack_zone *zone,
const struct nf_conntrack_tuple *tuple) const struct nf_conntrack_tuple *tuple, bool unlink)
{ {
struct nf_conntrack_net *cnet = nf_ct_pernet(net); struct nf_conntrack_net *cnet = nf_ct_pernet(net);
struct nf_conntrack_expect *i, *exp = NULL; struct nf_conntrack_expect *i, *exp = NULL;
...@@ -211,7 +211,7 @@ nf_ct_find_expectation(struct net *net, ...@@ -211,7 +211,7 @@ nf_ct_find_expectation(struct net *net,
!refcount_inc_not_zero(&exp->master->ct_general.use))) !refcount_inc_not_zero(&exp->master->ct_general.use)))
return NULL; return NULL;
if (exp->flags & NF_CT_EXPECT_PERMANENT) { if (exp->flags & NF_CT_EXPECT_PERMANENT || !unlink) {
refcount_inc(&exp->use); refcount_inc(&exp->use);
return exp; return exp;
} else if (del_timer(&exp->timeout)) { } else if (del_timer(&exp->timeout)) {
......
...@@ -262,6 +262,7 @@ static void nft_ct_set_zone_eval(const struct nft_expr *expr, ...@@ -262,6 +262,7 @@ static void nft_ct_set_zone_eval(const struct nft_expr *expr,
regs->verdict.code = NF_DROP; regs->verdict.code = NF_DROP;
return; return;
} }
__set_bit(IPS_CONFIRMED_BIT, &ct->status);
} }
nf_ct_set(skb, ct, IP_CT_NEW); nf_ct_set(skb, ct, IP_CT_NEW);
...@@ -368,6 +369,7 @@ static bool nft_ct_tmpl_alloc_pcpu(void) ...@@ -368,6 +369,7 @@ static bool nft_ct_tmpl_alloc_pcpu(void)
return false; return false;
} }
__set_bit(IPS_CONFIRMED_BIT, &tmp->status);
per_cpu(nft_ct_pcpu_template, cpu) = tmp; per_cpu(nft_ct_pcpu_template, cpu) = tmp;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment