1e82308eaa64510a0c001003d79ba06c4a24ec87
[openwrt/openwrt.git] /
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
4 values
5
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.
10
11 Dynamically configure the nf flow table GC timeout intervals according
12 to the user defined values.
13
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>
17 ---
18
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
24
25 +unsigned long flow_offload_get_timeout(struct flow_offload *flow);
26 +
27 static inline __s32 nf_flow_timeout_delta(unsigned int timeout)
28 {
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;
34 }
35
36 -#define NF_FLOWTABLE_TCP_PICKUP_TIMEOUT (120 * HZ)
37 -#define NF_FLOWTABLE_UDP_PICKUP_TIMEOUT (30 * HZ)
38 -
39 static void flow_offload_fixup_ct_timeout(struct nf_conn *ct)
40 {
41 const struct nf_conntrack_l4proto *l4proto;
42 + struct net *net = nf_ct_net(ct);
43 int l4num = nf_ct_protonum(ct);
44 unsigned int timeout;
45
46 @@ -188,12 +186,17 @@ static void flow_offload_fixup_ct_timeou
47 if (!l4proto)
48 return;
49
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;
54 - else
55 + if (l4num == IPPROTO_TCP) {
56 + struct nf_tcp_net *tn = nf_tcp_pernet(net);
57 +
58 + timeout = tn->offload_pickup;
59 + } else if (l4num == IPPROTO_UDP) {
60 + struct nf_udp_net *tn = nf_udp_pernet(net);
61 +
62 + timeout = tn->offload_pickup;
63 + } else {
64 return;
65 + }
66
67 if (nf_flow_timeout_delta(READ_ONCE(ct->timeout)) > (__s32)timeout)
68 WRITE_ONCE(ct->timeout, nfct_time_stamp + timeout);
69 @@ -265,11 +268,35 @@ static const struct rhashtable_params nf
70 .automatic_shrinking = true,
71 };
72
73 +unsigned long flow_offload_get_timeout(struct flow_offload *flow)
74 +{
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);
79 +
80 + l4proto = nf_ct_l4proto_find(l4num);
81 + if (!l4proto)
82 + return timeout;
83 +
84 + if (l4num == IPPROTO_TCP) {
85 + struct nf_tcp_net *tn = nf_tcp_pernet(net);
86 +
87 + timeout = tn->offload_timeout;
88 + } else if (l4num == IPPROTO_UDP) {
89 + struct nf_udp_net *tn = nf_udp_pernet(net);
90 +
91 + timeout = tn->offload_timeout;
92 + }
93 +
94 + return timeout;
95 +}
96 +
97 int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow)
98 {
99 int err;
100
101 - flow->timeout = nf_flowtable_time_stamp + NF_FLOW_TIMEOUT;
102 + flow->timeout = nf_flowtable_time_stamp + flow_offload_get_timeout(flow);
103
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)
109 {
110 - flow->timeout = nf_flowtable_time_stamp + NF_FLOW_TIMEOUT;
111 + flow->timeout = nf_flowtable_time_stamp + flow_offload_get_timeout(flow);
112
113 if (likely(!nf_flowtable_hw_offload(flow_table)))
114 return;
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
118
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));
123
124 if (offload->flowtable->flags & NF_FLOWTABLE_COUNTER) {
125 if (stats[0].pkts)
126 @@ -989,7 +989,7 @@ void nf_flow_offload_stats(struct nf_flo
127 __s32 delta;
128
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))
132 return;
133
134 offload = nf_flow_offload_work_alloc(flowtable, flow, FLOW_CLS_STATS);