Subject: kern/2661: Fix for PCI etherlink3 packet-receive bug
To: None <gnats-bugs@NetBSD.ORG>
From: Jonathan Stone <jonathan@DSG.Stanford.EDU>
List: netbsd-bugs
Date: 07/28/1996 16:57:41
>Number: 2661
>Category: kern
>Synopsis: Fix for PCI etherlink3 packet-receive bug
>Confidential: no
>Severity: serious
>Priority: high
>Responsible: kern-bug-people (Kernel Bug People)
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sun Jul 28 20:20:01 1996
>Last-Modified:
>Originator: Jonathan Stone
>Organization:
>Release: 1.2_BETA
>Environment:
System: NetBSD Cup.DSG.Stanford.EDU 1.2_BETA NetBSD 1.2_BETA (DSG) #45: Fri Jul 26 01:33:18 PDT 1996 jonathan@Cup.DSG.Stanford.EDU:/aga/n1/src/NetBSD/IP-PLUS/src/sys/arch/i386/compile/DSG i386
>Description:
The 1.2-Beta elink3 driver appears vulnerable to the "sniper bug".
The symptoms of this bug are as follows:
some early versions of the 3com 3c59x/3c79x ASIC on a PCI (or EISA,
but I haven't verified that) ccasionally inserts non-zero values in
its receive-adddress mask (register window 2, bytes 6-11).
This 48-bit field indicates that a bit in the Station Address field
(window 2, bytes 0-6) are "don't care" values and should be ignored
when comparing the destination address of a received packet with the
"Station Address" field.
If non-zero values appear in the StationMask address, the Ethernet
card may receive and deliver unicast packets that are not, in fact,
addressed to the local interface. (This is rumoured to be one
potential cause of the "windows NT sniper bug".)
If the payload of such packets is an IP datagram, this can cause
unwanted ICMP "host unreachable" messages to be sent, apparently
inexplicably, to the IP address in the IP source addrses of the
datagram. This, in turn, causes the TCP/IP stack on the remote
machine to close TCp connections the intended destination of the
erroneously-received packet.
An erroneously-received packet for a stack that NetBSD doesn't implement
correctly (e.g,. XNS or ipx) could conceivably cause a NetBSD host
that receives an unanticipated XNS packet to crash.
>How-To-Repeat:
See above. I don't know any deterministic method to get the hardware
to reset with a nonzero station mask. I have not yet observed it on a
NetBSD machine, but this bug has been observed on other machines here
with a slightly older vintage of 3c595 cards.
The effect can be emulated by writing some 1's into arbitrary portions,
(or all of) the StationMask field.
>Fix:
Don Becker's Linux driver alleviates the problem by explicitly zeroing
out the StationMask field.
The following patch adds a definition for the StationMask field to
sys/dev/ic/elink3reg.h, and uses that to reset the StationMask
immediately after setting the NIC's destination address.
Definitions for the Etherlink III "fast ethernet" bus-master DMA
register window present on PCI elink3 devices (3c59x) are also added.
I wrote these patches sometime in April, yet I cant' find them
in the bug database. The patch for the former sys/dev/isa/if_epreg.h;
but it applies cleanly to sys/dev/ic/elink3.h.
I have tested this patch on a PCI card.
I have not tested it on an EISA card.
Perhaps commenting out the "sc->bustype == EP_BUS_EISA" is safest.
*** if_epreg.h.DIST Mon Dec 11 12:39:50 1995
--- if_epreg.h Sat Apr 13 16:15:03 1996
***************
*** 87,92 ****
--- 87,93 ----
* Window 2 registers. Station Address Setup/Read
*/
/* Read/Write */
+ #define EP_W2_RECVMASK_0 0x06
#define EP_W2_ADDR_5 0x05
#define EP_W2_ADDR_4 0x04
#define EP_W2_ADDR_3 0x03
***************
*** 138,143 ****
--- 139,156 ----
#define TX_AFTER_X_COLLISIONS 0x02
#define TX_NO_SQE 0x01
#define TX_CD_LOST 0x00
+
+ /*
+ * Window 7 registers.
+ * Address and length for a single bus-master DMA transfer.
+ */
+ #define EP_W7_MASTER_ADDDRES 0x00
+ #define EP_W7_RX_ERROR 0x04
+ #define EP_W7_MASTER_LEN 0x06
+ #define EP_W7_RX_STATUS 0x08
+ #define EP_W7_TIMER 0x0a
+ #define EP_W7_TX_STATUS 0x0b
+ #define EP_W7_MASTER_STATUS 0x0c
/*
* Register definitions.
*** sys/dev/ic/elink3.c.orig Wed May 15 04:33:01 1996
--- sys/dev/ic/elink3.c Sun Jul 28 16:22:38 1996
***************
*** 200,205 ****
--- 200,210 ----
bus_io_write_1(bc, ioh, EP_W2_ADDR_0 + i,
sc->sc_arpcom.ac_enaddr[i]);
+ if (sc->bustype == EP_BUS_PCI || sc->bustype == EP_BUS_EISA)
+ /* Reset the station-address receive filter */
+ for (i = 0; i < 6; i++)
+ bus_io_write_1(bc, ioh,EP_W2_RECVMASK_0 + i, 0);
+
bus_io_write_2(bc, ioh, EP_COMMAND, RX_RESET);
bus_io_write_2(bc, ioh, EP_COMMAND, TX_RESET);
>Audit-Trail:
>Unformatted: