Add common functions for computing the Ethernet CRC on arbitrary length
authorJoerg Sonnenberger <joerg@dragonflybsd.org>
Sat, 3 Jul 2004 13:10:10 +0000 (13:10 +0000)
committerJoerg Sonnenberger <joerg@dragonflybsd.org>
Sat, 3 Jul 2004 13:10:10 +0000 (13:10 +0000)
buffers. ether_crc32_le() is available as table-driven version, which is
faster.

Obtained-from: NetBSD

sys/net/ethernet.h
sys/net/if_ethersubr.c
sys/net/if_var.h

index 8696f7b..d828dc6 100644 (file)
@@ -2,7 +2,7 @@
  * Fundamental constants relating to ethernet.
  *
  * $FreeBSD: src/sys/net/ethernet.h,v 1.12.2.8 2002/12/01 14:03:09 sobomax Exp $
- * $DragonFly: src/sys/net/ethernet.h,v 1.4 2004/03/14 15:36:54 joerg Exp $
+ * $DragonFly: src/sys/net/ethernet.h,v 1.5 2004/07/03 13:10:10 joerg Exp $
  *
  */
 
 #define        ETHER_IS_VALID_LEN(foo) \
        ((foo) >= ETHER_MIN_LEN && (foo) <= ETHER_MAX_LEN)
 
+/*
+ * Ethernet CRC32 polynomials (big- and little-endian verions).
+ */
+#define        ETHER_CRC_POLY_LE       0xedb88320
+#define        ETHER_CRC_POLY_BE       0x04c11db6
+
 /*
  * Structure of a 10Mb/s Ethernet header.
  */
index 8233731..180930a 100644 (file)
@@ -32,7 +32,7 @@
  *
  *     @(#)if_ethersubr.c      8.1 (Berkeley) 6/10/93
  * $FreeBSD: src/sys/net/if_ethersubr.c,v 1.70.2.33 2003/04/28 15:45:53 archie Exp $
- * $DragonFly: src/sys/net/if_ethersubr.c,v 1.15 2004/07/02 17:42:21 joerg Exp $
+ * $DragonFly: src/sys/net/if_ethersubr.c,v 1.16 2004/07/03 13:10:10 joerg Exp $
  */
 
 #include "opt_atalk.h"
@@ -1046,3 +1046,77 @@ ether_resolvemulti(ifp, llsa, sa)
                return EAFNOSUPPORT;
        }
 }
+
+#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.
+ */
+uint32_t
+ether_crc32_le(const uint8_t *buf, size_t len)
+{
+       uint32_t c, crc, carry;
+       size_t i, j;
+
+       crc = 0xffffffffU;      /* initial value */
+
+       for (i = 0; i < len; i++) {
+               c = buf[i];
+               for (j = 0; j < 8; j++) {
+                       carry = ((crc & 0x01) ? 1 : 0) ^ (c & 0x01);
+                       crc >>= 1;
+                       c >>= 1;
+                       if (carry)
+                               crc = (crc ^ ETHER_CRC_POLY_LE);
+               }
+       }
+
+       return(crc);
+}
+#else
+uint32_t
+ether_crc32_le(const uint8_t *buf, size_t len)
+{
+       static const uint32_t crctab[] = {
+               0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
+               0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
+               0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
+               0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
+       };
+       uint32_t crc;
+       size_t i;
+
+       crc = 0xffffffffU;      /* initial value */
+
+       for (i = 0; i < len; i++) {
+               crc ^= buf[i];
+               crc = (crc >> 4) ^ crctab[crc & 0xf];
+               crc = (crc >> 4) ^ crctab[crc & 0xf];
+       }
+
+       return(crc);
+}
+#endif
+
+uint32_t
+ether_crc32_be(const uint8_t *buf, size_t len)
+{
+       uint32_t c, crc, carry;
+       size_t i, j;
+
+       crc = 0xffffffffU;      /* initial value */
+
+       for (i = 0; i < len; i++) {
+               c = buf[i];
+               for (j = 0; j < 8; j++) {
+                       carry = ((crc & 0x80000000U) ? 1 : 0) ^ (c & 0x01);
+                       crc <<= 1;
+                       c >>= 1;
+                       if (carry)
+                               crc = (crc ^ ETHER_CRC_POLY_BE) | carry;
+               }
+       }
+
+       return(crc);
+}
index 17e7ae6..bd3156d 100644 (file)
@@ -32,7 +32,7 @@
  *
  *     From: @(#)if.h  8.1 (Berkeley) 6/10/93
  * $FreeBSD: src/sys/net/if_var.h,v 1.18.2.16 2003/04/15 18:11:19 fjoe Exp $
- * $DragonFly: src/sys/net/if_var.h,v 1.12 2004/06/27 19:40:14 dillon Exp $
+ * $DragonFly: src/sys/net/if_var.h,v 1.13 2004/07/03 13:10:10 joerg Exp $
  */
 
 #ifndef        _NET_IF_VAR_H_
@@ -371,6 +371,8 @@ int ether_output(struct ifnet *,
           struct mbuf *, struct sockaddr *, struct rtentry *);
 int    ether_output_frame(struct ifnet *, struct mbuf *);
 int    ether_ioctl(struct ifnet *, int, caddr_t);
+uint32_t       ether_crc32_le(const uint8_t *, size_t);
+uint32_t       ether_crc32_be(const uint8_t *, size_t);
 
 int    if_addmulti(struct ifnet *, struct sockaddr *, struct ifmultiaddr **);
 int    if_allmulti(struct ifnet *, int);