diff options
author | Jason Wright <jason@cvs.openbsd.org> | 1998-10-02 17:42:25 +0000 |
---|---|---|
committer | Jason Wright <jason@cvs.openbsd.org> | 1998-10-02 17:42:25 +0000 |
commit | 96ff0b3c34152b88160fb47d04d882bf4282d0ab (patch) | |
tree | a089fba59380ce4d4527b299199c6792e53c5519 /sys/arch/sparc | |
parent | 88ee0c04de3cd60e2f2fe2f908688fa10c279247 (diff) |
Fixed multicast filter setup.
Diffstat (limited to 'sys/arch/sparc')
-rw-r--r-- | sys/arch/sparc/dev/be.c | 76 | ||||
-rw-r--r-- | sys/arch/sparc/dev/hme.c | 78 |
2 files changed, 101 insertions, 53 deletions
diff --git a/sys/arch/sparc/dev/be.c b/sys/arch/sparc/dev/be.c index 0dfcdd30e2a..5f491b2cc94 100644 --- a/sys/arch/sparc/dev/be.c +++ b/sys/arch/sparc/dev/be.c @@ -1,4 +1,4 @@ -/* $OpenBSD: be.c,v 1.13 1998/09/28 05:12:22 jason Exp $ */ +/* $OpenBSD: be.c,v 1.14 1998/10/02 17:42:23 jason Exp $ */ /* * Copyright (c) 1998 Theo de Raadt and Jason L. Wright. @@ -1298,49 +1298,73 @@ be_mcreset(sc) struct arpcom *ac = &sc->sc_arpcom; struct ifnet *ifp = &sc->sc_arpcom.ac_if; struct be_bregs *br = sc->sc_br; + u_int32_t crc; + u_int16_t hash[4]; + u_int8_t octet; + int i, j; + struct ether_multi *enm; + struct ether_multistep step; if (ifp->if_flags & IFF_ALLMULTI) { br->htable3 = 0xffff; br->htable2 = 0xffff; br->htable1 = 0xffff; br->htable0 = 0xffff; + return; } - else if (ifp->if_flags & IFF_PROMISC) { + + if (ifp->if_flags & IFF_PROMISC) { br->rx_cfg |= BE_BR_RXCFG_PMISC; + return; } - else { - struct ether_multi *enm; - struct ether_multistep step; - u_int16_t hash[4]; - u_int32_t crc = 0xffffffffU; - br->htable3 = br->htable2 = br->htable1 = br->htable0 = 0; - hash[3] = hash[2] = hash[1] = hash[0] = 0; + hash[3] = hash[2] = hash[1] = hash[0] = 0; - ETHER_FIRST_MULTI(step, ac, enm); - while (enm != NULL) { - int i, j; + ETHER_FIRST_MULTI(step, ac, enm); + while (enm != NULL) { + if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) { + /* + * We must listen to a range of multicast + * addresses. For now, just accept all + * multicasts, rather than trying to set only + * those filter bits needed to match the range. + * (At this time, the only use of address + * ranges is for IP multicast routing, for + * which the range is big enough to require + * all bits set.) + */ + br->htable3 = 0xffff; + br->htable2 = 0xffff; + br->htable1 = 0xffff; + br->htable0 = 0xffff; + ifp->if_flags |= IFF_ALLMULTI; + return; + } - for (i = 0; i < ETHER_ADDR_LEN; i++) { - u_int8_t octet = enm->enm_addrlo[i]; + crc = 0xffffffff; - for (j = 0; j < 8; j++) { - u_int8_t bit; + for (i = 0; i < ETHER_ADDR_LEN; i++) { + octet = enm->enm_addrlo[i]; - bit = (octet << j) & 1; + for (j = 0; j < 8; j++) { + if ((crc & 1) ^ (octet & 1)) { crc >>= 1; - if ((bit ^ crc) & 1) - crc = crc ^ MC_POLY_LE; + crc ^= MC_POLY_LE; } + else + crc >>= 1; + octet >>= 1; } - crc >>= 26; - hash[crc >> 4] |= 1 << (crc & 0x0f); - ETHER_NEXT_MULTI(step, enm); } - br->htable0 = hash[0]; - br->htable1 = hash[1]; - br->htable2 = hash[2]; - br->htable3 = hash[3]; + crc >>= 26; + hash[crc >> 4] |= 1 << (crc & 0xf); + ETHER_NEXT_MULTI(step, enm); } + + br->htable3 = hash[3]; + br->htable2 = hash[2]; + br->htable1 = hash[1]; + br->htable0 = hash[0]; + ifp->if_flags &= ~IFF_ALLMULTI; } diff --git a/sys/arch/sparc/dev/hme.c b/sys/arch/sparc/dev/hme.c index 954edaa4401..59f93f793ae 100644 --- a/sys/arch/sparc/dev/hme.c +++ b/sys/arch/sparc/dev/hme.c @@ -1,4 +1,4 @@ -/* $OpenBSD: hme.c,v 1.11 1998/09/24 22:16:37 jason Exp $ */ +/* $OpenBSD: hme.c,v 1.12 1998/10/02 17:42:24 jason Exp $ */ /* * Copyright (c) 1998 Jason L. Wright (jason@thought.net) @@ -545,6 +545,7 @@ hmeinit(sc) cr->jsize = HME_DEFAULT_JSIZE; cr->ipkt_gap1 = HME_DEFAULT_IPKT_GAP1; cr->ipkt_gap2 = HME_DEFAULT_IPKT_GAP2; + cr->htable3 = 0; cr->htable2 = 0; cr->htable1 = 0; @@ -586,7 +587,7 @@ hmeinit(sc) DELAY(20); if (c != rxr->cfg) /* the receiver sometimes misses bits */ printf("%s: setting rxreg->cfg failed.\n", sc->sc_dev.dv_xname); - + cr->rx_cfg = CR_RXCFG_HENABLE; DELAY(10); @@ -983,51 +984,74 @@ hme_mcreset(sc) struct arpcom *ac = &sc->sc_arpcom; struct ifnet *ifp = &sc->sc_arpcom.ac_if; struct hme_cr *cr = sc->sc_cr; - struct ether_multi *enm; - struct ether_multistep step; - u_int16_t hash[4]; u_int32_t crc; + u_int16_t hash[4]; + u_int8_t octet; int i, j; + struct ether_multi *enm; + struct ether_multistep step; if (ifp->if_flags & IFF_ALLMULTI) { cr->htable3 = 0xffff; cr->htable2 = 0xffff; cr->htable1 = 0xffff; cr->htable0 = 0xffff; + return; } - else if (ifp->if_flags & IFF_PROMISC) { + + if (ifp->if_flags & IFF_PROMISC) { cr->rx_cfg |= CR_RXCFG_PMISC; + return; } - else { - cr->htable3 = cr->htable2 = cr->htable1 = cr->htable0 = 0; - hash[3] = hash[2] = hash[1] = hash[0] = 0; - crc = 0xffffffffU; - ETHER_FIRST_MULTI(step, ac, enm); - while (enm != NULL) { + hash[3] = hash[2] = hash[1] = hash[0] = 0; - for (i = 0; i < ETHER_ADDR_LEN; i++) { - u_int8_t octet = enm->enm_addrlo[i]; + ETHER_FIRST_MULTI(step, ac, enm); + while (enm != NULL) { + if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) { + /* + * We must listen to a range of multicast + * addresses. For now, just accept all + * multicasts, rather than trying to set only + * those filter bits needed to match the range. + * (At this time, the only use of address + * ranges is for IP multicast routing, for + * which the range is big enough to require + * all bits set.) + */ + cr->htable3 = 0xffff; + cr->htable2 = 0xffff; + cr->htable1 = 0xffff; + cr->htable0 = 0xffff; + ifp->if_flags |= IFF_ALLMULTI; + return; + } - for (j = 0; j < 8; j++) { - u_int8_t bit; + crc = 0xffffffff; - bit = (octet << j) & 1; + for (i = 0; i < ETHER_ADDR_LEN; i++) { + octet = enm->enm_addrlo[i]; + + for (j = 0; j < 8; j++) { + if ((crc & 1) ^ (octet & 1)) { crc >>= 1; - if ((bit ^ crc) & 1) - crc = crc ^ MC_POLY_LE; + crc ^= MC_POLY_LE; } + else + crc >>= 1; + octet >>= 1; } - - crc >>=26; - hash[crc >> 4] |= 1 << (crc & 0x0f); - ETHER_NEXT_MULTI(step, enm); } - cr->htable3 = hash[3]; - cr->htable2 = hash[2]; - cr->htable1 = hash[1]; - cr->htable0 = hash[0]; + + crc >>=26; + hash[crc >> 4] |= 1 << (crc & 0xf); + ETHER_NEXT_MULTI(step, enm); } + cr->htable3 = hash[3]; + cr->htable2 = hash[2]; + cr->htable1 = hash[1]; + cr->htable0 = hash[0]; + ifp->if_flags &= ~IFF_ALLMULTI; } /* |