Commit 6ad7969a authored by Breno Leitao's avatar Breno Leitao Committed by Jakub Kicinski
Browse files

netpoll: Extract IPv6 address retrieval function



Extract the IPv6 address retrieval logic from netpoll_setup() into
a dedicated helper function netpoll_take_ipv6() to improve code
organization and readability.

The function handles obtaining the local IPv6 address from the
network device, including proper address type matching between
local and remote addresses (link-local vs global), and includes
appropriate error handling when IPv6 is not supported or no
suitable address is available.

Signed-off-by: default avatarBreno Leitao <leitao@debian.org>
Reviewed-by: default avatarSimon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20250618-netpoll_ip_ref-v1-3-c2ac00fe558f@debian.org


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 3699f992
Loading
Loading
Loading
Loading
+44 −32
Original line number Diff line number Diff line
@@ -598,6 +598,47 @@ static void netpoll_wait_carrier(struct netpoll *np, struct net_device *ndev,
	}
}

/*
 * Take the IPv6 from ndev and populate local_ip structure in netpoll
 */
static int netpoll_take_ipv6(struct netpoll *np, struct net_device *ndev)
{
	char buf[MAC_ADDR_STR_LEN + 1];
	int err = -EDESTADDRREQ;
	struct inet6_dev *idev;

	if (!IS_ENABLED(CONFIG_IPV6)) {
		np_err(np, "IPv6 is not supported %s, aborting\n",
		       egress_dev(np, buf));
		return -EINVAL;
	}

	idev = __in6_dev_get(ndev);
	if (idev) {
		struct inet6_ifaddr *ifp;

		read_lock_bh(&idev->lock);
		list_for_each_entry(ifp, &idev->addr_list, if_list) {
			if (!!(ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL) !=
				!!(ipv6_addr_type(&np->remote_ip.in6) & IPV6_ADDR_LINKLOCAL))
				continue;
			/* Got the IP, let's return */
			np->local_ip.in6 = ifp->addr;
			err = 0;
			break;
		}
		read_unlock_bh(&idev->lock);
	}
	if (err) {
		np_err(np, "no IPv6 address for %s, aborting\n",
		       egress_dev(np, buf));
		return err;
	}

	np_info(np, "local IPv6 %pI6c\n", &np->local_ip.in6);
	return 0;
}

/*
 * Take the IPv4 from ndev and populate local_ip structure in netpoll
 */
@@ -675,41 +716,12 @@ int netpoll_setup(struct netpoll *np)
			err = netpoll_take_ipv4(np, ndev);
			if (err)
				goto put;
			ip_overwritten = true;
		} else {
#if IS_ENABLED(CONFIG_IPV6)
			struct inet6_dev *idev;

			err = -EDESTADDRREQ;
			idev = __in6_dev_get(ndev);
			if (idev) {
				struct inet6_ifaddr *ifp;

				read_lock_bh(&idev->lock);
				list_for_each_entry(ifp, &idev->addr_list, if_list) {
					if (!!(ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL) !=
					    !!(ipv6_addr_type(&np->remote_ip.in6) & IPV6_ADDR_LINKLOCAL))
						continue;
					np->local_ip.in6 = ifp->addr;
					ip_overwritten = true;
					err = 0;
					break;
				}
				read_unlock_bh(&idev->lock);
			}
			if (err) {
				np_err(np, "no IPv6 address for %s, aborting\n",
				       egress_dev(np, buf));
				goto put;
			} else
				np_info(np, "local IPv6 %pI6c\n", &np->local_ip.in6);
#else
			np_err(np, "IPv6 is not supported %s, aborting\n",
			       egress_dev(np, buf));
			err = -EINVAL;
			err = netpoll_take_ipv6(np, ndev);
			if (err)
				goto put;
#endif
		}
		ip_overwritten = true;
	}

	err = __netpoll_setup(np, ndev);