Re: Optimized ether_crc32_be()

From: John Baldwin <jhb_at_FreeBSD.org>
Date: Tue, 22 Jun 2004 17:12:13 -0400
On Friday 18 June 2004 07:37 pm, Christian Weisgerber wrote:
> 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?

Doesn't look like anyone responded.  Perhaps ask someone on sparc64 to test it 
along with some simple multicast test?  (Use mtest to join a group, turn on 
bmcastecho and then ping the multicast group to see if it responds?)

> 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)

-- 
John Baldwin <jhb_at_FreeBSD.org>  <><  http://www.FreeBSD.org/~jhb/
"Power Users Use the Power to Serve"  =  http://www.FreeBSD.org
Received on Tue Jun 22 2004 - 19:11:21 UTC

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