Index: sys/sys/sockio.h =================================================================== RCS file: /cvs/src/sys/sys/sockio.h,v diff -u -p -r1.84 sockio.h --- sys/sys/sockio.h 11 Nov 2021 10:03:10 -0000 1.84 +++ sys/sys/sockio.h 7 Jan 2025 04:50:27 -0000 @@ -82,6 +82,7 @@ #define SIOCBRDGGCACHE _IOWR('i', 65, struct ifbrparam)/* get cache size */ #define SIOCBRDGADDS _IOW('i', 65, struct ifbreq) /* add span port */ #define SIOCBRDGIFS _IOWR('i', 66, struct ifbreq) /* get member ifs */ +#define SIOCBRDGIFPARENT _IOWR('i', 66, struct if_parent) /* get parent bridge */ #define SIOCBRDGDELS _IOW('i', 66, struct ifbreq) /* del span port */ #define SIOCBRDGRTS _IOWR('i', 67, struct ifbaconf) /* get addresses */ #define SIOCBRDGSADDR _IOWR('i', 68, struct ifbareq) /* set addr flags */ Index: sys/net/if_veb.c =================================================================== RCS file: /cvs/src/sys/net/if_veb.c,v diff -u -p -r1.36 if_veb.c --- sys/net/if_veb.c 5 Aug 2024 17:47:29 -0000 1.36 +++ sys/net/if_veb.c 7 Jan 2025 04:50:27 -0000 @@ -2074,6 +2074,17 @@ veb_del_addr(struct veb_softc *sc, const } static int +veb_p_parent(struct veb_port *p, struct if_parent *brdgp) +{ + struct veb_softc *sc = p->p_veb; + + strlcpy(brdgp->ifp_parent, sc->sc_if.if_xname, + sizeof(brdgp->ifp_parent)); + + return (0); +} + +static int veb_p_ioctl(struct ifnet *ifp0, u_long cmd, caddr_t data) { const struct ether_brport *eb = ether_brport_get_locked(ifp0); @@ -2095,6 +2106,10 @@ veb_p_ioctl(struct ifnet *ifp0, u_long c error = EBUSY; break; + case SIOCBRDGIFPARENT: + error = veb_p_parent(p, (struct if_parent *)data); + break; + default: error = (*p->p_ioctl)(ifp0, cmd, data); break; @@ -2375,6 +2390,17 @@ vport_clone_destroy(struct ifnet *ifp) } static int +vport_parent(struct ifnet *ifp, struct if_parent *brdgp) +{ + const struct ether_brport *eb = ether_brport_get_locked(ifp); + + if (eb == NULL) + return (EADDRNOTAVAIL); + + return (veb_p_parent(eb->eb_port, brdgp)); +} + +static int vport_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) { struct vport_softc *sc = ifp->if_softc; @@ -2396,6 +2422,10 @@ vport_ioctl(struct ifnet *ifp, u_long cm case SIOCADDMULTI: case SIOCDELMULTI: + break; + + case SIOCBRDGIFPARENT: + error = vport_parent(ifp, (struct if_parent *)data); break; default: Index: sbin/ifconfig/ifconfig.c =================================================================== RCS file: /cvs/src/sbin/ifconfig/ifconfig.c,v diff -u -p -r1.474 ifconfig.c --- sbin/ifconfig/ifconfig.c 29 Jun 2024 12:09:51 -0000 1.474 +++ sbin/ifconfig/ifconfig.c 7 Jan 2025 04:50:27 -0000 @@ -251,7 +251,9 @@ void unsettrunkport(const char *, int); void settrunkproto(const char *, int); void settrunklacpmode(const char *, int); void settrunklacptimeout(const char *, int); +void linkwait(const char *, int); void trunk_status(void); +void bridge_parent(void); void list_cloners(void); #ifndef SMALL @@ -671,6 +673,7 @@ const struct cmd { { "inst", NEXTARG, A_MEDIAINST, setmediainst }, { "lladdr", NEXTARG, 0, setiflladdr }, { "llprio", NEXTARG, 0, setifllprio }, + { "wait", NEXTARG, 0, linkwait }, { NULL, /*src*/ 0, 0, setifaddr }, { NULL, /*dst*/ 0, 0, setifdstaddr }, { NULL, /*illegal*/0, 0, NULL }, @@ -3366,6 +3369,7 @@ status(int link, struct sockaddr_dl *sdl wg_status(ifaliases); #endif trunk_status(); + bridge_parent(); getifgroups(); (void) memset(&ifmr, 0, sizeof(ifmr)); @@ -4659,6 +4663,29 @@ trunk_status(void) printf("\ttrunk: trunkdev %s\n", rp.rp_ifname); } +void +bridge_parent(void) +{ + struct if_parent brdgp; + const char *parent = brdgp.ifp_parent; + + memset(&brdgp, 0, sizeof(brdgp)); + strlcpy(brdgp.ifp_name, ifname, sizeof(brdgp.ifp_name)); + + if (ioctl(sock, SIOCBRDGIFPARENT, &brdgp) == -1) { + if (errno == EADDRNOTAVAIL) + parent = "(unset)"; + else { + if (errno != ENOTTY) + warn("%s SIOCBRDGIFPARENT", ifname); + + return; + } + } + + printf("\tbridge: parent %s\n", parent); +} + #ifndef SMALL static const char *carp_states[] = { CARP_STATES }; static const char *carp_bal_modes[] = { CARP_BAL_MODES }; @@ -6743,6 +6770,35 @@ setiflladdr(const char *addr, int param) bcopy(eap, ifr.ifr_addr.sa_data, ETHER_ADDR_LEN); if (ioctl(sock, SIOCSIFLLADDR, (caddr_t)&ifr) == -1) warn("SIOCSIFLLADDR"); +} + +void +linkwait(const char *arg, int param) +{ + int waittime; + const char *errstr; + struct if_data ifrdat; + + waittime = strtonum(arg, 1, 120, &errstr); + if (errstr != NULL) + errx(1, "%s wait time %s: %s", ifname, arg, errstr); + + do { + memset(&ifr, 0, sizeof(ifr)); + memset(&ifrdat, 0, sizeof(ifrdat)); + + strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); + ifr.ifr_data = (caddr_t)&ifrdat; + if (ioctl(sock, SIOCGIFDATA, (caddr_t)&ifr) == -1) + err(1, "%s SIOCGIFDATA", ifname); + + if (LINK_STATE_IS_UP(ifrdat.ifi_link_state)) + return; + + sleep(1); + } while (--waittime > 1); + + errx(1, "%s wait %s expired", ifname, arg); } #ifndef SMALL