diff options
-rw-r--r-- | net/ipv4/ip_vti.c | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c index 5cf10b777b7e..a917903d5e97 100644 --- a/net/ipv4/ip_vti.c +++ b/net/ipv4/ip_vti.c | |||
@@ -156,6 +156,7 @@ static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev, | |||
156 | struct dst_entry *dst = skb_dst(skb); | 156 | struct dst_entry *dst = skb_dst(skb); |
157 | struct net_device *tdev; /* Device to other host */ | 157 | struct net_device *tdev; /* Device to other host */ |
158 | int err; | 158 | int err; |
159 | int mtu; | ||
159 | 160 | ||
160 | if (!dst) { | 161 | if (!dst) { |
161 | dev->stats.tx_carrier_errors++; | 162 | dev->stats.tx_carrier_errors++; |
@@ -192,6 +193,23 @@ static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev, | |||
192 | tunnel->err_count = 0; | 193 | tunnel->err_count = 0; |
193 | } | 194 | } |
194 | 195 | ||
196 | mtu = dst_mtu(dst); | ||
197 | if (skb->len > mtu) { | ||
198 | skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu); | ||
199 | if (skb->protocol == htons(ETH_P_IP)) { | ||
200 | icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, | ||
201 | htonl(mtu)); | ||
202 | } else { | ||
203 | if (mtu < IPV6_MIN_MTU) | ||
204 | mtu = IPV6_MIN_MTU; | ||
205 | |||
206 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); | ||
207 | } | ||
208 | |||
209 | dst_release(dst); | ||
210 | goto tx_error; | ||
211 | } | ||
212 | |||
195 | skb_scrub_packet(skb, !net_eq(tunnel->net, dev_net(dev))); | 213 | skb_scrub_packet(skb, !net_eq(tunnel->net, dev_net(dev))); |
196 | skb_dst_set(skb, dst); | 214 | skb_dst_set(skb, dst); |
197 | skb->dev = skb_dst(skb)->dev; | 215 | skb->dev = skb_dst(skb)->dev; |