[PATCH net v2 1/4] ipv4: add FIB_LOOKUP_REPORT_MISS

From: liamsmith827

Date: Tue Nov 10 2026 - 01:20:57 EST


From: liamsmith827 <liamsmith827@xxxxxxxxx>

IPv4 FIB lookup maps a routing miss to -ENETUNREACH, which is also
returned when an unreachable rule is encountered. This flag prevents the
mapping, returning -ESRCH instead.

Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: liamsmith827 <liamsmith827@xxxxxxxxx>
---
include/net/fib_rules.h | 5 +++++
include/net/ip_fib.h | 6 +++---
net/ipv4/fib_rules.c | 2 +-
3 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h
index c6b94790fa81..bcb6809dbd10 100644
--- a/include/net/fib_rules.h
+++ b/include/net/fib_rules.h
@@ -59,6 +59,11 @@ struct fib_lookup_arg {
int flags;
#define FIB_LOOKUP_NOREF 1
#define FIB_LOOKUP_IGNORE_LINKSTATE 2
+/* Return -ESRCH instead of mapping it to -ENETUNREACH. Only applies to IPv4
+ * lookups. When used with FIB_LOOKUP_NOREF, -ESRCH indicates the lookup
+ * exhausted all rules and tables without finding a usable route.
+ */
+#define FIB_LOOKUP_REPORT_MISS 4
};

struct fib_rules_ops {
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index 92f4eb8b86d7..d0b4f261585a 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -318,7 +318,7 @@ static inline int fib_lookup(struct net *net, const struct flowi4 *flp,
struct fib_result *res, unsigned int flags)
{
struct fib_table *tb;
- int err = -ENETUNREACH;
+ int err = -EAGAIN;

rcu_read_lock();

@@ -327,7 +327,7 @@ static inline int fib_lookup(struct net *net, const struct flowi4 *flp,
err = fib_table_lookup(tb, flp, res, flags | FIB_LOOKUP_NOREF);

if (err == -EAGAIN)
- err = -ENETUNREACH;
+ err = (flags & FIB_LOOKUP_REPORT_MISS) ? -ESRCH : -ENETUNREACH;

rcu_read_unlock();

@@ -398,7 +398,7 @@ static inline int fib_lookup(struct net *net, struct flowi4 *flp,
err = fib_table_lookup(tb, flp, res, flags);

if (err == -EAGAIN)
- err = -ENETUNREACH;
+ err = (flags & FIB_LOOKUP_REPORT_MISS) ? -ESRCH : -ENETUNREACH;
out:
rcu_read_unlock();

diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
index 060501b376a8..3d7dcb8d0865 100644
--- a/net/ipv4/fib_rules.c
+++ b/net/ipv4/fib_rules.c
@@ -101,7 +101,7 @@ int __fib_lookup(struct net *net, struct flowi4 *flp,
res->tclassid = 0;
#endif

- if (err == -ESRCH)
+ if (err == -ESRCH && !(flags & FIB_LOOKUP_REPORT_MISS))
err = -ENETUNREACH;

return err;
--
2.47.3