]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
ipv4: drop ipv6_stub usage and use direct function calls
authorFernando Fernandez Mancera <fmancera@suse.de>
Wed, 25 Mar 2026 12:08:48 +0000 (13:08 +0100)
committerJakub Kicinski <kuba@kernel.org>
Sun, 29 Mar 2026 18:21:23 +0000 (11:21 -0700)
As IPv6 is built-in only, the ipv6_stub infrastructure is no longer
necessary.

The IPv4 stack interacts with IPv6 mainly to support IPv4 routes with
IPv6 next-hops (RFC 8950). Convert all these cross-family calls from
ipv6_stub to direct function calls. The fallback functions introduced
previously will prevent linkage errors when CONFIG_IPV6 is disabled.

Signed-off-by: Fernando Fernandez Mancera <fmancera@suse.de>
Tested-by: Ricardo B. Marlière <rbm@suse.com>
Link: https://patch.msgid.link/20260325120928.15848-8-fmancera@suse.de
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/ipv4/fib_semantics.c
net/ipv4/icmp.c
net/ipv4/nexthop.c
net/ipv4/route.c
net/ipv4/udp.c

index 01cb587866d8f8d02c6bacce565c6e9f46afebeb..3e8fadc28798786d76cb476c88ae1d4bd5d5f427 100644 (file)
@@ -585,9 +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_stub->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;
 
@@ -1083,7 +1082,7 @@ static int fib_check_nh_v6_gw(struct net *net, struct fib_nh *nh,
        struct fib6_nh fib6_nh = {};
        int err;
 
-       err = ipv6_stub->fib6_nh_init(net, &fib6_nh, &cfg, GFP_KERNEL, extack);
+       err = fib6_nh_init(net, &fib6_nh, &cfg, GFP_KERNEL, extack);
        if (!err) {
                nh->fib_nh_dev = fib6_nh.fib_nh_dev;
                netdev_hold(nh->fib_nh_dev, &nh->fib_nh_dev_tracker,
@@ -1091,7 +1090,7 @@ static int fib_check_nh_v6_gw(struct net *net, struct fib_nh *nh,
                nh->fib_nh_oif = nh->fib_nh_dev->ifindex;
                nh->fib_nh_scope = RT_SCOPE_LINK;
 
-               ipv6_stub->fib6_nh_release(&fib6_nh);
+               fib6_nh_release(&fib6_nh);
        }
 
        return err;
@@ -2147,9 +2146,10 @@ 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)
-                       n = __ipv6_neigh_lookup_noref_stub(nh->fib_nh_dev,
-                                                          &nh->fib_nh_gw6);
+               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
                        n = NULL;
                if (n)
index 223e5efa5ac7de7b56c7d476d3f94efbb7e3b2fb..fb397fbb28fc67f012d39398de5e9fdd1dd216bd 100644 (file)
@@ -1344,7 +1344,7 @@ bool icmp_build_probe(struct sk_buff *skb, struct icmphdr *icmphdr)
                case ICMP_AFI_IP6:
                        if (iio->ident.addr.ctype3_hdr.addrlen != sizeof(struct in6_addr))
                                goto send_mal_query;
-                       dev = ipv6_stub->ipv6_dev_find(net, &iio->ident.addr.ip_addr.ipv6_addr, dev);
+                       dev = ipv6_dev_find(net, &iio->ident.addr.ip_addr.ipv6_addr, dev);
                        dev_hold(dev);
                        break;
 #endif
index c942f12822363c68fc2bdb8a8f252028ab229380..9703e67d552afb887bb70193d2d8fc0b8d916b47 100644 (file)
@@ -10,7 +10,7 @@
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <net/arp.h>
-#include <net/ipv6_stubs.h>
+#include <net/ip6_route.h>
 #include <net/lwtunnel.h>
 #include <net/ndisc.h>
 #include <net/nexthop.h>
@@ -510,7 +510,7 @@ static void nexthop_free_single(struct nexthop *nh)
                fib_nh_release(nh->net, &nhi->fib_nh);
                break;
        case AF_INET6:
-               ipv6_stub->fib6_nh_release(&nhi->fib6_nh);
+               fib6_nh_release(&nhi->fib6_nh);
                break;
        }
        kfree(nhi);
@@ -1367,7 +1367,7 @@ static bool ipv6_good_nh(const struct fib6_nh *nh)
 
        rcu_read_lock();
 
-       n = __ipv6_neigh_lookup_noref_stub(nh->fib_nh_dev, &nh->fib_nh_gw6);
+       n = __ipv6_neigh_lookup_noref(nh->fib_nh_dev, &nh->fib_nh_gw6);
        if (n)
                state = READ_ONCE(n->nud_state);
 
@@ -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;
@@ -2151,8 +2151,8 @@ static void __remove_nexthop_fib(struct net *net, struct nexthop *nh)
                fib6_info_hold(f6i);
 
                spin_unlock_bh(&nh->lock);
-               ipv6_stub->ip6_del_rt(net, f6i,
-                                     !READ_ONCE(net->ipv4.sysctl_nexthop_compat_mode));
+               ip6_del_rt(net, f6i,
+                          !READ_ONCE(net->ipv4.sysctl_nexthop_compat_mode));
 
                spin_lock_bh(&nh->lock);
        }
