--- linux-2.5.OLD/net/ipv6/ip6_output.c 2003-08-05 15:15:07.000000000 +0300 +++ linux-2.5/net/ipv6/ip6_output.c 2003-08-06 11:27:38.000000000 +0300 @@ -1217,7 +1217,7 @@ struct inet_opt *inet = inet_sk(sk); struct ipv6_pinfo *np = inet6_sk(sk); struct sk_buff *skb; - unsigned int maxfraglen, fragheaderlen; + unsigned int maxfraglen, fragheaderlen, xtra_fh_len; int exthdrlen; int hh_len; int mtu; @@ -1263,7 +1263,12 @@ hh_len = (rt->u.dst.dev->hard_header_len&~15) + 16; fragheaderlen = sizeof(struct ipv6hdr) + (opt ? opt->opt_nflen : 0); - maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen - sizeof(struct frag_hdr); + maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen; + + /* Only reserve space for frag_hdr if the packet will be fragmented */ + xtra_fh_len = (length > maxfraglen ? sizeof(struct frag_hdr) : 0); + + maxfraglen -= xtra_fh_len; if (mtu <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN) { if (inet->cork.length + length > sizeof(struct ipv6hdr) + IPV6_MAXPLEN - fragheaderlen) { @@ -1294,7 +1299,7 @@ alloclen = maxfraglen; else alloclen = fraglen; - alloclen += sizeof(struct frag_hdr); + alloclen += xtra_fh_len; if (transhdrlen) { skb = sock_alloc_send_skb(sk, alloclen + hh_len + 15, @@ -1317,7 +1322,7 @@ skb->ip_summed = csummode; skb->csum = 0; /* reserve 8 byte for fragmentation */ - skb_reserve(skb, hh_len+sizeof(struct frag_hdr)); + skb_reserve(skb, hh_len + xtra_fh_len); /* * Find where to start putting bytes