git: 0785c323f31c - main - Convert nfs bootp/diskless to use IfAPI

From: Justin Hibbits <jhibbits_at_FreeBSD.org>
Date: Tue, 02 May 2023 18:46:52 UTC
The branch main has been updated by jhibbits:

URL: https://cgit.FreeBSD.org/src/commit/?id=0785c323f31cd7c4039139bc8fb1f994dfe6cba6

commit 0785c323f31cd7c4039139bc8fb1f994dfe6cba6
Author:     Justin Hibbits <jhibbits@FreeBSD.org>
AuthorDate: 2023-02-07 19:37:03 +0000
Commit:     Justin Hibbits <jhibbits@FreeBSD.org>
CommitDate: 2023-05-02 18:35:58 +0000

    Convert nfs bootp/diskless to use IfAPI
    
    Use the new IfAPI interface and address iterators so the nfs driver
    doesn't need direct access to the interface structures.
    
    Sponsored by:   Juniper Networks, Inc.
    Differential Revision: https://reviews.freebsd.org/D38962
---
 sys/nfs/bootp_subr.c   | 100 +++++++++++++++++++++++++------------------------
 sys/nfs/nfs_diskless.c |  59 +++++++++++++++++------------
 2 files changed, 86 insertions(+), 73 deletions(-)

diff --git a/sys/nfs/bootp_subr.c b/sys/nfs/bootp_subr.c
index 62fcb06fbc5d..d10139756447 100644
--- a/sys/nfs/bootp_subr.c
+++ b/sys/nfs/bootp_subr.c
@@ -137,7 +137,7 @@ struct bootpc_ifcontext {
 	} _req;
 #define	ireq	_req._ifreq
 #define	iareq	_req._in_alias_req
-	struct ifnet *ifp;
+	if_t ifp;
 	struct sockaddr_dl *sdl;
 	struct sockaddr_in myaddr;
 	struct sockaddr_in netmask;
@@ -263,7 +263,6 @@ static void bootpc_tag_helper(struct bootpc_tagcontext *tctx,
 		    unsigned char *start, int len, int tag);
 
 #ifdef BOOTP_DEBUG
-void bootpboot_p_if(struct ifnet *ifp, struct ifaddr *ifa);
 void bootpboot_p_iflist(void);
 #endif
 
@@ -295,38 +294,35 @@ static __inline int bootpc_ifctx_isfailed(struct bootpc_ifcontext *ifctx);
  */
 
 #ifdef BOOTP_DEBUG
-void
-bootpboot_p_if(struct ifnet *ifp, struct ifaddr *ifa)
+static u_int
+bootpboot_p_ifa(void *ifp, struct ifaddr *ifa, u_int count __unused)
 {
 
 	printf("%s flags %x, addr ",
-	       ifp->if_xname, ifp->if_flags);
+	       if_name(ifp), if_getflags(ifp));
 	print_sin_addr((struct sockaddr_in *) ifa->ifa_addr);
 	printf(", broadcast ");
 	print_sin_addr((struct sockaddr_in *) ifa->ifa_dstaddr);
 	printf(", netmask ");
 	print_sin_addr((struct sockaddr_in *) ifa->ifa_netmask);
 	printf("\n");
+
+	return (0);
 }
 
 void
 bootpboot_p_iflist(void)
 {
-	struct ifnet *ifp;
-	struct ifaddr *ifa;
+	struct epoch_tracker et;
+	struct if_iter iter;
+	if_t ifp;
 
 	printf("Interface list:\n");
-	IFNET_RLOCK();
-	for (ifp = CK_STAILQ_FIRST(&V_ifnet);
-	     ifp != NULL;
-	     ifp = CK_STAILQ_NEXT(ifp, if_link)) {
-		for (ifa = CK_STAILQ_FIRST(&ifp->if_addrhead);
-		     ifa != NULL;
-		     ifa = CK_STAILQ_NEXT(ifa, ifa_link))
-			if (ifa->ifa_addr->sa_family == AF_INET)
-				bootpboot_p_if(ifp, ifa);
-	}
-	IFNET_RUNLOCK();
+	NET_EPOCH_ENTER(et);
+	for (ifp = if_iter_start(&iter); ifp != NULL; ifp = if_iter_next(&iter))
+		if_foreach_addr_type(ifp, AF_INET, bootpboot_p_ifa, ifp);
+	if_iter_finish(&iter);
+	NET_EPOCH_EXIT(et);
 }
 #endif /* defined(BOOTP_DEBUG) */
 
@@ -1498,14 +1494,31 @@ bootpc_decode_reply(struct nfsv3_diskless *nd, struct bootpc_ifcontext *ifctx,
 	}
 }
 
