Commit ef710370 authored by David S. Miller's avatar David S. Miller

Merge branch 'act_ct-software-offload-of-established-flows-fixes'

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: default avatarDavid S. Miller <davem@davemloft.net>
parents 97ec3b21 4cc5fdec
...@@ -188,13 +188,14 @@ static void tcf_ct_flow_table_process_conn(struct tcf_ct_flow_table *ct_ft, ...@@ -188,13 +188,14 @@ static void tcf_ct_flow_table_process_conn(struct tcf_ct_flow_table *ct_ft,
static bool static bool
tcf_ct_flow_table_fill_tuple_ipv4(struct sk_buff *skb, 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; struct flow_ports *ports;
unsigned int thoff; unsigned int thoff;
struct iphdr *iph; struct iphdr *iph;
if (!pskb_may_pull(skb, sizeof(*iph))) if (!pskb_network_may_pull(skb, sizeof(*iph)))
return false; return false;
iph = ip_hdr(skb); iph = ip_hdr(skb);
...@@ -211,11 +212,16 @@ tcf_ct_flow_table_fill_tuple_ipv4(struct sk_buff *skb, ...@@ -211,11 +212,16 @@ tcf_ct_flow_table_fill_tuple_ipv4(struct sk_buff *skb,
if (iph->ttl <= 1) if (iph->ttl <= 1)
return false; 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; 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->src_v4.s_addr = iph->saddr;
tuple->dst_v4.s_addr = iph->daddr; tuple->dst_v4.s_addr = iph->daddr;
tuple->src_port = ports->source; tuple->src_port = ports->source;
...@@ -228,13 +234,14 @@ tcf_ct_flow_table_fill_tuple_ipv4(struct sk_buff *skb, ...@@ -228,13 +234,14 @@ tcf_ct_flow_table_fill_tuple_ipv4(struct sk_buff *skb,
static bool static bool
tcf_ct_flow_table_fill_tuple_ipv6(struct sk_buff *skb, 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 flow_ports *ports;
struct ipv6hdr *ip6h; struct ipv6hdr *ip6h;
unsigned int thoff; unsigned int thoff;
if (!pskb_may_pull(skb, sizeof(*ip6h))) if (!pskb_network_may_pull(skb, sizeof(*ip6h)))
return false; return false;
ip6h = ipv6_hdr(skb); ip6h = ipv6_hdr(skb);
...@@ -247,11 +254,16 @@ tcf_ct_flow_table_fill_tuple_ipv6(struct sk_buff *skb, ...@@ -247,11 +254,16 @@ tcf_ct_flow_table_fill_tuple_ipv6(struct sk_buff *skb,
return false; return false;
thoff = sizeof(*ip6h); 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; 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->src_v6 = ip6h->saddr;
tuple->dst_v6 = ip6h->daddr; tuple->dst_v6 = ip6h->daddr;
tuple->src_port = ports->source; tuple->src_port = ports->source;
...@@ -262,24 +274,6 @@ tcf_ct_flow_table_fill_tuple_ipv6(struct sk_buff *skb, ...@@ -262,24 +274,6 @@ tcf_ct_flow_table_fill_tuple_ipv6(struct sk_buff *skb,
return true; 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, static bool tcf_ct_flow_table_lookup(struct tcf_ct_params *p,
struct sk_buff *skb, struct sk_buff *skb,
u8 family) u8 family)
...@@ -288,10 +282,9 @@ static bool tcf_ct_flow_table_lookup(struct tcf_ct_params *p, ...@@ -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_rhash *tuplehash;
struct flow_offload_tuple tuple = {}; struct flow_offload_tuple tuple = {};
enum ip_conntrack_info ctinfo; enum ip_conntrack_info ctinfo;
struct tcphdr *tcph = NULL;
struct flow_offload *flow; struct flow_offload *flow;
struct nf_conn *ct; struct nf_conn *ct;
unsigned int thoff;
int ip_proto;
u8 dir; u8 dir;
/* Previously seen or loopback */ /* Previously seen or loopback */
...@@ -301,11 +294,11 @@ static bool tcf_ct_flow_table_lookup(struct tcf_ct_params *p, ...@@ -301,11 +294,11 @@ static bool tcf_ct_flow_table_lookup(struct tcf_ct_params *p,
switch (family) { switch (family) {
case NFPROTO_IPV4: 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; return false;
break; break;
case NFPROTO_IPV6: 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; return false;
break; break;
default: default:
...@@ -320,15 +313,14 @@ static bool tcf_ct_flow_table_lookup(struct tcf_ct_params *p, ...@@ -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]); flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]);
ct = flow->ct; 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 : ctinfo = dir == FLOW_OFFLOAD_DIR_ORIGINAL ? IP_CT_ESTABLISHED :
IP_CT_ESTABLISHED_REPLY; 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_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