Re: [PATCH 00/11 net-next v4] Convert CONFIG_IPV6 to built-in and remove stubs
From: Ido Schimmel
Date: Sun Mar 22 2026 - 13:27:40 EST
On Fri, Mar 20, 2026 at 07:55:52PM +0100, Fernando Fernandez Mancera wrote:
> Changes:
> v4:
> Patch 2: new patch introduced on this revision
> Patch 3: drop some IS_BUILTIN(IPV6) on files compiled only when IPV6=y
> Patch 5: introduce ipv6_mod_enabled() checks on fib6_nh_init(), ip6_dst_lookup_flow() and ip6_fragment() to avoid crash when ipv6.disable=1 during boot
> Patch 6: use &nd_tbl on code guarded by IS_ENABLED(CONFIG_IPV6)
The IPv6 code is still using ipv6_get_nd_tbl() for some reason. If you
remove it from there (it's not needed), then we are only left with
handful of users that can be converted to use '&nd_tbl' when IPv6 is
enabled. Something like the patch below.
diff --git a/include/net/ndisc.h b/include/net/ndisc.h
index 9043ec00c050..6794ce58acca 100644
--- a/include/net/ndisc.h
+++ b/include/net/ndisc.h
@@ -67,12 +67,6 @@ struct prefix_info;
extern struct neigh_table nd_tbl;
-#if IS_ENABLED(CONFIG_IPV6)
-#define ipv6_get_nd_tbl() (&nd_tbl)
-#else
-#define ipv6_get_nd_tbl() NULL
-#endif
-
struct nd_msg {
struct icmp6hdr icmph;
struct in6_addr target;
@@ -360,7 +354,7 @@ static inline u32 ndisc_hashfn(const void *pkey, const struct net_device *dev, _
static inline struct neighbour *__ipv6_neigh_lookup_noref(struct net_device *dev, const void *pkey)
{
- return ___neigh_lookup_noref(ipv6_get_nd_tbl(), neigh_key_eq128,
+ return ___neigh_lookup_noref(&nd_tbl, neigh_key_eq128,
ndisc_hashfn, pkey, dev);
}
diff --git a/net/core/filter.c b/net/core/filter.c
index 4b0c98f0d994..d55525cc5540 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -6093,9 +6093,9 @@ static int bpf_fib_set_fwd_params(struct bpf_fib_lookup *params, u32 mtu)
static int bpf_ipv4_fib_lookup(struct net *net, struct bpf_fib_lookup *params,
u32 flags, bool check_mtu)
{
+ struct neighbour *neigh = NULL;
struct fib_nh_common *nhc;
struct in_device *in_dev;
- struct neighbour *neigh;
struct net_device *dev;
struct fib_result res;
struct flowi4 fl4;
@@ -6215,7 +6215,7 @@ static int bpf_ipv4_fib_lookup(struct net *net, struct bpf_fib_lookup *params,
if (likely(nhc->nhc_gw_family != AF_INET6))
neigh = __ipv4_neigh_lookup_noref(dev,
(__force u32)params->ipv4_dst);
- else
+ else if (IS_ENABLED(CONFIG_IPV6))
neigh = __ipv6_neigh_lookup_noref(dev, params->ipv6_dst);
if (!neigh || !(READ_ONCE(neigh->nud_state) & NUD_VALID))
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index b576dd74d678..3e8fadc28798 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -585,8 +585,8 @@ static int fib_detect_death(struct fib_info *fi, int order,
if (likely(nhc->nhc_gw_family == AF_INET))
n = neigh_lookup(&arp_tbl, &nhc->nhc_gw.ipv4, nhc->nhc_dev);
- else if (nhc->nhc_gw_family == AF_INET6)
- n = neigh_lookup(ipv6_get_nd_tbl(), &nhc->nhc_gw.ipv6, nhc->nhc_dev);
+ else if (IS_ENABLED(CONFIG_IPV6) && nhc->nhc_gw_family == AF_INET6)
+ n = neigh_lookup(&nd_tbl, &nhc->nhc_gw.ipv6, nhc->nhc_dev);
else
n = NULL;
@@ -2146,7 +2146,8 @@ static bool fib_good_nh(const struct fib_nh *nh)
if (likely(nh->fib_nh_gw_family == AF_INET))
n = __ipv4_neigh_lookup_noref(nh->fib_nh_dev,
(__force u32)nh->fib_nh_gw4);
- else if (nh->fib_nh_gw_family == AF_INET6)
+ else if (IS_ENABLED(CONFIG_IPV6) &&
+ nh->fib_nh_gw_family == AF_INET6)
n = __ipv6_neigh_lookup_noref(nh->fib_nh_dev,
&nh->fib_nh_gw6);
else
diff --git a/net/ipv4/nexthop.c b/net/ipv4/nexthop.c
index c65f88b253b9..9703e67d552a 100644
--- a/net/ipv4/nexthop.c
+++ b/net/ipv4/nexthop.c
@@ -1401,7 +1401,7 @@ static bool nexthop_is_good_nh(const struct nexthop *nh)
case AF_INET:
return ipv4_good_nh(&nhi->fib_nh);
case AF_INET6:
- return ipv6_good_nh(&nhi->fib6_nh);
+ return IS_ENABLED(CONFIG_IPV6) && ipv6_good_nh(&nhi->fib6_nh);
}
return false;
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 802c68a1b446..bc1296f0ea69 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -446,7 +446,7 @@ static void ipv4_confirm_neigh(const struct dst_entry *dst, const void *daddr)
if (rt->rt_gw_family == AF_INET) {
pkey = (const __be32 *)&rt->rt_gw4;
- } else if (rt->rt_gw_family == AF_INET6) {
+ } else if (IS_ENABLED(CONFIG_IPV6) && rt->rt_gw_family == AF_INET6) {
return __ipv6_confirm_neigh(dev, &rt->rt_gw6);
} else if (!daddr ||
(rt->rt_flags &