Subject: [Tsvwg] I-D ACTION:draft-ietf-tsvwg-sctpcsum-00.txt

From: [email-masked]
Date: Mon, 02 Jul 2001 10:56:55 -0400

A New Internet-Draft is available from the on-line Internet-Drafts directories.
This draft is a work item of the Transport Area Working Group Working Group of the IETF.

	Title		: SCTP Checksum Change
	Author(s)	: R. Stewart, C. Sharp, J. Stone
	Filename	: draft-ietf-tsvwg-sctpcsum-00.txt
	Pages		: 7
	Date		: 29-Jun-01
	
SCTP [RFC2960] currently uses an Adler-32 checksum.  For small
packets, this provides weak protection against the detection of
errors. This document changes that checksum and updates SCTP to use
the CRC-32 checksum.

A URL for this Internet-Draft is:
http://www.ietf.org/internet-drafts/draft-ietf-tsvwg-sctpcsum-00.txt

Internet-Drafts are also available by anonymous FTP. Login with the username
"anonymous" and a password of your e-mail address. After logging in,
type "cd internet-drafts" and then
	"get draft-ietf-tsvwg-sctpcsum-00.txt".

A list of Internet-Drafts directories can be found in
http://www.ietf.org/shadow.html 
or ftp://ftp.ietf.org/ietf/1shadow-sites.txt

Internet-Drafts can also be obtained by e-mail.

Send a message to:
	[email-masked].
In the body type:
	"FILE /internet-drafts/draft-ietf-tsvwg-sctpcsum-00.txt".
	
NOTE:	The mail server at ietf.org can return the document in
	MIME-encoded form by using the "mpack" utility.  To use this
	feature, insert the command "ENCODING mime" before the "FILE"
	command.  To decode the response(s), you will need "munpack" or
	a MIME-compliant mail reader.  Different MIME-compliant mail readers
	exhibit different behavior, especially when dealing with
	"multipart" MIME messages (i.e. documents which have been split
	up into multiple messages), so check your local documentation on
	how to manipulate these messages.

Below is the data which will enable a MIME compliant mail reader
implementation to automatically retrieve the ASCII version of the
Internet-Draft.

---

From: Matt Crawford <[email-masked]>
Date: Mon, 02 Jul 2001 14:10:55 -0500

errors.

"Protection against the DETECTION of errors"??

I don't think that's what you meant.

_______________________________________________
tsvwg mailing list
[email-masked]
http://www1.ietf.org/mailman/listinfo/tsvwg

---

From: "Douglas Otis" <[email-masked]>
Date: Mon, 2 Jul 2001 18:26:46 -0700

Randall,

I noticed a few things regarding this draft.

One, you failed to also indicate that the table value results in the byte
order being reversed which must be considered when storing.  The MS Byte in
the resultant CRC value is actually the LSB byte as result of the
reflection.  You should indicate the correct order for storing by example
with code.

Two, this is a different polynomial than that selected by the IPS group.

Three, you did not start with an all one's seed which is to improve leading
zero detection.  For some odd reason the Ethernet also stores the inverted
CRC value which again is not being done here.

Doug

---

From: Ian Rytina <[email-masked]>
Date: Thu, 05 Jul 2001 09:54:24 +1000

Hi Randy,

It is excellent that an attempt has been made to formalise this
issue.

A few comments :-

- why is this a work item of the TSV WG ? I would have though that
at this stage this is an individual I-D. Or did I miss a decision
somewhere ?

- I would have liked to have seen a bit more detail in the final
paragraph of Section 1. How does this relate to our Sigtran
requirements ? Also, I would have like to have seen a bit of an
expansion of why CRC-32 is a candidate for a transport layer
checksum (i.e. some of the advantages/disadvantages of CRC-32
in the context of SCTP).

/Ian

[email-masked] wrote:

>   ----------------------------------------------------------------------------------------

---

From: Randall Stewart at work <[email-masked]>
Date: Thu, 19 Jul 2001 07:54:19 -0500

> I don't think that's what you meant.

Hmm...

We probably should have phrased this:

"
      SCTP [RFC2960] currently uses an Adler-32 checksum.  For small
      packets, this provides weak error detection.
"

How does that sound... better?

(sorry for the long delay in response... I have been on PTO for
 the previous 2 weeks and this week I am slowly attempting to
 catch up in email while at a conference :0... maybe in a
 couple of weeks I will be caught up...)

R

-- 
Randall R. Stewart
Systems & Solutions Engineering
Cisco Systems Inc.
[email-masked] 815-342-5222 or 815-477-2127

