#include <net/flow.h>
 #include <net/flow_dissector.h>
 #include <net/netns/hash.h>
+#include <net/lwtunnel.h>
 
 #define IPV4_MAX_PMTU          65535U          /* RFC 2675, Section 5.1 */
 #define IPV4_MIN_MTU           68                      /* RFC 791 */
 
        /* 'forwarding = true' case should always honour route mtu */
        mtu = dst_metric_raw(dst, RTAX_MTU);
-       if (mtu)
-               return mtu;
+       if (!mtu)
+               mtu = min(READ_ONCE(dst->dev->mtu), IP_MAX_MTU);
 
-       return min(READ_ONCE(dst->dev->mtu), IP_MAX_MTU);
+       return mtu - lwtunnel_headroom(dst->lwtstate, mtu);
 }
 
 static inline unsigned int ip_skb_dst_mtu(struct sock *sk,
                                          const struct sk_buff *skb)
 {
+       unsigned int mtu;
+
        if (!sk || !sk_fullsock(sk) || ip_sk_use_pmtu(sk)) {
                bool forwarding = IPCB(skb)->flags & IPSKB_FORWARDED;
 
                return ip_dst_mtu_maybe_forward(skb_dst(skb), forwarding);
        }
 
-       return min(READ_ONCE(skb_dst(skb)->dev->mtu), IP_MAX_MTU);
+       mtu = min(READ_ONCE(skb_dst(skb)->dev->mtu), IP_MAX_MTU);
+       return mtu - lwtunnel_headroom(skb_dst(skb)->lwtstate, mtu);
 }
 
 int ip_metrics_convert(struct net *net, struct nlattr *fc_mx, int fc_mx_len,
 
 
 static inline int ip6_skb_dst_mtu(struct sk_buff *skb)
 {
+       int mtu;
+
        struct ipv6_pinfo *np = skb->sk && !dev_recursion_level() ?
                                inet6_sk(skb->sk) : NULL;
 
-       return (np && np->pmtudisc >= IPV6_PMTUDISC_PROBE) ?
-              skb_dst(skb)->dev->mtu : dst_mtu(skb_dst(skb));
+       if (np && np->pmtudisc >= IPV6_PMTUDISC_PROBE) {
+               mtu = READ_ONCE(skb_dst(skb)->dev->mtu);
+               mtu -= lwtunnel_headroom(skb_dst(skb)->lwtstate, mtu);
+       } else
+               mtu = dst_mtu(skb_dst(skb));
+
+       return mtu;
 }
 
 static inline bool ip6_sk_accept_pmtu(const struct sock *sk)
        if (dst_metric_locked(dst, RTAX_MTU)) {
                mtu = dst_metric_raw(dst, RTAX_MTU);
                if (mtu)
-                       return mtu;
+                       goto out;
        }
 
        mtu = IPV6_MIN_MTU;
                mtu = idev->cnf.mtu6;
        rcu_read_unlock();
 
-       return mtu;
+out:
+       return mtu - lwtunnel_headroom(dst->lwtstate, mtu);
 }
 
 u32 ip6_mtu_from_fib6(struct fib6_info *f6i, struct in6_addr *daddr,
 
                mtu = dst_metric_raw(dst, RTAX_MTU);
 
        if (mtu)
-               return mtu;
+               goto out;
 
        mtu = READ_ONCE(dst->dev->mtu);
 
                        mtu = 576;
        }
 
+out:
        mtu = min_t(unsigned int, mtu, IP_MAX_MTU);
 
        return mtu - lwtunnel_headroom(dst->lwtstate, mtu);