Subject: RE: iSCSI: [Fwd: Crc-32c example in iSCSI spec]

From: Sanjay Goyal <[email-masked]>
Date: Fri, 17 Aug 2001 12:00:18 -0400

Hi
 I get the remainder for iSCSI as 0x1c2d19ed if I complement my CRC and then
pass it through the CRC engine.
 
 As per CRC generation for data: the thing which is not clear to me is 
   why do we need to bit-swap the CRC reminader as is done in all your
examples. 

We can just complement it and append it after the DATA bytes.
 The other side also can just pass it through the CRC engine to check it.

Regards
Sanjay Goyal

-----Original Message-----
From: Mark Bakke [mailto:[email-masked]]
Sent: Thursday, August 16, 2001 1:43 PM
To: Steve Blightman; [email-masked]
Subject: Re: [Fwd: Crc-32c example in iSCSI spec]

One more thing that might be helpful.  When the Ethernet
polynomial is used in SCSI to generate its CRC, the T10
doc specifies the remainder polynomial that one should see
after running the data with a valid CRC through.  For
the Ethernet CRC, this was specified as 0xc704dd7b.  This
remainder polynomial is taken before the CRC is complemented
and bit-reflected.  For iSCSI, I came up with a remainder of
0x1c2d19ed.  Can anyone verify this result?

--
Mark

Mark Bakke wrote:
> 
> Steve-
> 
> I just ran some Ethernet packets with known CRCs through
> my iSCSI/Ethernet CRC generator, and found the same thing
> as you did.
> 
> All of my examples need to be byte-swapped, along with the
> fix I already posted for the all-ones example.  Here is a
> new set of examples, which will be in -08.  I also ran
> 64 bytes of zeroes and ones, which now agree with your
> numbers as well.
> 
> Thanks again for bringing this up.
> 
> --
> Mark
> 
>      07 CRC Examples
> 
>         N.B. all Values are Hexadecimal
> 
>           Byte:        0  1  2  3
> 
>              0:       01 a0 00 00
>              4:       00 00 00 00
>              8:       00 00 00 00
>             12:       00 00 00 00
>             16:       04 05 00 00
>             20:       00 01 00 00
>             24:       00 00 00 05
>             28:       00 00 00 04
>             32:       2a 00 00 00
>             36:       00 00 00 00
>             40:       80 00 00 00
>             44:       00 00 00 00
> 
>            CRC:       93 70 51 db
> 
>         32 bytes of zeroes:
> 
>           Byte:        0  1  2  3
> 
>              0:       00 00 00 00
>            ...
>             28:       00 00 00 00
> 
>            CRC:       aa 36 91 8a
> 
>         32 bytes of ones:
> 
>           Byte:        0  1  2  3
> 
>              0:       ff ff ff ff
>            ...
>             28:       ff ff ff ff
> 
>            CRC:       43 ab a8 62
> 
>         32 bytes of incrementing 00..1f:
> 
>           Byte:        0  1  2  3
> 
>              0:       00 01 02 03
>            ...
>             28:       1c 1d 1e 1f
> 
>            CRC:       4e 79 dd 46
> 
> 
> Steve Blightman wrote:
> >
> > I believe the examples for the ISCSI CRC  have the wrong endianness.
> >
> > As yiou suugested over the phone I ran some Ethernet frames through a
> > simulation. I have some difficulty running the exact simulations you
> > wanted becuase the minimum size Ethernet frame is 64 bytes.
> >
> > However using the Ethernet CRC polynomial,
> > Running 64 bytes of 0 onto the wire, we append "36 63 8d 75" onto the
> > wire for the CRC - "36" goes out first.
> > Running 64 bytes of all 1, we append "ba 87 61 0f" onto the wire - "ba"
> > goes out first.
> >
> > Using the same logic for the ISCSI polynomial
> > Running 64 bytes of 0 I think we should append "67 eb c8 03" - "67"
> > going out first
> > and running 64 bytes of all 1 we should append "66 4e cd 2f" - "66"
> > going out first
> >
> > And now for 32 bytes with the ISCSI polynomial
> >
> > Running 32 bytes of 0 we should append "aa 36 91 8a" - "aa" going out
> > first
> > Running 32 bytes of all 1 we should append "43 ab a8 62" - "43" going
> > out first
> >
> > I don't want to get into an endless endian debate, but I believe it is
> > important to get the order of these bytes in the right order, so that we
> > can use the same hardware to check as well as to generate CRCs.
> >
> > Thanks for your help on this,
> > Steve Blightman
> 
> --
> Mark A. Bakke
> Cisco Systems
> [email-masked]
> 763.398.1054

-- 
Mark A. Bakke
Cisco Systems
[email-masked]
763.398.1054

---

From: Mark Bakke <[email-masked]>
Date: Fri, 17 Aug 2001 12:06:04 -0500

>    why do we need to bit-swap the CRC reminader as is done in all your

As far as I can tell, bit-swapping does nothing to help or hurt
the effectiveness of the CRC.  When I ran my examples, I thought
that it would be the simplest for our CRC to different from the
Ethernet CRC only in the polynomial.  Ethernet, FDDI, FC, and SCSI
all do this, so I figured it would cause the least confusion if
we did the same.

>   ----------------------------------------------------------------------------------------------------
> 
>    Part 1.2    Type: application/ms-tnef
>            Encoding: base64

-- 
Mark A. Bakke
Cisco Systems
[email-masked]
763.398.1054

---

From: "Douglas Otis" <[email-masked]>
Date: Fri, 17 Aug 2001 11:53:40 -0700

Mark,

The reason for the bit swap within the table is to allow a serial hardware
scheme as CRC is processed ms to ls over the entire stream as if a single
number.  Ethernet sends the byte out least significant bit first.  The
entire table is also swapped ls to ms and actually reduces the operations
needed within the table calculations.  This reflects the method used for
Ethernet as it is being stored inverted and the initial value is started as
all ones.  The reason for the initial value being set to all ones is clear
for leading zero interaction, but I do not understand the value in storing
the CRC inverted.  I thought to include my ignorance to the mix.

Doug

---

From: Mark Bakke <[email-masked]>
Date: Fri, 17 Aug 2001 15:10:22 -0500

OK.  I don't see any reason for sending the CRC inverted either
(we would just have a different remainder poly), but since Ethernet
does it that way, and it doesn't cost anything, we might as well
do it, too.

--
Mark

-- 
Mark A. Bakke
Cisco Systems
[email-masked]
763.398.1054

---

From: "Douglas Otis" <[email-masked]>
Date: Fri, 17 Aug 2001 14:52:47 -0700

Mark,

You save a step in handling the table by doing it this way as well as
keeping the possibility of implementing a serial hardware implementation
without special handling.  Those seem to be good things and can easily
justify the reason for the reflected table.  Be aware the entire table is
reflected but that this only affects byte placement as bytes remain
reflected where the ms result is stored in the ls position as this position
is the first bit shipped.

As the initialization is set to ones, there is no danger of the remainder
being zero except in extremely rare cases.  This would seem to also negate
the advantage from doing an inversion before storing.  In addition, with the
initialization set to all ones, the result is also all ones and not zero.
To do a check, the inverted remainder needs to be un-inverted before entered
into the calculation.  This requires two additional instructions for little
benefit other than keeping with tradition.  It would seem if the
initialization is set to all ones, then the inverted store is not needed.
The check however can be made by just comparing results without a full
processing of the CRC.

Doug