All of lore.kernel.org
 help / color / mirror / Atom feed
* ether_crc wrong in 2.5.50
@ 2002-12-10 20:35 Manfred Spraul
  0 siblings, 0 replies; only message in thread
From: Manfred Spraul @ 2002-12-10 20:35 UTC (permalink / raw)
  To: netdev

[-- Attachment #1: Type: text/plain, Size: 705 bytes --]

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


[-- Attachment #2: patch-crc --]
[-- Type: text/plain, Size: 3707 bytes --]

// $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;

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2002-12-10 20:35 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-12-10 20:35 ether_crc wrong in 2.5.50 Manfred Spraul

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.