netfilter: flowtable: reduce calls to pskb_may_pull()
authorPablo Neira Ayuso <pablo@netfilter.org>
Sun, 11 Oct 2020 22:18:07 +0000 (00:18 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Sun, 11 Oct 2020 23:58:10 +0000 (01:58 +0200)
Make two unfront calls to pskb_may_pull() to linearize the network and
transport header.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
net/netfilter/nf_flow_table_core.c
net/netfilter/nf_flow_table_ip.c

index 4f7a567..513f78d 100644 (file)
@@ -395,8 +395,7 @@ static int nf_flow_nat_port_tcp(struct sk_buff *skb, unsigned int thoff,
 {
        struct tcphdr *tcph;
 
-       if (!pskb_may_pull(skb, thoff + sizeof(*tcph)) ||
-           skb_try_make_writable(skb, thoff + sizeof(*tcph)))
+       if (skb_try_make_writable(skb, thoff + sizeof(*tcph)))
                return -1;
 
        tcph = (void *)(skb_network_header(skb) + thoff);
@@ -410,8 +409,7 @@ static int nf_flow_nat_port_udp(struct sk_buff *skb, unsigned int thoff,
 {
        struct udphdr *udph;
 
-       if (!pskb_may_pull(skb, thoff + sizeof(*udph)) ||
-           skb_try_make_writable(skb, thoff + sizeof(*udph)))
+       if (skb_try_make_writable(skb, thoff + sizeof(*udph)))
                return -1;
 
        udph = (void *)(skb_network_header(skb) + thoff);
@@ -449,8 +447,7 @@ int nf_flow_snat_port(const struct flow_offload *flow,
        struct flow_ports *hdr;
        __be16 port, new_port;
 
-       if (!pskb_may_pull(skb, thoff + sizeof(*hdr)) ||
-           skb_try_make_writable(skb, thoff + sizeof(*hdr)))
+       if (skb_try_make_writable(skb, thoff + sizeof(*hdr)))
                return -1;
 
        hdr = (void *)(skb_network_header(skb) + thoff);
@@ -481,8 +478,7 @@ int nf_flow_dnat_port(const struct flow_offload *flow,
        struct flow_ports *hdr;
        __be16 port, new_port;
 
-       if (!pskb_may_pull(skb, thoff + sizeof(*hdr)) ||
-           skb_try_make_writable(skb, thoff + sizeof(*hdr)))
+       if (skb_try_make_writable(skb, thoff + sizeof(*hdr)))
                return -1;
 
        hdr = (void *)(skb_network_header(skb) + thoff);
index a3bca75..a698dbe 100644 (file)
@@ -25,9 +25,6 @@ static int nf_flow_state_check(struct flow_offload *flow, int proto,
        if (proto != IPPROTO_TCP)
                return 0;
 
-       if (!pskb_may_pull(skb, thoff + sizeof(*tcph)))
-               return -1;
-
        tcph = (void *)(skb_network_header(skb) + thoff);
        if (unlikely(tcph->fin || tcph->rst)) {
                flow_offload_teardown(flow);
@@ -42,8 +39,7 @@ static int nf_flow_nat_ip_tcp(struct sk_buff *skb, unsigned int thoff,
 {
        struct tcphdr *tcph;
 
-       if (!pskb_may_pull(skb, thoff + sizeof(*tcph)) ||
-           skb_try_make_writable(skb, thoff + sizeof(*tcph)))
+       if (skb_try_make_writable(skb, thoff + sizeof(*tcph)))
                return -1;
 
        tcph = (void *)(skb_network_header(skb) + thoff);
@@ -57,8 +53,7 @@ static int nf_flow_nat_ip_udp(struct sk_buff *skb, unsigned int thoff,
 {
        struct udphdr *udph;
 
-       if (!pskb_may_pull(skb, thoff + sizeof(*udph)) ||
-           skb_try_make_writable(skb, thoff + sizeof(*udph)))
+       if (skb_try_make_writable(skb, thoff + sizeof(*udph)))
                return -1;
 
        udph = (void *)(skb_network_header(skb) + thoff);
@@ -167,8 +162,8 @@ static bool ip_has_options(unsigned int thoff)
 static int nf_flow_tuple_ip(struct sk_buff *skb, const struct net_device *dev,
                            struct flow_offload_tuple *tuple)
 {
+       unsigned int thoff, hdrsize;
        struct flow_ports *ports;
-       unsigned int thoff;
        struct iphdr *iph;
 
        if (!pskb_may_pull(skb, sizeof(*iph)))
@@ -181,15 +176,22 @@ static int nf_flow_tuple_ip(struct sk_buff *skb, const struct net_device *dev,
            unlikely(ip_has_options(thoff)))
                return -1;
 
-       if (iph->protocol != IPPROTO_TCP &&
-           iph->protocol != IPPROTO_UDP)
+       switch (iph->protocol) {
+       case IPPROTO_TCP:
+               hdrsize = sizeof(struct tcphdr);
+               break;
+       case IPPROTO_UDP:
+               hdrsize = sizeof(struct udphdr);
+               break;
+       default:
                return -1;
+       }
 
        if (iph->ttl <= 1)
                return -1;
 
        thoff = iph->ihl * 4;
-       if (!pskb_may_pull(skb, thoff + sizeof(*ports)))
+       if (!pskb_may_pull(skb, thoff + hdrsize))
                return -1;
 
        iph = ip_hdr(skb);
@@ -315,8 +317,7 @@ static int nf_flow_nat_ipv6_tcp(struct sk_buff *skb, unsigned int thoff,
 {
        struct tcphdr *tcph;
 
-       if (!pskb_may_pull(skb, thoff + sizeof(*tcph)) ||
-           skb_try_make_writable(skb, thoff + sizeof(*tcph)))
+       if (skb_try_make_writable(skb, thoff + sizeof(*tcph)))
                return -1;
 
        tcph = (void *)(skb_network_header(skb) + thoff);
@@ -332,8 +333,7 @@ static int nf_flow_nat_ipv6_udp(struct sk_buff *skb, unsigned int thoff,
 {
        struct udphdr *udph;
 
-       if (!pskb_may_pull(skb, thoff + sizeof(*udph)) ||
-           skb_try_make_writable(skb, thoff + sizeof(*udph)))
+       if (skb_try_make_writable(skb, thoff + sizeof(*udph)))
                return -1;
 
        udph = (void *)(skb_network_header(skb) + thoff);
@@ -439,24 +439,31 @@ static int nf_flow_nat_ipv6(const struct flow_offload *flow,
 static int nf_flow_tuple_ipv6(struct sk_buff *skb, const struct net_device *dev,
                              struct flow_offload_tuple *tuple)
 {
+       unsigned int thoff, hdrsize;
        struct flow_ports *ports;
        struct ipv6hdr *ip6h;
-       unsigned int thoff;
 
        if (!pskb_may_pull(skb, sizeof(*ip6h)))
                return -1;
 
        ip6h = ipv6_hdr(skb);
 
-       if (ip6h->nexthdr != IPPROTO_TCP &&
-           ip6h->nexthdr != IPPROTO_UDP)
+       switch (ip6h->nexthdr) {
+       case IPPROTO_TCP:
+               hdrsize = sizeof(struct tcphdr);
+               break;
+       case IPPROTO_UDP:
+               hdrsize = sizeof(struct udphdr);
+               break;
+       default:
                return -1;
+       }
 
        if (ip6h->hop_limit <= 1)
                return -1;
 
        thoff = sizeof(*ip6h);
-       if (!pskb_may_pull(skb, thoff + sizeof(*ports)))
+       if (!pskb_may_pull(skb, thoff + hdrsize))
                return -1;
 
        ip6h = ipv6_hdr(skb);