+static u_int
+bootpc_init_ifa_cb(void *arg, struct ifaddr *ifa, u_int count)
+{
+	struct sockaddr_dl *sdl = (struct sockaddr_dl *)ifa->ifa_addr;
+
+	if (count != 0)
+		return (0);
+
+	if (sdl->sdl_type != IFT_ETHER)
+		return (0);
+
+	*(struct sockaddr_dl **)arg = sdl;
+
+	return (1);
+}
+
 void
 bootpc_init(void)
 {
+	struct epoch_tracker et;
 	struct bootpc_ifcontext *ifctx = NULL;	/* Interface BOOTP contexts */
 	struct bootpc_globalcontext *gctx; 	/* Global BOOTP context */
-	struct ifnet *ifp;
 	struct sockaddr_dl *sdl;
-	struct ifaddr *ifa;
+	struct if_iter iter;
+	if_t ifp;
 	int error;
 #ifndef BOOTP_WIRED_TO
 	int ifcnt;
@@ -1573,22 +1586,15 @@ bootpc_init(void)
 	 * attaches and wins the race, it won't be eligible for bootp.
 	 */
 	ifcnt = 0;
-	IFNET_RLOCK();
-	CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) {
-		if ((ifp->if_flags &
-		     (IFF_LOOPBACK | IFF_POINTOPOINT | IFF_BROADCAST)) !=
+	NET_EPOCH_ENTER(et);
+	for (if_t ifp = if_iter_start(&iter); ifp != NULL; ifp = if_iter_next(&iter)) {
+		if ((if_getflags(ifp) &
+		    (IFF_LOOPBACK | IFF_POINTOPOINT | IFF_BROADCAST)) ==
 		    IFF_BROADCAST)
-			continue;
-		switch (ifp->if_alloctype) {
-			case IFT_ETHER:
-				break;
-			default:
-				continue;
-		}
-		ifcnt++;
+			ifcnt++;
 	}
-
-	IFNET_RUNLOCK();
+	if_iter_finish(&iter);
+	NET_EPOCH_EXIT(et);
 	if (ifcnt == 0) {
 		printf("WARNING: BOOTP found no eligible network interfaces, skipping!\n");
 		goto out;
@@ -1600,37 +1606,32 @@ bootpc_init(void)
 
 retry:
 	ifctx = STAILQ_FIRST(&gctx->interfaces);
-	IFNET_RLOCK();
-	CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) {
+	NET_EPOCH_ENTER(et);
+	for (ifp = if_iter_start(&iter); ifp != NULL; ifp = if_iter_next(&iter)) {
 		if (ifctx == NULL)
 			break;
 #ifdef BOOTP_WIRED_TO
-		if (strcmp(ifp->if_xname, __XSTRING(BOOTP_WIRED_TO)) != 0)
+		if (strcmp(if_name(ifp), __XSTRING(BOOTP_WIRED_TO)) != 0)
 			continue;
 #else
-		if ((ifp->if_flags &
+		if ((if_getflags(ifp) &
 		     (IFF_LOOPBACK | IFF_POINTOPOINT | IFF_BROADCAST)) !=
 		    IFF_BROADCAST)
-			continue;
-		switch (ifp->if_alloctype) {
+			break;
+		switch (if_getalloctype(ifp)) {
 			case IFT_ETHER:
 				break;
 			default:
 				continue;
 		}
 #endif
-		strlcpy(ifctx->ireq.ifr_name, ifp->if_xname,
+		strlcpy(ifctx->ireq.ifr_name, if_name(ifp),
 		    sizeof(ifctx->ireq.ifr_name));
 		ifctx->ifp = ifp;
 
 		/* Get HW address */
 		sdl = NULL;
-		CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
-			if (ifa->ifa_addr->sa_family == AF_LINK) {
-				sdl = (struct sockaddr_dl *)ifa->ifa_addr;
-				if (sdl->sdl_type == IFT_ETHER)
-					break;
-			}
+		if_foreach_addr_type(ifp, AF_LINK, bootpc_init_ifa_cb, &sdl);
 		if (sdl == NULL)
 			panic("bootpc: Unable to find HW address for %s",
 			    ifctx->ireq.ifr_name);
@@ -1638,7 +1639,8 @@ retry:
 
 		ifctx = STAILQ_NEXT(ifctx, next);
 	}
-	IFNET_RUNLOCK();
+	if_iter_finish(&iter);
+	NET_EPOCH_EXIT(et);
 	CURVNET_RESTORE();
 
 	if (STAILQ_EMPTY(&gctx->interfaces) ||
@@ -1702,7 +1704,7 @@ retry:
 	if (gctx->gotrootpath != 0) {
 		struct epoch_tracker et;
 
-		kern_setenv("boot.netif.name", ifctx->ifp->if_xname);
+		kern_setenv("boot.netif.name", if_name(ifctx->ifp));
 
 		NET_EPOCH_ENTER(et);
 		bootpc_add_default_route(ifctx);
diff --git a/sys/nfs/nfs_diskless.c b/sys/nfs/nfs_diskless.c
index 6df01e56f9b2..8f21861ab27e 100644
--- a/sys/nfs/nfs_diskless.c
+++ b/sys/nfs/nfs_diskless.c
@@ -146,6 +146,19 @@ nfs_parse_options(const char *envopts, struct nfs_args *nd)
 	free(opts, M_TEMP);
 }
 
+static u_int
+nfs_setup_diskless_ifa_cb(void *arg, struct sockaddr_dl *sdl, u_int count)
+{
+	struct sockaddr_dl *ourdl = arg;
+
+	if ((sdl->sdl_type == ourdl->sdl_type) &&
+	    (sdl->sdl_alen == ourdl->sdl_alen) &&
+	    !bcmp(LLADDR(sdl), LLADDR(ourdl), sdl->sdl_alen))
+		return (1);
+
+	return (0);
+}
+
 /*
  * Populate the essential fields in the nfsv3_diskless structure.
  *
@@ -166,16 +179,18 @@ nfs_parse_options(const char *envopts, struct nfs_args *nd)
 void
 nfs_setup_diskless(void)
 {
+	struct epoch_tracker et;
+	struct if_iter iter;
 	struct nfs_diskless *nd = &nfs_diskless;
 	struct nfsv3_diskless *nd3 = &nfsv3_diskless;
-	struct ifnet *ifp;
-	struct ifaddr *ifa;
-	struct sockaddr_dl *sdl, ourdl;
+	if_t ifp;
+	struct sockaddr_dl ourdl;
 	struct sockaddr_in myaddr, netmask;
 	char *cp;
 	int cnt, fhlen, is_nfsv3;
 	uint32_t len;
 	time_t timeout_at;
+	u_int count;
 
 	if (nfs_diskless_valid != 0)
 		return;
@@ -219,29 +234,25 @@ nfs_setup_diskless(void)
 		printf("nfs_diskless: no hardware address\n");
 		return;
 	}
-	ifa = NULL;
 	timeout_at = time_uptime + NFS_IFACE_TIMEOUT_SECS;
 retry:
 	CURVNET_SET(TD_TO_VNET(curthread));
-	IFNET_RLOCK();
-	CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) {
-		CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
-			if (ifa->ifa_addr->sa_family == AF_LINK) {
-				sdl = (struct sockaddr_dl *)ifa->ifa_addr;
-				if ((sdl->sdl_type == ourdl.sdl_type) &&
-				    (sdl->sdl_alen == ourdl.sdl_alen) &&
-				    !bcmp(LLADDR(sdl),
-					  LLADDR(&ourdl),
-					  sdl->sdl_alen)) {
-				    IFNET_RUNLOCK();
-				    CURVNET_RESTORE();
-				    goto match_done;
-				}
-			}
-		}
+	NET_EPOCH_ENTER(et);
+
+	for (ifp = if_iter_start(&iter); ifp != NULL; ifp = if_iter_next(&iter)) {
+		count = if_foreach_lladdr(ifp, nfs_setup_diskless_ifa_cb, &ourdl);
+
+		if (count > 0)
+			break;
+
 	}
-	IFNET_RUNLOCK();
+	if_iter_finish(&iter);
+	NET_EPOCH_EXIT(et);
 	CURVNET_RESTORE();
+	if (cnt > 0) {
+		goto match_done;
+	}
+
 	if (time_uptime < timeout_at) {
 		pause("nfssdl", hz / 5);
 		goto retry;
@@ -249,9 +260,9 @@ retry:
 	printf("nfs_diskless: no interface\n");
 	return;	/* no matching interface */
 match_done:
-	kern_setenv("boot.netif.name", ifp->if_xname);
+	kern_setenv("boot.netif.name", if_name(ifp));
 	if (is_nfsv3 != 0) {
-		strlcpy(nd3->myif.ifra_name, ifp->if_xname,
+		strlcpy(nd3->myif.ifra_name, if_name(ifp),
 		    sizeof(nd3->myif.ifra_name));
 
 		/* set up gateway */
@@ -290,7 +301,7 @@ match_done:
 
 		nfs_diskless_valid = 3;
 	} else {
-		strlcpy(nd->myif.ifra_name, ifp->if_xname,
+		strlcpy(nd->myif.ifra_name, if_name(ifp),
 		    sizeof(nd->myif.ifra_name));
 
 		/* set up gateway */