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

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

问题描述:

我试图计算逐个字节的以太网数据包的帧校验序列(FCS)。多项式为0x104C11DB7。 我也跟着在这里看到http://en.wikipedia.org/wiki/Cyclic_redundancy_check或这里http://www.woodmann.com/fravia/crctut1.htm以太网CRC32计算 - 软件vs算法结果

的XOR-SHIFT算法假设应该有一个CRC只有一个字节的信息。假设它是0x03。

  1. 步骤:垫32位到右侧

    0x0300000000

  2. 对齐多项式,并在与它们的第一比特的左手侧是不为零的数据和XOR它们

    0x300000000 xor 0x209823B6E = 0x109823b6e

  3. 带余数对齐再次异或

    0x109823b6e xor 0x104C11DB7 = 0x0d4326d9

由于没有更多的位左的×03的CRC32应该是0x0d4326d9

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

Python的告诉我:

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

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

UPDATE:

原来有一个类似的问题已经在堆栈溢出:

您发现这里Python CRC-32 woes

答案虽然这不是很直观。如果你想它是如何对以太网进行更正式的描述帧,你可以看看Ethernet Standard document 802.3 3部分 - 第二章3.2.9帧校验序列字段

让我们继续从上面的例子:

  1. 颠倒你消息的位顺序。这代表他们会逐渐进入接收器的方式。因此

    0x030xC0

  2. 补充第一32位的消息的。注意我们再次用32位填充单个字节。

    0xC000000000 xor 0xFFFFFFFF = 0x3FFFFFFF00

  3. 从上面再次完成XOR和移方法。经过约6步你:然后

    0x13822f2d

  4. 以上位sequense的补充。

    0x13822f2d xor 0xFFFFFFFF = 0xec7dd0d2

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

    0x4b0bbe37

谁用做它应该是这样过来......

很多时候,你真正想知道您收到的消息是正确的。为了达到此目的,您需要收到您收到的包含FCS的消息,并执行与上述相同的步骤1至5。结果应该是他们所说的残渣。对于给定的多项式,这是一个常数。在这种情况下,它是0xC704DD7B

作为mcdowella提到你必须玩弄你的一些东西,直到你找到正确的,取决于你使用的应用程序。

+1

0x209823B6E从哪里来? – grieve 2012-02-15 05:31:26

+0

您是否还将初始余数设置为0xFFFFFFFF – grieve 2012-02-15 05:48:41

+0

0x209823B6E是多项式的移位版本,以便将其与数据 – sebs 2012-02-15 20:56:14

通常需要一些试验和错误才能使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来查找第一个不同的地方,并逐个修正差异。

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

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

在互联网上有很多地方你会读到在计算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. 
+0

“第一位”和“最后一位”是指传输顺序 - 由于这个原因,它们*不会说“最重要的位”或“最不重要的位”)。 – hobbs 2015-03-06 17:37:08

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

会救我一些时间,如果我发现这个在这里。