Since commit 7d3f3b4367f3 ("net: ipv4: Cache pmtu for all packet paths
if multipath enabled") __ip_rt_update_pmtu() updates the exception of
every path of a multipath route, but update_or_create_fnhe() overwrites
whatever pmtu a path already has. A Packet Too Big from a wider path
thus raises the pmtu a narrower path has learned, and flows on that path
blackhole until it gets its own Packet Too Big again.
The early return in __ip_rt_update_pmtu() already keeps a pmtu from going
up on the path the Packet Too Big was looked up on. Do the same for the
other paths: leave an unexpired exception with a lower pmtu alone.
Signed-off-by: Vladimir Vdovin <redacted>
---
net/ipv4/route.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index d0a5f6d77094..596af782c1fb 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -676,6 +676,14 @@ static void update_or_create_fnhe(struct fib_nh_common *nhc, __be32 daddr,
}
if (fnhe) {
+ /* __ip_rt_update_pmtu() caches a pmtu on every path of a
+ * multipath route, don't let a Packet Too Big from one path
+ * raise the pmtu another path already learned.
+ */
+ if (pmtu && fnhe->fnhe_genid == genid && fnhe->fnhe_pmtu &&
+ pmtu > fnhe->fnhe_pmtu &&
+ time_before(jiffies, fnhe->fnhe_expires))
+ goto out_unlock;
if (fnhe->fnhe_genid != genid)
fnhe->fnhe_genid = genid;
if (gw)--
2.56.0