diff options
Diffstat (limited to 'net/ipv6/ip6_output.c')
-rw-r--r-- | net/ipv6/ip6_output.c | 16 |
1 files changed, 10 insertions, 6 deletions
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index d5d20cde8d92..6e3ddf806ec2 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -1098,11 +1098,12 @@ static inline struct ipv6_rt_hdr *ip6_rthdr_dup(struct ipv6_rt_hdr *src, | |||
1098 | return src ? kmemdup(src, (src->hdrlen + 1) * 8, gfp) : NULL; | 1098 | return src ? kmemdup(src, (src->hdrlen + 1) * 8, gfp) : NULL; |
1099 | } | 1099 | } |
1100 | 1100 | ||
1101 | static void ip6_append_data_mtu(int *mtu, | 1101 | static void ip6_append_data_mtu(unsigned int *mtu, |
1102 | int *maxfraglen, | 1102 | int *maxfraglen, |
1103 | unsigned int fragheaderlen, | 1103 | unsigned int fragheaderlen, |
1104 | struct sk_buff *skb, | 1104 | struct sk_buff *skb, |
1105 | struct rt6_info *rt) | 1105 | struct rt6_info *rt, |
1106 | bool pmtuprobe) | ||
1106 | { | 1107 | { |
1107 | if (!(rt->dst.flags & DST_XFRM_TUNNEL)) { | 1108 | if (!(rt->dst.flags & DST_XFRM_TUNNEL)) { |
1108 | if (skb == NULL) { | 1109 | if (skb == NULL) { |
@@ -1114,7 +1115,9 @@ static void ip6_append_data_mtu(int *mtu, | |||
1114 | * this fragment is not first, the headers | 1115 | * this fragment is not first, the headers |
1115 | * space is regarded as data space. | 1116 | * space is regarded as data space. |
1116 | */ | 1117 | */ |
1117 | *mtu = dst_mtu(rt->dst.path); | 1118 | *mtu = min(*mtu, pmtuprobe ? |
1119 | rt->dst.dev->mtu : | ||
1120 | dst_mtu(rt->dst.path)); | ||
1118 | } | 1121 | } |
1119 | *maxfraglen = ((*mtu - fragheaderlen) & ~7) | 1122 | *maxfraglen = ((*mtu - fragheaderlen) & ~7) |
1120 | + fragheaderlen - sizeof(struct frag_hdr); | 1123 | + fragheaderlen - sizeof(struct frag_hdr); |
@@ -1131,11 +1134,10 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1131 | struct ipv6_pinfo *np = inet6_sk(sk); | 1134 | struct ipv6_pinfo *np = inet6_sk(sk); |
1132 | struct inet_cork *cork; | 1135 | struct inet_cork *cork; |
1133 | struct sk_buff *skb, *skb_prev = NULL; | 1136 | struct sk_buff *skb, *skb_prev = NULL; |
1134 | unsigned int maxfraglen, fragheaderlen; | 1137 | unsigned int maxfraglen, fragheaderlen, mtu; |
1135 | int exthdrlen; | 1138 | int exthdrlen; |
1136 | int dst_exthdrlen; | 1139 | int dst_exthdrlen; |
1137 | int hh_len; | 1140 | int hh_len; |
1138 | int mtu; | ||
1139 | int copy; | 1141 | int copy; |
1140 | int err; | 1142 | int err; |
1141 | int offset = 0; | 1143 | int offset = 0; |
@@ -1292,7 +1294,9 @@ alloc_new_skb: | |||
1292 | /* update mtu and maxfraglen if necessary */ | 1294 | /* update mtu and maxfraglen if necessary */ |
1293 | if (skb == NULL || skb_prev == NULL) | 1295 | if (skb == NULL || skb_prev == NULL) |
1294 | ip6_append_data_mtu(&mtu, &maxfraglen, | 1296 | ip6_append_data_mtu(&mtu, &maxfraglen, |
1295 | fragheaderlen, skb, rt); | 1297 | fragheaderlen, skb, rt, |
1298 | np->pmtudisc == | ||
1299 | IPV6_PMTUDISC_PROBE); | ||
1296 | 1300 | ||
1297 | skb_prev = skb; | 1301 | skb_prev = skb; |
1298 | 1302 | ||