diff options
Diffstat (limited to 'net/ipv6/udp_offload.c')
-rw-r--r-- | net/ipv6/udp_offload.c | 20 |
1 files changed, 12 insertions, 8 deletions
diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c index 3bb3a891a424..d3cfaf9c7a08 100644 --- a/net/ipv6/udp_offload.c +++ b/net/ipv6/udp_offload.c | |||
@@ -46,11 +46,12 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, | |||
46 | unsigned int mss; | 46 | unsigned int mss; |
47 | unsigned int unfrag_ip6hlen, unfrag_len; | 47 | unsigned int unfrag_ip6hlen, unfrag_len; |
48 | struct frag_hdr *fptr; | 48 | struct frag_hdr *fptr; |
49 | u8 *mac_start, *prevhdr; | 49 | u8 *packet_start, *prevhdr; |
50 | u8 nexthdr; | 50 | u8 nexthdr; |
51 | u8 frag_hdr_sz = sizeof(struct frag_hdr); | 51 | u8 frag_hdr_sz = sizeof(struct frag_hdr); |
52 | int offset; | 52 | int offset; |
53 | __wsum csum; | 53 | __wsum csum; |
54 | int tnl_hlen; | ||
54 | 55 | ||
55 | mss = skb_shinfo(skb)->gso_size; | 56 | mss = skb_shinfo(skb)->gso_size; |
56 | if (unlikely(skb->len <= mss)) | 57 | if (unlikely(skb->len <= mss)) |
@@ -83,9 +84,11 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, | |||
83 | skb->ip_summed = CHECKSUM_NONE; | 84 | skb->ip_summed = CHECKSUM_NONE; |
84 | 85 | ||
85 | /* Check if there is enough headroom to insert fragment header. */ | 86 | /* Check if there is enough headroom to insert fragment header. */ |
86 | if ((skb_mac_header(skb) < skb->head + frag_hdr_sz) && | 87 | tnl_hlen = skb_tnl_header_len(skb); |
87 | pskb_expand_head(skb, frag_hdr_sz, 0, GFP_ATOMIC)) | 88 | if (skb_headroom(skb) < (tnl_hlen + frag_hdr_sz)) { |
88 | goto out; | 89 | if (gso_pskb_expand_head(skb, tnl_hlen + frag_hdr_sz)) |
90 | goto out; | ||
91 | } | ||
89 | 92 | ||
90 | /* Find the unfragmentable header and shift it left by frag_hdr_sz | 93 | /* Find the unfragmentable header and shift it left by frag_hdr_sz |
91 | * bytes to insert fragment header. | 94 | * bytes to insert fragment header. |
@@ -93,11 +96,12 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, | |||
93 | unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr); | 96 | unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr); |
94 | nexthdr = *prevhdr; | 97 | nexthdr = *prevhdr; |
95 | *prevhdr = NEXTHDR_FRAGMENT; | 98 | *prevhdr = NEXTHDR_FRAGMENT; |
96 | unfrag_len = skb_network_header(skb) - skb_mac_header(skb) + | 99 | unfrag_len = (skb_network_header(skb) - skb_mac_header(skb)) + |
97 | unfrag_ip6hlen; | 100 | unfrag_ip6hlen + tnl_hlen; |
98 | mac_start = skb_mac_header(skb); | 101 | packet_start = (u8 *) skb->head + SKB_GSO_CB(skb)->mac_offset; |
99 | memmove(mac_start-frag_hdr_sz, mac_start, unfrag_len); | 102 | memmove(packet_start-frag_hdr_sz, packet_start, unfrag_len); |
100 | 103 | ||
104 | SKB_GSO_CB(skb)->mac_offset -= frag_hdr_sz; | ||
101 | skb->mac_header -= frag_hdr_sz; | 105 | skb->mac_header -= frag_hdr_sz; |
102 | skb->network_header -= frag_hdr_sz; | 106 | skb->network_header -= frag_hdr_sz; |
103 | 107 | ||