以太网CRC32计算 - 软件与算法结果

时间:2012-02-15 01:16:15

标签: python algorithm ethernet crc32

我正在尝试逐字节计算以太网数据包的帧校验序列(FCS)。多项式为0x104C11DB7。 我确实遵循了此处http://en.wikipedia.org/wiki/Cyclic_redundancy_check或此处http://www.woodmann.com/fravia/crctut1.htm

所见的XOR-SHIFT算法

假设假定具有CRC的信息仅为一个字节。假设它是0x03。

  1. 步骤:向右填充32位

    0x0300000000

  2. 将多项式和左侧的数据与第一个非零和xor的位对齐

    0x300000000 xor 0x209823B6E = 0x109823b6e

  3. 将余数对齐并再次xor

    0x109823b6e xor 0x104C11DB7 = 0x0d4326d9

  4. 由于不再有位,0x03的CRC32应为0x0d4326d9

    不幸的是,所有的软件实现都告诉我我错了,但是我做错了什么或者他们做了什么不同?

    Python告诉我:

     "0x%08x" % binascii.crc32(chr(0x03))
     0x4b0bbe37
    

    此处的在线工具http://www.lammertbies.nl/comm/info/crc-calculation.html#intr获得相同的结果。 我的手计算与上述软件使用的算法有什么区别?

    更新

    原来在堆栈溢出上已经存在类似的问题:

    你在这里找到答案Python CRC-32 woes

    虽然这不是很直观。如果您想要更加正式地描述如何为以太网帧完成,您可以查看Ethernet Standard document 802.3第3部分 - 第3.2.9章帧校验序列字段

    让我们继续上面的例子:

    1. 反转邮件的位顺序。这代表了他们逐点进入接收器的方式。

      0x03因此是0xC0

    2. 补充邮件的前32位。请注意,我们再次使用32位填充单个字节。

      0xC000000000 xor 0xFFFFFFFF = 0x3FFFFFFF00

    3. 再次从上面完成Xor和shift方法。大约6步之后,你得到:

      0x13822f2d

    4. 然后补充上述位序列。

      0x13822f2d xor 0xFFFFFFFF = 0xec7dd0d2

    5. 请记住,我们颠倒了位顺序,以便在第一步中获得以太网线上的表示。现在我们必须扭转这一步,我们终于完成了我们的任务。

      0x4b0bbe37

    6. 无论是谁想出这样做,都应该......

      很多时候你真的想知道你收到的信息是正确的。为了达到这个目的,您可以收到包括FCS在内的收到的消息,并执行与上述相同的步骤1到5。结果应该是他们所谓的残留物。这是给定多项式的常数。在这种情况下,它是0xC704DD7B

      正如 mcdowella 提到的那样,你必须玩弄你的位,直到你做对了,这取决于你正在使用的应用程序。

4 个答案:

答案 0 :(得分:5)

此Python代码段为以太网写入正确的CRC:

# write payload
for byte in data:
    f.write('%02X\n' % ord(byte))
# write FCS
crc = zlib.crc32(data)&0xFFFFFFFF
for i in range(4):
    b = (crc >> (8*i)) & 0xFF
    f.write('%02X\n' % b)
如果我在这里找到这个,我本可以节省一些时间。

答案 1 :(得分:3)

通常需要一些试验和错误才能使CRC计算匹配,因为你永远不会完全阅读必须完成的工作。有时您必须对输入字节或多项式进行位反转,有时您必须从非零值开始,依此类推。

绕过这种情况的一种方法是查看正确的程序来源,例如http://sourceforge.net/projects/crcmod/files/(至少它声称匹配,并附带单元测试)。

另一个是玩实现。例如,如果我在http://www.lammertbies.nl/comm/info/crc-calculation.html#intr使用计算器,我可以看到给它00000000产生一个0x2144DF1C的CRC,但给它FFFFFFFF产生FFFFFFFF - 所以它不完全是你描述的多项式除法,其中0将有校验和0

从快速浏览源代码和这些结果我认为你需要从0xFFFFFFFF的CRC开始 - 但我可能是错的,你可能最终调试你的代码并执行,使用相应的printfs来找出第一个不同的地方,逐一修复差异。

答案 2 :(得分:3)

在互联网上有很多地方你会读到在计算FCS之前必须颠倒位顺序,但802.3规范不是其中之一。引用2008版规范:

3.2.9 Frame Check Sequence (FCS) field

A cyclic redundancy check (CRC) is used by the transmit and receive algorithms to
generate a CRC value for the FCS field. The FCS field contains a 4-octet (32-bit)
CRC value. This value is computed as a function of the contents of the protected
fields of the MAC frame: the Destination Address, Source Address, Length/ Type 
field, MAC Client Data, and Pad (that is, all fields except FCS). The encoding is
defined by the following generating polynomial.

  G(x) = x32 + x26 + x23 + x22 + x16 + x12 + x11 
             + x10 + x8 + x7 + x5 + x4 + x2 + x + 1

Mathematically, the CRC value corresponding to a given MAC frame is defined by 
the following procedure:

a) The first 32 bits of the frame are complemented.
b) The n bits of the protected fields are then considered to be the coefficients
   of a polynomial M(x) of degree n – 1. (The first bit of the Destination Address
   field corresponds to the x(n–1) term and the last bit of the MAC Client Data 
   field (or Pad field if present) corresponds to the x0 term.)
c) M(x) is multiplied by x32 and divided by G(x), producing a remainder R(x) of
   degree ≤ 31.
d) The coefficients of R(x) are considered to be a 32-bit sequence.
e) The bit sequence is complemented and the result is the CRC.

The 32 bits of the CRC value are placed in the FCS field so that the x31 term is
the left-most bit of the first octet, and the x0 term is the right most bit of the
last octet. (The bits of the CRC are thus transmitted in the order x31, x30,..., 
x1, x0.) See Hammond, et al. [B37].

当然,帧中的其余位以相反的顺序传输,但不包括FCS。再次,从规范:

3.3 Order of bit transmission

Each octet of the MAC frame, with the exception of the FCS, is transmitted least
significant bit first.

答案 3 :(得分:2)

http://en.wikipedia.org/wiki/Cyclic_redundancy_check

具有以太网的所有数据和丰富的重要细节,例如,(至少)2个约定将多项式编码为32位值,最大术语第一个或最小项首先。