xen-netback: use new skb_checksum_setup function
authorPaul Durrant <Paul.Durrant@citrix.com>
Thu, 9 Jan 2014 10:02:47 +0000 (10:02 +0000)
committerDavid S. Miller <davem@davemloft.net>
Tue, 14 Jan 2014 22:24:19 +0000 (14:24 -0800)
Use skb_checksum_setup to set up partial checksum offsets rather
then a private implementation.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Cc: Ian Campbell <ian.campbell@citrix.com>
Cc: Wei Liu <wei.liu2@citrix.com>
Acked-by: Wei Liu <wei.liu2@citrix.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/xen-netback/netback.c

index 2738563..6b62c3e 100644 (file)
@@ -39,7 +39,6 @@
 #include <linux/udp.h>
 
 #include <net/tcp.h>
-#include <net/ip6_checksum.h>
 
 #include <xen/xen.h>
 #include <xen/events.h>
@@ -1051,257 +1050,9 @@ static int xenvif_set_skb_gso(struct xenvif *vif,
        return 0;
 }
 
-static inline int maybe_pull_tail(struct sk_buff *skb, unsigned int len,
-                                 unsigned int max)
-{
-       if (skb_headlen(skb) >= len)
-               return 0;
-
-       /* If we need to pullup then pullup to the max, so we
-        * won't need to do it again.
-        */
-       if (max > skb->len)
-               max = skb->len;
-
-       if (__pskb_pull_tail(skb, max - skb_headlen(skb)) == NULL)
-               return -ENOMEM;
-
-       if (skb_headlen(skb) < len)
-               return -EPROTO;
-
-       return 0;
-}
-
-/* This value should be large enough to cover a tagged ethernet header plus
- * maximally sized IP and TCP or UDP headers.
- */
-#define MAX_IP_HDR_LEN 128
-
-static int checksum_setup_ip(struct xenvif *vif, struct sk_buff *skb,
-                            int recalculate_partial_csum)
-{
-       unsigned int off;
-       bool fragment;
-       int err;
-
-       fragment = false;
-
-       err = maybe_pull_tail(skb,
-                             sizeof(struct iphdr),
-                             MAX_IP_HDR_LEN);
-       if (err < 0)
-               goto out;
-
-       if (ip_hdr(skb)->frag_off & htons(IP_OFFSET | IP_MF))
-               fragment = true;
-
-       off = ip_hdrlen(skb);
-
-       err = -EPROTO;
-
-       if (fragment)
-               goto out;
-
-       switch (ip_hdr(skb)->protocol) {
-       case IPPROTO_TCP:
-               err = maybe_pull_tail(skb,
-                                     off + sizeof(struct tcphdr),
-                                     MAX_IP_HDR_LEN);
-               if (err < 0)
-                       goto out;
-
-               if (!skb_partial_csum_set(skb, off,
-                                         offsetof(struct tcphdr, check))) {
-                       err = -EPROTO;
-                       goto out;
-               }
-
-               if (recalculate_partial_csum)
-                       tcp_hdr(skb)->check =
-                               ~csum_tcpudp_magic(ip_hdr(skb)->saddr,
-                                                  ip_hdr(skb)->daddr,
-                                                  skb->len - off,
-                                                  IPPROTO_TCP, 0);
-               break;
-       case IPPROTO_UDP:
-               err = maybe_pull_tail(skb,
-                                     off + sizeof(struct udphdr),
-                                     MAX_IP_HDR_LEN);
-               if (err < 0)
-                       goto out;
-
-               if (!skb_partial_csum_set(skb, off,
-                                         offsetof(struct udphdr, check))) {
-                       err = -EPROTO;
-                       goto out;
-               }
-
-               if (recalculate_partial_csum)
-                       udp_hdr(skb)->check =
-                               ~csum_tcpudp_magic(ip_hdr(skb)->saddr,
-                                                  ip_hdr(skb)->daddr,
-                                                  skb->len - off,
-                                                  IPPROTO_UDP, 0);
-               break;
-       default:
-               goto out;
-       }
-
-       err = 0;
-
-out:
-       return err;
-}
-
-/* This value should be large enough to cover a tagged ethernet header plus
- * an IPv6 header, all options, and a maximal TCP or UDP header.
- */
-#define MAX_IPV6_HDR_LEN 256
-
-#define OPT_HDR(type, skb, off) \
-       (type *)(skb_network_header(skb) + (off))
-
-static int checksum_setup_ipv6(struct xenvif *vif, struct sk_buff *skb,
-                              int recalculate_partial_csum)
-{
-       int err;
-       u8 nexthdr;
-       unsigned int off;
-       unsigned int len;
-       bool fragment;
-       bool done;
-
-       fragment = false;
-       done = false;
-
-       off = sizeof(struct ipv6hdr);
-
-       err = maybe_pull_tail(skb, off, MAX_IPV6_HDR_LEN);
-       if (err < 0)
-               goto out;
-
-       nexthdr = ipv6_hdr(skb)->nexthdr;
-
-       len = sizeof(struct ipv6hdr) + ntohs(ipv6_hdr(skb)->payload_len);
-       while (off <= len && !done) {
-               switch (nexthdr) {
-               case IPPROTO_DSTOPTS:
-               case IPPROTO_HOPOPTS:
-               case IPPROTO_ROUTING: {
-                       struct ipv6_opt_hdr *hp;
-
-                       err = maybe_pull_tail(skb,
-                                             off +
-                                             sizeof(struct ipv6_opt_hdr),
-                                             MAX_IPV6_HDR_LEN);
-                       if (err < 0)
-                               goto out;
-
-                       hp = OPT_HDR(struct ipv6_opt_hdr, skb, off);
-                       nexthdr = hp->nexthdr;
-                       off += ipv6_optlen(hp);
-                       break;
-               }
-               case IPPROTO_AH: {
-                       struct ip_auth_hdr *hp;
-
-                       err = maybe_pull_tail(skb,
-                                             off +
-                                             sizeof(struct ip_auth_hdr),
-                                             MAX_IPV6_HDR_LEN);
-                       if (err < 0)
-                               goto out;
-
-                       hp = OPT_HDR(struct ip_auth_hdr, skb, off);
-                       nexthdr = hp->nexthdr;
-                       off += ipv6_authlen(hp);
-                       break;
-               }
-               case IPPROTO_FRAGMENT: {
-                       struct frag_hdr *hp;
-
-                       err = maybe_pull_tail(skb,
-                                             off +
-                                             sizeof(struct frag_hdr),
-                                             MAX_IPV6_HDR_LEN);
-                       if (err < 0)
-                               goto out;
-
-                       hp = OPT_HDR(struct frag_hdr, skb, off);
-
-                       if (hp->frag_off & htons(IP6_OFFSET | IP6_MF))
-                               fragment = true;
-
-                       nexthdr = hp->nexthdr;
-                       off += sizeof(struct frag_hdr);
-                       break;
-               }
-               default:
-                       done = true;
-                       break;
-               }
-       }
-
-       err = -EPROTO;
-
-       if (!done || fragment)
-               goto out;
-
-       switch (nexthdr) {
-       case IPPROTO_TCP:
-               err = maybe_pull_tail(skb,
-                                     off + sizeof(struct tcphdr),
-                                     MAX_IPV6_HDR_LEN);
-               if (err < 0)
-                       goto out;
-
-               if (!skb_partial_csum_set(skb, off,
-                                         offsetof(struct tcphdr, check))) {
-                       err = -EPROTO;
-                       goto out;
-               }
-
-               if (recalculate_partial_csum)
-                       tcp_hdr(skb)->check =
-                               ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
-                                                &ipv6_hdr(skb)->daddr,
-                                                skb->len - off,
-                                                IPPROTO_TCP, 0);
-               break;
-       case IPPROTO_UDP:
-               err = maybe_pull_tail(skb,
-                                     off + sizeof(struct udphdr),
-                                     MAX_IPV6_HDR_LEN);
-               if (err < 0)
-                       goto out;
-
-               if (!skb_partial_csum_set(skb, off,
-                                         offsetof(struct udphdr, check))) {
-                       err = -EPROTO;
-                       goto out;
-               }
-
-               if (recalculate_partial_csum)
-                       udp_hdr(skb)->check =
-                               ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
-                                                &ipv6_hdr(skb)->daddr,
-                                                skb->len - off,
-                                                IPPROTO_UDP, 0);
-               break;
-       default:
-               goto out;
-       }
-
-       err = 0;
-
-out:
-       return err;
-}
-
 static int checksum_setup(struct xenvif *vif, struct sk_buff *skb)
 {
-       int err = -EPROTO;
-       int recalculate_partial_csum = 0;
+       bool recalculate_partial_csum = false;
 
        /* A GSO SKB must be CHECKSUM_PARTIAL. However some buggy
         * peers can fail to set NETRXF_csum_blank when sending a GSO
@@ -1311,19 +1062,14 @@ static int checksum_setup(struct xenvif *vif, struct sk_buff *skb)
        if (skb->ip_summed != CHECKSUM_PARTIAL && skb_is_gso(skb)) {
                vif->rx_gso_checksum_fixup++;
                skb->ip_summed = CHECKSUM_PARTIAL;
-               recalculate_partial_csum = 1;
+               recalculate_partial_csum = true;
        }
 
        /* A non-CHECKSUM_PARTIAL SKB does not require setup. */
        if (skb->ip_summed != CHECKSUM_PARTIAL)
                return 0;
 
-       if (skb->protocol == htons(ETH_P_IP))
-               err = checksum_setup_ip(vif, skb, recalculate_partial_csum);
-       else if (skb->protocol == htons(ETH_P_IPV6))
-               err = checksum_setup_ipv6(vif, skb, recalculate_partial_csum);
-
-       return err;
+       return skb_checksum_setup(skb, recalculate_partial_csum);
 }
 
 static bool tx_credit_exceeded(struct xenvif *vif, unsigned size)