Optimized ether_crc32_be()

From: Christian Weisgerber <naddy_at_mips.inka.de>
Date: Fri, 18 Jun 2004 23:37:40 +0000 (UTC)
Taken from kern/49957, here's a table-driven implementation of
ether_crc32_be() to complement the little-endian one.  For 6-byte
MAC addresses it's about five times faster than the double loop.

Comments?

Index: net/if_ethersubr.c
===================================================================
RCS file: /home/ncvs/src/sys/net/if_ethersubr.c,v
retrieving revision 1.172
diff -u -r1.172 if_ethersubr.c
--- net/if_ethersubr.c	15 Jun 2004 23:57:41 -0000	1.172
+++ net/if_ethersubr.c	18 Jun 2004 23:28:37 -0000
_at__at_ -883,9 +883,8 _at__at_
 
 #if 0
 /*
- * This is for reference.  We have a table-driven version
- * of the little-endian crc32 generator, which is faster
- * than the double-loop.
+ * This is for reference.  We have table-driven versions of the
+ * crc32 generators, which are faster than the double-loop.
  */
 uint32_t
 ether_crc32_le(const uint8_t *buf, size_t len)
_at__at_ -907,6 +906,28 _at__at_
 
 	return (crc);
 }
+
+uint32_t
+ether_crc32_be(const uint8_t *buf, size_t len)
+{
+	size_t i;
+	uint32_t crc, carry;
+	int bit;
+	uint8_t data;
+
+	crc = 0xffffffff;	/* initial value */
+
+	for (i = 0; i < len; i++) {
+		for (data = *buf++, bit = 0; bit < 8; bit++, data >>= 1) {
+			carry = ((crc & 0x80000000) ? 1 : 0) ^ (data & 0x01);
+			crc <<= 1;
+			if (carry)
+				crc = (crc ^ ETHER_CRC_POLY_BE) | carry;
+		}
+	}
+
+	return (crc);
+}
 #else
 uint32_t
 ether_crc32_le(const uint8_t *buf, size_t len)
_at__at_ -930,29 +951,35 _at__at_
 
 	return (crc);
 }
-#endif
 
 uint32_t
 ether_crc32_be(const uint8_t *buf, size_t len)
 {
+	static const uint8_t rev[] = {
+		0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
+		0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf
+	};
+	static const uint32_t crctab[] = {
+		0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
+		0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
+		0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
+		0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd
+	};
 	size_t i;
-	uint32_t crc, carry;
-	int bit;
+	uint32_t crc;
 	uint8_t data;
 
 	crc = 0xffffffff;	/* initial value */
 
 	for (i = 0; i < len; i++) {
-		for (data = *buf++, bit = 0; bit < 8; bit++, data >>= 1) {
-			carry = ((crc & 0x80000000) ? 1 : 0) ^ (data & 0x01);
-			crc <<= 1;
-			if (carry)
-				crc = (crc ^ ETHER_CRC_POLY_BE) | carry;
-		}
+		data = buf[i];
+		crc = (crc << 4) ^ crctab[(crc >> 28) ^ rev[data & 0xf]];
+		crc = (crc << 4) ^ crctab[(crc >> 28) ^ rev[data >> 4]];
 	}
 
 	return (crc);
 }
+#endif
 
 int
 ether_ioctl(struct ifnet *ifp, int command, caddr_t data)
-- 
Christian "naddy" Weisgerber                          naddy_at_mips.inka.de
Received on Fri Jun 18 2004 - 21:58:42 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:37:58 UTC