@@ -2208,8 +2208,11 @@ static void nh_rt_cache_flush(struct net *net, struct nexthop *nh,
        if (!list_empty(&nh->fi_list))
                rt_cache_flush(net);
 
-       list_for_each_entry(f6i, &nh->f6i_list, nh_list)
-               ipv6_stub->fib6_update_sernum(net, f6i);
+       list_for_each_entry(f6i, &nh->f6i_list, nh_list) {
+               spin_lock_bh(&f6i->fib6_table->tb6_lock);
+               fib6_update_sernum_upto_root(net, f6i);
+               spin_unlock_bh(&f6i->fib6_table->tb6_lock);
+       }
 
        /* if an IPv6 group was replaced, we have to release all old
         * dsts to make sure all refcounts are released
@@ -2223,7 +2226,7 @@ static void nh_rt_cache_flush(struct net *net, struct nexthop *nh,
                struct nh_info *nhi = rtnl_dereference(nhge->nh->nh_info);
 
                if (nhi->family == AF_INET6)
-                       ipv6_stub->fib6_nh_release_dsts(&nhi->fib6_nh);
+                       fib6_nh_release_dsts(&nhi->fib6_nh);
        }
 }
 
@@ -2504,7 +2507,7 @@ static void __nexthop_replace_notify(struct net *net, struct nexthop *nh,
        }
 
        list_for_each_entry(f6i, &nh->f6i_list, nh_list)
-               ipv6_stub->fib6_rt_update(net, f6i, info);
+               fib6_rt_update(net, f6i, info);
 }
 
 /* send RTM_NEWROUTE with REPLACE flag set for all FIB entries
@@ -2877,13 +2880,12 @@ static int nh_create_ipv6(struct net *net,  struct nexthop *nh,
                fib6_cfg.fc_flags |= RTF_GATEWAY;
 
        /* sets nh_dev if successful */
-       err = ipv6_stub->fib6_nh_init(net, fib6_nh, &fib6_cfg, GFP_KERNEL,
-                                     extack);
+       err = fib6_nh_init(net, fib6_nh, &fib6_cfg, GFP_KERNEL, extack);
        if (err) {
                /* IPv6 is not enabled, don't call fib6_nh_release */
                if (err == -EAFNOSUPPORT)
                        goto out;
-               ipv6_stub->fib6_nh_release(fib6_nh);
+               fib6_nh_release(fib6_nh);
        } else {
                nh->nh_flags = fib6_nh->fib_nh_flags;
        }
index 463236e0dc2d5f2ffefbdd8677c2baa14930ab57..bc1296f0ea69b0705e00e547a0d550129e03326a 100644 (file)
@@ -446,8 +446,8 @@ 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) {
-               return __ipv6_confirm_neigh_stub(dev, &rt->rt_gw6);
+       } 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 &
                  (RTCF_MULTICAST | RTCF_BROADCAST | RTCF_LOCAL))) {
index e7b93b874f34c9d0503b93dde0db2709f2659d85..ab415de32443c5d32eedca5f093d5d96681f6b48 100644 (file)
 #include <net/addrconf.h>
 #include <net/udp_tunnel.h>
 #include <net/gro.h>
-#if IS_ENABLED(CONFIG_IPV6)
-#include <net/ipv6_stubs.h>
-#endif
 #include <net/rps.h>
 
 struct udp_table udp_table __read_mostly;
@@ -2855,7 +2852,7 @@ static void set_xfrm_gro_udp_encap_rcv(__u16 encap_type, unsigned short family,
 
        if (udp_test_bit(GRO_ENABLED, sk) && encap_type == UDP_ENCAP_ESPINUDP) {
                if (IS_ENABLED(CONFIG_IPV6) && family == AF_INET6)
-                       new_gro_receive = ipv6_stub->xfrm6_gro_udp_encap_rcv;
+                       new_gro_receive = xfrm6_gro_udp_encap_rcv;
                else
                        new_gro_receive = xfrm4_gro_udp_encap_rcv;
 
@@ -2927,7 +2924,7 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname,
 #if IS_ENABLED(CONFIG_IPV6)
                        if (sk->sk_family == AF_INET6)
                                WRITE_ONCE(up->encap_rcv,
-                                          ipv6_stub->xfrm6_udp_encap_rcv);
+                                          xfrm6_udp_encap_rcv);
                        else
 #endif
                                WRITE_ONCE(up->encap_rcv,