On 2009/05/27 20:59, Brad wrote:
> Please test the following diff with any sis(4) adapters using
> any apps making use of multicast (IPv6, OSPF, CARP, etc.) and/or
> promiscuous mode of operation.
>
> Please provide a dmesg.
Works fine on an soekris 4521 (natsemi 83816A). dmesg below.
Anyone tried it with a sis 900/7016?
For people testing, to be clear, these multicast diffs need
testing with multicast both _with_ and _without_ the interface
in promiscuous mode.
If you have a lan segment with other machines that respond
normally to icmp6 node-information queries (standard OpenBSD
config) you can do this:
ping6 -w ff02::1%sis0 from machine under test
<check you get replies from other machines in the lan segment>
ping6 -w ff02::1%<iface> from another machine
<check the machine under test responds>
and check you get the same results while "tcpdump -nisis0" is
running.
> Index: if_sis.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/pci/if_sis.c,v
> retrieving revision 1.88
> diff -u -p -r1.88 if_sis.c
> --- if_sis.c 14 Apr 2009 19:06:49 -0000 1.88
> +++ if_sis.c 15 Apr 2009 05:56:10 -0000
> @@ -153,10 +153,9 @@ void sis_miibus_writereg(struct device *
> void sis_miibus_statchg(struct device *);
>
> u_int32_t sis_mchash(struct sis_softc *, const uint8_t *);
> -void sis_setmulti(struct sis_softc *);
> -void sis_setmulti_sis(struct sis_softc *);
> -void sis_setmulti_ns(struct sis_softc *);
> -void sis_setpromisc(struct sis_softc *);
> +void sis_iff(struct sis_softc *);
> +void sis_iff_ns(struct sis_softc *);
> +void sis_iff_sis(struct sis_softc *);
> void sis_reset(struct sis_softc *);
> int sis_ring_init(struct sis_softc *);
>
> @@ -699,144 +698,129 @@ sis_mchash(struct sis_softc *sc, const u
> }
>
> void
> -sis_setmulti(struct sis_softc *sc)
> +sis_iff(struct sis_softc *sc)
> {
> if (sc->sis_type == SIS_TYPE_83815)
> - sis_setmulti_ns(sc);
> + sis_iff_ns(sc);
> else
> - sis_setmulti_sis(sc);
> + sis_iff_sis(sc);
> }
>
> void
> -sis_setmulti_ns(struct sis_softc *sc)
> +sis_iff_ns(struct sis_softc *sc)
> {
> - struct ifnet *ifp;
> + struct ifnet *ifp = &sc->arpcom.ac_if;
> struct arpcom *ac = &sc->arpcom;
> struct ether_multi *enm;
> struct ether_multistep step;
> - u_int32_t h = 0, i, filtsave;
> + u_int32_t h = 0, i, rxfilt;
> int bit, index;
>
> - ifp = &sc->arpcom.ac_if;
> + rxfilt = CSR_READ_4(sc, SIS_RXFILT_CTL);
> + rxfilt &= ~(SIS_RXFILTCTL_ALLMULTI | SIS_RXFILTCTL_ALLPHYS |
> + SIS_RXFILTCTL_BROAD | NS_RXFILTCTL_MCHASH);
> + ifp->if_flags &= ~IFF_ALLMULTI;
>
> - if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
> -allmulti:
> - SIS_CLRBIT(sc, SIS_RXFILT_CTL, NS_RXFILTCTL_MCHASH);
> - SIS_SETBIT(sc, SIS_RXFILT_CTL, SIS_RXFILTCTL_ALLMULTI);
> - return;
> - }
> + /*
> + * Always accept broadcast frames.
> + */
> + rxfilt |= SIS_RXFILTCTL_BROAD;
>
> - ETHER_FIRST_MULTI(step, ac, enm);
> - while (enm != NULL) {
> - if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
> - ifp->if_flags |= IFF_ALLMULTI;
> - goto allmulti;
> + if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0) {
> + ifp->if_flags |= IFF_ALLMULTI;
> + rxfilt |= SIS_RXFILTCTL_ALLMULTI;
> + if (ifp->if_flags & IFF_PROMISC)
> + rxfilt |= SIS_RXFILTCTL_ALLPHYS;
> + } else {
> + /*
> + * We have to explicitly enable the multicast hash table
> + * on the NatSemi chip if we want to use it, which we do.
> + */
> + rxfilt |= NS_RXFILTCTL_MCHASH;
> +
> + /* first, zot all the existing hash bits */
> + for (i = 0; i < 32; i++) {
> + CSR_WRITE_4(sc, SIS_RXFILT_CTL, NS_FILTADDR_FMEM_LO +
> (i*2));
> + CSR_WRITE_4(sc, SIS_RXFILT_DATA, 0);
> }
> - ETHER_NEXT_MULTI(step, enm);
> - }
>
> - /*
> - * We have to explicitly enable the multicast hash table
> - * on the NatSemi chip if we want to use it, which we do.
> - */
> - SIS_SETBIT(sc, SIS_RXFILT_CTL, NS_RXFILTCTL_MCHASH);
> - SIS_CLRBIT(sc, SIS_RXFILT_CTL, SIS_RXFILTCTL_ALLMULTI);
> + ETHER_FIRST_MULTI(step, ac, enm);
> + while (enm != NULL) {
> + h = sis_mchash(sc, enm->enm_addrlo);
>
> - filtsave = CSR_READ_4(sc, SIS_RXFILT_CTL);
> + index = h >> 3;
> + bit = h & 0x1F;
>
> - /* first, zot all the existing hash bits */
> - for (i = 0; i < 32; i++) {
> - CSR_WRITE_4(sc, SIS_RXFILT_CTL, NS_FILTADDR_FMEM_LO + (i*2));
> - CSR_WRITE_4(sc, SIS_RXFILT_DATA, 0);
> - }
> + CSR_WRITE_4(sc, SIS_RXFILT_CTL, NS_FILTADDR_FMEM_LO +
> index);
>
> - ETHER_FIRST_MULTI(step, ac, enm);
> - while (enm != NULL) {
> - h = sis_mchash(sc, enm->enm_addrlo);
> - index = h >> 3;
> - bit = h & 0x1F;
> - CSR_WRITE_4(sc, SIS_RXFILT_CTL, NS_FILTADDR_FMEM_LO + index);
> - if (bit > 0xF)
> - bit -= 0x10;
> - SIS_SETBIT(sc, SIS_RXFILT_DATA, (1 << bit));
> - ETHER_NEXT_MULTI(step, enm);
> + if (bit > 0xF)
> + bit -= 0x10;
> +
> + SIS_SETBIT(sc, SIS_RXFILT_DATA, (1 << bit));
> +
> + ETHER_NEXT_MULTI(step, enm);
> + }
> }
>
> - CSR_WRITE_4(sc, SIS_RXFILT_CTL, filtsave);
> + CSR_WRITE_4(sc, SIS_RXFILT_CTL, rxfilt);
> }
>
> void
> -sis_setmulti_sis(struct sis_softc *sc)
> +sis_iff_sis(struct sis_softc *sc)
> {
> - struct ifnet *ifp;
> + struct ifnet *ifp = &sc->arpcom.ac_if;
> struct arpcom *ac = &sc->arpcom;
> struct ether_multi *enm;
> struct ether_multistep step;
> - u_int32_t h, i, n, ctl;
> + u_int32_t h, i, maxmulti, rxfilt;
> u_int16_t hashes[16];
>
> - ifp = &sc->arpcom.ac_if;
> -
> /* hash table size */
> if (sc->sis_rev >= SIS_REV_635 ||
> sc->sis_rev == SIS_REV_900B)
> - n = 16;
> + maxmulti = 16;
> else
> - n = 8;
> + maxmulti = 8;
>
> - ctl = CSR_READ_4(sc, SIS_RXFILT_CTL) & SIS_RXFILTCTL_ENABLE;
> + rxfilt = CSR_READ_4(sc, SIS_RXFILT_CTL);
> + rxfilt &= ~(SIS_RXFILTCTL_ALLMULTI | SIS_RXFILTCTL_ALLPHYS |
> + SIS_RXFILTCTL_BROAD);
> + ifp->if_flags &= ~IFF_ALLMULTI;
>
> - if (ifp->if_flags & IFF_BROADCAST)
> - ctl |= SIS_RXFILTCTL_BROAD;
> + /*
> + * Always accept broadcast frames.
> + */
> + rxfilt |= SIS_RXFILTCTL_BROAD;
>
> - if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
> -allmulti:
> - ctl |= SIS_RXFILTCTL_ALLMULTI;
> + if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0 ||
> + ac->ac_multicnt > maxmulti) {
> + ifp->if_flags |= IFF_ALLMULTI;
> + rxfilt |= SIS_RXFILTCTL_ALLMULTI;
> if (ifp->if_flags & IFF_PROMISC)
> - ctl |= SIS_RXFILTCTL_BROAD|SIS_RXFILTCTL_ALLPHYS;
> - for (i = 0; i < n; i++)
> + rxfilt |= SIS_RXFILTCTL_ALLPHYS;
> +
> + for (i = 0; i < maxmulti; i++)
> hashes[i] = ~0;
> } else {
> - for (i = 0; i < n; i++)
> + for (i = 0; i < maxmulti; i++)
> hashes[i] = 0;
> - i = 0;
> +
> ETHER_FIRST_MULTI(step, ac, enm);
> while (enm != NULL) {
> - if (bcmp(enm->enm_addrlo, enm->enm_addrhi,
> ETHER_ADDR_LEN)) {
> - ifp->if_flags |= IFF_ALLMULTI;
> - goto allmulti;
> - }
> -
> h = sis_mchash(sc, enm->enm_addrlo);
> +
> hashes[h >> 4] |= 1 << (h & 0xf);
> - i++;
> +
> ETHER_NEXT_MULTI(step, enm);
> }
> - if (i > n) {
> - ctl |= SIS_RXFILTCTL_ALLMULTI;
> - for (i = 0; i < n; i++)
> - hashes[i] = ~0;
> - }
> }
>
> - for (i = 0; i < n; i++) {
> + for (i = 0; i < maxmulti; i++) {
> CSR_WRITE_4(sc, SIS_RXFILT_CTL, (4 + i) << 16);
> CSR_WRITE_4(sc, SIS_RXFILT_DATA, hashes[i]);
> }
>
> - CSR_WRITE_4(sc, SIS_RXFILT_CTL, ctl);
> -}
> -
> -void
> -sis_setpromisc(struct sis_softc *sc)
> -{
> - struct ifnet *ifp = &sc->arpcom.ac_if;
> -
> - /* If we want promiscuous mode, set the allframes bit. */
> - if (ifp->if_flags & IFF_PROMISC)
> - SIS_SETBIT(sc, SIS_RXFILT_CTL, SIS_RXFILTCTL_ALLPHYS);
> - else
> - SIS_CLRBIT(sc, SIS_RXFILT_CTL, SIS_RXFILTCTL_ALLPHYS);
> + CSR_WRITE_4(sc, SIS_RXFILT_CTL, rxfilt);
> }
>
> void
> @@ -1745,20 +1729,9 @@ sis_init(void *xsc)
> }
>
> /*
> - * Set the capture broadcast bit to capture broadcast frames.
> - */
> - if (ifp->if_flags & IFF_BROADCAST)
> - SIS_SETBIT(sc, SIS_RXFILT_CTL, SIS_RXFILTCTL_BROAD);
> - else
> - SIS_CLRBIT(sc, SIS_RXFILT_CTL, SIS_RXFILTCTL_BROAD);
> -
> - /* Set promiscuous mode. */
> - sis_setpromisc(sc);
> -
> - /*
> - * Load the multicast filter.
> + * Program promiscuous mode and multicast filters.
> */
> - sis_setmulti(sc);
> + sis_iff(sc);
>
> /* Turn the receive filter on */
> SIS_SETBIT(sc, SIS_RXFILT_CTL, SIS_RXFILTCTL_ENABLE);
> @@ -1919,24 +1892,14 @@ sis_ioctl(struct ifnet *ifp, u_long comm
>
> case SIOCSIFFLAGS:
> if (ifp->if_flags & IFF_UP) {
> - if (ifp->if_flags & IFF_RUNNING &&
> - (ifp->if_flags ^ sc->sc_if_flags) &
> - IFF_PROMISC) {
> - sis_setpromisc(sc);
> - sis_setmulti(sc);
> - } else if (ifp->if_flags & IFF_RUNNING &&
> - (ifp->if_flags ^ sc->sc_if_flags) &
> - IFF_ALLMULTI) {
> - sis_setmulti(sc);
> - } else {
> - if (!(ifp->if_flags & IFF_RUNNING))
> - sis_init(sc);
> - }
> + if (ifp->if_flags & IFF_RUNNING)
> + error = ENETRESET;
> + else
> + sis_init(sc);
> } else {
> if (ifp->if_flags & IFF_RUNNING)
> sis_stop(sc);
> }
> - sc->sc_if_flags = ifp->if_flags;
> break;
>
> case SIOCGIFMEDIA:
> @@ -1951,7 +1914,7 @@ sis_ioctl(struct ifnet *ifp, u_long comm
>
> if (error == ENETRESET) {
> if (ifp->if_flags & IFF_RUNNING)
> - sis_setmulti(sc);
> + sis_iff(sc);
> error = 0;
> }
>
> Index: if_sisreg.h
> ===================================================================
> RCS file: /cvs/src/sys/dev/pci/if_sisreg.h,v
> retrieving revision 1.29
> diff -u -p -r1.29 if_sisreg.h
> --- if_sisreg.h 14 Apr 2009 19:06:49 -0000 1.29
> +++ if_sisreg.h 15 Apr 2009 06:40:50 -0000
> @@ -465,7 +465,6 @@ struct sis_softc {
> caddr_t sc_listkva;
> bus_dmamap_t sc_tx_sparemap;
> int sis_stopped;
> - int sc_if_flags;
> };
>
> /*
>
> --
> This message has been scanned for viruses and
> dangerous content by MailScanner, and is
> believed to be clean.
>
OpenBSD 4.5-current (GENERIC) #69: Thu May 28 15:20:06 BST 2009
[email protected]:/usr/src/sys/arch/i386/compile/GENERIC
cpu0: AMD Am5x86 W/B 133/160 ("AuthenticAMD" 486-class)
cpu0: FPU
real mem = 66678784 (63MB)
avail mem = 55091200 (52MB)
mainbus0 at root
bios0 at mainbus0: AT/286+ BIOS, date 20/70/14, BIOS32 rev. 0 @ 0xf7840
pcibios0 at bios0: rev 2.0 @ 0xf0000/0x10000
pcibios0: pcibios_get_intr_routing - function not supported
pcibios0: PCI IRQ Routing information unavailable.
pcibios0: PCI bus #2 is the last bus
bios0: ROM list: 0xc8000/0x9000
cpu0 at mainbus0: (uniprocessor)
pci0 at mainbus0 bus 0: configuration mode 1 (bios)
elansc0 at pci0 dev 0 function 0 "AMD ElanSC520 PCI" rev 0x00: product 0
stepping 1.1, CPU clock 133MHz, reset 40<SCP>
gpio0 at elansc0: 32 pins
cbb0 at pci0 dev 17 function 0 "TI PCI1420 CardBus" rev 0x00: irq 10
cbb1 at pci0 dev 17 function 1 "TI PCI1420 CardBus" rev 0x00: irq 10
sis0 at pci0 dev 18 function 0 "NS DP83815 10/100" rev 0x00, DP83816A: irq 11,
address 00:00:24:c2:e1:f8
nsphyter0 at sis0 phy 0: DP83815 10/100 PHY, rev. 1
sis1 at pci0 dev 19 function 0 "NS DP83815 10/100" rev 0x00, DP83816A: irq 5,
address 00:00:24:c2:e1:f9
nsphyter1 at sis1 phy 0: DP83815 10/100 PHY, rev. 1
cardslot0 at cbb0 slot 0 flags 0
cardbus0 at cardslot0: bus 1 device 0 cacheline 0x10, lattimer 0x3f
pcmcia0 at cardslot0
cardslot1 at cbb1 slot 1 flags 0
cardbus1 at cardslot1: bus 2 device 0 cacheline 0x10, lattimer 0x3f
pcmcia1 at cardslot1
isa0 at mainbus0
isadma0 at isa0
com0 at isa0 port 0x3f8/8 irq 4: ns16550a, 16 byte fifo
com0: console
com1 at isa0 port 0x2f8/8 irq 3: ns16550a, 16 byte fifo
pckbc0 at isa0 port 0x60/5
pckbd0 at pckbc0 (kbd slot)
pckbc0: using irq 1 for kbd slot
wskbd0 at pckbd0: console keyboard
wdc0 at isa0 port 0x1f0/8 irq 14
wd0 at wdc0 channel 0 drive 0: <SanDisk SDCFB-2048>
wd0: 4-sector PIO, LBA, 1953MB, 4001760 sectors
wd0(wdc0:0:0): using BIOS timings
pcppi0 at isa0 port 0x61
midi0 at pcppi0: <PC speaker>
spkr0 at pcppi0
npx0 at isa0 port 0xf0/16: reported by CPUID; using exception 16
biomask f7c5 netmask ffe5 ttymask ffff
softraid0 at root
wi0 at pcmcia0 function 0 "WLAN, 11Mbps_PC-Card_3.0, ISL37100P" port 0xa000/64
wi0: PRISM3 ISL37300P (0x801b), Firmware 1.1.1 (primary), 1.5.6 (station),
address 00:02:6f:35:34:fe
com3 at pcmcia1 function 0 "Nokia Mobile Phones, Nokia Card Phone" port
0xa040/16: ns16550a, 16 byte fifo
root on wd0a swap on wd0b dump on wd0b