|
@@ -156,6 +156,7 @@ static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev,
|
|
|
struct dst_entry *dst = skb_dst(skb);
|
|
|
struct net_device *tdev; /* Device to other host */
|
|
|
int err;
|
|
|
+ int mtu;
|
|
|
|
|
|
if (!dst) {
|
|
|
dev->stats.tx_carrier_errors++;
|
|
@@ -192,6 +193,23 @@ static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev,
|
|
|
tunnel->err_count = 0;
|
|
|
}
|
|
|
|
|
|
+ mtu = dst_mtu(dst);
|
|
|
+ if (skb->len > mtu) {
|
|
|
+ skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu);
|
|
|
+ if (skb->protocol == htons(ETH_P_IP)) {
|
|
|
+ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
|
|
|
+ htonl(mtu));
|
|
|
+ } else {
|
|
|
+ if (mtu < IPV6_MIN_MTU)
|
|
|
+ mtu = IPV6_MIN_MTU;
|
|
|
+
|
|
|
+ icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
|
|
|
+ }
|
|
|
+
|
|
|
+ dst_release(dst);
|
|
|
+ goto tx_error;
|
|
|
+ }
|
|
|
+
|
|
|
skb_scrub_packet(skb, !net_eq(tunnel->net, dev_net(dev)));
|
|
|
skb_dst_set(skb, dst);
|
|
|
skb->dev = skb_dst(skb)->dev;
|