mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-15 12:54:27 +00:00
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
This commit is contained in:
parent
4db5958a06
commit
0785c323f3
|
@ -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 @@ bootpc_init(void)
|
|||
|
||||
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 @@ bootpc_init(void)
|
|||
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);
|
||||
|
|
|
@ -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 @@ nfs_setup_diskless(void)
|
|||
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 @@ nfs_setup_diskless(void)
|
|||
|
||||
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 */
|
||||
|
|
Loading…
Reference in a new issue