summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--net/core/dev.c3
-rw-r--r--net/core/skbuff.c11
2 files changed, 13 insertions, 1 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 3337cf98f231..247f1614a796 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2391,7 +2391,8 @@ void *skb_gro_header(struct sk_buff *skb, unsigned int hlen)
return pskb_may_pull(skb, hlen) ? skb->data + offset : NULL;
return page_address(skb_shinfo(skb)->frags[0].page) +
- skb_shinfo(skb)->frags[0].page_offset + offset;
+ skb_shinfo(skb)->frags[0].page_offset +
+ offset - skb_headlen(skb);
}
EXPORT_SYMBOL(skb_gro_header);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index e55d1ef5690d..67f2a2f85827 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -2678,6 +2678,17 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb)
p = nskb;
merge:
+ if (skb_gro_offset(skb) > skb_headlen(skb)) {
+ skb_shinfo(skb)->frags[0].page_offset +=
+ skb_gro_offset(skb) - skb_headlen(skb);
+ skb_shinfo(skb)->frags[0].size -=
+ skb_gro_offset(skb) - skb_headlen(skb);
+ skb_gro_reset_offset(skb);
+ skb_gro_pull(skb, skb_headlen(skb));
+ }
+
+ __skb_pull(skb, skb_gro_offset(skb));
+
p->prev->next = skb;
p->prev = skb;
skb_header_release(skb);