diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv6/ip6_output.c | 42 |
1 files changed, 21 insertions, 21 deletions
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 827a3f5ff3bb..fcd3c66ded16 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -195,37 +195,37 @@ int ip6_xmit(const struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6, | |||
195 | const struct ipv6_pinfo *np = inet6_sk(sk); | 195 | const struct ipv6_pinfo *np = inet6_sk(sk); |
196 | struct in6_addr *first_hop = &fl6->daddr; | 196 | struct in6_addr *first_hop = &fl6->daddr; |
197 | struct dst_entry *dst = skb_dst(skb); | 197 | struct dst_entry *dst = skb_dst(skb); |
198 | unsigned int head_room; | ||
198 | struct ipv6hdr *hdr; | 199 | struct ipv6hdr *hdr; |
199 | u8 proto = fl6->flowi6_proto; | 200 | u8 proto = fl6->flowi6_proto; |
200 | int seg_len = skb->len; | 201 | int seg_len = skb->len; |
201 | int hlimit = -1; | 202 | int hlimit = -1; |
202 | u32 mtu; | 203 | u32 mtu; |
203 | 204 | ||
204 | if (opt) { | 205 | head_room = sizeof(struct ipv6hdr) + LL_RESERVED_SPACE(dst->dev); |
205 | unsigned int head_room; | 206 | if (opt) |
207 | head_room += opt->opt_nflen + opt->opt_flen; | ||
206 | 208 | ||
207 | /* First: exthdrs may take lots of space (~8K for now) | 209 | if (unlikely(skb_headroom(skb) < head_room)) { |
208 | MAX_HEADER is not enough. | 210 | struct sk_buff *skb2 = skb_realloc_headroom(skb, head_room); |
209 | */ | 211 | if (!skb2) { |
210 | head_room = opt->opt_nflen + opt->opt_flen; | 212 | IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), |
211 | seg_len += head_room; | 213 | IPSTATS_MIB_OUTDISCARDS); |
212 | head_room += sizeof(struct ipv6hdr) + LL_RESERVED_SPACE(dst->dev); | 214 | kfree_skb(skb); |
213 | 215 | return -ENOBUFS; | |
214 | if (skb_headroom(skb) < head_room) { | ||
215 | struct sk_buff *skb2 = skb_realloc_headroom(skb, head_room); | ||
216 | if (!skb2) { | ||
217 | IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), | ||
218 | IPSTATS_MIB_OUTDISCARDS); | ||
219 | kfree_skb(skb); | ||
220 | return -ENOBUFS; | ||
221 | } | ||
222 | if (skb->sk) | ||
223 | skb_set_owner_w(skb2, skb->sk); | ||
224 | consume_skb(skb); | ||
225 | skb = skb2; | ||
226 | } | 216 | } |
217 | if (skb->sk) | ||
218 | skb_set_owner_w(skb2, skb->sk); | ||
219 | consume_skb(skb); | ||
220 | skb = skb2; | ||
221 | } | ||
222 | |||
223 | if (opt) { | ||
224 | seg_len += opt->opt_nflen + opt->opt_flen; | ||
225 | |||
227 | if (opt->opt_flen) | 226 | if (opt->opt_flen) |
228 | ipv6_push_frag_opts(skb, opt, &proto); | 227 | ipv6_push_frag_opts(skb, opt, &proto); |
228 | |||
229 | if (opt->opt_nflen) | 229 | if (opt->opt_nflen) |
230 | ipv6_push_nfrag_opts(skb, opt, &proto, &first_hop, | 230 | ipv6_push_nfrag_opts(skb, opt, &proto, &first_hop, |
231 | &fl6->saddr); | 231 | &fl6->saddr); |