Commit 8b3646d6 authored by Paul Blakey's avatar Paul Blakey Committed by David S. Miller

net/sched: act_ct: Support refreshing the flow table entries

If driver deleted an FT entry, a FT failed to offload, or registered to the
flow table after flows were already added, we still get packets in
software.

For those packets, while restoring the ct state from the flow table
entry, refresh it's hardware offload.
Signed-off-by: default avatarPaul Blakey <paulb@mellanox.com>
Reviewed-by: default avatarJiri Pirko <jiri@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 30b0cf90
...@@ -162,6 +162,9 @@ int flow_offload_route_init(struct flow_offload *flow, ...@@ -162,6 +162,9 @@ int flow_offload_route_init(struct flow_offload *flow,
const struct nf_flow_route *route); const struct nf_flow_route *route);
int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow); 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);
struct flow_offload_tuple_rhash *flow_offload_lookup(struct nf_flowtable *flow_table, struct flow_offload_tuple_rhash *flow_offload_lookup(struct nf_flowtable *flow_table,
struct flow_offload_tuple *tuple); struct flow_offload_tuple *tuple);
void nf_flow_table_cleanup(struct net_device *dev); void nf_flow_table_cleanup(struct net_device *dev);
......
...@@ -252,6 +252,19 @@ int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow) ...@@ -252,6 +252,19 @@ int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow)
} }
EXPORT_SYMBOL_GPL(flow_offload_add); 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;
if (likely(!nf_flowtable_hw_offload(flow_table) ||
!test_and_clear_bit(NF_FLOW_HW_REFRESH, &flow->flags)))
return;
nf_flow_offload_add(flow_table, flow);
}
EXPORT_SYMBOL_GPL(flow_offload_refresh);
static inline bool nf_flow_has_expired(const struct flow_offload *flow) static inline bool nf_flow_has_expired(const struct flow_offload *flow)
{ {
return nf_flow_timeout_delta(flow->timeout) <= 0; return nf_flow_timeout_delta(flow->timeout) <= 0;
......
...@@ -232,13 +232,6 @@ static unsigned int nf_flow_xmit_xfrm(struct sk_buff *skb, ...@@ -232,13 +232,6 @@ static unsigned int nf_flow_xmit_xfrm(struct sk_buff *skb,
return NF_STOLEN; return NF_STOLEN;
} }
static bool nf_flow_offload_refresh(struct nf_flowtable *flow_table,
struct flow_offload *flow)
{
return nf_flowtable_hw_offload(flow_table) &&
test_and_clear_bit(NF_FLOW_HW_REFRESH, &flow->flags);
}
unsigned int unsigned int
nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb, nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state) const struct nf_hook_state *state)
...@@ -279,8 +272,7 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb, ...@@ -279,8 +272,7 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
if (nf_flow_state_check(flow, ip_hdr(skb)->protocol, skb, thoff)) if (nf_flow_state_check(flow, ip_hdr(skb)->protocol, skb, thoff))
return NF_ACCEPT; return NF_ACCEPT;
if (unlikely(nf_flow_offload_refresh(flow_table, flow))) flow_offload_refresh(flow_table, flow);
nf_flow_offload_add(flow_table, flow);
if (nf_flow_offload_dst_check(&rt->dst)) { if (nf_flow_offload_dst_check(&rt->dst)) {
flow_offload_teardown(flow); flow_offload_teardown(flow);
...@@ -290,7 +282,6 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb, ...@@ -290,7 +282,6 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
if (nf_flow_nat_ip(flow, skb, thoff, dir) < 0) if (nf_flow_nat_ip(flow, skb, thoff, dir) < 0)
return NF_DROP; return NF_DROP;
flow->timeout = nf_flowtable_time_stamp + NF_FLOW_TIMEOUT;
iph = ip_hdr(skb); iph = ip_hdr(skb);
ip_decrease_ttl(iph); ip_decrease_ttl(iph);
skb->tstamp = 0; skb->tstamp = 0;
...@@ -508,8 +499,7 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb, ...@@ -508,8 +499,7 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
sizeof(*ip6h))) sizeof(*ip6h)))
return NF_ACCEPT; return NF_ACCEPT;
if (unlikely(nf_flow_offload_refresh(flow_table, flow))) flow_offload_refresh(flow_table, flow);
nf_flow_offload_add(flow_table, flow);
if (nf_flow_offload_dst_check(&rt->dst)) { if (nf_flow_offload_dst_check(&rt->dst)) {
flow_offload_teardown(flow); flow_offload_teardown(flow);
...@@ -522,7 +512,6 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb, ...@@ -522,7 +512,6 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
if (nf_flow_nat_ipv6(flow, skb, dir) < 0) if (nf_flow_nat_ipv6(flow, skb, dir) < 0)
return NF_DROP; return NF_DROP;
flow->timeout = nf_flowtable_time_stamp + NF_FLOW_TIMEOUT;
ip6h = ipv6_hdr(skb); ip6h = ipv6_hdr(skb);
ip6h->hop_limit--; ip6h->hop_limit--;
skb->tstamp = 0; skb->tstamp = 0;
......
...@@ -531,6 +531,7 @@ static bool tcf_ct_flow_table_lookup(struct tcf_ct_params *p, ...@@ -531,6 +531,7 @@ static bool tcf_ct_flow_table_lookup(struct tcf_ct_params *p,
ctinfo = dir == FLOW_OFFLOAD_DIR_ORIGINAL ? IP_CT_ESTABLISHED : ctinfo = dir == FLOW_OFFLOAD_DIR_ORIGINAL ? IP_CT_ESTABLISHED :
IP_CT_ESTABLISHED_REPLY; IP_CT_ESTABLISHED_REPLY;
flow_offload_refresh(nf_ft, flow);
nf_conntrack_get(&ct->ct_general); nf_conntrack_get(&ct->ct_general);
nf_ct_set(skb, ct, ctinfo); nf_ct_set(skb, ct, ctinfo);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment