NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
kern/47788: Incorrect packet length transmitted for odd-lengths with smc91cxx driver
>Number: 47788
>Category: kern
>Synopsis: Incorrect packet length transmitted for odd-lengths with
>smc91cxx driver
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: kern-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Mon Apr 29 21:55:01 +0000 2013
>Originator: Robert Sprowson
>Release: N/A
>Organization:
N/A
>Environment:
N/A
>Description:
The padding logic in src/sys/dev/ic/smc91cxx.c is incorrectly padding by being
confused about padding to get to ETHER_MIN_LEN and padding needed because the
SMSC91Cxx family needs odd length packets handling specially.
By example, the following "ping -s" commands yield the following packet sizes
when inspected with WireShark
1400 -> 1400 (correct)
1401 -> 1402 (1 byte too long)
1402 -> 1402 (correct)
1403 -> 1405 (2 bytes too long)
this pattern repeats every 4 bytes.
The patch below simplifies the copying routine to always stop at a word
boundary, regardless of the state of SMC91CXX_NO_BYTE_WRITE, then builds any
padding needed in variables which are then written using only word accesses
(hence are compatible with both byte-write capable and non-byte-write capable
targets).
Tested by inspection in WireShark with "ping -s" of sizes 8; 9; 10; 11 (to
check the padding of < ETHER_MIN_LEN) and 1400 to 1407 inclusive.
Please note the patch is a diff assuming the patch in PR/47765 is applied first.
>How-To-Repeat:
ping -s 1401 my.host.address
ping -s 1403 my.host.address
or any other odd number.
>Fix:
--- smc91cxx_new.c Thu Apr 25 06:49:32 2013
+++ smc91cxx_len.c Mon Apr 29 21:30:58 2013
@@ -652,13 +652,12 @@
*/
for (len = 0; m != NULL; m = m->m_next)
len += m->m_len;
- pad = (len & 1);
/*
* We drop packets that are too large. Perhaps we should
* truncate them instead?
*/
- if ((len + pad) > (ETHER_MAX_LEN - ETHER_CRC_LEN)) {
+ if (len > (ETHER_MAX_LEN - ETHER_CRC_LEN)) {
printf("%s: large packet discarded\n",
device_xname(sc->sc_dev));
ifp->if_oerrors++;
IFQ_DEQUEUE(&ifp->if_snd, m);
@@ -666,6 +665,7 @@
goto readcheck;
}
+ pad = 0;
#ifdef SMC91CXX_SW_PAD
/*
* Not using hardware padding; pad to ETHER_MIN_LEN.
@@ -745,24 +745,25 @@
IFQ_DEQUEUE(&ifp->if_snd, m);
/*
- * Push the packet out to the card.
+ * Push the packet out to the card. The copying function only does
whole
+ * words and returns the straggling byte (if any).
*/
oddbyte = smc91cxx_copy_tx_frame(sc, m);
#ifdef SMC91CXX_SW_PAD
-#ifdef SMC91CXX_NO_BYTE_WRITE
#if BYTE_ORDER == LITTLE_ENDIAN
if (pad > 1 && (pad & 1)) {
bus_space_write_2(bst, bsh, DATA_REG_W, oddbyte << 0);
oddbyte = 0;
+ pad -= 1;
}
#else
if (pad > 1 && (pad & 1)) {
bus_space_write_2(bst, bsh, DATA_REG_W, oddbyte << 8);
oddbyte = 0;
+ pad -= 1;
}
#endif
-#endif
/*
* Push out padding.
@@ -773,22 +774,17 @@
}
#endif
-#ifdef SMC91CXX_NO_BYTE_WRITE
/*
* Push out control byte and unused packet byte. The control byte
- * is 0, meaning the packet is even lengthed and no special
+ * denotes whether this is an odd or even length packet, and that no
special
* CRC handling is necessary.
*/
#if BYTE_ORDER == LITTLE_ENDIAN
bus_space_write_2(bst, bsh, DATA_REG_W,
- oddbyte | (pad ? (CTLB_ODD << 8) : 0));
+ oddbyte | ((length & 1) ? (CTLB_ODD << 8) : 0));
#else
bus_space_write_2(bst, bsh, DATA_REG_W,
- (oddbyte << 8) | (pad ? CTLB_ODD : 0));
-#endif
-#else
- if (pad)
- bus_space_write_1(bst, bsh, DATA_REG_B, 0);
+ (oddbyte << 8) | ((length & 1) ? CTLB_ODD : 0));
#endif
/*
@@ -892,10 +888,7 @@
panic("smc91cxx_copy_tx_frame: p != lim");
#endif
}
-#ifndef SMC91CXX_NO_BYTE_WRITE
- if (leftover)
- bus_space_write_1(bst, bsh, DATA_REG_B, dbuf);
-#endif
+
return dbuf;
}
Home |
Main Index |
Thread Index |
Old Index