]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - net/ipv4/fou.c
gro: Fix remcsum offload to deal with frags in GRO
[linux.git] / net / ipv4 / fou.c
index 34968cd5c1464bf896ba1a2130fc223c50973499..eb11f9506894662d90ed78e36429190ce6507f22 100644 (file)
@@ -79,7 +79,11 @@ static struct guehdr *gue_remcsum(struct sk_buff *skb, struct guehdr *guehdr,
        __be16 *pd = data;
        size_t start = ntohs(pd[0]);
        size_t offset = ntohs(pd[1]);
-       size_t plen = hdrlen + max_t(size_t, offset + sizeof(u16), start);
+       size_t plen = sizeof(struct udphdr) + hdrlen +
+           max_t(size_t, offset + sizeof(u16), start);
+
+       if (skb->remcsum_offload)
+               return guehdr;
 
        if (!pskb_may_pull(skb, plen))
                return NULL;
@@ -221,29 +225,21 @@ static int fou_gro_complete(struct sk_buff *skb, int nhoff,
 
 static struct guehdr *gue_gro_remcsum(struct sk_buff *skb, unsigned int off,
                                      struct guehdr *guehdr, void *data,
-                                     size_t hdrlen, u8 ipproto,
-                                     struct gro_remcsum *grc, bool nopartial)
+                                     size_t hdrlen, struct gro_remcsum *grc,
+                                     bool nopartial)
 {
        __be16 *pd = data;
        size_t start = ntohs(pd[0]);
        size_t offset = ntohs(pd[1]);
-       size_t plen = hdrlen + max_t(size_t, offset + sizeof(u16), start);
 
        if (skb->remcsum_offload)
-               return NULL;
+               return guehdr;
 
        if (!NAPI_GRO_CB(skb)->csum_valid)
                return NULL;
 
-       /* Pull checksum that will be written */
-       if (skb_gro_header_hard(skb, off + plen)) {
-               guehdr = skb_gro_header_slow(skb, off + plen, off);
-               if (!guehdr)
-                       return NULL;
-       }
-
-       skb_gro_remcsum_process(skb, (void *)guehdr + hdrlen,
-                               start, offset, grc, nopartial);
+       guehdr = skb_gro_remcsum_process(skb, (void *)guehdr, off, hdrlen,
+                                        start, offset, grc, nopartial);
 
        skb->remcsum_offload = 1;
 
@@ -307,10 +303,10 @@ static struct sk_buff **gue_gro_receive(struct sk_buff **head,
 
                if (flags & GUE_PFLAG_REMCSUM) {
                        guehdr = gue_gro_remcsum(skb, off, guehdr,
-                                                data + doffset, hdrlen,
-                                                guehdr->proto_ctype, &grc,
+                                                data + doffset, hdrlen, &grc,
                                                 !!(fou->flags &
                                                    FOU_F_REMCSUM_NOPARTIAL));
+
                        if (!guehdr)
                                goto out;