Index: if.c =================================================================== RCS file: /home/ncvs/src/sys/net/if.c,v retrieving revision 1.209 diff -u -r1.209 if.c --- if.c 22 Sep 2004 12:53:27 -0000 1.209 +++ if.c 16 Oct 2004 20:32:20 -0000 @@ -1122,8 +1122,11 @@ } else if (ifp->if_pcount == 0) { ifp->if_flags &= ~IFF_PROMISC; } - if (ifp->if_ioctl) + if (ifp->if_ioctl) { + IFF_LOCKGIANT(ifp); (void) (*ifp->if_ioctl)(ifp, cmd, data); + IFF_UNLOCKGIANT(ifp); + } getmicrotime(&ifp->if_lastchange); break; @@ -1135,7 +1138,9 @@ return (EOPNOTSUPP); if (ifr->ifr_reqcap & ~ifp->if_capabilities) return (EINVAL); + IFF_LOCKGIANT(ifp); error = (*ifp->if_ioctl)(ifp, cmd, data); + IFF_UNLOCKGIANT(ifp); if (error == 0) getmicrotime(&ifp->if_lastchange); break; @@ -1207,7 +1212,9 @@ return (error); if (ifp->if_ioctl == NULL) return (EOPNOTSUPP); + IFF_LOCKGIANT(ifp); error = (*ifp->if_ioctl)(ifp, cmd, data); + IFF_UNLOCKGIANT(ifp); if (error == 0) getmicrotime(&ifp->if_lastchange); break; @@ -1223,7 +1230,9 @@ return (EINVAL); if (ifp->if_ioctl == NULL) return (EOPNOTSUPP); + IFF_LOCKGIANT(ifp); error = (*ifp->if_ioctl)(ifp, cmd, data); + IFF_UNLOCKGIANT(ifp); if (error == 0) { getmicrotime(&ifp->if_lastchange); rt_ifmsg(ifp); @@ -1276,7 +1285,9 @@ return (error); if (ifp->if_ioctl == NULL) return (EOPNOTSUPP); + IFF_LOCKGIANT(ifp); error = (*ifp->if_ioctl)(ifp, cmd, data); + IFF_UNLOCKGIANT(ifp); if (error == 0) getmicrotime(&ifp->if_lastchange); break; @@ -1292,7 +1303,9 @@ case SIOCGIFGENERIC: if (ifp->if_ioctl == NULL) return (EOPNOTSUPP); + IFF_LOCKGIANT(ifp); error = (*ifp->if_ioctl)(ifp, cmd, data); + IFF_UNLOCKGIANT(ifp); break; case SIOCSIFLLADDR: @@ -1459,7 +1472,9 @@ } ifr.ifr_flags = ifp->if_flags & 0xffff; ifr.ifr_flagshigh = ifp->if_flags >> 16; + IFF_LOCKGIANT(ifp); error = (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr); + IFF_UNLOCKGIANT(ifp); if (error == 0) { log(LOG_INFO, "%s: promiscuous mode %s\n", ifp->if_xname, @@ -1585,7 +1600,9 @@ ifp->if_flags |= IFF_ALLMULTI; ifr.ifr_flags = ifp->if_flags & 0xffff; ifr.ifr_flagshigh = ifp->if_flags >> 16; + IFF_LOCKGIANT(ifp); error = ifp->if_ioctl(ifp, SIOCSIFFLAGS, (caddr_t)&ifr); + IFF_UNLOCKGIANT(ifp); } } else { if (ifp->if_amcount > 1) { @@ -1595,7 +1612,9 @@ ifp->if_flags &= ~IFF_ALLMULTI; ifr.ifr_flags = ifp->if_flags & 0xffff;; ifr.ifr_flagshigh = ifp->if_flags >> 16; + IFF_LOCKGIANT(ifp); error = ifp->if_ioctl(ifp, SIOCSIFFLAGS, (caddr_t)&ifr); + IFF_UNLOCKGIANT(ifp); } } splx(s); @@ -1690,7 +1709,9 @@ * interface to let them know about it. */ s = splimp(); + IFF_LOCKGIANT(ifp); ifp->if_ioctl(ifp, SIOCADDMULTI, 0); + IFF_UNLOCKGIANT(ifp); splx(s); return 0; @@ -1725,8 +1746,11 @@ * Make sure the interface driver is notified * in the case of a link layer mcast group being left. */ - if (ifma->ifma_addr->sa_family == AF_LINK && sa == 0) + if (ifma->ifma_addr->sa_family == AF_LINK && sa == 0) { + IFF_LOCKGIANT(ifp); ifp->if_ioctl(ifp, SIOCDELMULTI, 0); + IFF_UNLOCKGIANT(ifp); + } splx(s); free(ifma->ifma_addr, M_IFMADDR); free(ifma, M_IFMADDR); @@ -1757,7 +1781,9 @@ s = splimp(); TAILQ_REMOVE(&ifp->if_multiaddrs, ifma, ifma_link); + IFF_LOCKGIANT(ifp); ifp->if_ioctl(ifp, SIOCDELMULTI, 0); + IFF_UNLOCKGIANT(ifp); splx(s); free(ifma->ifma_addr, M_IFMADDR); free(sa, M_IFMADDR); @@ -1812,6 +1838,7 @@ * address filter. */ if ((ifp->if_flags & IFF_UP) != 0) { + IFF_LOCKGIANT(ifp); ifp->if_flags &= ~IFF_UP; ifr.ifr_flags = ifp->if_flags & 0xffff; ifr.ifr_flagshigh = ifp->if_flags >> 16; @@ -1820,6 +1847,7 @@ ifr.ifr_flags = ifp->if_flags & 0xffff; ifr.ifr_flagshigh = ifp->if_flags >> 16; (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr); + IFF_UNLOCKGIANT(ifp); #ifdef INET /* * Also send gratuitous ARPs to notify other nodes about Index: if_stf.c =================================================================== RCS file: /home/ncvs/src/sys/net/if_stf.c,v retrieving revision 1.42 diff -u -r1.42 if_stf.c --- if_stf.c 15 Jul 2004 08:26:06 -0000 1.42 +++ if_stf.c 2 Aug 2004 00:09:24 -0000 @@ -139,13 +139,11 @@ #define sc_ro __sc_ro46.__sc_ro4 const struct encaptab *encap_cookie; LIST_ENTRY(stf_softc) sc_list; /* all stf's are linked */ + struct mtx sc_mtx; /* protect sc_ro */ }; /* * All mutable global variables in if_stf.c are protected by stf_mtx. - * XXXRW: Note that mutable fields in the softc are not currently locked: - * in particular, sc_ro needs to be protected from concurrent entrance - * of stf_output(). */ static struct mtx stf_mtx; static LIST_HEAD(, stf_softc) stf_softc_list; @@ -231,6 +229,7 @@ ifc_free_unit(ifc, unit); return (ENOMEM); } + mtx_init(&sc->sc_mtx, "stf sc_mtx", NULL, MTX_DEF); ifp->if_mtu = IPV6_MMTU; ifp->if_ioctl = stf_ioctl; @@ -255,6 +254,7 @@ bpfdetach(&sc->sc_if); if_detach(&sc->sc_if); + mtx_destroy(&sc->sc_mtx); free(sc, M_STF); } @@ -430,9 +430,10 @@ struct ip *ip; struct ip6_hdr *ip6; struct in6_ifaddr *ia6; -#ifdef MAC + struct route ro; int error; +#ifdef MAC error = mac_check_ifnet_transmit(ifp, m); if (error) { m_freem(m); @@ -534,9 +535,7 @@ else ip_ecn_ingress(ECN_NOCARE, &ip->ip_tos, &tos); - /* - * XXXRW: Locking of sc_ro required. - */ + mtx_lock(&sc->sc_mtx); dst4 = (struct sockaddr_in *)&sc->sc_ro.ro_dst; if (dst4->sin_family != AF_INET || bcmp(&dst4->sin_addr, &ip->ip_dst, sizeof(ip->ip_dst)) != 0) { @@ -555,12 +554,21 @@ if (sc->sc_ro.ro_rt == NULL) { m_freem(m); ifp->if_oerrors++; + mtx_unlock(&sc->sc_mtx); return ENETUNREACH; } } + /* + * XXXRW: Holding mutex over call to ip_output(): potential lock + * order issue? Hard to resolve cleanly with the current route + * caching model, as we have to synchronize access to shared softc + * state. + */ ifp->if_opackets++; - return ip_output(m, NULL, &sc->sc_ro, 0, NULL, NULL); + error = ip_output(m, NULL, &ro, 0, NULL, NULL); + mtx_unlock(&sc->sc_mtx); + return (error); } static int Index: if_var.h =================================================================== RCS file: /home/ncvs/src/sys/net/if_var.h,v retrieving revision 1.84 diff -u -r1.84 if_var.h --- if_var.h 15 Aug 2004 06:24:42 -0000 1.84 +++ if_var.h 16 Oct 2004 20:31:54 -0000 @@ -327,6 +327,16 @@ #define IF_AFDATA_UNLOCK(ifp) mtx_unlock(&(ifp)->if_afdata_mtx) #define IF_AFDATA_DESTROY(ifp) mtx_destroy(&(ifp)->if_afdata_mtx) +#define IFF_LOCKGIANT(ifp) do { \ + if ((ifp)->if_flags & IFF_NEEDSGIANT) \ + mtx_lock(&Giant); \ +} while (0) + +#define IFF_UNLOCKGIANT(ifp) do { \ + if ((ifp)->if_flags & IFF_NEEDSGIANT) \ + mtx_unlock(&Giant); \ +} while (0) + #define IF_HANDOFF(ifq, m, ifp) \ if_handoff((struct ifqueue *)ifq, m, ifp, 0) #define IF_HANDOFF_ADJ(ifq, m, ifp, adj) \