Skip to content

Commit

Permalink
netfilter: flowtable: Set offload timeouts according to proto values
Browse files Browse the repository at this point in the history
Currently the aging period for tcp/udp connections is hard coded to
30 seconds. Aged tcp/udp connections configure a hard coded 120/30
seconds pickup timeout for conntrack.
This configuration may be too aggressive or permissive for some users.

Dynamically configure the nf flow table GC timeout intervals according
to the user defined values.

Signed-off-by: Oz Shlomo <ozsh@nvidia.com>
Reviewed-by: Paul Blakey <paulb@nvidia.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
  • Loading branch information
Oz Shlomo authored and Pablo Neira Ayuso committed Jun 7, 2021
1 parent 975c575 commit 1d91d2e
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 12 deletions.
2 changes: 2 additions & 0 deletions include/net/netfilter/nf_flow_table.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@ struct flow_offload {
#define NF_FLOW_TIMEOUT (30 * HZ)
#define nf_flowtable_time_stamp (u32)jiffies

unsigned long flow_offload_get_timeout(struct flow_offload *flow);

static inline __s32 nf_flow_timeout_delta(unsigned int timeout)
{
return (__s32)(timeout - nf_flowtable_time_stamp);
Expand Down
47 changes: 37 additions & 10 deletions net/netfilter/nf_flow_table_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -178,25 +178,28 @@ static void flow_offload_fixup_tcp(struct ip_ct_tcp *tcp)
tcp->seen[1].td_maxwin = 0;
}

#define NF_FLOWTABLE_TCP_PICKUP_TIMEOUT (120 * HZ)
#define NF_FLOWTABLE_UDP_PICKUP_TIMEOUT (30 * HZ)

static void flow_offload_fixup_ct_timeout(struct nf_conn *ct)
{
const struct nf_conntrack_l4proto *l4proto;
struct net *net = nf_ct_net(ct);
int l4num = nf_ct_protonum(ct);
unsigned int timeout;

l4proto = nf_ct_l4proto_find(l4num);
if (!l4proto)
return;

if (l4num == IPPROTO_TCP)
timeout = NF_FLOWTABLE_TCP_PICKUP_TIMEOUT;
else if (l4num == IPPROTO_UDP)
timeout = NF_FLOWTABLE_UDP_PICKUP_TIMEOUT;
else
if (l4num == IPPROTO_TCP) {
struct nf_tcp_net *tn = nf_tcp_pernet(net);

timeout = tn->offload_pickup;
} else if (l4num == IPPROTO_UDP) {
struct nf_udp_net *tn = nf_udp_pernet(net);

timeout = tn->offload_pickup;
} else {
return;
}

if (nf_flow_timeout_delta(ct->timeout) > (__s32)timeout)
ct->timeout = nfct_time_stamp + timeout;
Expand Down Expand Up @@ -268,11 +271,35 @@ static const struct rhashtable_params nf_flow_offload_rhash_params = {
.automatic_shrinking = true,
};

unsigned long flow_offload_get_timeout(struct flow_offload *flow)
{
const struct nf_conntrack_l4proto *l4proto;
unsigned long timeout = NF_FLOW_TIMEOUT;
struct net *net = nf_ct_net(flow->ct);
int l4num = nf_ct_protonum(flow->ct);

l4proto = nf_ct_l4proto_find(l4num);
if (!l4proto)
return timeout;

if (l4num == IPPROTO_TCP) {
struct nf_tcp_net *tn = nf_tcp_pernet(net);

timeout = tn->offload_timeout;
} else if (l4num == IPPROTO_UDP) {
struct nf_udp_net *tn = nf_udp_pernet(net);

timeout = tn->offload_timeout;
}

return timeout;
}

int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow)
{
int err;

flow->timeout = nf_flowtable_time_stamp + NF_FLOW_TIMEOUT;
flow->timeout = nf_flowtable_time_stamp + flow_offload_get_timeout(flow);

err = rhashtable_insert_fast(&flow_table->rhashtable,
&flow->tuplehash[0].node,
Expand Down Expand Up @@ -304,7 +331,7 @@ EXPORT_SYMBOL_GPL(flow_offload_add);
void flow_offload_refresh(struct nf_flowtable *flow_table,
struct flow_offload *flow)
{
flow->timeout = nf_flowtable_time_stamp + NF_FLOW_TIMEOUT;
flow->timeout = nf_flowtable_time_stamp + flow_offload_get_timeout(flow);

if (likely(!nf_flowtable_hw_offload(flow_table)))
return;
Expand Down
4 changes: 2 additions & 2 deletions net/netfilter/nf_flow_table_offload.c
Original file line number Diff line number Diff line change
Expand Up @@ -937,7 +937,7 @@ static void flow_offload_work_stats(struct flow_offload_work *offload)

lastused = max_t(u64, stats[0].lastused, stats[1].lastused);
offload->flow->timeout = max_t(u64, offload->flow->timeout,
lastused + NF_FLOW_TIMEOUT);
lastused + flow_offload_get_timeout(offload->flow));

if (offload->flowtable->flags & NF_FLOWTABLE_COUNTER) {
if (stats[0].pkts)
Expand Down Expand Up @@ -1041,7 +1041,7 @@ void nf_flow_offload_stats(struct nf_flowtable *flowtable,
__s32 delta;

delta = nf_flow_timeout_delta(flow->timeout);
if ((delta >= (9 * NF_FLOW_TIMEOUT) / 10))
if ((delta >= (9 * flow_offload_get_timeout(flow)) / 10))
return;

offload = nf_flow_offload_work_alloc(flowtable, flow, FLOW_CLS_STATS);
Expand Down

0 comments on commit 1d91d2e

Please sign in to comment.