On Wed, May 06, 2020 at 02:27:29PM +0300, Paul Blakey wrote: > Once a flow is considered expired, it is marked as DYING, and > scheduled a delete from hardware. The flow will be deleted from > software, in the next gc_step after hardware deletes the flow > (and flow is marked DEAD). Till that happens, the flow's timeout > might be updated from a previous scheduled stats, or software packets > (refresh). This will cause the gc_step to no longer consider the flow > expired, and it will not be deleted from software. > > Fix that by looking at the DYING flag as in deciding > a flow should be deleted from software. Would this work for you? The idea is to skip the refresh if this has already expired. Thanks.
diff --git a/net/netfilter/nf_flow_table_core.c b/net/netfilter/nf_flow_table_core.c index 4344e572b7f9..862efa7c606d 100644 --- a/net/netfilter/nf_flow_table_core.c +++ b/net/netfilter/nf_flow_table_core.c @@ -252,10 +252,18 @@ int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow) } EXPORT_SYMBOL_GPL(flow_offload_add); +static inline bool nf_flow_has_expired(const struct flow_offload *flow) +{ + return nf_flow_timeout_delta(flow->timeout) <= 0; +} + void flow_offload_refresh(struct nf_flowtable *flow_table, struct flow_offload *flow) { - flow->timeout = nf_flowtable_time_stamp + NF_FLOW_TIMEOUT; + if (!nf_flow_has_expired(flow)) { + flow->timeout = nf_flowtable_time_stamp + NF_FLOW_TIMEOUT; + return; + } if (likely(!nf_flowtable_hw_offload(flow_table) || !test_and_clear_bit(NF_FLOW_HW_REFRESH, &flow->flags))) @@ -265,11 +273,6 @@ void flow_offload_refresh(struct nf_flowtable *flow_table, } EXPORT_SYMBOL_GPL(flow_offload_refresh); -static inline bool nf_flow_has_expired(const struct flow_offload *flow) -{ - return nf_flow_timeout_delta(flow->timeout) <= 0; -} - static void flow_offload_del(struct nf_flowtable *flow_table, struct flow_offload *flow) {