@@ -75,6 +75,7 @@ struct nf_flowtable {
unsigned int flags;
struct flow_block flow_block;
struct rw_semaphore flow_block_lock; /* Guards flow_block */
+ u32 flow_timeout;
possible_net_t net;
};
@@ -143,7 +144,6 @@ struct flow_offload {
struct rcu_head rcu_head;
};
-#define NF_FLOW_TIMEOUT (30 * HZ)
#define nf_flowtable_time_stamp (u32)jiffies
static inline __s32 nf_flow_timeout_delta(unsigned int timeout)
@@ -151,6 +151,11 @@ static inline __s32 nf_flow_timeout_delta(unsigned int timeout)
return (__s32)(timeout - nf_flowtable_time_stamp);
}
+static inline __s32 nf_flow_offload_timeout(struct nf_flowtable *flow_table)
+{
+ return flow_table->flow_timeout;
+}
+
struct nf_flow_route {
struct {
struct dst_entry *dst;
@@ -225,7 +225,8 @@ 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 +
+ nf_flow_offload_timeout(flow_table);
err = rhashtable_insert_fast(&flow_table->rhashtable,
&flow->tuplehash[0].node,
@@ -255,7 +256,8 @@ int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow)
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 +
+ nf_flow_offload_timeout(flow_table);
if (likely(!nf_flowtable_hw_offload(flow_table) ||
!test_and_clear_bit(NF_FLOW_HW_REFRESH, &flow->flags)))
@@ -547,10 +549,16 @@ int nf_flow_dnat_port(const struct flow_offload *flow,
}
EXPORT_SYMBOL_GPL(nf_flow_dnat_port);
+#define NF_DEFAULT_FLOW_TIMEOUT (30 * HZ)
+
int nf_flow_table_init(struct nf_flowtable *flowtable)
{
int err;
+ flowtable->flow_timeout = flowtable->flow_timeout ?
+ flowtable->flow_timeout * HZ :
+ NF_DEFAULT_FLOW_TIMEOUT;
+
INIT_DEFERRABLE_WORK(&flowtable->gc_work, nf_flow_offload_work_gc);
flow_block_init(&flowtable->flow_block);
init_rwsem(&flowtable->flow_block_lock);
@@ -779,6 +779,7 @@ static void flow_offload_tuple_stats(struct flow_offload_work *offload,
static void flow_offload_work_stats(struct flow_offload_work *offload)
{
+ u64 flow_timeout = nf_flow_offload_timeout(offload->flowtable);
struct flow_stats stats[FLOW_OFFLOAD_DIR_MAX] = {};
u64 lastused;
@@ -787,7 +788,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_timeout);
if (offload->flowtable->flags & NF_FLOWTABLE_COUNTER) {
if (stats[0].pkts)
@@ -880,7 +881,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 * nf_flow_offload_timeout(flowtable)) / 10))
return;
offload = nf_flow_offload_work_alloc(flowtable, flow, FLOW_CLS_STATS);