udp: move logic out of udp[46]_ufo_send_check
authorTom Herbert <therbert@google.com>
Sat, 20 Sep 2014 21:52:29 +0000 (14:52 -0700)
committerDavid S. Miller <davem@davemloft.net>
Fri, 26 Sep 2014 04:22:46 +0000 (00:22 -0400)
In udp[46]_ufo_send_check the UDP checksum initialized to the pseudo
header checksum. We can move this logic into udp[46]_ufo_fragment.
After this change udp[64]_ufo_send_check is a no-op.

Signed-off-by: Tom Herbert <therbert@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv4/udp_offload.c
net/ipv6/udp_offload.c

index d7c43f764c71b031090e24998d513e6c1e13d0f7..2918cc914824b34f4b30b908a84e930d5287079d 100644 (file)
@@ -27,23 +27,6 @@ struct udp_offload_priv {
 
 static int udp4_ufo_send_check(struct sk_buff *skb)
 {
-       if (!pskb_may_pull(skb, sizeof(struct udphdr)))
-               return -EINVAL;
-
-       if (likely(!skb->encapsulation)) {
-               const struct iphdr *iph;
-               struct udphdr *uh;
-
-               iph = ip_hdr(skb);
-               uh = udp_hdr(skb);
-
-               uh->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, skb->len,
-                               IPPROTO_UDP, 0);
-               skb->csum_start = skb_transport_header(skb) - skb->head;
-               skb->csum_offset = offsetof(struct udphdr, check);
-               skb->ip_summed = CHECKSUM_PARTIAL;
-       }
-
        return 0;
 }
 
@@ -128,8 +111,9 @@ static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
 {
        struct sk_buff *segs = ERR_PTR(-EINVAL);
        unsigned int mss;
-       int offset;
        __wsum csum;
+       struct udphdr *uh;
+       struct iphdr *iph;
 
        if (skb->encapsulation &&
            (skb_shinfo(skb)->gso_type &
@@ -138,6 +122,9 @@ static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
                goto out;
        }
 
+       if (!pskb_may_pull(skb, sizeof(struct udphdr)))
+               goto out;
+
        mss = skb_shinfo(skb)->gso_size;
        if (unlikely(skb->len <= mss))
                goto out;
@@ -165,10 +152,16 @@ static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
         * HW cannot do checksum of UDP packets sent as multiple
         * IP fragments.
         */
-       offset = skb_checksum_start_offset(skb);
-       csum = skb_checksum(skb, offset, skb->len - offset, 0);
-       offset += skb->csum_offset;
-       *(__sum16 *)(skb->data + offset) = csum_fold(csum);
+
+       uh = udp_hdr(skb);
+       iph = ip_hdr(skb);
+
+       uh->check = 0;
+       csum = skb_checksum(skb, 0, skb->len, 0);
+       uh->check = udp_v4_check(skb->len, iph->saddr, iph->daddr, csum);
+       if (uh->check == 0)
+               uh->check = CSUM_MANGLED_0;
+
        skb->ip_summed = CHECKSUM_NONE;
 
        /* Fragment the skb. IP headers of the fragments are updated in
index de85f809bf2985a882d0b056b92c5705ee2e74e9..e4af6437ea3baeabaeaa74af83be751455c0db66 100644 (file)
 
 static int udp6_ufo_send_check(struct sk_buff *skb)
 {
-       const struct ipv6hdr *ipv6h;
-       struct udphdr *uh;
-
-       if (!pskb_may_pull(skb, sizeof(*uh)))
-               return -EINVAL;
-
-       if (likely(!skb->encapsulation)) {
-               ipv6h = ipv6_hdr(skb);
-               uh = udp_hdr(skb);
-
-               uh->check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, skb->len,
-                                            IPPROTO_UDP, 0);
-               skb->csum_start = skb_transport_header(skb) - skb->head;
-               skb->csum_offset = offsetof(struct udphdr, check);
-               skb->ip_summed = CHECKSUM_PARTIAL;
-       }
-
        return 0;
 }
 
@@ -49,7 +32,6 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
        u8 *packet_start, *prevhdr;
        u8 nexthdr;
        u8 frag_hdr_sz = sizeof(struct frag_hdr);
-       int offset;
        __wsum csum;
        int tnl_hlen;
 
@@ -83,13 +65,27 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
            (SKB_GSO_UDP_TUNNEL|SKB_GSO_UDP_TUNNEL_CSUM))
                segs = skb_udp_tunnel_segment(skb, features);
        else {
+               const struct ipv6hdr *ipv6h;
+               struct udphdr *uh;
+
+               if (!pskb_may_pull(skb, sizeof(struct udphdr)))
+                       goto out;
+
                /* Do software UFO. Complete and fill in the UDP checksum as HW cannot
                 * do checksum of UDP packets sent as multiple IP fragments.
                 */
-               offset = skb_checksum_start_offset(skb);
-               csum = skb_checksum(skb, offset, skb->len - offset, 0);
-               offset += skb->csum_offset;
-               *(__sum16 *)(skb->data + offset) = csum_fold(csum);
+
+               uh = udp_hdr(skb);
+               ipv6h = ipv6_hdr(skb);
+
+               uh->check = 0;
+               csum = skb_checksum(skb, 0, skb->len, 0);
+               uh->check = udp_v6_check(skb->len, &ipv6h->saddr,
+                                         &ipv6h->daddr, csum);
+
+               if (uh->check == 0)
+                       uh->check = CSUM_MANGLED_0;
+
                skb->ip_summed = CHECKSUM_NONE;
 
                /* Check if there is enough headroom to insert fragment header. */