return --iph->ttl;
 }
 
+static inline int ip_mtu_locked(const struct dst_entry *dst)
+{
+       const struct rtable *rt = (const struct rtable *)dst;
+
+       return rt->rt_mtu_locked || dst_metric_locked(dst, RTAX_MTU);
+}
+
 static inline
 int ip_dont_fragment(const struct sock *sk, const struct dst_entry *dst)
 {
 
        return  pmtudisc == IP_PMTUDISC_DO ||
                (pmtudisc == IP_PMTUDISC_WANT &&
-                !(dst_metric_locked(dst, RTAX_MTU)));
+                !ip_mtu_locked(dst));
 }
 
 static inline bool ip_sk_accept_pmtu(const struct sock *sk)
        struct net *net = dev_net(dst->dev);
 
        if (net->ipv4.sysctl_ip_fwd_use_pmtu ||
-           dst_metric_locked(dst, RTAX_MTU) ||
+           ip_mtu_locked(dst) ||
            !forwarding)
                return dst_mtu(dst);
 
 
 static void fill_route_from_fnhe(struct rtable *rt, struct fib_nh_exception *fnhe)
 {
        rt->rt_pmtu = fnhe->fnhe_pmtu;
+       rt->rt_mtu_locked = fnhe->fnhe_mtu_locked;
        rt->dst.expires = fnhe->fnhe_expires;
 
        if (fnhe->fnhe_gw) {
 }
 
 static void update_or_create_fnhe(struct fib_nh *nh, __be32 daddr, __be32 gw,
-                                 u32 pmtu, unsigned long expires)
+                                 u32 pmtu, bool lock, unsigned long expires)
 {
        struct fnhe_hash_bucket *hash;
        struct fib_nh_exception *fnhe;
                        fnhe->fnhe_genid = genid;
                if (gw)
                        fnhe->fnhe_gw = gw;
-               if (pmtu)
+               if (pmtu) {
                        fnhe->fnhe_pmtu = pmtu;
+                       fnhe->fnhe_mtu_locked = lock;
+               }
                fnhe->fnhe_expires = max(1UL, expires);
                /* Update all cached dsts too */
                rt = rcu_dereference(fnhe->fnhe_rth_input);
                fnhe->fnhe_daddr = daddr;
                fnhe->fnhe_gw = gw;
                fnhe->fnhe_pmtu = pmtu;
+               fnhe->fnhe_mtu_locked = lock;
                fnhe->fnhe_expires = expires;
 
                /* Exception created; mark the cached routes for the nexthop
                                struct fib_nh *nh = &FIB_RES_NH(res);
 
                                update_or_create_fnhe(nh, fl4->daddr, new_gw,
-                                               0, jiffies + ip_rt_gc_timeout);
+                                               0, false,
+                                               jiffies + ip_rt_gc_timeout);
                        }
                        if (kill_route)
                                rt->dst.obsolete = DST_OBSOLETE_KILL;
 {
        struct dst_entry *dst = &rt->dst;
        struct fib_result res;
+       bool lock = false;
 
-       if (dst_metric_locked(dst, RTAX_MTU))
+       if (ip_mtu_locked(dst))
                return;
 
        if (ipv4_mtu(dst) < mtu)
                return;
 
-       if (mtu < ip_rt_min_pmtu)
+       if (mtu < ip_rt_min_pmtu) {
+               lock = true;
                mtu = ip_rt_min_pmtu;
+       }
 
        if (rt->rt_pmtu == mtu &&
            time_before(jiffies, dst->expires - ip_rt_mtu_expires / 2))
        if (fib_lookup(dev_net(dst->dev), fl4, &res, 0) == 0) {
                struct fib_nh *nh = &FIB_RES_NH(res);
 
-               update_or_create_fnhe(nh, fl4->daddr, 0, mtu,
+               update_or_create_fnhe(nh, fl4->daddr, 0, mtu, lock,
                                      jiffies + ip_rt_mtu_expires);
        }
        rcu_read_unlock();
 
        mtu = READ_ONCE(dst->dev->mtu);
 
-       if (unlikely(dst_metric_locked(dst, RTAX_MTU))) {
+       if (unlikely(ip_mtu_locked(dst))) {
                if (rt->rt_uses_gateway && mtu > 576)
                        mtu = 576;
        }
                rt->rt_is_input = 0;
                rt->rt_iif = 0;
                rt->rt_pmtu = 0;
+               rt->rt_mtu_locked = 0;
                rt->rt_gateway = 0;
                rt->rt_uses_gateway = 0;
                rt->rt_table_id = 0;
                rt->rt_is_input = ort->rt_is_input;
                rt->rt_iif = ort->rt_iif;
                rt->rt_pmtu = ort->rt_pmtu;
+               rt->rt_mtu_locked = ort->rt_mtu_locked;
 
                rt->rt_genid = rt_genid_ipv4(net);
                rt->rt_flags = ort->rt_flags;
        memcpy(metrics, dst_metrics_ptr(&rt->dst), sizeof(metrics));
        if (rt->rt_pmtu && expires)
                metrics[RTAX_MTU - 1] = rt->rt_pmtu;
+       if (rt->rt_mtu_locked && expires)
+               metrics[RTAX_LOCK - 1] |= BIT(RTAX_MTU);
        if (rtnetlink_put_metrics(skb, metrics) < 0)
                goto nla_put_failure;