---

From: Matt Crawford <[email-masked]>
Date: Thu, 19 Jul 2001 11:02:58 -0500

> How does that sound... better?

Yes, much.

---

From: Randall Stewart <[email-masked]>
Date: Fri, 20 Jul 2001 10:02:14 -0500

Doug:

Now that I am back from my vacation/conference and inbetween my
next travel... a response or two..

> reflection.  You should indicate the correct order for storing by example

The appendix code was COPIED from the ssh implementation on FreeBSD. I
am
not sure what you are getting at.. to quote the AD's

"Send text"

> Two, this is a different polynomial than that selected by the IPS group.

This was by choice. The CRC-32 ITU version has been well studied and
is well known and used extensively. SCTP may be used by IPS but is
NOT an IPS protocol... I think since IPS will be adding there own
layer of protection this is ok, since they can use the alternate
polynomial
and thus get double CRC protection...

> CRC value which again is not being done here.

I assume you are again refering to the code in the appendix... again I
took this right from the ssh code in FreeBSD since it was free...

send suggested text :)

R

-- 
Randall R. Stewart
[email-masked] 815-342-5222 (cell phone)

---

From: "Douglas Otis" <[email-masked]>
Date: Tue, 24 Jul 2001 11:28:36 -0700

Randall,

Sorry for my slow response as well.  The use of a reflected table means that
either we intentionally store the crc result in reversed order which will
occur if we blindly use the htonl() function, or we store the crc result in
the correct byte order by using a flip_htonl() and flip_ntoh() function.
This simple is a matter of documentation and only a small problem for those
wishing to implement hardware.

With respect to the polynomial selection, there was a discussion on ips
reflector as to the justification for the CRC32c rather than the standard
polynomial now used on Ethernet, FDDI, Fibre-channel, etc.  Once larger
packets are allowed, the reliability of this polynomial drops.  By combining
the Ethernet polynomial found on the medium together with the Castagnoli
polynomial, a much better result was obtained.

I have included the suggested sample code together with sample code for
generating the polynomial table and a serial method of testing the
polynomial.  Once you recognize that the table results in a flipped byte
order with respect to bytes, then how these values are stored is simply a
matter of documentation regardless of what seems correct.  I would hope that
there could be a benefit derived from the investigations done by the IPS
work group.  The polynomial has nothing to do with IP storage and everything
to do with dealing with larger packets.  Do you envision the possibility
that SCTP may be employed on jumbo frames?

Doug

/* Example CRC32 use */

#include "crc32_tab.h"

int insert_crc32(unsigned char *buffer, int length)
{
SCTP_message *message;
unsigned int i;
unsigned long original_crc32, crc32;

/* save crc value from PDU */
if (length > NMAX  || length < NMIN)
  return -1;

message = (SCTP_message *) buffer;
message->common_header.crc32 = 0L;
crc32 = CRC_INIT;

for (i = 0; i < length; i++)
{
  CRC32(crc32, buffer[i]);
}

/* and insert it into the message */
message->common_header.checksum = flip_htonl(crc32);
    return 1;
}

int validate_crc32(unsigned char *buffer, int length)
{
SCTP_message *message;
unsigned int i;
unsigned long original_crc32, crc32;

/* save crc value from PDU */
if (length > NMAX  || length < NMIN)
  return -1;

message = (SCTP_message *) buffer;
original_crc32 = flip_ntohl(message->common_header.crc32);
message->common_header.crc32 = 0L;
crc32 = CRC_INIT;

for (i = 0; i < length; i++)
{
  CRC32(crc32, buffer[i]);
}

if (original_crc32 != crc32)
	return -1;

/* and insert it into the message */
message->common_header.checksum = flip_htonl(crc32);
    return 1;
}

/* Example CRC32 reflected table creation */

#include <stdio.h>
#include <stdlib.h>

#define OUTPUT_FILE   "crc32_tab.h"
#define ETHER_POLY			1

#ifdef ETHER_POLY
#define CRC32_POLY			0x04C11DB7L
#define CRC_TYPE  "\
/* Ethernet, FDDI, & Fibre-Channel                                     */\n\
/* x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x^1+x^0 */\n"
#else
#define CRC32_POLY			0x1EDC6F41L
#define CRC_TYPE  "\
/* Castagnoli93                                                        */\n\
/* x^32+x^28+x^27+x^26+x^25+x^23+x^22+x^20+x^19+x^18+x^14+x^13+x^11+   */\n\
/* x^10+* x^9+x^8+x^6+x^0                                              */\n\
/* Guy Castagnoli Stefan Braeuer and Martin Herrman                    */\n\
/* \"Optimization of Cyclic Redundancy-Check Codes
*/\n\
/* with 24 and 32 Parity Bits\",
*/\n\
/* IEEE Transactions on Communications, Vol. 41, No. 6, June 1993      */\n"
#endif

FILE *tf;

unsigned long
  reflect_8 (int b)
{
  int i;
  unsigned long rb = 0;

  for (i = 0; i < 8; i++)
    {
      if (b & 1)
        rb |= 1 << (7 - i);
      b >>= 1;
    }
  return (rb);
}

unsigned long
  reflect_32 (unsigned long b)
{
  int i;
  unsigned long rw = 0;

  for (i = 0; i < 32; i++)
    {
      if (b & 1)
        rw |= 1 << (31 - i);
      b >>= 1;
    }
  return (rw);
}

unsigned long
  build_crc_table (int index)
{
  int i;
  unsigned long rb;

  rb = reflect_8 (index);
  rb <<= 24;

  for (i = 0; i < 8; i++)
    {
      if (rb & 0x80000000L)
	rb = (rb << 1) ^ CRC32_POLY;
      else
	rb <<= 1;
    }

  return (reflect_32 (rb));
}

/* here is a means to verify the bype order via serial equivalent */

unsigned long
  serial_gen (unsigned char buf[], int length)
{
  int i;
  int j = 0;
  unsigned char d;
  unsigned long crc = 0;

  while (j < length)
    {
      d = buf[j++];
      for (i = 0; i < 8; i++)
	  {
	  if ((crc >> 31) ^ (d & 1))
	      crc = (crc << 1) ^ CRC32_POLY;
	  else
	      crc <<= 1;
	  d >>= 1;
	  }
    }

  return (crc);
}

main ()
{
  int i;

  printf ("\nGenerating CRC32 Table file <%s>\n", OUTPUT_FILE);
  if ((tf = fopen (OUTPUT_FILE, "w")) == NULL)
    {
      printf ("Unable to open %s\n", OUTPUT_FILE);
      exit (1);
    }
  fprintf (tf, "#ifndef __crc32_table_h__\n");
  fprintf (tf, "#define __crc32_table_h__\n\n");
  fprintf (tf, "#define CRC32_POLY 0x%08lX\n", CRC32_POLY);
  fprintf (tf, "#define CRC32(c,d) (c=(c>>8)^crc32tab[(c^(d))&0xFF])\n");
  fprintf (tf, "\
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */\n\
/* 32 Bit Reflected CRC table generation for SCTP.                     */\n\
/* To accomodate serial byte data being shifted out least              */\n\
/* significant bit first, the table's 32 bit words are reflected       */\n\
/* which flips both byte and bit MS and LS positions.  The CRC         */\n\
/* is calculated MS bits first from the perspective of the serial      */\n\
/* stream.  The x^32 term is implied and the x^0 term may also         */\n\
/* be shown as +1.  The polynomial code used is 0x%08lX.            */\n%s\
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */\n"
	   , CRC32_POLY, CRC_TYPE);

  fprintf (tf, "\nunsigned long  crc32tab[256] =\n{\n");
  for (i = 0; i < 256; i++)
    {
      fprintf (tf, "0x%08lXL, ", build_crc_table (i));
      if ((i & 3) == 3)
        fprintf (tf, "\n");
    }

  fprintf (tf, "};\n\n#endif\n");

  if (fclose (tf) != 0)
    printf ("Unable to close <%s>." OUTPUT_FILE);
  else
    printf ("\nThe CRC32 table has been written to <%s>.\n", OUTPUT_FILE);
}

> -----Original Message-----
> From: [email-masked] [mailto:[email-masked]]On Behalf Of
> Randall Stewart
> Sent: Friday, July 20, 2001 8:02 AM
> To: Douglas Otis
> Cc: Tsvwg
> Subject: Re: [Tsvwg] I-D ACTION:draft-ietf-tsvwg-sctpcsum-00.txt
>
>
> Doug:
>

---

From: Randall Stewart <[email-masked]>
Date: Tue, 24 Jul 2001 14:48:37 -0500

Doug:

Thanks for your response.. I think we should be able
to get a pint in london..

As far as why I specified CRC-32 ITU ... this is what
I beleive the WG was discussing... Before I think
we could adopt CRC-32c the WG would need to say this
is what they really want...

So?? what do all of you feel out there??

The ITU CRC-32 aka same as ethernet OR is CRC-32c the
one we should be going with??

R