|
@@ -1093,11 +1093,12 @@ static inline struct ipv6_rt_hdr *ip6_rthdr_dup(struct ipv6_rt_hdr *src,
|
|
|
return src ? kmemdup(src, (src->hdrlen + 1) * 8, gfp) : NULL;
|
|
|
}
|
|
|
|
|
|
-static void ip6_append_data_mtu(int *mtu,
|
|
|
+static void ip6_append_data_mtu(unsigned int *mtu,
|
|
|
int *maxfraglen,
|
|
|
unsigned int fragheaderlen,
|
|
|
struct sk_buff *skb,
|
|
|
- struct rt6_info *rt)
|
|
|
+ struct rt6_info *rt,
|
|
|
+ bool pmtuprobe)
|
|
|
{
|
|
|
if (!(rt->dst.flags & DST_XFRM_TUNNEL)) {
|
|
|
if (skb == NULL) {
|
|
@@ -1109,7 +1110,9 @@ static void ip6_append_data_mtu(int *mtu,
|
|
|
* this fragment is not first, the headers
|
|
|
* space is regarded as data space.
|
|
|
*/
|
|
|
- *mtu = dst_mtu(rt->dst.path);
|
|
|
+ *mtu = min(*mtu, pmtuprobe ?
|
|
|
+ rt->dst.dev->mtu :
|
|
|
+ dst_mtu(rt->dst.path));
|
|
|
}
|
|
|
*maxfraglen = ((*mtu - fragheaderlen) & ~7)
|
|
|
+ fragheaderlen - sizeof(struct frag_hdr);
|
|
@@ -1126,11 +1129,10 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
|
|
|
struct ipv6_pinfo *np = inet6_sk(sk);
|
|
|
struct inet_cork *cork;
|
|
|
struct sk_buff *skb, *skb_prev = NULL;
|
|
|
- unsigned int maxfraglen, fragheaderlen;
|
|
|
+ unsigned int maxfraglen, fragheaderlen, mtu;
|
|
|
int exthdrlen;
|
|
|
int dst_exthdrlen;
|
|
|
int hh_len;
|
|
|
- int mtu;
|
|
|
int copy;
|
|
|
int err;
|
|
|
int offset = 0;
|
|
@@ -1287,7 +1289,9 @@ alloc_new_skb:
|
|
|
/* update mtu and maxfraglen if necessary */
|
|
|
if (skb == NULL || skb_prev == NULL)
|
|
|
ip6_append_data_mtu(&mtu, &maxfraglen,
|
|
|
- fragheaderlen, skb, rt);
|
|
|
+ fragheaderlen, skb, rt,
|
|
|
+ np->pmtudisc ==
|
|
|
+ IPV6_PMTUDISC_PROBE);
|
|
|
|
|
|
skb_prev = skb;
|
|
|
|