diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv6/ip6_vti.c | 14 |
1 files changed, 14 insertions, 0 deletions
diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c index ff3bd863fa03..0224c032dca5 100644 --- a/net/ipv6/ip6_vti.c +++ b/net/ipv6/ip6_vti.c | |||
@@ -435,6 +435,7 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl) | |||
435 | struct net_device *tdev; | 435 | struct net_device *tdev; |
436 | struct xfrm_state *x; | 436 | struct xfrm_state *x; |
437 | int err = -1; | 437 | int err = -1; |
438 | int mtu; | ||
438 | 439 | ||
439 | if (!dst) | 440 | if (!dst) |
440 | goto tx_err_link_failure; | 441 | goto tx_err_link_failure; |
@@ -468,6 +469,19 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl) | |||
468 | skb_dst_set(skb, dst); | 469 | skb_dst_set(skb, dst); |
469 | skb->dev = skb_dst(skb)->dev; | 470 | skb->dev = skb_dst(skb)->dev; |
470 | 471 | ||
472 | mtu = dst_mtu(dst); | ||
473 | if (!skb->ignore_df && skb->len > mtu) { | ||
474 | skb_dst(skb)->ops->update_pmtu(dst, NULL, skb, mtu); | ||
475 | |||
476 | if (skb->protocol == htons(ETH_P_IPV6)) | ||
477 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); | ||
478 | else | ||
479 | icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, | ||
480 | htonl(mtu)); | ||
481 | |||
482 | return -EMSGSIZE; | ||
483 | } | ||
484 | |||
471 | err = dst_output(skb); | 485 | err = dst_output(skb); |
472 | if (net_xmit_eval(err) == 0) { | 486 | if (net_xmit_eval(err) == 0) { |
473 | struct pcpu_sw_netstats *tstats = this_cpu_ptr(dev->tstats); | 487 | struct pcpu_sw_netstats *tstats = this_cpu_ptr(dev->tstats); |