From: Pablo Neira Ayuso <pablo@netfilter.org>
To: netfilter-devel@vger.kernel.org
Cc: sven.auhagen@voleatech.de, cratiu@nvidia.com, ozsh@nvidia.com,
vladbu@nvidia.com, gal@nvidia.com
Subject: [PATCH nf 1/2] netfilter: flowtable: infer TCP state and timeout before flow teardown
Date: Wed, 20 Mar 2024 10:26:37 +0100 [thread overview]
Message-ID: <20240320092638.798076-1-pablo@netfilter.org> (raw)
In case that either FIN or RST packet is seen, infer current TCP state
based on the TCP packet flags before setting the _TEARDOWN flag:
- FIN packets result in TCP_CONNTRACK_FIN_WAIT which uses a default
timeout of 2 minutes.
- RST packets lead to tcp_state TCP_CONNTRACK_CLOSE of 10 seconds.
Therefore, TCP established state with a low timeout is not used anymore
when handing over the flow to the classic conntrack path, otherwise a
FIN packet coming in the reply direction could re-offload this flow
again.
Fixes: e5eaac2beb54 ("netfilter: flowtable: fix TCP flow teardown")
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
v2: leave things as is for the flow timeout expiration case.
No established state and _unack timeout is assumed per Sven.
include/net/netfilter/nf_flow_table.h | 1 +
net/netfilter/nf_flow_table_core.c | 38 ++++++++++++++++++++-------
net/netfilter/nf_flow_table_ip.c | 2 +-
3 files changed, 30 insertions(+), 11 deletions(-)
diff --git a/include/net/netfilter/nf_flow_table.h b/include/net/netfilter/nf_flow_table.h
index a763dd327c6e..924f3720143f 100644
--- a/include/net/netfilter/nf_flow_table.h
+++ b/include/net/netfilter/nf_flow_table.h
@@ -293,6 +293,7 @@ int nf_flow_table_init(struct nf_flowtable *flow_table);
void nf_flow_table_free(struct nf_flowtable *flow_table);
void flow_offload_teardown(struct flow_offload *flow);
+void flow_offload_teardown_tcp(struct flow_offload *flow, bool fin);
void nf_flow_snat_port(const struct flow_offload *flow,
struct sk_buff *skb, unsigned int thoff,
diff --git a/net/netfilter/nf_flow_table_core.c b/net/netfilter/nf_flow_table_core.c
index a0571339239c..bd880c58bfab 100644
--- a/net/netfilter/nf_flow_table_core.c
+++ b/net/netfilter/nf_flow_table_core.c
@@ -165,10 +165,16 @@ void flow_offload_route_init(struct flow_offload *flow,
}
EXPORT_SYMBOL_GPL(flow_offload_route_init);
-static void flow_offload_fixup_tcp(struct ip_ct_tcp *tcp)
+static s32 flow_offload_fixup_tcp(struct net *net, struct nf_conn *ct,
+ enum tcp_conntrack tcp_state)
{
- tcp->seen[0].td_maxwin = 0;
- tcp->seen[1].td_maxwin = 0;
+ struct nf_tcp_net *tn = nf_tcp_pernet(net);
+
+ ct->proto.tcp.state = tcp_state;
+ ct->proto.tcp.seen[0].td_maxwin = 0;
+ ct->proto.tcp.seen[1].td_maxwin = 0;
+
+ return tn->timeouts[tcp_state];
}
static void flow_offload_fixup_ct(struct nf_conn *ct)
@@ -178,12 +184,7 @@ static void flow_offload_fixup_ct(struct nf_conn *ct)
s32 timeout;
if (l4num == IPPROTO_TCP) {
- struct nf_tcp_net *tn = nf_tcp_pernet(net);
-
- flow_offload_fixup_tcp(&ct->proto.tcp);
-
- timeout = tn->timeouts[ct->proto.tcp.state];
- timeout -= tn->offload_timeout;
+ timeout = flow_offload_fixup_tcp(net, ct, ct->proto.tcp.state);
} else if (l4num == IPPROTO_UDP) {
struct nf_udp_net *tn = nf_udp_pernet(net);
enum udp_conntrack state =
@@ -346,12 +347,29 @@ static void flow_offload_del(struct nf_flowtable *flow_table,
void flow_offload_teardown(struct flow_offload *flow)
{
+ flow_offload_fixup_ct(flow->ct);
+ smp_mb__before_atomic();
clear_bit(IPS_OFFLOAD_BIT, &flow->ct->status);
set_bit(NF_FLOW_TEARDOWN, &flow->flags);
- flow_offload_fixup_ct(flow->ct);
}
EXPORT_SYMBOL_GPL(flow_offload_teardown);
+void flow_offload_teardown_tcp(struct flow_offload *flow, bool fin)
+{
+ enum tcp_conntrack tcp_state;
+
+ if (fin)
+ tcp_state = TCP_CONNTRACK_FIN_WAIT;
+ else /* rst */
+ tcp_state = TCP_CONNTRACK_CLOSE;
+
+ flow_offload_fixup_tcp(nf_ct_net(flow->ct), flow->ct, tcp_state);
+ smp_mb__before_atomic();
+ clear_bit(IPS_OFFLOAD_BIT, &flow->ct->status);
+ set_bit(NF_FLOW_TEARDOWN, &flow->flags);
+}
+EXPORT_SYMBOL_GPL(flow_offload_teardown_tcp);
+
struct flow_offload_tuple_rhash *
flow_offload_lookup(struct nf_flowtable *flow_table,
struct flow_offload_tuple *tuple)
diff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c
index e45fade76409..13b6c453d8bc 100644
--- a/net/netfilter/nf_flow_table_ip.c
+++ b/net/netfilter/nf_flow_table_ip.c
@@ -29,7 +29,7 @@ static int nf_flow_state_check(struct flow_offload *flow, int proto,
tcph = (void *)(skb_network_header(skb) + thoff);
if (unlikely(tcph->fin || tcph->rst)) {
- flow_offload_teardown(flow);
+ flow_offload_teardown_tcp(flow, tcph->fin);
return -1;
}
--
2.30.2
next reply other threads:[~2024-03-20 9:26 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-03-20 9:26 Pablo Neira Ayuso [this message]
2024-03-20 9:26 ` [PATCH nf 2/2] netfilter: flowtable: use UDP timeout after flow teardown Pablo Neira Ayuso
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240320092638.798076-1-pablo@netfilter.org \
--to=pablo@netfilter.org \
--cc=cratiu@nvidia.com \
--cc=gal@nvidia.com \
--cc=netfilter-devel@vger.kernel.org \
--cc=ozsh@nvidia.com \
--cc=sven.auhagen@voleatech.de \
--cc=vladbu@nvidia.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).