Commit d98adfbd authored by Fernando Fernandez Mancera's avatar Fernando Fernandez Mancera Committed by Jakub Kicinski
Browse files

ipv4: drop ipv6_stub usage and use direct function calls



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: default avatarFernando Fernandez Mancera <fmancera@suse.de>
Tested-by: default avatarRicardo B. Marlière <rbm@suse.com>
Link: https://patch.msgid.link/20260325120928.15848-8-fmancera@suse.de


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 29ae61b2
Loading
Loading
Loading
Loading
+8 −8
Original line number Diff line number Diff line
@@ -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,8 +2146,9 @@ 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,
		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;
+1 −1
Original line number Diff line number Diff line
@@ -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
+15 −13
Original line number Diff line number Diff line
@@ -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,7 +2151,7 @@ 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,
		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;
	}
+2 −2
Original line number Diff line number Diff line
@@ -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))) {
+2 −5
Original line number Diff line number Diff line
@@ -118,9 +118,6 @@
#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,