1 From: Oz Shlomo <ozsh@nvidia.com>
2 Date: Thu, 3 Jun 2021 15:12:35 +0300
3 Subject: [PATCH] netfilter: flowtable: Set offload timeouts according to proto
6 Currently the aging period for tcp/udp connections is hard coded to
7 30 seconds. Aged tcp/udp connections configure a hard coded 120/30
8 seconds pickup timeout for conntrack.
9 This configuration may be too aggressive or permissive for some users.
11 Dynamically configure the nf flow table GC timeout intervals according
12 to the user defined values.
14 Signed-off-by: Oz Shlomo <ozsh@nvidia.com>
15 Reviewed-by: Paul Blakey <paulb@nvidia.com>
16 Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
19 --- a/include/net/netfilter/nf_flow_table.h
20 +++ b/include/net/netfilter/nf_flow_table.h
21 @@ -174,6 +174,8 @@ struct flow_offload {
22 #define NF_FLOW_TIMEOUT (30 * HZ)
23 #define nf_flowtable_time_stamp (u32)jiffies
25 +unsigned long flow_offload_get_timeout(struct flow_offload *flow);
27 static inline __s32 nf_flow_timeout_delta(unsigned int timeout)
29 return (__s32)(timeout - nf_flowtable_time_stamp);
30 --- a/net/netfilter/nf_flow_table_core.c
31 +++ b/net/netfilter/nf_flow_table_core.c
32 @@ -175,12 +175,10 @@ static void flow_offload_fixup_tcp(struc
33 tcp->seen[1].td_maxwin = 0;
36 -#define NF_FLOWTABLE_TCP_PICKUP_TIMEOUT (120 * HZ)
37 -#define NF_FLOWTABLE_UDP_PICKUP_TIMEOUT (30 * HZ)
39 static void flow_offload_fixup_ct_timeout(struct nf_conn *ct)
41 const struct nf_conntrack_l4proto *l4proto;
42 + struct net *net = nf_ct_net(ct);
43 int l4num = nf_ct_protonum(ct);
46 @@ -188,12 +186,17 @@ static void flow_offload_fixup_ct_timeou
50 - if (l4num == IPPROTO_TCP)
51 - timeout = NF_FLOWTABLE_TCP_PICKUP_TIMEOUT;
52 - else if (l4num == IPPROTO_UDP)
53 - timeout = NF_FLOWTABLE_UDP_PICKUP_TIMEOUT;
55 + if (l4num == IPPROTO_TCP) {
56 + struct nf_tcp_net *tn = nf_tcp_pernet(net);
58 + timeout = tn->offload_pickup;
59 + } else if (l4num == IPPROTO_UDP) {
60 + struct nf_udp_net *tn = nf_udp_pernet(net);
62 + timeout = tn->offload_pickup;
67 if (nf_flow_timeout_delta(ct->timeout) > (__s32)timeout)
68 ct->timeout = nfct_time_stamp + timeout;
69 @@ -265,11 +268,35 @@ static const struct rhashtable_params nf
70 .automatic_shrinking = true,
73 +unsigned long flow_offload_get_timeout(struct flow_offload *flow)
75 + const struct nf_conntrack_l4proto *l4proto;
76 + unsigned long timeout = NF_FLOW_TIMEOUT;
77 + struct net *net = nf_ct_net(flow->ct);
78 + int l4num = nf_ct_protonum(flow->ct);
80 + l4proto = nf_ct_l4proto_find(l4num);
84 + if (l4num == IPPROTO_TCP) {
85 + struct nf_tcp_net *tn = nf_tcp_pernet(net);
87 + timeout = tn->offload_timeout;
88 + } else if (l4num == IPPROTO_UDP) {
89 + struct nf_udp_net *tn = nf_udp_pernet(net);
91 + timeout = tn->offload_timeout;
97 int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow)
101 - flow->timeout = nf_flowtable_time_stamp + NF_FLOW_TIMEOUT;
102 + flow->timeout = nf_flowtable_time_stamp + flow_offload_get_timeout(flow);
104 err = rhashtable_insert_fast(&flow_table->rhashtable,
105 &flow->tuplehash[0].node,
106 @@ -301,7 +328,7 @@ EXPORT_SYMBOL_GPL(flow_offload_add);
107 void flow_offload_refresh(struct nf_flowtable *flow_table,
108 struct flow_offload *flow)
110 - flow->timeout = nf_flowtable_time_stamp + NF_FLOW_TIMEOUT;
111 + flow->timeout = nf_flowtable_time_stamp + flow_offload_get_timeout(flow);
113 if (likely(!nf_flowtable_hw_offload(flow_table)))
115 --- a/net/netfilter/nf_flow_table_offload.c
116 +++ b/net/netfilter/nf_flow_table_offload.c
117 @@ -885,7 +885,7 @@ static void flow_offload_work_stats(stru
119 lastused = max_t(u64, stats[0].lastused, stats[1].lastused);
120 offload->flow->timeout = max_t(u64, offload->flow->timeout,
121 - lastused + NF_FLOW_TIMEOUT);
122 + lastused + flow_offload_get_timeout(offload->flow));
124 if (offload->flowtable->flags & NF_FLOWTABLE_COUNTER) {
126 @@ -989,7 +989,7 @@ void nf_flow_offload_stats(struct nf_flo
129 delta = nf_flow_timeout_delta(flow->timeout);
130 - if ((delta >= (9 * NF_FLOW_TIMEOUT) / 10))
131 + if ((delta >= (9 * flow_offload_get_timeout(flow)) / 10))
134 offload = nf_flow_offload_work_alloc(flowtable, flow, FLOW_CLS_STATS);