Commit c9cabe05 authored by Kuniyuki Iwashima's avatar Kuniyuki Iwashima Committed by Paolo Abeni
Browse files

ipv6: Move nexthop_find_by_id() after fib6_info_alloc().



We will get rid of RTNL from RTM_NEWROUTE and SIOCADDRT.

Then, we must perform two lookups for nexthop and dev under RCU
to guarantee their lifetime.

ip6_route_info_create() calls nexthop_find_by_id() first if
RTA_NH_ID is specified, and then allocates struct fib6_info.

nexthop_find_by_id() must be called under RCU, but we do not want
to use GFP_ATOMIC for memory allocation here, which will be likely
to fail in ip6_route_multipath_add().

Let's move nexthop_find_by_id() after the memory allocation so
that we can later split ip6_route_info_create() into two parts:
the sleepable part and the RCU part.

Signed-off-by: default avatarKuniyuki Iwashima <kuniyu@amazon.com>
Acked-by: default avatarPaolo Abeni <pabeni@redhat.com>
Link: https://patch.msgid.link/20250418000443.43734-6-kuniyu@amazon.com


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent e6f49795
Loading
Loading
Loading
Loading
+18 −16
Original line number Diff line number Diff line
@@ -3734,24 +3734,11 @@ static struct fib6_info *ip6_route_info_create(struct fib6_config *cfg,
{
	struct net *net = cfg->fc_nlinfo.nl_net;
	struct fib6_info *rt = NULL;
	struct nexthop *nh = NULL;
	struct fib6_table *table;
	struct fib6_nh *fib6_nh;
	int err = -EINVAL;
	int err = -ENOBUFS;
	int addr_type;

	if (cfg->fc_nh_id) {
		nh = nexthop_find_by_id(net, cfg->fc_nh_id);
		if (!nh) {
			NL_SET_ERR_MSG(extack, "Nexthop id does not exist");
			goto out;
		}
		err = fib6_check_nexthop(nh, cfg, extack);
		if (err)
			goto out;
	}

	err = -ENOBUFS;
	if (cfg->fc_nlinfo.nlh &&
	    !(cfg->fc_nlinfo.nlh->nlmsg_flags & NLM_F_CREATE)) {
		table = fib6_get_table(net, cfg->fc_table);
@@ -3767,7 +3754,7 @@ static struct fib6_info *ip6_route_info_create(struct fib6_config *cfg,
		goto out;

	err = -ENOMEM;
	rt = fib6_info_alloc(gfp_flags, !nh);
	rt = fib6_info_alloc(gfp_flags, !cfg->fc_nh_id);
	if (!rt)
		goto out;

@@ -3803,12 +3790,27 @@ static struct fib6_info *ip6_route_info_create(struct fib6_config *cfg,
	ipv6_addr_prefix(&rt->fib6_src.addr, &cfg->fc_src, cfg->fc_src_len);
	rt->fib6_src.plen = cfg->fc_src_len;
#endif
	if (nh) {

	if (cfg->fc_nh_id) {
		struct nexthop *nh;

		nh = nexthop_find_by_id(net, cfg->fc_nh_id);
		if (!nh) {
			err = -EINVAL;
			NL_SET_ERR_MSG(extack, "Nexthop id does not exist");
			goto out_free;
		}

		err = fib6_check_nexthop(nh, cfg, extack);
		if (err)
			goto out_free;

		if (!nexthop_get(nh)) {
			NL_SET_ERR_MSG(extack, "Nexthop has been deleted");
			err = -ENOENT;
			goto out_free;
		}

		rt->nh = nh;
		fib6_nh = nexthop_fib6_nh(rt->nh);
	} else {