From owner-svn-src-projects@FreeBSD.ORG Tue Jan 20 23:05:03 2015 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id AECF99EF; Tue, 20 Jan 2015 23:05:03 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 98C66B51; Tue, 20 Jan 2015 23:05:03 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id t0KN537w091704; Tue, 20 Jan 2015 23:05:03 GMT (envelope-from glebius@FreeBSD.org) Received: (from glebius@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id t0KN51NG091685; Tue, 20 Jan 2015 23:05:01 GMT (envelope-from glebius@FreeBSD.org) Message-Id: <201501202305.t0KN51NG091685@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: glebius set sender to glebius@FreeBSD.org using -f From: Gleb Smirnoff Date: Tue, 20 Jan 2015 23:05:01 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r277456 - in projects/ifnet/sys: dev/bge dev/msk dev/virtio/network dev/xl net X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 20 Jan 2015 23:05:03 -0000 Author: glebius Date: Tue Jan 20 23:05:00 2015 New Revision: 277456 URL: https://svnweb.freebsd.org/changeset/base/277456 Log: New KPI for if_flags management: stack sends SICSIFFLAGS to a driver, and if driver approves, then stack updates flags. Drivers usually cache if_flags in their softc. If a driver needs to change its flags, it needs to run if_drvioctl(). Sponsored by: Netflix Sponsored by: Nginx, Inc. Modified: projects/ifnet/sys/dev/bge/if_bge.c projects/ifnet/sys/dev/bge/if_bgereg.h projects/ifnet/sys/dev/msk/if_msk.c projects/ifnet/sys/dev/virtio/network/if_vtnet.c projects/ifnet/sys/dev/xl/if_xl.c projects/ifnet/sys/net/if.c projects/ifnet/sys/net/if.h projects/ifnet/sys/net/if_loop.c Modified: projects/ifnet/sys/dev/bge/if_bge.c ============================================================================== --- projects/ifnet/sys/dev/bge/if_bge.c Tue Jan 20 23:00:17 2015 (r277455) +++ projects/ifnet/sys/dev/bge/if_bge.c Tue Jan 20 23:05:00 2015 (r277456) @@ -1634,14 +1634,11 @@ bge_init_tx_ring(struct bge_softc *sc) static void bge_setpromisc(struct bge_softc *sc) { - if_t ifp; BGE_LOCK_ASSERT(sc); - ifp = sc->bge_ifp; - /* Enable or disable promiscuous mode as needed. */ - if (if_get(ifp, IF_FLAGS) & IFF_PROMISC) + if (sc->bge_if_flags & IFF_PROMISC) BGE_SETBIT(sc, BGE_RX_MODE, BGE_RXMODE_RX_PROMISC); else BGE_CLRBIT(sc, BGE_RX_MODE, BGE_RXMODE_RX_PROMISC); @@ -1664,15 +1661,12 @@ bge_hash_maddr(void *arg, struct sockadd static void bge_setmulti(struct bge_softc *sc) { - if_t ifp; uint32_t hashes[4] = { 0, 0, 0, 0 }; int i; BGE_LOCK_ASSERT(sc); - ifp = sc->bge_ifp; - - if (if_get(ifp, IF_FLAGS) & (IFF_ALLMULTI | IFF_PROMISC)) { + if (sc->bge_if_flags & (IFF_ALLMULTI | IFF_PROMISC)) { for (i = 0; i < 4; i++) CSR_WRITE_4(sc, BGE_MAR0 + (i * 4), 0xFFFFFFFF); return; @@ -1682,7 +1676,7 @@ bge_setmulti(struct bge_softc *sc) for (i = 0; i < 4; i++) CSR_WRITE_4(sc, BGE_MAR0 + (i * 4), 0); - if_foreach_maddr(ifp, bge_hash_maddr, hashes); + if_foreach_maddr(sc->bge_ifp, bge_hash_maddr, hashes); for (i = 0; i < 4; i++) CSR_WRITE_4(sc, BGE_MAR0 + (i * 4), hashes[i]); @@ -5703,7 +5697,7 @@ bge_ifmedia_sts(if_t ifp, struct ifmedia BGE_LOCK(sc); - if ((if_get(ifp, IF_FLAGS) & IFF_UP) == 0) { + if ((sc->bge_if_flags & IFF_UP) == 0) { BGE_UNLOCK(sc); return; } @@ -5741,7 +5735,7 @@ bge_ioctl(if_t ifp, u_long command, void struct bge_softc *sc = if_getsoftc(ifp, IF_DRIVER_SOFTC); struct ifreq *ifr = (struct ifreq *) data; struct mii_data *mii; - int flags, mask, error = 0; + int oflags, mask, error = 0; switch (command) { case SIOCSIFMTU: @@ -5766,7 +5760,9 @@ bge_ioctl(if_t ifp, u_long command, void break; case SIOCSIFFLAGS: BGE_LOCK(sc); - if (if_get(ifp, IF_FLAGS) & IFF_UP) { + oflags = sc->bge_if_flags; + sc->bge_if_flags = ifr->ifr_flags; + if (sc->bge_if_flags & IFF_UP) { /* * If only the state of the PROMISC flag changed, * then just use the 'set promisc mode' command @@ -5776,22 +5772,15 @@ bge_ioctl(if_t ifp, u_long command, void * second or two. Similarly for ALLMULTI. */ if (sc->bge_flags & BGE_FLAG_RUNNING) { - flags = if_get(ifp, IF_FLAGS) ^ - sc->bge_if_flags; - if (flags & IFF_PROMISC) + if ((oflags ^ sc->bge_if_flags) & IFF_PROMISC) bge_setpromisc(sc); - if (flags & IFF_ALLMULTI) + if ((oflags ^ sc->bge_if_flags) & IFF_ALLMULTI) bge_setmulti(sc); } else bge_init_locked(sc); - } else { - if (sc->bge_flags & BGE_FLAG_RUNNING) { - bge_stop(sc); - } - } - sc->bge_if_flags = if_get(ifp, IF_FLAGS); + } else if (sc->bge_flags & BGE_FLAG_RUNNING) + bge_stop(sc); BGE_UNLOCK(sc); - error = 0; break; case SIOCADDMULTI: case SIOCDELMULTI: @@ -6050,12 +6039,10 @@ static int bge_resume(device_t dev) { struct bge_softc *sc; - if_t ifp; sc = device_get_softc(dev); BGE_LOCK(sc); - ifp = sc->bge_ifp; - if (if_get(ifp, IF_FLAGS) & IFF_UP) { + if (sc->bge_if_flags & IFF_UP) { bge_init_locked(sc); if (sc->bge_flags & BGE_FLAG_RUNNING) bge_start_locked(sc); Modified: projects/ifnet/sys/dev/bge/if_bgereg.h ============================================================================== --- projects/ifnet/sys/dev/bge/if_bgereg.h Tue Jan 20 23:00:17 2015 (r277455) +++ projects/ifnet/sys/dev/bge/if_bgereg.h Tue Jan 20 23:05:00 2015 (r277456) @@ -3035,7 +3035,7 @@ struct bge_softc { uint32_t bge_rx_max_coal_bds; uint32_t bge_tx_max_coal_bds; uint32_t bge_mi_mode; - int bge_if_flags; + uint32_t bge_if_flags; int bge_txcnt; int bge_link; /* link state */ int bge_link_evt; /* pending link event */ Modified: projects/ifnet/sys/dev/msk/if_msk.c ============================================================================== --- projects/ifnet/sys/dev/msk/if_msk.c Tue Jan 20 23:00:17 2015 (r277455) +++ projects/ifnet/sys/dev/msk/if_msk.c Tue Jan 20 23:05:00 2015 (r277456) @@ -607,7 +607,7 @@ msk_rxfilter(struct msk_if_softc *sc_if) { struct msk_softc *sc; if_t ifp; - uint32_t mchash[2], flags; + uint32_t mchash[2]; uint16_t mode; sc = sc_if->msk_softc; @@ -618,10 +618,9 @@ msk_rxfilter(struct msk_if_softc *sc_if) bzero(mchash, sizeof(mchash)); mode = GMAC_READ_2(sc, sc_if->msk_port, GM_RX_CTRL); - flags = if_get(ifp, IF_FLAGS); - if ((flags & IFF_PROMISC) != 0) + if ((sc_if->msk_if_flags & IFF_PROMISC) != 0) mode &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA); - else if ((flags & IFF_ALLMULTI) != 0) { + else if ((sc_if->msk_if_flags & IFF_ALLMULTI) != 0) { mode |= GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA; mchash[0] = 0xffff; mchash[1] = 0xffff; @@ -1055,11 +1054,12 @@ msk_mediastatus(if_t ifp, struct ifmedia struct msk_if_softc *sc_if; struct mii_data *mii; - if ((if_get(ifp, IF_FLAGS) & IFF_UP) == 0) - return; sc_if = if_getsoftc(ifp, IF_DRIVER_SOFTC); MSK_IF_LOCK(sc_if); - sc_if = if_getsoftc(ifp, IF_DRIVER_SOFTC); + if ((sc_if->msk_if_flags & IFF_UP) == 0) { + MSK_IF_UNLOCK(sc_if); + return; + } mii = device_get_softc(sc_if->msk_miibus); mii_pollstat(mii); ifmr->ifm_active = mii->mii_media_active; @@ -1074,7 +1074,7 @@ msk_ioctl(if_t ifp, u_long command, void struct ifreq *ifr; struct mii_data *mii; int error, reinit, setvlan; - uint32_t flags, mask; + uint32_t oflags, mask; sc_if = if_getsoftc(ifp, IF_DRIVER_SOFTC); ifr = (struct ifreq *)data; @@ -1114,17 +1114,17 @@ msk_ioctl(if_t ifp, u_long command, void break; case SIOCSIFFLAGS: MSK_IF_LOCK(sc_if); - flags = if_get(ifp, IF_FLAGS); - if ((flags & IFF_UP) != 0) { + oflags = sc_if->msk_if_flags; + sc_if->msk_if_flags = ifr->ifr_flags; + if ((sc_if->msk_if_flags & IFF_UP) != 0) { if ((sc_if->msk_flags & MSK_FLAG_RUNNING) != 0 && - ((flags ^ sc_if->msk_if_flags) & + ((oflags ^ sc_if->msk_if_flags) & (IFF_PROMISC | IFF_ALLMULTI)) != 0) msk_rxfilter(sc_if); else if ((sc_if->msk_flags & MSK_FLAG_DETACH) == 0) msk_init_locked(sc_if); } else if ((sc_if->msk_flags & MSK_FLAG_RUNNING) != 0) msk_stop(sc_if); - sc_if->msk_if_flags = flags; MSK_IF_UNLOCK(sc_if); break; case SIOCADDMULTI: @@ -3035,7 +3035,7 @@ mskc_resume(device_t dev) mskc_reset(sc); for (i = 0; i < sc->msk_num_port; i++) { if (sc->msk_if[i] != NULL && sc->msk_if[i]->msk_ifp != NULL && - (if_get(sc->msk_if[i]->msk_ifp, IF_FLAGS) & IFF_UP)) { + (sc->msk_if[i]->msk_if_flags & IFF_UP)) { sc->msk_if[i]->msk_flags &= ~MSK_FLAG_RUNNING; msk_init_locked(sc->msk_if[i]); } Modified: projects/ifnet/sys/dev/virtio/network/if_vtnet.c ============================================================================== --- projects/ifnet/sys/dev/virtio/network/if_vtnet.c Tue Jan 20 23:00:17 2015 (r277455) +++ projects/ifnet/sys/dev/virtio/network/if_vtnet.c Tue Jan 20 23:05:00 2015 (r277456) @@ -475,13 +475,11 @@ static int vtnet_resume(device_t dev) { struct vtnet_softc *sc; - if_t ifp; sc = device_get_softc(dev); - ifp = sc->vtnet_ifp; VTNET_CORE_LOCK(sc); - if (if_get(ifp, IF_FLAGS) & IFF_UP) + if (sc->vtnet_if_flags & IFF_UP) vtnet_init_locked(sc); sc->vtnet_flags &= ~VTNET_FLAG_SUSPENDED; VTNET_CORE_UNLOCK(sc); @@ -1016,7 +1014,7 @@ vtnet_ioctl(if_t ifp, u_long cmd, void * { struct vtnet_softc *sc; struct ifreq *ifr; - int error; + int oflags, error; sc = if_getsoftc(ifp, IF_DRIVER_SOFTC); ifr = (struct ifreq *) data; @@ -1030,23 +1028,23 @@ vtnet_ioctl(if_t ifp, u_long cmd, void * break; case SIOCSIFFLAGS: + if ((ifr->ifr_flags & (IFF_PROMISC | IFF_ALLMULTI)) && + (sc->vtnet_flags & VTNET_FLAG_CTRL_RX) == 0) { + error = EINVAL; + break; + } VTNET_CORE_LOCK(sc); - if ((if_get(ifp, IF_FLAGS) & IFF_UP) == 0) { + oflags = sc->vtnet_if_flags; + sc->vtnet_if_flags = ifr->ifr_flags; + if ((sc->vtnet_if_flags & IFF_UP) == 0) { if (sc->vtnet_flags & VTNET_FLAG_RUNNING) vtnet_stop(sc); } else if (sc->vtnet_flags & VTNET_FLAG_RUNNING) { - if ((if_get(ifp, IF_FLAGS) ^ sc->vtnet_if_flags) & - (IFF_PROMISC | IFF_ALLMULTI)) { - if (sc->vtnet_flags & VTNET_FLAG_CTRL_RX) - vtnet_rx_filter(sc); - else - error = ENOTSUP; - } + if ((oflags ^ sc->vtnet_if_flags) & + (IFF_PROMISC | IFF_ALLMULTI)) + vtnet_rx_filter(sc); } else vtnet_init_locked(sc); - - if (error == 0) - sc->vtnet_if_flags = if_get(ifp, IF_FLAGS); VTNET_CORE_UNLOCK(sc); break; @@ -3066,15 +3064,20 @@ vtnet_set_allmulti(struct vtnet_softc *s static void vtnet_attach_disable_promisc(struct vtnet_softc *sc) { + struct ifreq ifr; if_t ifp; ifp = sc->vtnet_ifp; VTNET_CORE_LOCK(sc); if ((sc->vtnet_flags & VTNET_FLAG_CTRL_RX) == 0) { - if_addflags(ifp, IF_FLAGS, IFF_PROMISC); + (void )if_drvioctl(SIOCGIFFLAGS, ifp, &ifr, curthread); + ifr.ifr_flagslow |= IFF_PROMISC; + (void )if_drvioctl(SIOCSIFFLAGS, ifp, &ifr, curthread); } else if (vtnet_set_promisc(sc, 0) != 0) { - if_addflags(ifp, IF_FLAGS, IFF_PROMISC); + (void )if_drvioctl(SIOCGIFFLAGS, ifp, &ifr, curthread); + ifr.ifr_flagslow |= IFF_PROMISC; + (void )if_drvioctl(SIOCSIFFLAGS, ifp, &ifr, curthread); device_printf(sc->vtnet_dev, "cannot disable default promiscuous mode\n"); } @@ -3092,16 +3095,14 @@ vtnet_rx_filter(struct vtnet_softc *sc) VTNET_CORE_LOCK_ASSERT(sc); - if (vtnet_set_promisc(sc, - if_get(ifp, IF_FLAGS) & IFF_PROMISC) != 0) + if (vtnet_set_promisc(sc, sc->vtnet_if_flags & IFF_PROMISC) != 0) device_printf(dev, "cannot %s promiscuous mode\n", - if_get(ifp, IF_FLAGS) & IFF_PROMISC ? + sc->vtnet_if_flags & IFF_PROMISC ? "enable" : "disable"); - if (vtnet_set_allmulti(sc, - if_get(ifp, IF_FLAGS) & IFF_ALLMULTI) != 0) + if (vtnet_set_allmulti(sc, sc->vtnet_if_flags & IFF_ALLMULTI) != 0) device_printf(dev, "cannot %s all-multicast mode\n", - if_get(ifp, IF_FLAGS) & IFF_ALLMULTI ? + sc->vtnet_if_flags & IFF_ALLMULTI ? "enable" : "disable"); } Modified: projects/ifnet/sys/dev/xl/if_xl.c ============================================================================== --- projects/ifnet/sys/dev/xl/if_xl.c Tue Jan 20 23:00:17 2015 (r277455) +++ projects/ifnet/sys/dev/xl/if_xl.c Tue Jan 20 23:05:00 2015 (r277456) @@ -630,15 +630,10 @@ xl_check_maddr_90x(void *arg, struct soc static void xl_rxfilter_90x(struct xl_softc *sc) { - if_t ifp; - uint32_t flags; uint8_t rxfilt; XL_LOCK_ASSERT(sc); - ifp = sc->xl_ifp; - flags = if_get(ifp, IF_FLAGS); - XL_SEL_WIN(5); rxfilt = CSR_READ_1(sc, XL_W5_RX_FILTER); rxfilt &= ~(XL_RXFILTER_ALLFRAMES | XL_RXFILTER_ALLMULTI | @@ -647,17 +642,16 @@ xl_rxfilter_90x(struct xl_softc *sc) /* Set the individual bit to receive frames for this host only. */ rxfilt |= XL_RXFILTER_INDIVIDUAL; /* Set capture broadcast bit to capture broadcast frames. */ - if (flags & IFF_BROADCAST) - rxfilt |= XL_RXFILTER_BROADCAST; + rxfilt |= XL_RXFILTER_BROADCAST; /* If we want promiscuous mode, set the allframes bit. */ - if (flags & (IFF_PROMISC | IFF_ALLMULTI)) { - if (flags & IFF_PROMISC) + if (sc->xl_if_flags & (IFF_PROMISC | IFF_ALLMULTI)) { + if (sc->xl_if_flags & IFF_PROMISC) rxfilt |= XL_RXFILTER_ALLFRAMES; - if (flags & IFF_ALLMULTI) + if (sc->xl_if_flags & IFF_ALLMULTI) rxfilt |= XL_RXFILTER_ALLMULTI; } else - if_foreach_maddr(ifp, xl_check_maddr_90x, &rxfilt); + if_foreach_maddr(sc->xl_ifp, xl_check_maddr_90x, &rxfilt); CSR_WRITE_2(sc, XL_COMMAND, rxfilt | XL_CMD_RX_SET_FILT); XL_SEL_WIN(7); @@ -689,15 +683,10 @@ xl_check_maddr_90xB(void *arg, struct so static void xl_rxfilter_90xB(struct xl_softc *sc) { - if_t ifp; - uint32_t flags; uint8_t rxfilt; XL_LOCK_ASSERT(sc); - ifp = sc->xl_ifp; - flags = if_get(ifp, IF_FLAGS); - XL_SEL_WIN(5); rxfilt = CSR_READ_1(sc, XL_W5_RX_FILTER); rxfilt &= ~(XL_RXFILTER_ALLFRAMES | XL_RXFILTER_ALLMULTI | @@ -707,14 +696,13 @@ xl_rxfilter_90xB(struct xl_softc *sc) /* Set the individual bit to receive frames for this host only. */ rxfilt |= XL_RXFILTER_INDIVIDUAL; /* Set capture broadcast bit to capture broadcast frames. */ - if (flags & IFF_BROADCAST) - rxfilt |= XL_RXFILTER_BROADCAST; + rxfilt |= XL_RXFILTER_BROADCAST; /* If we want promiscuous mode, set the allframes bit. */ - if (flags & (IFF_PROMISC | IFF_ALLMULTI)) { - if (flags & IFF_PROMISC) + if (sc->xl_if_flags & (IFF_PROMISC | IFF_ALLMULTI)) { + if (sc->xl_if_flags & IFF_PROMISC) rxfilt |= XL_RXFILTER_ALLFRAMES; - if (flags & IFF_ALLMULTI) + if (sc->xl_if_flags & IFF_ALLMULTI) rxfilt |= XL_RXFILTER_ALLMULTI; } else { /* First, zot all the existing hash bits. */ @@ -722,12 +710,12 @@ xl_rxfilter_90xB(struct xl_softc *sc) CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_HASH | i); /* Now program new ones. */ - if_foreach_maddr(ifp, xl_check_maddr_90xB, sc); + if_foreach_maddr(sc->xl_ifp, xl_check_maddr_90xB, sc); /* * XXXGL: a bit dirty, but easier then make a context * containing softc and rxfilt. */ - if_foreach_maddr(ifp, xl_check_maddr_90x, &rxfilt); + if_foreach_maddr(sc->xl_ifp, xl_check_maddr_90x, &rxfilt); } CSR_WRITE_2(sc, XL_COMMAND, rxfilt | XL_CMD_RX_SET_FILT); @@ -2973,7 +2961,7 @@ xl_ioctl(if_t ifp, u_long command, void { struct xl_softc *sc; struct ifreq *ifr = (struct ifreq *) data; - uint32_t flags; + uint32_t oflags; int error = 0; struct mii_data *mii = NULL; @@ -2982,19 +2970,17 @@ xl_ioctl(if_t ifp, u_long command, void switch (command) { case SIOCSIFFLAGS: XL_LOCK(sc); - flags = if_get(ifp, IF_FLAGS); - if (flags & IFF_UP) { + oflags = sc->xl_if_flags; + sc->xl_if_flags = ifr->ifr_flags; + if (sc->xl_if_flags & IFF_UP) { if (sc->xl_flags & XL_FLAG_RUNNING && - (flags ^ sc->xl_if_flags) & + (oflags ^ sc->xl_if_flags) & (IFF_PROMISC | IFF_ALLMULTI)) xl_rxfilter(sc); else xl_init_locked(sc); - } else { - if (sc->xl_flags & XL_FLAG_RUNNING) - xl_stop(sc); - } - sc->xl_if_flags = flags; + } else if (sc->xl_flags & XL_FLAG_RUNNING) + xl_stop(sc); XL_UNLOCK(sc); break; case SIOCADDMULTI: @@ -3205,18 +3191,13 @@ static int xl_resume(device_t dev) { struct xl_softc *sc; - if_t ifp; sc = device_get_softc(dev); - ifp = sc->xl_ifp; - XL_LOCK(sc); - - if (if_get(ifp, IF_FLAGS) & IFF_UP) { + if (sc->xl_if_flags & IFF_UP) { sc->xl_flags &= ~XL_FLAG_RUNNING; xl_init_locked(sc); } - XL_UNLOCK(sc); return (0); Modified: projects/ifnet/sys/net/if.c ============================================================================== --- projects/ifnet/sys/net/if.c Tue Jan 20 23:00:17 2015 (r277455) +++ projects/ifnet/sys/net/if.c Tue Jan 20 23:05:00 2015 (r277456) @@ -1528,9 +1528,6 @@ if_getfeature(if_t ifp, ift_feature f, u *ptr = NULL; switch (f) { - case IF_FLAGS: - *f32 = &ifp->if_flags; - break; case IF_BAUDRATE: *f64 = &ifp->if_baudrate; break; @@ -2367,14 +2364,14 @@ int if_drvioctl(u_long cmd, struct ifnet *ifp, void *data, struct thread *td) { struct ifreq *ifr; - int error = 0; - int new_flags, temp_flags; size_t namelen, onamelen; size_t descrlen; char *descrbuf, *odescrbuf; char new_name[IFNAMSIZ]; struct ifaddr *ifa; struct sockaddr_dl *sdl; + uint32_t flags; + int error = 0; ifr = (struct ifreq *)data; switch (cmd) { @@ -2383,9 +2380,8 @@ if_drvioctl(u_long cmd, struct ifnet *if break; case SIOCGIFFLAGS: - temp_flags = ifp->if_flags; - ifr->ifr_flags = temp_flags & 0xffff; - ifr->ifr_flagshigh = temp_flags >> 16; + ifr->ifr_flagslow = ifp->if_flags & 0xffff; + ifr->ifr_flagshigh = ifp->if_flags >> 16; break; case SIOCGIFCAP: @@ -2484,31 +2480,41 @@ if_drvioctl(u_long cmd, struct ifnet *if if (error) return (error); /* - * Currently, no driver owned flags pass the IFF_CANTCHANGE - * check, so we don't need special handling here yet. + * Historically if_flags were 16-bit, and thus + * they come from userland in two parts, that + * we need to swap. */ - new_flags = (ifr->ifr_flags & 0xffff) | + flags = (ifr->ifr_flagslow & 0xffff) | (ifr->ifr_flagshigh << 16); - if (ifp->if_flags & IFF_UP && - (new_flags & IFF_UP) == 0) { + if ((flags & IFF_CANTCHANGE) != + (ifp->if_flags & IFF_CANTCHANGE)) + return (EINVAL); + /* + * Pass new flags down to driver and see if it accepts them. + */ + ifr->ifr_flags = flags; + error = if_ioctl(ifp, cmd, data, td); + if (error) + return (error); + flags = ifr->ifr_flags; + /* + * Manage IFF_UP flip. + */ + if (ifp->if_flags & IFF_UP && (flags & IFF_UP) == 0) if_down(ifp); - } else if (new_flags & IFF_UP && - (ifp->if_flags & IFF_UP) == 0) { + else if (flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) if_up(ifp); - } /* See if permanently promiscuous mode bit is about to flip */ - if ((ifp->if_flags ^ new_flags) & IFF_PPROMISC) { - if (new_flags & IFF_PPROMISC) + if ((ifp->if_flags ^ flags) & IFF_PPROMISC) { + if (flags & IFF_PPROMISC) ifp->if_flags |= IFF_PROMISC; else if (ifp->if_pcount == 0) ifp->if_flags &= ~IFF_PROMISC; log(LOG_INFO, "%s: permanently promiscuous mode %s\n", ifp->if_xname, - (new_flags & IFF_PPROMISC) ? "enabled" : "disabled"); + (flags & IFF_PPROMISC) ? "enabled" : "disabled"); } - ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) | - (new_flags &~ IFF_CANTCHANGE); - if_ioctl(ifp, cmd, data, td); + ifp->if_flags = flags; getmicrotime(&ifp->if_lastchange); break; Modified: projects/ifnet/sys/net/if.h ============================================================================== --- projects/ifnet/sys/net/if.h Tue Jan 20 23:00:17 2015 (r277455) +++ projects/ifnet/sys/net/if.h Tue Jan 20 23:05:00 2015 (r277456) @@ -382,7 +382,8 @@ struct ifreq { uint32_t ifrucap_curcap; /* current values */ uint64_t ifrucap_hwassist; /* returned hwassist */ } ifru_cap; - short ifru_flags[2]; + u_int ifru_flags; + short ifru_sflags[2]; short ifru_index; int ifru_jid; int ifru_metric; @@ -396,8 +397,9 @@ struct ifreq { #define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-to-p link */ #define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */ #define ifr_buffer ifr_ifru.ifru_buffer /* user supplied buffer with its length */ -#define ifr_flags ifr_ifru.ifru_flags[0] /* flags (low 16 bits) */ -#define ifr_flagshigh ifr_ifru.ifru_flags[1] /* flags (high 16 bits) */ +#define ifr_flags ifr_ifru.ifru_flags /* flags (after fixup) */ +#define ifr_flagslow ifr_ifru.ifru_sflags[0] /* flags (low 16 bits) */ +#define ifr_flagshigh ifr_ifru.ifru_sflags[1] /* flags (high 16 bits) */ #define ifr_jid ifr_ifru.ifru_jid /* jail/vnet */ #define ifr_metric ifr_ifru.ifru_metric /* metric */ #define ifr_mtu ifr_ifru.ifru_mtu /* mtu */ @@ -573,8 +575,6 @@ typedef enum { } ift_counter; typedef enum { - /* uint32_t */ - IF_FLAGS, /* uint64_t */ IF_BAUDRATE, /* pointers */ Modified: projects/ifnet/sys/net/if_loop.c ============================================================================== --- projects/ifnet/sys/net/if_loop.c Tue Jan 20 23:00:17 2015 (r277455) +++ projects/ifnet/sys/net/if_loop.c Tue Jan 20 23:05:00 2015 (r277456) @@ -346,22 +346,12 @@ int loioctl(if_t ifp, u_long cmd, void *data, struct thread *td) { struct ifreq *ifr = (struct ifreq *)data; - int error = 0; switch (cmd) { - case SIOCSIFADDR: - if_addflags(ifp, IF_FLAGS, IFF_UP); - /* - * Everything else is done at a higher level. - */ - break; - case SIOCADDMULTI: case SIOCDELMULTI: - if (ifr == 0) { - error = EAFNOSUPPORT; /* XXX */ - break; - } + if (ifr == NULL) + return (EAFNOSUPPORT); /* XXX */ switch (ifr->ifr_addr.sa_family) { #ifdef INET @@ -374,8 +364,7 @@ loioctl(if_t ifp, u_long cmd, void *dat #endif default: - error = EAFNOSUPPORT; - break; + return (EAFNOSUPPORT); } break; @@ -384,7 +373,7 @@ loioctl(if_t ifp, u_long cmd, void *dat break; default: - error = EINVAL; + return (EOPNOTSUPP); } - return (error); + return (0); }