net/sched: act_ct: Support refreshing the flow table entries
authorPaul Blakey <paulb@mellanox.com>
Thu, 12 Mar 2020 10:23:08 +0000 (12:23 +0200)
committerDavid S. Miller <davem@davemloft.net>
Thu, 12 Mar 2020 22:00:39 +0000 (15:00 -0700)
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: Paul Blakey <paulb@mellanox.com>
Reviewed-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/netfilter/nf_flow_table.h
net/netfilter/nf_flow_table_core.c
net/netfilter/nf_flow_table_ip.c
net/sched/act_ct.c

index c2d5cdd9904dff9ea5634c02e9d5c0294c837101..6890f1ca3e31b5b6a1f570d1c0ef422e821356b9 100644 (file)
@@ -162,6 +162,9 @@ int flow_offload_route_init(struct flow_offload *flow,
                            const struct nf_flow_route *route);
 
 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 *tuple);
 void nf_flow_table_cleanup(struct net_device *dev);
index 4af0327992cfa0d2922a080e4015677373637d94..9a477bd563b74e00360a05c338c44e725c654789 100644 (file)
@@ -252,6 +252,19 @@ int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow)
 }
 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)
 {
        return nf_flow_timeout_delta(flow->timeout) <= 0;
index 9e563fd3da0f88168f287fb171dbe3f52f54d41d..5272721080f8c5abe2ad64b3c1f01591390af772 100644 (file)
@@ -232,13 +232,6 @@ static unsigned int nf_flow_xmit_xfrm(struct sk_buff *skb,
        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
 nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
                        const struct nf_hook_state *state)
@@ -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))
                return NF_ACCEPT;
 
-       if (unlikely(nf_flow_offload_refresh(flow_table, flow)))
-               nf_flow_offload_add(flow_table, flow);
+       flow_offload_refresh(flow_table, flow);
 
        if (nf_flow_offload_dst_check(&rt->dst)) {
                flow_offload_teardown(flow);
@@ -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)
                return NF_DROP;
 
-       flow->timeout = nf_flowtable_time_stamp + NF_FLOW_TIMEOUT;
        iph = ip_hdr(skb);
        ip_decrease_ttl(iph);
        skb->tstamp = 0;
@@ -508,8 +499,7 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
                                sizeof(*ip6h)))
                return NF_ACCEPT;
 
-       if (unlikely(nf_flow_offload_refresh(flow_table, flow)))
-               nf_flow_offload_add(flow_table, flow);
+       flow_offload_refresh(flow_table, flow);
 
        if (nf_flow_offload_dst_check(&rt->dst)) {
                flow_offload_teardown(flow);
@@ -522,7 +512,6 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
        if (nf_flow_nat_ipv6(flow, skb, dir) < 0)
                return NF_DROP;
 
-       flow->timeout = nf_flowtable_time_stamp + NF_FLOW_TIMEOUT;
        ip6h = ipv6_hdr(skb);
        ip6h->hop_limit--;
        skb->tstamp = 0;
index 31eef8a847d206cf707768079bdb2c749e9f9948..16fc731e5b039bb79f5104d65cb43ececa267f2f 100644 (file)
@@ -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 :
                                                    IP_CT_ESTABLISHED_REPLY;
 
+       flow_offload_refresh(nf_ft, flow);
        nf_conntrack_get(&ct->ct_general);
        nf_ct_set(skb, ct, ctinfo);