diff --git a/net/netfilter/nf_flow_table_core.c b/net/netfilter/nf_flow_table_core.c index 20b4a14e5d4e..7af1e2e8f595 100644 --- a/net/netfilter/nf_flow_table_core.c +++ b/net/netfilter/nf_flow_table_core.c @@ -362,8 +362,6 @@ static void flow_offload_del(struct nf_flowtable *flow_table, &flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].node, nf_flow_offload_rhash_params); - clear_bit(IPS_OFFLOAD_BIT, &flow->ct->status); - if (nf_flow_has_expired(flow)) flow_offload_fixup_ct(flow->ct); else @@ -375,6 +373,7 @@ static void flow_offload_del(struct nf_flowtable *flow_table, void flow_offload_teardown(struct flow_offload *flow) { set_bit(NF_FLOW_TEARDOWN, &flow->flags); + clear_bit(IPS_OFFLOAD_BIT, &flow->ct->status); flow_offload_fixup_ct_state(flow->ct); } diff --git a/net/netfilter/nft_flow_offload.c b/net/netfilter/nft_flow_offload.c index 187b8cb9a510..7bc56377496c 100644 --- a/net/netfilter/nft_flow_offload.c +++ b/net/netfilter/nft_flow_offload.c @@ -273,6 +273,12 @@ static bool nft_flow_offload_skip(struct sk_buff *skb, int family) return false; } +static bool flow_offload_teardown_state(const struct ip_ct_tcp *state) +{ + return state->state > TCP_CONNTRACK_ESTABLISHED && + state->state <= TCP_CONNTRACK_CLOSE; +} + static void nft_flow_offload_eval(const struct nft_expr *expr, struct nft_regs *regs, const struct nft_pktinfo *pkt) @@ -298,7 +304,8 @@ static void nft_flow_offload_eval(const struct nft_expr *expr, case IPPROTO_TCP: tcph = skb_header_pointer(pkt->skb, nft_thoff(pkt), sizeof(_tcph), &_tcph); - if (unlikely(!tcph || tcph->fin || tcph->rst)) + if (unlikely(!tcph || tcph->fin || tcph->rst || + flow_offload_teardown_state(ct->proto.tcp))) goto out; break; case IPPROTO_UDP: