|
@@ -634,6 +634,7 @@ static inline u32 fnhe_hashfun(__be32 daddr)
|
|
|
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) {
|
|
@@ -644,7 +645,7 @@ static void fill_route_from_fnhe(struct rtable *rt, struct fib_nh_exception *fnh
|
|
|
}
|
|
|
|
|
|
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;
|
|
@@ -681,8 +682,10 @@ static void update_or_create_fnhe(struct fib_nh *nh, __be32 daddr, __be32 gw,
|
|
|
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);
|
|
@@ -706,6 +709,7 @@ static void update_or_create_fnhe(struct fib_nh *nh, __be32 daddr, __be32 gw,
|
|
|
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
|
|
@@ -787,7 +791,8 @@ static void __ip_do_redirect(struct rtable *rt, struct sk_buff *skb, struct flow
|
|
|
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;
|
|
@@ -1009,15 +1014,18 @@ static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu)
|
|
|
{
|
|
|
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))
|
|
@@ -1027,7 +1035,7 @@ static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu)
|
|
|
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();
|
|
@@ -1280,7 +1288,7 @@ static unsigned int ipv4_mtu(const struct dst_entry *dst)
|
|
|
|
|
|
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;
|
|
|
}
|
|
@@ -1521,6 +1529,7 @@ struct rtable *rt_dst_alloc(struct net_device *dev,
|
|
|
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;
|
|
@@ -2546,6 +2555,7 @@ struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_or
|
|
|
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;
|
|
@@ -2648,6 +2658,8 @@ static int rt_fill_info(struct net *net, __be32 dst, __be32 src, u32 table_id,
|
|
|
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;
|
|
|
|