| To: | netdev@xxxxxxxxxxx |
|---|---|
| Subject: | ether_crc wrong in 2.5.50 |
| From: | Manfred Spraul <manfred@xxxxxxxxxxxxxxxx> |
| Date: | Tue, 10 Dec 2002 21:35:31 +0100 |
| Sender: | netdev-bounce@xxxxxxxxxxx |
| User-agent: | Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.2) Gecko/20021202 |
The ether_crc were converted to use the crc32 library in 2.5. The conversion is incorrect: crc32_le and _be are about the bit order in which the bits are processed: _le means least significant bit first, _be msb first. ethernet is always lsb first. ether_crc means the output should be in the cpu bit order [msb in bit 31], ether_crc_le means the output should be with msb in bit 0: that what crc32_le usually generates. The attached patch is tested with winbond-840, natsemi and 8139too, i.e. ether_crc works. ether_crc_le generates the same output as the inline functions from 2.4.18, but it's untested due to lack of nics. Could someone test it on a nic that uses ether_crc_le? -- Manfred // $Header$
// Kernel Version:
// VERSION = 2
// PATCHLEVEL = 5
// SUBLEVEL = 50
// EXTRAVERSION =
--- 2.5/include/linux/crc32.h 2002-11-04 23:30:16.000000000 +0100
+++ build-2.5/include/linux/crc32.h 2002-12-10 19:15:50.000000000 +0100
@@ -9,9 +9,19 @@
extern u32 crc32_le(u32 crc, unsigned char const *p, size_t len);
extern u32 crc32_be(u32 crc, unsigned char const *p, size_t len);
+extern u32 bitreverse(u32 in);
#define crc32(seed, data, length) crc32_le(seed, (unsigned char const *)data,
length)
+
+/*
+ * Helpers for hash table generation of ethernet nics:
+ *
+ * Ethernet sends the least significant bit of a byte first, thus crc32_le
+ * is used. The output of crc32_le is bit reversed [most significant bit
+ * is in bit nr 0], thus it must be reversed before use. Except for
+ * nics that bit swap the result internally...
+ */
+#define ether_crc(length, data) bitreverse(crc32_le(~0, data, length))
#define ether_crc_le(length, data) crc32_le(~0, data, length)
-#define ether_crc(length, data) crc32_be(~0, data, length)
#endif /* _LINUX_CRC32_H */
--- 2.5/lib/crc32.c 2002-11-04 23:30:03.000000000 +0100
+++ build-2.5/lib/crc32.c 2002-12-10 19:16:47.000000000 +0100
@@ -255,6 +255,16 @@
}
#endif
+u32 bitreverse(u32 x)
+{
+ x = (x >> 16) | (x << 16);
+ x = (x >> 8 & 0x00ff00ff) | (x << 8 & 0xff00ff00);
+ x = (x >> 4 & 0x0f0f0f0f) | (x << 4 & 0xf0f0f0f0);
+ x = (x >> 2 & 0x33333333) | (x << 2 & 0xcccccccc);
+ x = (x >> 1 & 0x55555555) | (x << 1 & 0xaaaaaaaa);
+ return x;
+}
+
/*
* A brief CRC tutorial.
*
@@ -399,16 +409,6 @@
}
#endif
-static u32 attribute((const)) bitreverse(u32 x)
-{
- x = (x >> 16) | (x << 16);
- x = (x >> 8 & 0x00ff00ff) | (x << 8 & 0xff00ff00);
- x = (x >> 4 & 0x0f0f0f0f) | (x << 4 & 0xf0f0f0f0);
- x = (x >> 2 & 0x33333333) | (x << 2 & 0xcccccccc);
- x = (x >> 1 & 0x55555555) | (x << 1 & 0xaaaaaaaa);
- return x;
-}
-
static void bytereverse(unsigned char *buf, size_t len)
{
while (len--) {
--- 2.5/drivers/net/natsemi.c 2002-11-04 23:30:05.000000000 +0100
+++ build-2.5/drivers/net/natsemi.c 2002-12-10 19:20:01.000000000 +0100
@@ -164,6 +164,7 @@
#include <linux/delay.h>
#include <linux/rtnetlink.h>
#include <linux/mii.h>
+#include <linux/crc32.h>
#include <asm/processor.h> /* Processor type for cache alignment. */
#include <asm/bitops.h>
#include <asm/io.h>
@@ -1898,44 +1899,6 @@
return &np->stats;
}
-/**
- * dp83815_crc - computer CRC for hash table entries
- *
- * Note - this is, for some reason, *not* the same function
- * as ether_crc_le() or ether_crc(), though it uses the
- * same big-endian polynomial.
- */
-#define DP_POLYNOMIAL 0x04C11DB7
-static unsigned dp83815_crc(int length, unsigned char *data)
-{
- u32 crc;
- u8 cur_byte;
- u8 msb;
- u8 byte, bit;
-
- crc = ~0;
- for (byte=0; byte<length; byte++) {
- cur_byte = *data++;
- for (bit=0; bit<8; bit++) {
- msb = crc >> 31;
- crc <<= 1;
- if (msb ^ (cur_byte & 1)) {
- crc ^= DP_POLYNOMIAL;
- crc |= 1;
- }
- cur_byte >>= 1;
- }
- }
- crc >>= 23;
-
- return (crc);
-}
-
-
-void set_bit_le(int offset, unsigned char * data)
-{
- data[offset >> 3] |= (1 << (offset & 0x07));
-}
#define HASH_TABLE 0x200
static void __set_rx_mode(struct net_device *dev)
{
@@ -1960,9 +1923,8 @@
memset(mc_filter, 0, sizeof(mc_filter));
for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
i++, mclist = mclist->next) {
- set_bit_le(
- dp83815_crc(ETH_ALEN, mclist->dmi_addr) & 0x1ff,
- mc_filter);
+ int i = (ether_crc(ETH_ALEN, mclist->dmi_addr) >> 23) &
0x1ff;
+ mc_filter[i/8] |= (1 << (i & 0x07));
}
rx_mode = RxFilterEnable | AcceptBroadcast
| AcceptMulticast | AcceptMyPhys;
|
| <Prev in Thread] | Current Thread | [Next in Thread> |
|---|---|---|
| ||
| Previous by Date: | [PATCH]: forgotten dev_put for bridge-devices in nf_reinject, Patrick McHardy |
|---|---|
| Next by Date: | pci-skeleton duplex check, Roger Luethi |
| Previous by Thread: | [PATCH]: forgotten dev_put for bridge-devices in nf_reinject, Patrick McHardy |
| Next by Thread: | pci-skeleton duplex check, Roger Luethi |
| Indexes: | [Date] [Thread] [Top] [All Lists] |