Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/pci Capture incomplete packets coming from the card, ...



details:   https://anonhg.NetBSD.org/src/rev/9f41ec11356c
branches:  trunk
changeset: 573402:9f41ec11356c
user:      jmmv <jmmv%NetBSD.org@localhost>
date:      Tue Jan 25 17:02:09 2005 +0000

description:
Capture incomplete packets coming from the card, as this driver doesn't
support this feature.  This avoids multiple crashes that I've had in the
past.  Also ensure that packets are not empty when DIAGNOSTIC is set.

However, this is just another sanity check of the received packets, but
does not address the real problem.  The issue seems to be the following:
if the card receives data while doing a reset (vr_init), it later finds
a bunch of empty packets in the receive ring.

This explains the crashes I've hit: running a program which needs
promiscuous mode (dhclient) while the card was already running in
that mode (tcpdump).  In this situation, it's easy that the second
reset receives stuff from the network.

Unfortunately, I don't know why the card is producing these packets...

While here, fix a typo in a comment.

diffstat:

 sys/dev/pci/if_vr.c |  41 ++++++++++++++++++++++++++++++++++++++---
 1 files changed, 38 insertions(+), 3 deletions(-)

diffs (76 lines):

diff -r cc773505376e -r 9f41ec11356c sys/dev/pci/if_vr.c
--- a/sys/dev/pci/if_vr.c       Tue Jan 25 14:56:09 2005 +0000
+++ b/sys/dev/pci/if_vr.c       Tue Jan 25 17:02:09 2005 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_vr.c,v 1.71 2005/01/13 14:51:28 jmmv Exp $  */
+/*     $NetBSD: if_vr.c,v 1.72 2005/01/25 17:02:09 jmmv Exp $  */
 
 /*-
  * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
@@ -104,7 +104,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_vr.c,v 1.71 2005/01/13 14:51:28 jmmv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_vr.c,v 1.72 2005/01/25 17:02:09 jmmv Exp $");
 
 #include "rnd.h"
 
@@ -643,6 +643,23 @@
                        VR_INIT_RXDESC(sc, i);
 
                        continue;
+               } else if (!(rxstat & VR_RXSTAT_FIRSTFRAG) ||
+                          !(rxstat & VR_RXSTAT_LASTFRAG)) {
+                       /*
+                        * This driver expects to receive whole packets every
+                        * time.  In case we receive a fragment that is not
+                        * a complete packet, we discard it.
+                        */
+                       ifp->if_ierrors++;
+
+                       printf("%s: receive error: incomplete frame; "
+                              "size = %d, status = 0x%x\n",
+                              sc->vr_dev.dv_xname,
+                              VR_RXBYTES(le32toh(d->vr_status)), rxstat);
+
+                       VR_INIT_RXDESC(sc, i);
+
+                       continue;
                }
 
                bus_dmamap_sync(sc->vr_dmat, ds->ds_dmamap, 0,
@@ -650,6 +667,24 @@
 
                /* No errors; receive the packet. */
                total_len = VR_RXBYTES(le32toh(d->vr_status));
+#ifdef DIAGNOSTIC
+               if (total_len == 0) {
+                       /*
+                        * If we receive a zero-length packet, we probably
+                        * missed to handle an error condition above.
+                        * Discard it to avoid a later crash.
+                        */
+                       ifp->if_ierrors++;
+
+                       printf("%s: receive error: zero-length packet; "
+                              "status = 0x%x\n",
+                              sc->vr_dev.dv_xname, rxstat);
+
+                       VR_INIT_RXDESC(sc, i);
+
+                       continue;
+               }
+#endif
 
 #ifdef __NO_STRICT_ALIGNMENT
                /*
@@ -1121,7 +1156,7 @@
        VR_SETBIT(sc, VR_TXCFG, VR_TXTHRESH_STORENFWD);
 
        /*
-        * Initialize the transmit desciptor ring.  txlast is initialized
+        * Initialize the transmit descriptor ring.  txlast is initialized
         * to the end of the list so that it will wrap around to the first
         * descriptor when the first packet is transmitted.
         */



Home | Main Index | Thread Index | Old Index