--- //depot/vendor/freebsd/src/sys/dev/ath/if_ath.c 2005/07/22 18:00:59 +++ //depot/projects/netsmp/src/sys/dev/ath/if_ath.c 2005/07/23 00:06:01 @@ -1661,6 +1661,7 @@ /* calculate and install multicast filter */ if ((ifp->if_flags & IFF_ALLMULTI) == 0) { mfilt[0] = mfilt[1] = 0; + IF_ADDR_LOCK(ifp); TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { caddr_t dl; @@ -1673,6 +1674,7 @@ pos &= 0x3f; mfilt[pos / 32] |= (1 << (pos % 32)); } + IF_ADDR_UNLOCK(ifp); } else { mfilt[0] = mfilt[1] = ~0; } --- //depot/vendor/freebsd/src/sys/dev/awi/awi.c 2005/07/22 16:50:36 +++ //depot/projects/netsmp/src/sys/dev/awi/awi.c 2005/07/23 00:06:01 @@ -1146,15 +1146,19 @@ #ifdef __FreeBSD__ if (ifp->if_flags & IFF_ALLMULTI) goto set_mib; + IF_ADDR_LOCK(ifp); TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; - if (n == AWI_GROUP_ADDR_SIZE) + if (n == AWI_GROUP_ADDR_SIZE) { + IF_ADDR_UNLOCK(ifp); goto set_mib; + } IEEE80211_ADDR_COPY(sc->sc_mib_addr.aGroup_Addresses[n], LLADDR((struct sockaddr_dl *)ifma->ifma_addr)); n++; } + IF_ADDR_UNLOCK(ifp); #else ETHER_FIRST_MULTI(step, &sc->sc_ic.ic_ec, enm); while (enm != NULL) { --- //depot/vendor/freebsd/src/sys/dev/bfe/if_bfe.c 2005/06/10 16:51:34 +++ //depot/projects/netsmp/src/sys/dev/bfe/if_bfe.c 2005/07/19 21:29:46 @@ -883,12 +883,14 @@ val |= BFE_RXCONF_ALLMULTI; else { val &= ~BFE_RXCONF_ALLMULTI; + IF_ADDR_LOCK(ifp); TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; bfe_cam_write(sc, LLADDR((struct sockaddr_dl *)ifma->ifma_addr), i++); } + IF_ADDR_UNLOCK(ifp); } CSR_WRITE_4(sc, BFE_RXCONF, val); --- //depot/vendor/freebsd/src/sys/dev/bge/if_bge.c 2005/06/24 21:45:25 +++ //depot/projects/netsmp/src/sys/dev/bge/if_bge.c 2005/07/19 21:29:46 @@ -1171,6 +1171,7 @@ CSR_WRITE_4(sc, BGE_MAR0 + (i * 4), 0); /* Now program new ones. */ + IF_ADDR_LOCK(ifp); TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; @@ -1178,6 +1179,7 @@ ifma->ifma_addr), ETHER_ADDR_LEN) & 0x7F; hashes[(h & 0x60) >> 5] |= 1 << (h & 0x1F); } + IF_ADDR_UNLOCK(ifp); for (i = 0; i < 4; i++) CSR_WRITE_4(sc, BGE_MAR0 + (i * 4), hashes[i]); --- //depot/vendor/freebsd/src/sys/dev/ed/if_ed.c 2005/06/15 20:25:30 +++ //depot/projects/netsmp/src/sys/dev/ed/if_ed.c 2005/07/19 21:29:46 @@ -1778,6 +1778,7 @@ mcaf[0] = 0; mcaf[1] = 0; + IF_ADDR_LOCK(sc->ifp); TAILQ_FOREACH(ifma, &sc->ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; @@ -1785,6 +1786,7 @@ ifma->ifma_addr), ETHER_ADDR_LEN) >> 26; af[index >> 3] |= 1 << (index & 7); } + IF_ADDR_UNLOCK(sc->ifp); } int --- //depot/vendor/freebsd/src/sys/dev/em/if_em.c 2005/06/10 16:51:34 +++ //depot/projects/netsmp/src/sys/dev/em/if_em.c 2005/07/19 21:29:46 @@ -1596,7 +1596,8 @@ E1000_WRITE_REG(&adapter->hw, RCTL, reg_rctl); msec_delay(5); } - + + IF_ADDR_LOCK(ifp); #if __FreeBSD_version < 500000 LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { #else @@ -1611,6 +1612,7 @@ &mta[mcnt*ETH_LENGTH_OF_ADDRESS], ETH_LENGTH_OF_ADDRESS); mcnt++; } + IF_ADDR_UNLOCK(ifp); if (mcnt >= MAX_NUM_MULTICAST_ADDRESSES) { reg_rctl = E1000_READ_REG(&adapter->hw, RCTL); --- //depot/vendor/freebsd/src/sys/dev/ex/if_ex.c 2005/06/10 16:51:34 +++ //depot/projects/netsmp/src/sys/dev/ex/if_ex.c 2005/07/19 21:29:46 @@ -840,11 +840,13 @@ ifp = sc->ifp; count = 0; + IF_ADDR_LOCK(ifp); TAILQ_FOREACH(maddr, &ifp->if_multiaddrs, ifma_link) { if (maddr->ifma_addr->sa_family != AF_LINK) continue; count++; } + IF_ADDR_UNLOCK(ifp); if ((ifp->if_flags & IFF_PROMISC) || (ifp->if_flags & IFF_ALLMULTI) || count > 63) { @@ -871,7 +873,8 @@ CSR_WRITE_2(sc, IO_PORT_REG, 0); CSR_WRITE_2(sc, IO_PORT_REG, 0); CSR_WRITE_2(sc, IO_PORT_REG, (count + 1) * 6); - + + IF_ADDR_LOCK(ifp); TAILQ_FOREACH(maddr, &ifp->if_multiaddrs, ifma_link) { if (maddr->ifma_addr->sa_family != AF_LINK) continue; @@ -882,6 +885,7 @@ CSR_WRITE_2(sc, IO_PORT_REG, *addr++); CSR_WRITE_2(sc, IO_PORT_REG, *addr++); } + IF_ADDR_UNLOCK(ifp); /* Program our MAC address as well */ /* XXX: Is this necessary? The Linux driver does this --- //depot/vendor/freebsd/src/sys/dev/fe/if_fe.c 2005/06/10 16:51:34 +++ //depot/projects/netsmp/src/sys/dev/fe/if_fe.c 2005/07/19 21:29:46 @@ -2060,6 +2060,7 @@ struct ifmultiaddr *ifma; filter = fe_filter_nothing; + IF_ADDR_LOCK(sc->ifp); TAILQ_FOREACH(ifma, &sc->ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; @@ -2072,6 +2073,7 @@ filter.data[index >> 3] |= 1 << (index & 7); } + IF_ADDR_UNLOCK(sc->ifp); return ( filter ); } --- //depot/vendor/freebsd/src/sys/dev/fxp/if_fxp.c 2005/06/11 00:50:21 +++ //depot/projects/netsmp/src/sys/dev/fxp/if_fxp.c 2005/07/19 21:29:46 @@ -2484,6 +2484,7 @@ nmcasts = 0; if ((sc->flags & FXP_FLAG_ALL_MCAST) == 0) { + IF_ADDR_LOCK(ifp); #if __FreeBSD_version < 500000 LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { #else @@ -2500,6 +2501,7 @@ &sc->mcsp->mc_addr[nmcasts][0], ETHER_ADDR_LEN); nmcasts++; } + IF_ADDR_UNLOCK(ifp); } mcsp->mc_cnt = htole16(nmcasts * ETHER_ADDR_LEN); return (nmcasts); --- //depot/vendor/freebsd/src/sys/dev/gem/if_gem.c 2005/06/12 15:35:17 +++ //depot/projects/netsmp/src/sys/dev/gem/if_gem.c 2005/07/19 21:29:46 @@ -1894,6 +1894,7 @@ /* Clear hash table */ memset(hash, 0, sizeof(hash)); + IF_ADDR_LOCK(ifp); TAILQ_FOREACH(inm, &ifp->if_multiaddrs, ifma_link) { if (inm->ifma_addr->sa_family != AF_LINK) continue; @@ -1906,6 +1907,7 @@ /* Set the corresponding bit in the filter. */ hash[crc >> 4] |= 1 << (15 - (crc & 15)); } + IF_ADDR_UNLOCK(ifp); v |= GEM_MAC_RX_HASH_FILTER; ifp->if_flags &= ~IFF_ALLMULTI; --- //depot/vendor/freebsd/src/sys/dev/hme/if_hme.c 2005/06/10 16:51:34 +++ //depot/projects/netsmp/src/sys/dev/hme/if_hme.c 2005/07/19 21:29:46 @@ -1679,6 +1679,7 @@ * the word. */ + IF_ADDR_LOCK(sc->sc_ifp); TAILQ_FOREACH(inm, &sc->sc_ifp->if_multiaddrs, ifma_link) { if (inm->ifma_addr->sa_family != AF_LINK) continue; @@ -1691,6 +1692,7 @@ /* Set the corresponding bit in the filter. */ hash[crc >> 4] |= 1 << (crc & 0xf); } + IF_ADDR_UNLOCK(sc->sc_ifp); ifp->if_flags &= ~IFF_ALLMULTI; --- //depot/vendor/freebsd/src/sys/dev/ie/if_ie.c 2005/06/10 16:51:34 +++ //depot/projects/netsmp/src/sys/dev/ie/if_ie.c 2005/07/19 21:29:46 @@ -1676,6 +1676,7 @@ * Step through the list of addresses. */ sc->mcast_count = 0; + IF_ADDR_LOCK(sc->ifp); TAILQ_FOREACH(ifma, &sc->ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; @@ -1690,6 +1691,7 @@ &(sc->mcast_addrs[sc->mcast_count]), 6); sc->mcast_count++; } + IF_ADDR_UNLOCK(sc->ifp); setflag: sc->want_mcsetup = 1; --- //depot/vendor/freebsd/src/sys/dev/if_ndis/if_ndis.c 2005/06/14 17:50:27 +++ //depot/projects/netsmp/src/sys/dev/if_ndis/if_ndis.c 2005/07/19 21:29:46 @@ -265,6 +265,7 @@ sc->ndis_filter |= NDIS_PACKET_TYPE_MULTICAST; len = 0; + IF_ADDR_LOCK(ifp); TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; @@ -272,11 +273,13 @@ mclist + (ETHER_ADDR_LEN * len), ETHER_ADDR_LEN); len++; if (len > mclistsz) { + IF_ADDR_UNLOCK(ifp); sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST; sc->ndis_filter &= ~NDIS_PACKET_TYPE_MULTICAST; goto out; } } + IF_ADDR_UNLOCK(ifp); len = len * ETHER_ADDR_LEN; error = ndis_set_info(sc, OID_802_3_MULTICAST_LIST, mclist, &len); --- //depot/vendor/freebsd/src/sys/dev/ixgb/if_ixgb.c 2005/06/10 16:51:34 +++ //depot/projects/netsmp/src/sys/dev/ixgb/if_ixgb.c 2005/07/19 21:29:46 @@ -1065,6 +1065,7 @@ IOCTL_DEBUGOUT("ixgb_set_multi: begin"); + IF_ADDR_LOCK(ifp); #if __FreeBSD_version < 500000 LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { #else @@ -1077,6 +1078,7 @@ &mta[mcnt * IXGB_ETH_LENGTH_OF_ADDRESS], IXGB_ETH_LENGTH_OF_ADDRESS); mcnt++; } + IF_ADDR_UNLOCK(ifp); if (mcnt > MAX_NUM_MULTICAST_ADDRESSES) { reg_rctl = IXGB_READ_REG(&adapter->hw, RCTL); --- //depot/vendor/freebsd/src/sys/dev/lge/if_lge.c 2005/06/10 16:51:34 +++ //depot/projects/netsmp/src/sys/dev/lge/if_lge.c 2005/07/19 21:29:46 @@ -390,6 +390,7 @@ CSR_WRITE_4(sc, LGE_MAR1, 0); /* now program new ones */ + IF_ADDR_LOCK(ifp); TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; @@ -400,6 +401,7 @@ else hashes[1] |= (1 << (h - 32)); } + IF_ADDR_UNLOCK(ifp); CSR_WRITE_4(sc, LGE_MAR0, hashes[0]); CSR_WRITE_4(sc, LGE_MAR1, hashes[1]); --- //depot/vendor/freebsd/src/sys/dev/lnc/if_lnc.c 2005/06/10 16:51:34 +++ //depot/projects/netsmp/src/sys/dev/lnc/if_lnc.c 2005/07/19 21:29:46 @@ -239,6 +239,7 @@ */ bzero(sc->init_block->ladrf, MULTICAST_FILTER_LEN); + IF_ADDR_LOCK(ifp); TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; @@ -247,6 +248,7 @@ ifma->ifma_addr), ETHER_ADDR_LEN) >> 26; sc->init_block->ladrf[index >> 3] |= 1 << (index & 7); } + IF_ADDR_UNLOCK(ifp); } void --- //depot/vendor/freebsd/src/sys/dev/my/if_my.c 2005/06/10 16:51:34 +++ //depot/projects/netsmp/src/sys/dev/my/if_my.c 2005/07/19 21:29:46 @@ -346,6 +346,7 @@ CSR_WRITE_4(sc, MY_MAR1, 0); /* now program new ones */ + IF_ADDR_LOCK(ifp); TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; @@ -357,6 +358,7 @@ hashes[1] |= (1 << (h - 32)); mcnt++; } + IF_ADDR_UNLOCK(ifp); if (mcnt) rxfilt |= MY_AM; --- //depot/vendor/freebsd/src/sys/dev/nge/if_nge.c 2005/06/10 16:51:34 +++ //depot/projects/netsmp/src/sys/dev/nge/if_nge.c 2005/07/19 21:29:46 @@ -705,6 +705,7 @@ * that needs to be updated, and the lower 4 bits represent * which bit within that byte needs to be set. */ + IF_ADDR_LOCK(ifp); TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; @@ -716,6 +717,7 @@ NGE_FILTADDR_MCAST_LO + (index * 2)); NGE_SETBIT(sc, NGE_RXFILT_DATA, (1 << bit)); } + IF_ADDR_UNLOCK(ifp); CSR_WRITE_4(sc, NGE_RXFILT_CTL, filtsave); --- //depot/vendor/freebsd/src/sys/dev/nve/if_nve.c 2005/06/11 01:40:36 +++ //depot/projects/netsmp/src/sys/dev/nve/if_nve.c 2005/07/19 21:29:46 @@ -1074,6 +1074,7 @@ return; } /* Setup multicast filter */ + IF_ADDR_LOCK(ifp); TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { u_char *addrp; @@ -1087,6 +1088,7 @@ oraddr[i] |= mcaddr; } } + IF_ADDR_UNLOCK(ifp); for (i = 0; i < 6; i++) { hwfilter.acMulticastAddress[i] = andaddr[i] & oraddr[i]; hwfilter.acMulticastMask[i] = andaddr[i] | (~oraddr[i]); --- //depot/vendor/freebsd/src/sys/dev/owi/if_owi.c 2005/06/10 16:51:34 +++ //depot/projects/netsmp/src/sys/dev/owi/if_owi.c 2005/07/19 21:29:46 @@ -1213,6 +1213,7 @@ return; } + IF_ADDR_LOCK(ifp); TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; @@ -1225,6 +1226,7 @@ break; } } + IF_ADDR_UNLOCK(ifp); mcast.wi_len = (i * 3) + 1; wi_write_record(sc, (struct wi_ltv_gen *)&mcast); --- //depot/vendor/freebsd/src/sys/dev/pdq/pdq_ifsubr.c 2005/06/10 16:51:34 +++ //depot/projects/netsmp/src/sys/dev/pdq/pdq_ifsubr.c 2005/07/19 21:29:46 @@ -273,6 +273,7 @@ PDQ_IFNET(sc)->if_flags &= ~IFF_ALLMULTI; #endif + IF_ADDR_LOCK(PDQ_IFNET(sc)); for (ifma = TAILQ_FIRST(&PDQ_IFNET(sc)->if_multiaddrs); ifma && num_addrs > 0; ifma = TAILQ_NEXT(ifma, ifma_link)) { char *mcaddr; @@ -285,6 +286,7 @@ addr++; num_addrs--; } + IF_ADDR_UNLOCK(PDQ_IFNET(sc)); /* * If not all the address fit into the CAM, turn on all-multicast mode. */ --- //depot/vendor/freebsd/src/sys/dev/ray/if_ray.c 2005/06/10 16:51:34 +++ //depot/projects/netsmp/src/sys/dev/ray/if_ray.c 2005/07/19 21:29:46 @@ -2704,6 +2704,7 @@ * The multicast list is only 16 items long so use promiscuous * mode and don't bother updating the multicast list. */ + IF_ADDR_LOCK(ifp); TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) count++; if (count == 0) { @@ -2711,6 +2712,7 @@ return; } else if (count > 16) { ifp->if_flags |= IFF_ALLMULTI; + IF_ADDR_UNLOCK(ifp); ray_com_runq_done(sc); return; } else if (ifp->if_flags & IFF_ALLMULTI) @@ -2732,6 +2734,7 @@ ); bufp += ETHER_ADDR_LEN; } + IF_ADDR_UNLOCK(ifp); ray_com_ecf(sc, com); } --- //depot/vendor/freebsd/src/sys/dev/re/if_re.c 2005/07/01 04:16:05 +++ //depot/projects/netsmp/src/sys/dev/re/if_re.c 2005/07/19 21:29:46 @@ -601,6 +601,7 @@ CSR_WRITE_4(sc, RL_MAR4, 0); /* now program new ones */ + IF_ADDR_LOCK(ifp); TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; @@ -612,6 +613,7 @@ hashes[1] |= (1 << (h - 32)); mcnt++; } + IF_ADDR_UNLOCK(ifp); if (mcnt) rxfilt |= RL_RXCFG_RX_MULTI; --- //depot/vendor/freebsd/src/sys/dev/sn/if_sn.c 2005/07/18 23:45:24 +++ //depot/projects/netsmp/src/sys/dev/sn/if_sn.c 2005/07/19 21:29:46 @@ -1410,6 +1410,7 @@ bzero(mcf, MCFSZ); + IF_ADDR_LOCK(ifp); TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) return 0; @@ -1423,5 +1424,6 @@ } af[index2 >> 3] |= 1 << (index2 & 7); } + IF_ADDR_UNLOCK(ifp); return 1; /* use multicast filter */ } --- //depot/vendor/freebsd/src/sys/dev/snc/dp83932.c 2005/06/12 15:25:25 +++ //depot/projects/netsmp/src/sys/dev/snc/dp83932.c 2005/07/19 21:29:46 @@ -675,6 +675,7 @@ ifp->if_flags &= ~IFF_ALLMULTI; /* Loop through multicast addresses */ + IF_ADDR_LOCK(ifp); TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; @@ -688,6 +689,7 @@ LLADDR((struct sockaddr_dl *)ifma->ifma_addr)); mcount++; } + IF_ADDR_UNLOCK(ifp); NIC_PUT(sc, SNCR_CDP, LOWER(sc->v_cda)); NIC_PUT(sc, SNCR_CDC, MAXCAM); --- //depot/vendor/freebsd/src/sys/dev/tx/if_tx.c 2005/06/10 16:51:34 +++ //depot/projects/netsmp/src/sys/dev/tx/if_tx.c 2005/07/19 21:29:46 @@ -1409,6 +1409,7 @@ filter[2] = 0; filter[3] = 0; + IF_ADDR_LOCK(ifp); #if __FreeBSD_version < 500000 LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { #else @@ -1420,6 +1421,7 @@ ifma->ifma_addr), ETHER_ADDR_LEN) >> 26; filter[h >> 4] |= 1 << (h & 0xF); } + IF_ADDR_UNLOCK(ifp); CSR_WRITE_4(sc, MC0, filter[0]); CSR_WRITE_4(sc, MC1, filter[1]); --- //depot/vendor/freebsd/src/sys/dev/txp/if_txp.c 2005/06/10 16:51:34 +++ //depot/projects/netsmp/src/sys/dev/txp/if_txp.c 2005/07/19 21:29:46 @@ -1774,6 +1774,7 @@ else { hash[0] = hash[1] = 0; + IF_ADDR_LOCK(ifp); TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; @@ -1797,6 +1798,7 @@ hashbit = (u_int16_t)(crc & (64 - 1)); hash[hashbit / 32] |= (1 << hashbit % 32); } + IF_ADDR_UNLOCK(ifp); if (mcnt > 0) { filter |= TXP_RXFILT_HASHMULTI; --- //depot/vendor/freebsd/src/sys/dev/usb/if_aue.c 2005/06/10 16:51:34 +++ //depot/projects/netsmp/src/sys/dev/usb/if_aue.c 2005/07/19 21:29:46 @@ -539,6 +539,7 @@ aue_csr_write_1(sc, AUE_MAR0 + i, 0); /* now program new ones */ + IF_ADDR_LOCK(ifp); #if __FreeBSD_version >= 500000 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) #else @@ -551,6 +552,7 @@ ifma->ifma_addr), ETHER_ADDR_LEN) & ((1 << AUE_BITS) - 1); AUE_SETBIT(sc, AUE_MAR + (h >> 3), 1 << (h & 0x7)); } + IF_ADDR_UNLOCK(ifp); return; } --- //depot/vendor/freebsd/src/sys/dev/usb/if_axe.c 2005/06/10 16:51:34 +++ //depot/projects/netsmp/src/sys/dev/usb/if_axe.c 2005/07/19 21:29:46 @@ -338,6 +338,7 @@ } else rxmode &= ~AXE_RXCMD_ALLMULTI; + IF_ADDR_LOCK(ifp); #if __FreeBSD_version >= 500000 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) #else @@ -350,6 +351,7 @@ ifma->ifma_addr), ETHER_ADDR_LEN) >> 26; hashtbl[h / 8] |= 1 << (h % 8); } + IF_ADDR_UNLOCK(ifp); axe_cmd(sc, AXE_CMD_WRITE_MCAST, 0, 0, (void *)&hashtbl); axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, rxmode, NULL); --- //depot/vendor/freebsd/src/sys/dev/usb/if_cue.c 2005/06/10 16:51:34 +++ //depot/projects/netsmp/src/sys/dev/usb/if_cue.c 2005/07/19 21:29:46 @@ -356,6 +356,7 @@ sc->cue_mctab[i] = 0; /* now program new ones */ + IF_ADDR_LOCK(ifp); #if __FreeBSD_version >= 500000 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) #else @@ -367,6 +368,7 @@ h = cue_mchash(LLADDR((struct sockaddr_dl *)ifma->ifma_addr)); sc->cue_mctab[h >> 3] |= 1 << (h & 0x7); } + IF_ADDR_UNLOCK(ifp); /* * Also include the broadcast address in the filter --- //depot/vendor/freebsd/src/sys/dev/usb/if_kue.c 2005/06/10 16:51:34 +++ //depot/projects/netsmp/src/sys/dev/usb/if_kue.c 2005/07/19 21:29:46 @@ -327,6 +327,7 @@ sc->kue_rxfilt &= ~KUE_RXFILT_ALLMULTI; + IF_ADDR_LOCK(ifp); #if __FreeBSD_version >= 500000 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) #else @@ -345,6 +346,7 @@ KUE_MCFILT(sc, i), ETHER_ADDR_LEN); i++; } + IF_ADDR_UNLOCK(ifp); if (i == KUE_MCFILTCNT(sc)) sc->kue_rxfilt |= KUE_RXFILT_ALLMULTI; --- //depot/vendor/freebsd/src/sys/dev/usb/if_rue.c 2005/06/10 16:51:34 +++ //depot/projects/netsmp/src/sys/dev/usb/if_rue.c 2005/07/19 22:53:09 @@ -500,6 +500,7 @@ rue_csr_write_4(sc, RUE_MAR4, 0); /* now program new ones */ + IF_ADDR_LOCK(ifp); #if __FreeBSD_version >= 500000 TAILQ_FOREACH (ifma, &ifp->if_multiaddrs, ifma_link) #else @@ -516,6 +517,7 @@ hashes[1] |= (1 << (h - 32)); mcnt++; } + IF_ADDR_UNLOCK(ifp); if (mcnt) rxcfg |= RUE_RCR_AM; --- //depot/vendor/freebsd/src/sys/dev/usb/if_udav.c 2005/06/10 16:51:34 +++ //depot/projects/netsmp/src/sys/dev/usb/if_udav.c 2005/07/19 21:29:46 @@ -1044,6 +1044,7 @@ ETHER_NEXT_MULTI(step, enm); } #elif defined(__FreeBSD__) + IF_ADDR_LOCK(ifp); #if __FreeBSD_version >= 500000 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) #else @@ -1056,6 +1057,7 @@ ifma->ifma_addr)); hashes[h>>3] |= 1 << (h & 0x7); } + IF_ADDR_UNLOCK(ifp); #endif /* disable all multicast */ --- //depot/vendor/freebsd/src/sys/dev/vge/if_vge.c 2005/06/11 01:40:36 +++ //depot/projects/netsmp/src/sys/dev/vge/if_vge.c 2005/07/19 21:29:46 @@ -594,6 +594,7 @@ } /* Now program new ones */ + IF_ADDR_LOCK(ifp); TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; @@ -626,6 +627,7 @@ CSR_WRITE_4(sc, VGE_MAR0, hashes[0]); CSR_WRITE_4(sc, VGE_MAR1, hashes[1]); } + IF_ADDR_UNLOCK(ifp); return; } --- //depot/vendor/freebsd/src/sys/dev/wi/if_wi.c 2005/07/22 16:50:36 +++ //depot/projects/netsmp/src/sys/dev/wi/if_wi.c 2005/07/23 00:06:01 @@ -1739,6 +1739,7 @@ } n = 0; + IF_ADDR_LOCK(ifp); #if __FreeBSD_version < 500000 LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { #else @@ -1752,6 +1753,7 @@ (LLADDR((struct sockaddr_dl *)ifma->ifma_addr))); n++; } + IF_ADDR_UNLOCK(ifp); return wi_write_rid(sc, WI_RID_MCAST_LIST, &mlist, IEEE80211_ADDR_LEN * n); } --- //depot/vendor/freebsd/src/sys/dev/wl/if_wl.c 2005/06/10 16:51:34 +++ //depot/projects/netsmp/src/sys/dev/wl/if_wl.c 2005/07/19 21:29:46 @@ -2121,6 +2121,7 @@ outw(PIOP1(base), 0); /* ac_status */ outw(PIOP1(base), AC_MCSETUP|AC_CW_EL); /* ac_command */ outw(PIOR1(base), OFFSET_CU + 8); + IF_ADDR_LOCK(sc->ifp); TAILQ_FOREACH(ifma, &sc->ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; @@ -2131,6 +2132,7 @@ outw(PIOP1(base), addrp[4] + (addrp[5] << 8)); ++cnt; } + IF_ADDR_UNLOCK(sc->ifp); outw(PIOR1(base), OFFSET_CU + 6); /* mc-cnt */ outw(PIOP1(base), cnt * WAVELAN_ADDR_SIZE); if (wlcmd(sc, "config()-mcaddress") == 0) --- //depot/vendor/freebsd/src/sys/dev/xe/if_xe.c 2005/07/15 06:11:01 +++ //depot/projects/netsmp/src/sys/dev/xe/if_xe.c 2005/07/19 21:29:46 @@ -1274,6 +1274,7 @@ /* Iterate over multicast address list */ count = 0; + IF_ADDR_LOCK(ifp); #if __FreeBSD_version < 500000 LIST_FOREACH(maddr, &ifp->if_multiaddrs, ifma_link) { #else @@ -1295,6 +1296,7 @@ /* Nowhere else to put them on CE2 */ break; } + IF_ADDR_UNLOCK(ifp); DEVPRINTF(2, (scp->dev, "set_multicast: count = %u\n", count)); --- //depot/vendor/freebsd/src/sys/kern/subr_witness.c 2005/06/04 23:25:18 +++ //depot/projects/netsmp/src/sys/kern/subr_witness.c 2005/07/23 00:36:47 @@ -286,6 +286,13 @@ { "ifaddr", &lock_class_mtx_sleep }, { NULL, NULL }, /* + * Multicast - protocol locks before interface locks. + */ + { "in_multi_mtx", &lock_class_mtx_sleep }, + { "igmp_mtx", &lock_class_mtx_sleep }, + { "if_addr_mtx", &lock_class_mtx_sleep }, + { NULL, NULL }, + /* * UNIX Domain Sockets */ { "unp", &lock_class_mtx_sleep }, --- //depot/vendor/freebsd/src/sys/net/if.c 2005/07/19 10:16:50 +++ //depot/projects/netsmp/src/sys/net/if.c 2005/07/22 23:59:30 @@ -417,6 +417,8 @@ { if_free_type(ifp, ifp->if_type); + + IF_ADDR_LOCK_DESTROY(ifp); } void @@ -460,6 +462,7 @@ TASK_INIT(&ifp->if_starttask, 0, if_start_deferred, ifp); TASK_INIT(&ifp->if_linktask, 0, do_link_state_change, ifp); IF_AFDATA_LOCK_INIT(ifp); + IF_ADDR_LOCK_INIT(ifp); ifp->if_afdata_initialized = 0; IFNET_WLOCK(); TAILQ_INSERT_TAIL(&ifnet, ifp, if_link); @@ -1824,99 +1827,229 @@ return (if_setflag(ifp, IFF_ALLMULTI, 0, &ifp->if_amcount, onswitch)); } +struct ifmultiaddr * +ifmaof_ifpforaddr(struct sockaddr *sa, struct ifnet *ifp) +{ + struct ifmultiaddr *ifma; + + IF_ADDR_LOCK_ASSERT(ifp); + + TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { + if (sa_equal(ifma->ifma_addr, sa)) + break; + } + + return ifma; +} + +/* + * XXXRW: ifmaof_ifpforaddr() is an unsensible name, and appears not to be + * used, so use my more sensibly named version here. + */ +static struct ifmultiaddr * +if_findmulti(struct ifnet *ifp, struct sockaddr *sa) +{ + + IF_ADDR_LOCK_ASSERT(ifp); + + return (ifmaof_ifpforaddr(sa, ifp)); +} + +/* + * Allocate a new ifmultiaddr and initialize based on passed arguments. We + * make copies of passed sockaddrs. The ifmultiaddr will not be added to + * the ifnet multicast address list here, so the caller must do that and + * other setup work (such as notifying the device driver). The reference + * count is initialized to 1. + */ +static struct ifmultiaddr * +if_allocmulti(struct ifnet *ifp, struct sockaddr *sa, struct sockaddr *llsa, + int mflags) +{ + struct ifmultiaddr *ifma; + struct sockaddr *dupsa; + + MALLOC(ifma, struct ifmultiaddr *, sizeof *ifma, M_IFMADDR, mflags | + M_ZERO); + if (ifma == NULL) + return (NULL); + + MALLOC(dupsa, struct sockaddr *, sa->sa_len, M_IFMADDR, mflags); + if (dupsa == NULL) { + FREE(ifma, M_IFMADDR); + return (NULL); + } + bcopy(sa, dupsa, sa->sa_len); + ifma->ifma_addr = dupsa; + + ifma->ifma_ifp = ifp; + ifma->ifma_refcount = 1; + ifma->ifma_protospec = NULL; + + if (llsa == NULL) { + ifma->ifma_lladdr = NULL; + return (ifma); + } + + MALLOC(dupsa, struct sockaddr *, llsa->sa_len, M_IFMADDR, mflags); + if (dupsa == NULL) { + FREE(ifma->ifma_addr, M_IFMADDR); + FREE(ifma, M_IFMADDR); + return (NULL); + } + bcopy(llsa, dupsa, llsa->sa_len); + ifma->ifma_lladdr = dupsa; + + return (ifma); +} + +/* + * if_freemulti: free ifmultiaddr structure and possibly attached related + * addresses. The caller is responsible for implementing reference + * counting, notifying the driver, handling routing messages, and releasing + * any dependent link layer state. + */ +static void +if_freemulti(struct ifmultiaddr *ifma) +{ + + KASSERT(ifma->ifma_refcount == 1, ("if_freemulti: refcount %d", + ifma->ifma_refcount)); + KASSERT(ifma->ifma_protospec == NULL, + ("if_freemulti: protospec not NULL")); + + if (ifma->ifma_lladdr != NULL) + FREE(ifma->ifma_lladdr, M_IFMADDR); + FREE(ifma->ifma_addr, M_IFMADDR); + FREE(ifma, M_IFMADDR); +} + /* - * Add a multicast listenership to the interface in question. - * The link layer provides a routine which converts + * Register an additional multicast address with a network interface. + * + * - If the address is already present, bump the reference count on the + * address and return. + * - If the address is not link-layer, look up a link layer address. + * - Allocate address structures for one or both addresses, and attach to the + * multicast address list on the interface. If automatically adding a link + * layer address, the protocol address will own a reference to the link + * layer address, to be freed when it is freed. + * - Notify the network device driver of an addition to the multicast address + * list. + * + * 'sa' points to caller-owned memory with the desired multicast address. + * + * 'retifma' will be used to return a pointer to the resulting multicast + * address reference, if desired. */ int -if_addmulti(struct ifnet *ifp, struct sockaddr *sa, struct ifmultiaddr **retifma) +if_addmulti(struct ifnet *ifp, struct sockaddr *sa, + struct ifmultiaddr **retifma) { - struct sockaddr *llsa, *dupsa; - int error, s; - struct ifmultiaddr *ifma; + struct ifmultiaddr *ifma, *ll_ifma; + struct sockaddr *llsa; + int error; /* - * If the matching multicast address already exists - * then don't add a new one, just add a reference + * If the address is already present, return a new reference to it; + * otherwise, allocate storage and set up a new address. */ - TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { - if (sa_equal(sa, ifma->ifma_addr)) { - ifma->ifma_refcount++; - if (retifma) - *retifma = ifma; - return 0; - } + IF_ADDR_LOCK(ifp); + ifma = if_findmulti(ifp, sa); + if (ifma != NULL) { + ifma->ifma_refcount++; + if (retifma != NULL) + *retifma = ifma; + IF_ADDR_UNLOCK(ifp); + return (0); } /* - * Give the link layer a chance to accept/reject it, and also - * find out which AF_LINK address this maps to, if it isn't one - * already. + * The address isn't already present; resolve the protocol address + * into a link layer address, and then look that up, bump its + * refcount or allocate an ifma for that also. If 'llsa' was + * returned, we will need to free it later. */ + llsa = NULL; + ll_ifma = NULL; if (ifp->if_resolvemulti != NULL) { error = ifp->if_resolvemulti(ifp, &llsa, sa); - if (error) return error; - } else { - llsa = NULL; + if (error) + goto unlock_out; } - MALLOC(ifma, struct ifmultiaddr *, sizeof *ifma, M_IFMADDR, M_WAITOK); - MALLOC(dupsa, struct sockaddr *, sa->sa_len, M_IFMADDR, M_WAITOK); - bcopy(sa, dupsa, sa->sa_len); + /* + * Allocate the new address. Don't hook it up yet, as we may also + * need to allocate a link layer multicast address. + */ + ifma = if_allocmulti(ifp, sa, llsa, M_NOWAIT); + if (ifma == NULL) { + error = ENOMEM; + goto free_llsa_out; + } - ifma->ifma_addr = dupsa; - ifma->ifma_lladdr = llsa; - ifma->ifma_ifp = ifp; - ifma->ifma_refcount = 1; - ifma->ifma_protospec = NULL; - rt_newmaddrmsg(RTM_NEWMADDR, ifma); + /* + * If a link layer address is found, we'll need to see if it's + * already present in the address list, or allocate is as well. + * When this block finishes, the link layer address will be on the + * list. + */ + if (llsa != NULL) { + ll_ifma = if_findmulti(ifp, llsa); + if (ll_ifma == NULL) { + ll_ifma = if_allocmulti(ifp, llsa, NULL, M_NOWAIT); + if (ll_ifma == NULL) { + if_freemulti(ifma); + error = ENOMEM; + goto free_llsa_out; + } + TAILQ_INSERT_HEAD(&ifp->if_multiaddrs, ll_ifma, + ifma_link); + } else + ll_ifma->ifma_refcount++; + } /* - * Some network interfaces can scan the address list at - * interrupt time; lock them out. + * We now have a new multicast address, ifma, and possibly a new or + * referenced link layer address. Add the primary address to the + * ifnet address list. */ - s = splimp(); TAILQ_INSERT_HEAD(&ifp->if_multiaddrs, ifma, ifma_link); - splx(s); + if (retifma != NULL) *retifma = ifma; - if (llsa != NULL) { - TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { - if (sa_equal(ifma->ifma_addr, llsa)) - break; - } - if (ifma) { - ifma->ifma_refcount++; - } else { - MALLOC(ifma, struct ifmultiaddr *, sizeof *ifma, - M_IFMADDR, M_WAITOK); - MALLOC(dupsa, struct sockaddr *, llsa->sa_len, - M_IFMADDR, M_WAITOK); - bcopy(llsa, dupsa, llsa->sa_len); - ifma->ifma_addr = dupsa; - ifma->ifma_lladdr = NULL; - ifma->ifma_ifp = ifp; - ifma->ifma_refcount = 1; - ifma->ifma_protospec = NULL; - s = splimp(); - TAILQ_INSERT_HEAD(&ifp->if_multiaddrs, ifma, ifma_link); - splx(s); - } - } + /* + * Must generate the message while holding the lock so that 'ifma' + * pointer is still valid. + * + * XXXRW: How come we don't announce ll_ifma? + */ + rt_newmaddrmsg(RTM_NEWMADDR, ifma); + IF_ADDR_UNLOCK(ifp); + /* * We are certain we have added something, so call down to the * interface to let them know about it. */ if (ifp->if_ioctl != NULL) { - s = splimp(); IFF_LOCKGIANT(ifp); (void) (*ifp->if_ioctl)(ifp, SIOCADDMULTI, 0); IFF_UNLOCKGIANT(ifp); - splx(s); } - return 0; + if (llsa != NULL) + FREE(llsa, M_IFMADDR); + + return (0); + +free_llsa_out: + if (llsa != NULL) + FREE(llsa, M_IFMADDR); + +unlock_out: + IF_ADDR_UNLOCK(ifp); + return (error); } /* @@ -1926,72 +2059,53 @@ int if_delmulti(struct ifnet *ifp, struct sockaddr *sa) { - struct ifmultiaddr *ifma; - int s; + struct ifmultiaddr *ifma, *ll_ifma; - TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) - if (sa_equal(sa, ifma->ifma_addr)) - break; - if (ifma == NULL) + IF_ADDR_LOCK(ifp); + ifma = if_findmulti(ifp, sa); + if (ifma == NULL) { + IF_ADDR_UNLOCK(ifp); return ENOENT; + } if (ifma->ifma_refcount > 1) { ifma->ifma_refcount--; + IF_ADDR_UNLOCK(ifp); return 0; } - rt_newmaddrmsg(RTM_DELMADDR, ifma); sa = ifma->ifma_lladdr; - s = splimp(); - TAILQ_REMOVE(&ifp->if_multiaddrs, ifma, ifma_link); + if (sa != NULL) + ll_ifma = if_findmulti(ifp, sa); + else + ll_ifma = NULL; + /* - * Make sure the interface driver is notified - * in the case of a link layer mcast group being left. + * XXXRW: How come we don't announce ll_ifma? */ - if (ifp->if_ioctl && ifma->ifma_addr->sa_family == AF_LINK && sa == 0) { - IFF_LOCKGIANT(ifp); - (void) (*ifp->if_ioctl)(ifp, SIOCDELMULTI, 0); - IFF_UNLOCKGIANT(ifp); + rt_newmaddrmsg(RTM_DELMADDR, ifma); + + TAILQ_REMOVE(&ifp->if_multiaddrs, ifma, ifma_link); + if_freemulti(ifma); + + if (ll_ifma != NULL) { + if (ll_ifma->ifma_refcount == 1) { + TAILQ_REMOVE(&ifp->if_multiaddrs, ll_ifma, ifma_link); + if_freemulti(ll_ifma); + } else + ll_ifma->ifma_refcount--; } - splx(s); - free(ifma->ifma_addr, M_IFMADDR); - free(ifma, M_IFMADDR); - if (sa == NULL) - return 0; + IF_ADDR_UNLOCK(ifp); /* - * Now look for the link-layer address which corresponds to - * this network address. It had been squirreled away in - * ifma->ifma_lladdr for this purpose (so we don't have - * to call ifp->if_resolvemulti() again), and we saved that - * value in sa above. If some nasty deleted the - * link-layer address out from underneath us, we can deal because - * the address we stored was is not the same as the one which was - * in the record for the link-layer address. (So we don't complain - * in that case.) + * Make sure the interface driver is notified + * in the case of a link layer mcast group being left. */ - TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) - if (sa_equal(sa, ifma->ifma_addr)) - break; - if (ifma == NULL) - return 0; - - if (ifma->ifma_refcount > 1) { - ifma->ifma_refcount--; - return 0; - } - - s = splimp(); - TAILQ_REMOVE(&ifp->if_multiaddrs, ifma, ifma_link); - if (ifp->if_ioctl != NULL) { + if (ifp->if_ioctl) { IFF_LOCKGIANT(ifp); (void) (*ifp->if_ioctl)(ifp, SIOCDELMULTI, 0); IFF_UNLOCKGIANT(ifp); } - splx(s); - free(ifma->ifma_addr, M_IFMADDR); - free(sa, M_IFMADDR); - free(ifma, M_IFMADDR); return 0; } @@ -2070,18 +2184,6 @@ return (0); } -struct ifmultiaddr * -ifmaof_ifpforaddr(struct sockaddr *sa, struct ifnet *ifp) -{ - struct ifmultiaddr *ifma; - - TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) - if (sa_equal(ifma->ifma_addr, sa)) - break; - - return ifma; -} - /* * The name argument must be a pointer to storage which will last as * long as the interface does. For physical devices, the result of --- //depot/vendor/freebsd/src/sys/net/if_arcsubr.c 2005/06/10 16:51:34 +++ //depot/projects/netsmp/src/sys/net/if_arcsubr.c 2005/07/22 02:45:35 @@ -798,7 +798,9 @@ if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) return EADDRNOTAVAIL; MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR, - M_ZERO); + M_NOWAIT | M_ZERO); + if (sdl == NULL) + return ENOMEM; sdl->sdl_len = sizeof *sdl; sdl->sdl_family = AF_LINK; sdl->sdl_index = ifp->if_index; @@ -824,7 +826,9 @@ if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) return EADDRNOTAVAIL; MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR, - M_ZERO); + M_NOWAIT | M_ZERO); + if (sdl == NULL) + return ENOMEM; sdl->sdl_len = sizeof *sdl; sdl->sdl_family = AF_LINK; sdl->sdl_index = ifp->if_index; --- //depot/vendor/freebsd/src/sys/net/if_ethersubr.c 2005/07/21 09:02:12 +++ //depot/projects/netsmp/src/sys/net/if_ethersubr.c 2005/07/23 00:06:01 @@ -1144,7 +1144,9 @@ if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) return EADDRNOTAVAIL; MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR, - M_WAITOK|M_ZERO); + M_NOWAIT|M_ZERO); + if (sdl == NULL) + return ENOMEM; sdl->sdl_len = sizeof *sdl; sdl->sdl_family = AF_LINK; sdl->sdl_index = ifp->if_index; @@ -1171,7 +1173,9 @@ if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) return EADDRNOTAVAIL; MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR, - M_WAITOK|M_ZERO); + M_NOWAIT|M_ZERO); + if (sdl == NULL) + return (ENOMEM); sdl->sdl_len = sizeof *sdl; sdl->sdl_family = AF_LINK; sdl->sdl_index = ifp->if_index; --- //depot/vendor/freebsd/src/sys/net/if_fddisubr.c 2005/06/10 16:51:34 +++ //depot/projects/netsmp/src/sys/net/if_fddisubr.c 2005/07/22 02:45:35 @@ -720,7 +720,9 @@ if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) return (EADDRNOTAVAIL); MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR, - M_WAITOK); + M_NOWAIT | M_ZERO); + if (sdl == NULL) + return (ENOMEM); sdl->sdl_len = sizeof *sdl; sdl->sdl_family = AF_LINK; sdl->sdl_index = ifp->if_index; @@ -749,7 +751,9 @@ if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) return (EADDRNOTAVAIL); MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR, - M_WAITOK); + M_NOWAIT | M_ZERO); + if (sdl == NULL) + return (ENOMEM); sdl->sdl_len = sizeof *sdl; sdl->sdl_family = AF_LINK; sdl->sdl_index = ifp->if_index; --- //depot/vendor/freebsd/src/sys/net/if_iso88025subr.c 2005/06/10 16:51:34 +++ //depot/projects/netsmp/src/sys/net/if_iso88025subr.c 2005/07/22 02:45:35 @@ -720,7 +720,9 @@ return (EADDRNOTAVAIL); } MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR, - M_WAITOK|M_ZERO); + M_NOWAIT|M_ZERO); + if (sdl == NULL) + return (ENOMEM); sdl->sdl_len = sizeof *sdl; sdl->sdl_family = AF_LINK; sdl->sdl_index = ifp->if_index; @@ -748,7 +750,9 @@ return (EADDRNOTAVAIL); } MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR, - M_WAITOK|M_ZERO); + M_NOWAIT|M_ZERO); + if (sdl == NULL) + return (ENOMEM); sdl->sdl_len = sizeof *sdl; sdl->sdl_family = AF_LINK; sdl->sdl_index = ifp->if_index; --- //depot/vendor/freebsd/src/sys/net/if_var.h 2005/07/21 22:05:31 +++ //depot/projects/netsmp/src/sys/net/if_var.h 2005/07/23 00:06:01 @@ -177,6 +177,7 @@ void *if_afdata[AF_MAX]; int if_afdata_initialized; struct mtx if_afdata_mtx; + struct mtx if_addr_mtx; /* mutex to protect address lists */ struct task if_starttask; /* task for IFF_NEEDSGIANT */ struct task if_linktask; /* task for link change events */ }; @@ -217,6 +218,16 @@ #define if_list if_link /* + * Locks for address lists on the network interface. + */ +#define IF_ADDR_LOCK_INIT(if) mtx_init(&(if)->if_addr_mtx, \ + "if_addr_mtx", NULL, MTX_DEF) +#define IF_ADDR_LOCK_DESTROY(if) mtx_destroy(&(if)->if_addr_mtx) +#define IF_ADDR_LOCK(if) mtx_lock(&(if)->if_addr_mtx) +#define IF_ADDR_UNLOCK(if) mtx_unlock(&(if)->if_addr_mtx) +#define IF_ADDR_LOCK_ASSERT(if) mtx_assert(&(if)->if_addr_mtx, MA_OWNED) + +/* * Output queues (ifp->if_snd) and slow device input queues (*ifp->if_slowq) * are queues of messages stored on ifqueue structures * (defined above). Entries are added to and deleted from these structures --- //depot/vendor/freebsd/src/sys/net/if_vlan.c 2005/06/10 16:51:34 +++ //depot/projects/netsmp/src/sys/net/if_vlan.c 2005/07/19 21:29:46 @@ -188,21 +188,27 @@ } /* Now program new ones. */ + IF_ADDR_LOCK(ifp); TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; mc = malloc(sizeof(struct vlan_mc_entry), M_VLAN, M_NOWAIT); - if (mc == NULL) + if (mc == NULL) { + IF_ADDR_UNLOCK(ifp); return (ENOMEM); + } bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr), (char *)&mc->mc_addr, ETHER_ADDR_LEN); SLIST_INSERT_HEAD(&sc->vlan_mc_listhead, mc, mc_entries); bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr), LLADDR(&sdl), ETHER_ADDR_LEN); error = if_addmulti(ifp_p, (struct sockaddr *)&sdl, &rifma); - if (error) + if (error) { + IF_ADDR_UNLOCK(ifp); return (error); + } } + IF_ADDR_UNLOCK(ifp); return (0); } --- //depot/vendor/freebsd/src/sys/net/rtsock.c 2005/07/15 09:51:31 +++ //depot/projects/netsmp/src/sys/net/rtsock.c 2005/07/19 21:29:46 @@ -1178,6 +1178,11 @@ continue; ifa = ifaddr_byindex(ifp->if_index); info.rti_info[RTAX_IFP] = ifa ? ifa->ifa_addr : NULL; + + /* + * XXXRW: Can't acquire IF_ADDR_LOCK() due to call + * to SYSCTL_OUT(). + */ TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (af && af != ifma->ifma_addr->sa_family) continue; --- //depot/vendor/freebsd/src/sys/netinet/igmp.c 2005/03/26 22:25:15 +++ //depot/projects/netsmp/src/sys/netinet/igmp.c 2005/07/23 00:32:37 @@ -286,6 +286,7 @@ * - Use the value specified in the query message as * the maximum timeout. */ + IN_MULTI_LOCK(); IN_FIRST_MULTI(step, inm); while (inm != NULL) { if (inm->inm_ifp == ifp && @@ -301,6 +302,7 @@ } IN_NEXT_MULTI(step, inm); } + IN_MULTI_UNLOCK(); break; @@ -343,14 +345,15 @@ * If we belong to the group being reported, stop * our timer for that group. */ + IN_MULTI_LOCK(); IN_LOOKUP_MULTI(igmp->igmp_group, ifp, inm); - if (inm != NULL) { inm->inm_timer = 0; ++igmpstat.igps_rcv_ourreports; inm->inm_state = IGMP_OTHERMEMBER; } + IN_MULTI_UNLOCK(); break; } @@ -365,7 +368,8 @@ void igmp_joingroup(struct in_multi *inm) { - int s = splnet(); + + IN_MULTI_LOCK_ASSERT(); if (inm->inm_addr.s_addr == igmp_all_hosts_group || inm->inm_ifp->if_flags & IFF_LOOPBACK) { @@ -384,13 +388,14 @@ } /* XXX handling of failure case? */ } - splx(s); } void igmp_leavegroup(struct in_multi *inm) { + IN_MULTI_LOCK_ASSERT(); + if (inm->inm_state == IGMP_IREPORTEDLAST && inm->inm_addr.s_addr != igmp_all_hosts_group && !(inm->inm_ifp->if_flags & IFF_LOOPBACK) && @@ -403,7 +408,6 @@ { register struct in_multi *inm; struct in_multistep step; - int s; /* * Quick check to see if any work needs to be done, in order @@ -413,7 +417,7 @@ if (!igmp_timers_are_running) return; - s = splnet(); + IN_MULTI_LOCK(); igmp_timers_are_running = 0; IN_FIRST_MULTI(step, inm); while (inm != NULL) { @@ -427,13 +431,12 @@ } IN_NEXT_MULTI(step, inm); } - splx(s); + IN_MULTI_UNLOCK(); } void igmp_slowtimo(void) { - int s = splnet(); struct router_info *rti; IGMP_PRINTF("[igmp.c,_slowtimo] -- > entering \n"); @@ -447,7 +450,6 @@ } mtx_unlock(&igmp_mtx); IGMP_PRINTF("[igmp.c,_slowtimo] -- > exiting \n"); - splx(s); } static void @@ -458,6 +460,8 @@ struct ip *ip; struct ip_moptions imo; + IN_MULTI_LOCK_ASSERT(); + MGETHDR(m, M_DONTWAIT, MT_HEADER); if (m == NULL) return; --- //depot/vendor/freebsd/src/sys/netinet/in.c 2005/06/02 00:07:10 +++ //depot/projects/netsmp/src/sys/netinet/in.c 2005/07/23 00:17:48 @@ -68,7 +68,14 @@ SYSCTL_INT(_net_inet_ip, OID_AUTO, subnets_are_local, CTLFLAG_RW, &subnetsarelocal, 0, "Treat all subnets as directly connected"); +/* + * The IPv4 multicast list (in_multihead and associated structures) + * are protected by the global in_multi_mtx. See in_var.h for + * more details. + */ struct in_multihead in_multihead; /* XXX BSS initialization */ +struct mtx in_multi_mtx; +MTX_SYSINIT(in_multi_mtx, &in_multi_mtx, "in_multi_mtx", MTX_DEF); extern struct inpcbinfo ripcbinfo; extern struct inpcbinfo udbinfo; @@ -949,8 +956,8 @@ int error; struct sockaddr_in sin; struct ifmultiaddr *ifma; - int s = splnet(); + IN_MULTI_LOCK(); /* * Call generic routine to add membership or increment * refcount. It wants addresses in the form of a sockaddr, @@ -962,7 +969,7 @@ sin.sin_addr = *ap; error = if_addmulti(ifp, (struct sockaddr *)&sin, &ifma); if (error) { - splx(s); + IN_MULTI_UNLOCK(); return 0; } @@ -971,16 +978,14 @@ * a new record. Otherwise, we are done. */ if (ifma->ifma_protospec != NULL) { - splx(s); + IN_MULTI_UNLOCK(); return ifma->ifma_protospec; } - /* XXX - if_addmulti uses M_WAITOK. Can this really be called - at interrupt time? If so, need to fix if_addmulti. XXX */ inm = (struct in_multi *)malloc(sizeof(*inm), M_IPMADDR, M_NOWAIT | M_ZERO); if (inm == NULL) { - splx(s); + IN_MULTI_UNLOCK(); return (NULL); } @@ -994,7 +999,7 @@ * Let IGMP know that we have joined a new IP multicast group. */ igmp_joingroup(inm); - splx(s); + IN_MULTI_UNLOCK(); return (inm); } @@ -1005,10 +1010,11 @@ in_delmulti(inm) register struct in_multi *inm; { - struct ifmultiaddr *ifma = inm->inm_ifma; + struct ifmultiaddr *ifma; struct in_multi my_inm; - int s = splnet(); + IN_MULTI_LOCK(); + ifma = inm->inm_ifma; my_inm.inm_ifp = NULL ; /* don't send the leave msg */ if (ifma->ifma_refcount == 1) { /* @@ -1026,5 +1032,5 @@ if_delmulti(ifma->ifma_ifp, ifma->ifma_addr); if (my_inm.inm_ifp != NULL) igmp_leavegroup(&my_inm); - splx(s); + IN_MULTI_UNLOCK(); } --- //depot/vendor/freebsd/src/sys/netinet/in_var.h 2005/01/07 01:52:23 +++ //depot/projects/netsmp/src/sys/netinet/in_var.h 2005/07/22 02:48:12 @@ -167,6 +167,17 @@ extern LIST_HEAD(in_multihead, in_multi) in_multihead; /* + * Lock macros for IPv4 layer multicast address lists. IPv4 lock goes + * before link layer multicast locks in the lock order. In most cases, + * consumers of IN_*_MULTI() macros should acquire the locks before + * calling them; users of the in_{add,del}multi() functions should not. + */ +extern struct mtx in_multi_mtx; +#define IN_MULTI_LOCK() mtx_lock(&in_multi_mtx) +#define IN_MULTI_UNLOCK() mtx_unlock(&in_multi_mtx) +#define IN_MULTI_LOCK_ASSERT() mtx_assert(&in_multi_mtx, MA_OWNED) + +/* * Structure used by macros below to remember position when stepping through * all of the in_multi records. */ @@ -177,6 +188,8 @@ /* * Macro for looking up the in_multi record for a given IP multicast address * on a given interface. If no matching record is found, "inm" is set null. + * + * Caller must hold IF_ADDR_LOCK(). */ #define IN_LOOKUP_MULTI(addr, ifp, inm) \ /* struct in_addr addr; */ \ @@ -185,6 +198,8 @@ do { \ struct ifmultiaddr *ifma; \ \ + IN_MULTI_LOCK_ASSERT(); \ + IF_ADDR_LOCK(ifp); \ TAILQ_FOREACH(ifma, &((ifp)->if_multiaddrs), ifma_link) { \ if (ifma->ifma_addr->sa_family == AF_INET \ && ((struct sockaddr_in *)ifma->ifma_addr)->sin_addr.s_addr == \ @@ -192,6 +207,7 @@ break; \ } \ (inm) = ifma ? ifma->ifma_protospec : 0; \ + IF_ADDR_UNLOCK(ifp); \ } while(0) /* @@ -205,6 +221,7 @@ /* struct in_multistep step; */ \ /* struct in_multi *inm; */ \ do { \ + IN_MULTI_LOCK_ASSERT(); \ if (((inm) = (step).i_inm) != NULL) \ (step).i_inm = LIST_NEXT((step).i_inm, inm_link); \ } while(0) @@ -213,6 +230,7 @@ /* struct in_multistep step; */ \ /* struct in_multi *inm; */ \ do { \ + IN_MULTI_LOCK_ASSERT(); \ (step).i_inm = LIST_FIRST(&in_multihead); \ IN_NEXT_MULTI((step), (inm)); \ } while(0) --- //depot/vendor/freebsd/src/sys/netinet/ip_input.c 2005/07/19 12:16:03 +++ //depot/projects/netsmp/src/sys/netinet/ip_input.c 2005/07/22 02:49:24 @@ -607,7 +607,9 @@ * See if we belong to the destination multicast group on the * arrival interface. */ + IN_MULTI_LOCK(); IN_LOOKUP_MULTI(ip->ip_dst, m->m_pkthdr.rcvif, inm); + IN_MULTI_UNLOCK(); if (inm == NULL) { ipstat.ips_notmember++; m_freem(m); --- //depot/vendor/freebsd/src/sys/netinet/ip_output.c 2005/07/05 23:40:38 +++ //depot/projects/netsmp/src/sys/netinet/ip_output.c 2005/07/22 02:49:24 @@ -291,9 +291,15 @@ ip->ip_src = IA_SIN(ia)->sin_addr; } + /* + * XXXRW: Should the in_multi_mtx be held over + * ip_mloopback() or ip_mforward()? + */ + IN_MULTI_LOCK(); IN_LOOKUP_MULTI(ip->ip_dst, ifp, inm); if (inm != NULL && (imo == NULL || imo->imo_multicast_loop)) { + IN_MULTI_UNLOCK(); /* * If we belong to the destination multicast group * on the outgoing interface, and the caller did not @@ -302,6 +308,7 @@ ip_mloopback(ifp, m, dst, hlen); } else { + IN_MULTI_UNLOCK(); /* * If we are acting as a multicast router, perform * multicast forwarding as if the packet had just --- //depot/vendor/freebsd/src/sys/netinet6/in6_var.h 2005/02/22 13:06:15 +++ //depot/projects/netsmp/src/sys/netinet6/in6_var.h 2005/07/23 00:13:17 @@ -543,6 +543,7 @@ /* struct in6_multi *in6m; */ \ do { \ struct ifmultiaddr *ifma; \ + IF_ADDR_LOCK(ifp); \ TAILQ_FOREACH(ifma, &(ifp)->if_multiaddrs, ifma_link) { \ if (ifma->ifma_addr->sa_family == AF_INET6 \ && IN6_ARE_ADDR_EQUAL(&((struct sockaddr_in6 *)ifma->ifma_addr)->sin6_addr, \ @@ -550,6 +551,7 @@ break; \ } \ (in6m) = (struct in6_multi *)(ifma ? ifma->ifma_protospec : 0); \ + IF_ADDR_UNLOCK(ifp); \ } while(0) /* --- //depot/vendor/freebsd/src/sys/netinet6/mld6.c 2005/07/21 15:10:30 +++ //depot/projects/netsmp/src/sys/netinet6/mld6.c 2005/07/23 00:06:01 @@ -266,6 +266,7 @@ mld6_all_nodes_linklocal.s6_addr16[1] = htons(ifp->if_index); /* XXX */ + IF_ADDR_LOCK(ifp); TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_INET6) continue; @@ -296,6 +297,7 @@ } } } + IF_ADDR_UNLOCK(ifp); if (IN6_IS_ADDR_MC_LINKLOCAL(&mldh->mld_addr)) mldh->mld_addr.s6_addr16[1] = 0; /* XXX */ --- //depot/vendor/freebsd/src/sys/pci/if_dc.c 2005/06/10 16:51:34 +++ //depot/projects/netsmp/src/sys/pci/if_dc.c 2005/07/19 21:29:46 @@ -1110,6 +1110,7 @@ else DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI); + IF_ADDR_LOCK(ifp); TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; @@ -1117,6 +1118,7 @@ LLADDR((struct sockaddr_dl *)ifma->ifma_addr)); sp[h >> 4] |= htole32(1 << (h & 0xF)); } + IF_ADDR_UNLOCK(ifp); if (ifp->if_flags & IFF_BROADCAST) { h = dc_mchash_le(sc, ifp->if_broadcastaddr); @@ -1179,6 +1181,7 @@ return; /* Now program new ones. */ + IF_ADDR_LOCK(ifp); TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; @@ -1193,6 +1196,7 @@ else hashes[1] |= (1 << (h - 32)); } + IF_ADDR_UNLOCK(ifp); CSR_WRITE_4(sc, DC_AL_MAR0, hashes[0]); CSR_WRITE_4(sc, DC_AL_MAR1, hashes[1]); @@ -1250,6 +1254,7 @@ return; /* now program new ones */ + IF_ADDR_LOCK(ifp); TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; @@ -1259,6 +1264,7 @@ else hashes[1] |= (1 << (h - 32)); } + IF_ADDR_UNLOCK(ifp); CSR_WRITE_4(sc, DC_AX_FILTIDX, DC_AX_FILTIDX_MAR0); CSR_WRITE_4(sc, DC_AX_FILTDATA, hashes[0]); @@ -1302,6 +1308,7 @@ else DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI); + IF_ADDR_LOCK(ifp); TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; @@ -1309,6 +1316,7 @@ LLADDR((struct sockaddr_dl *)ifma->ifma_addr)); sp[h >> 4] |= htole32(1 << (h & 0xF)); } + IF_ADDR_UNLOCK(ifp); if (ifp->if_flags & IFF_BROADCAST) { h = dc_mchash_le(sc, ifp->if_broadcastaddr); --- //depot/vendor/freebsd/src/sys/pci/if_de.c 2005/07/21 16:45:20 +++ //depot/projects/netsmp/src/sys/pci/if_de.c 2005/07/23 00:06:01 @@ -2968,6 +2968,7 @@ #endif multicnt = 0; + IF_ADDR_LOCK(sc->tulip_ifp); TAILQ_FOREACH(ifma, &sc->tulip_ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family == AF_LINK) @@ -3089,6 +3090,7 @@ #endif } } + IF_ADDR_UNLOCK(sc->tulip_ifp); #if defined(IFF_ALLMULTI) if (sc->tulip_flags & TULIP_ALLMULTI) sc->tulip_ifp->if_flags |= IFF_ALLMULTI; --- //depot/vendor/freebsd/src/sys/pci/if_pcn.c 2005/06/10 16:51:34 +++ //depot/projects/netsmp/src/sys/pci/if_pcn.c 2005/07/19 21:29:46 @@ -351,6 +351,7 @@ pcn_csr_write(sc, PCN_CSR_MAR0 + i, 0); /* now program new ones */ + IF_ADDR_LOCK(ifp); TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; @@ -358,6 +359,7 @@ ifma->ifma_addr), ETHER_ADDR_LEN) >> 26; hashes[h >> 4] |= 1 << (h & 0xF); } + IF_ADDR_UNLOCK(ifp); for (i = 0; i < 4; i++) pcn_csr_write(sc, PCN_CSR_MAR0 + i, hashes[i]); --- //depot/vendor/freebsd/src/sys/pci/if_rl.c 2005/06/11 01:40:36 +++ //depot/projects/netsmp/src/sys/pci/if_rl.c 2005/07/19 21:29:46 @@ -685,6 +685,7 @@ CSR_WRITE_4(sc, RL_MAR4, 0); /* now program new ones */ + IF_ADDR_LOCK(ifp); TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; @@ -696,6 +697,7 @@ hashes[1] |= (1 << (h - 32)); mcnt++; } + IF_ADDR_UNLOCK(ifp); if (mcnt) rxfilt |= RL_RXCFG_RX_MULTI; --- //depot/vendor/freebsd/src/sys/pci/if_sf.c 2005/06/11 01:40:36 +++ //depot/projects/netsmp/src/sys/pci/if_sf.c 2005/07/19 21:29:46 @@ -431,6 +431,7 @@ SF_SETBIT(sc, SF_RXFILT, SF_RXFILT_ALLMULTI); } else { i = 1; + IF_ADDR_LOCK(ifp); TAILQ_FOREACH_REVERSE(ifma, &ifp->if_multiaddrs, ifmultihead, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; @@ -449,6 +450,7 @@ sf_sethash(sc, LLADDR((struct sockaddr_dl *)ifma->ifma_addr), 0); } + IF_ADDR_UNLOCK(ifp); } } --- //depot/vendor/freebsd/src/sys/pci/if_sis.c 2005/06/10 16:51:34 +++ //depot/projects/netsmp/src/sys/pci/if_sis.c 2005/07/19 21:29:46 @@ -763,6 +763,7 @@ CSR_WRITE_4(sc, SIS_RXFILT_DATA, 0); } + IF_ADDR_LOCK(ifp); TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; @@ -775,6 +776,7 @@ bit -= 0x10; SIS_SETBIT(sc, SIS_RXFILT_DATA, (1 << bit)); } + IF_ADDR_UNLOCK(ifp); CSR_WRITE_4(sc, SIS_RXFILT_CTL, filtsave); @@ -813,6 +815,7 @@ for (i = 0; i < n; i++) hashes[i] = 0; i = 0; + IF_ADDR_LOCK(ifp); TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; @@ -821,6 +824,7 @@ hashes[h >> 4] |= 1 << (h & 0xf); i++; } + IF_ADDR_UNLOCK(ifp); if (i > n) { ctl |= SIS_RXFILTCTL_ALLMULTI; for (i = 0; i < n; i++) --- //depot/vendor/freebsd/src/sys/pci/if_sk.c 2005/06/10 16:51:34 +++ //depot/projects/netsmp/src/sys/pci/if_sk.c 2005/07/19 21:29:46 @@ -823,6 +823,7 @@ hashes[1] = 0xFFFFFFFF; } else { i = 1; + IF_ADDR_LOCK(ifp); TAILQ_FOREACH_REVERSE(ifma, &ifp->if_multiaddrs, ifmultihead, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; @@ -855,6 +856,7 @@ else hashes[1] |= (1 << (h - 32)); } + IF_ADDR_UNLOCK(ifp); } switch(sc->sk_type) { --- //depot/vendor/freebsd/src/sys/pci/if_ste.c 2005/07/08 13:11:56 +++ //depot/projects/netsmp/src/sys/pci/if_ste.c 2005/07/19 21:29:46 @@ -579,6 +579,7 @@ CSR_WRITE_2(sc, STE_MAR3, 0); /* now program new ones */ + IF_ADDR_LOCK(ifp); TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; @@ -589,6 +590,7 @@ else hashes[1] |= (1 << (h - 32)); } + IF_ADDR_UNLOCK(ifp); CSR_WRITE_2(sc, STE_MAR0, hashes[0] & 0xFFFF); CSR_WRITE_2(sc, STE_MAR1, (hashes[0] >> 16) & 0xFFFF); --- //depot/vendor/freebsd/src/sys/pci/if_ti.c 2005/07/07 01:10:31 +++ //depot/projects/netsmp/src/sys/pci/if_ti.c 2005/07/19 21:29:46 @@ -1621,6 +1621,7 @@ } /* Now program new ones. */ + IF_ADDR_LOCK(ifp); TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; @@ -1634,6 +1635,7 @@ SLIST_INSERT_HEAD(&sc->ti_mc_listhead, mc, mc_entries); ti_add_mcast(sc, &mc->mc_addr); } + IF_ADDR_UNLOCK(ifp); /* Re-enable interrupts. */ CSR_WRITE_4(sc, TI_MB_HOSTINTR, intrs); --- //depot/vendor/freebsd/src/sys/pci/if_tl.c 2005/06/10 16:51:34 +++ //depot/projects/netsmp/src/sys/pci/if_tl.c 2005/07/19 21:29:46 @@ -960,6 +960,7 @@ hashes[1] = 0xFFFFFFFF; } else { i = 1; + IF_ADDR_LOCK(ifp); TAILQ_FOREACH_REVERSE(ifma, &ifp->if_multiaddrs, ifmultihead, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; @@ -982,6 +983,7 @@ else hashes[1] |= (1 << (h - 32)); } + IF_ADDR_UNLOCK(ifp); } tl_dio_write32(sc, TL_HASH1, hashes[0]); --- //depot/vendor/freebsd/src/sys/pci/if_vr.c 2005/06/10 16:51:34 +++ //depot/projects/netsmp/src/sys/pci/if_vr.c 2005/07/19 21:29:46 @@ -533,6 +533,7 @@ CSR_WRITE_4(sc, VR_MAR1, 0); /* Now program new ones. */ + IF_ADDR_LOCK(ifp); TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; @@ -544,6 +545,7 @@ hashes[1] |= (1 << (h - 32)); mcnt++; } + IF_ADDR_UNLOCK(ifp); if (mcnt) rxfilt |= VR_RXCFG_RX_MULTI; --- //depot/vendor/freebsd/src/sys/pci/if_wb.c 2005/06/10 16:51:34 +++ //depot/projects/netsmp/src/sys/pci/if_wb.c 2005/07/19 21:29:46 @@ -614,6 +614,7 @@ CSR_WRITE_4(sc, WB_MAR1, 0); /* now program new ones */ + IF_ADDR_LOCK(ifp); TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; @@ -625,6 +626,7 @@ hashes[1] |= (1 << (h - 32)); mcnt++; } + IF_ADDR_UNLOCK(ifp); if (mcnt) rxfilt |= WB_NETCFG_RX_MULTI; --- //depot/vendor/freebsd/src/sys/pci/if_xl.c 2005/07/13 14:10:33 +++ //depot/projects/netsmp/src/sys/pci/if_xl.c 2005/07/19 21:29:46 @@ -777,8 +777,10 @@ return; } + IF_ADDR_LOCK(ifp); TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) mcnt++; + IF_ADDR_UNLOCK(ifp); if (mcnt) rxfilt |= XL_RXFILTER_ALLMULTI; @@ -817,6 +819,7 @@ CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_HASH|i); /* now program new ones */ + IF_ADDR_LOCK(ifp); TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; @@ -838,6 +841,7 @@ h | XL_CMD_RX_SET_HASH | XL_HASH_SET); mcnt++; } + IF_ADDR_UNLOCK(ifp); if (mcnt) rxfilt |= XL_RXFILTER_MULTIHASH;