Skip to content

Commit

Permalink
Merge branch 'act_ct-software-offload-of-established-flows-fixes'
Browse files Browse the repository at this point in the history
Paul Blakey says:

====================
Fixes for tc act_ct software offload of established flows (diff v4->v6)

v4 of the original patchset was accidentally merged while we moved ahead
with v6 review. This two patches are the diff between v4 that was merged and
v6 that was the final revision, which was acked by the community.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Mar 4, 2020
2 parents 97ec3b2 + 4cc5fde commit ef71037
Showing 1 changed file with 28 additions and 36 deletions.
64 changes: 28 additions & 36 deletions net/sched/act_ct.c
Original file line number Diff line number Diff line change
Expand Up @@ -188,13 +188,14 @@ static void tcf_ct_flow_table_process_conn(struct tcf_ct_flow_table *ct_ft,

static bool
tcf_ct_flow_table_fill_tuple_ipv4(struct sk_buff *skb,
struct flow_offload_tuple *tuple)
struct flow_offload_tuple *tuple,
struct tcphdr **tcph)
{
struct flow_ports *ports;
unsigned int thoff;
struct iphdr *iph;

if (!pskb_may_pull(skb, sizeof(*iph)))
if (!pskb_network_may_pull(skb, sizeof(*iph)))
return false;

iph = ip_hdr(skb);
Expand All @@ -211,11 +212,16 @@ tcf_ct_flow_table_fill_tuple_ipv4(struct sk_buff *skb,
if (iph->ttl <= 1)
return false;

if (!pskb_may_pull(skb, thoff + sizeof(*ports)))
if (!pskb_network_may_pull(skb, iph->protocol == IPPROTO_TCP ?
thoff + sizeof(struct tcphdr) :
thoff + sizeof(*ports)))
return false;

ports = (struct flow_ports *)(skb_network_header(skb) + thoff);
iph = ip_hdr(skb);
if (iph->protocol == IPPROTO_TCP)
*tcph = (void *)(skb_network_header(skb) + thoff);

ports = (struct flow_ports *)(skb_network_header(skb) + thoff);
tuple->src_v4.s_addr = iph->saddr;
tuple->dst_v4.s_addr = iph->daddr;
tuple->src_port = ports->source;
Expand All @@ -228,13 +234,14 @@ tcf_ct_flow_table_fill_tuple_ipv4(struct sk_buff *skb,

static bool
tcf_ct_flow_table_fill_tuple_ipv6(struct sk_buff *skb,
struct flow_offload_tuple *tuple)
struct flow_offload_tuple *tuple,
struct tcphdr **tcph)
{
struct flow_ports *ports;
struct ipv6hdr *ip6h;
unsigned int thoff;

if (!pskb_may_pull(skb, sizeof(*ip6h)))
if (!pskb_network_may_pull(skb, sizeof(*ip6h)))
return false;

ip6h = ipv6_hdr(skb);
Expand All @@ -247,11 +254,16 @@ tcf_ct_flow_table_fill_tuple_ipv6(struct sk_buff *skb,
return false;

thoff = sizeof(*ip6h);
if (!pskb_may_pull(skb, thoff + sizeof(*ports)))
if (!pskb_network_may_pull(skb, ip6h->nexthdr == IPPROTO_TCP ?
thoff + sizeof(struct tcphdr) :
thoff + sizeof(*ports)))
return false;

ports = (struct flow_ports *)(skb_network_header(skb) + thoff);
ip6h = ipv6_hdr(skb);
if (ip6h->nexthdr == IPPROTO_TCP)
*tcph = (void *)(skb_network_header(skb) + thoff);

ports = (struct flow_ports *)(skb_network_header(skb) + thoff);
tuple->src_v6 = ip6h->saddr;
tuple->dst_v6 = ip6h->daddr;
tuple->src_port = ports->source;
Expand All @@ -262,24 +274,6 @@ tcf_ct_flow_table_fill_tuple_ipv6(struct sk_buff *skb,
return true;
}

static bool tcf_ct_flow_table_check_tcp(struct flow_offload *flow,
struct sk_buff *skb,
unsigned int thoff)
{
struct tcphdr *tcph;

if (!pskb_may_pull(skb, thoff + sizeof(*tcph)))
return false;

tcph = (void *)(skb_network_header(skb) + thoff);
if (unlikely(tcph->fin || tcph->rst)) {
flow_offload_teardown(flow);
return false;
}

return true;
}

static bool tcf_ct_flow_table_lookup(struct tcf_ct_params *p,
struct sk_buff *skb,
u8 family)
Expand All @@ -288,10 +282,9 @@ static bool tcf_ct_flow_table_lookup(struct tcf_ct_params *p,
struct flow_offload_tuple_rhash *tuplehash;
struct flow_offload_tuple tuple = {};
enum ip_conntrack_info ctinfo;
struct tcphdr *tcph = NULL;
struct flow_offload *flow;
struct nf_conn *ct;
unsigned int thoff;
int ip_proto;
u8 dir;

/* Previously seen or loopback */
Expand All @@ -301,11 +294,11 @@ static bool tcf_ct_flow_table_lookup(struct tcf_ct_params *p,

switch (family) {
case NFPROTO_IPV4:
if (!tcf_ct_flow_table_fill_tuple_ipv4(skb, &tuple))
if (!tcf_ct_flow_table_fill_tuple_ipv4(skb, &tuple, &tcph))
return false;
break;
case NFPROTO_IPV6:
if (!tcf_ct_flow_table_fill_tuple_ipv6(skb, &tuple))
if (!tcf_ct_flow_table_fill_tuple_ipv6(skb, &tuple, &tcph))
return false;
break;
default:
Expand All @@ -320,15 +313,14 @@ static bool tcf_ct_flow_table_lookup(struct tcf_ct_params *p,
flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]);
ct = flow->ct;

if (tcph && (unlikely(tcph->fin || tcph->rst))) {
flow_offload_teardown(flow);
return false;
}

ctinfo = dir == FLOW_OFFLOAD_DIR_ORIGINAL ? IP_CT_ESTABLISHED :
IP_CT_ESTABLISHED_REPLY;

thoff = ip_hdr(skb)->ihl * 4;
ip_proto = ip_hdr(skb)->protocol;
if (ip_proto == IPPROTO_TCP &&
!tcf_ct_flow_table_check_tcp(flow, skb, thoff))
return false;

nf_conntrack_get(&ct->ct_general);
nf_ct_set(skb, ct, ctinfo);

Expand Down

0 comments on commit ef71037

Please sign in to comment.