以太网 CRC32 计算 - 软件与算法结果
Posted
技术标签:
【中文标题】以太网 CRC32 计算 - 软件与算法结果【英文标题】:Ethernet CRC32 calculation - software vs algorithmic result 【发布时间】:2012-03-06 09:30:26 【问题描述】:我正在尝试逐字节计算以太网数据包的帧校验序列 (FCS)。多项式是0x104C11DB7
。
我确实遵循了这里看到的 XOR-SHIFT 算法 http://en.wikipedia.org/wiki/Cyclic_redundancy_check 或这里 http://www.woodmann.com/fravia/crctut1.htm
假设应该有 CRC 的信息只有一个字节。假设它是 0x03。
步骤:向右填充 32 位
0x0300000000
将左侧的多项式和数据与其第一个不为零的位对齐并异或
0x300000000 xor 0x209823B6E = 0x109823b6e
进行余数对齐并再次异或
0x109823b6e xor 0x104C11DB7 = 0x0d4326d9
由于没有剩余位,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 章帧检查序列字段
让我们继续上面的例子:
反转消息的位顺序。这代表了它们将一点一点地进入接收器的方式。
0x03
因此是0xC0
补充消息的前 32 位。请注意,我们再次用 32 位填充单个字节。
0xC000000000 xor 0xFFFFFFFF = 0x3FFFFFFF00
再次完成上面的 Xor 和 shift 方法。大约 6 步后,您会得到:
0x13822f2d
然后对上述位序列进行补码。
0x13822f2d xor 0xFFFFFFFF = 0xec7dd0d2
请记住,我们在第一步中颠倒了位顺序以获得以太网线上的表示。现在我们必须扭转这一步,我们终于完成了我们的任务。
0x4b0bbe37
想出这种方法的人应该是……
很多时候你真的想知道你收到的信息是正确的。为了实现这一点,您将收到包含 FCS 的消息并执行与上述相同的步骤 1 到 5。结果应该是他们所说的残留物。这是给定多项式的常数。在这种情况下,它是0xC704DD7B
。
正如 mcdowella 所提到的,您必须根据您所使用的应用程序来调整自己的位,直到正确为止。
【问题讨论】:
0x209823B6E从何而来? 您是否也将初始余数设置为 0xFFFFFFFF 0x209823B6E 是多项式的移位版本,以使其与数据对齐 @sebs,如何转移? @cp.engr 左移一位。(0x104C11DB7 << 1)
【参考方案1】:
这个 sn-p 为以太网写入正确的 CRC。
Python 3
# write payload
for byte in data:
f.write(f'byte:02X\n')
# write FCS
crc = zlib.crc32(data) & 0xFFFF_FFFF
for i in range(4):
byte = (crc >> (8*i)) & 0xFF
f.write(f'byte:02X\n')
Python 2
# write payload
for byte in data:
f.write('%02X\n' % ord(byte))
# write FCS
crc = zlib.crc32(data) & 0xFFFFFFFF
for i in range(4):
byte = (crc >> (8*i)) & 0xFF
f.write('%02X\n' % byte)
如果我在这里找到这个会节省我一些时间。
【讨论】:
这为我节省了数小时的冲突。谢谢,谢谢。【参考方案2】:在 Internet 上的许多地方,您会读到在计算 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.
【讨论】:
这只是暗示“第一位”和“最后一位”指的是传输顺序——他们不说“最高有效位”或“最低有效位”那个原因:) 该标准描述了CRC32 BZIP2,这是一个左移CRC,然后先传输数据lsb,但先传输FCS msb(第31位)。另一种方法是使用右移 CRC32,这会导致 CRC 是 FCS 的位反转,之后数据和 CRC 都可以先发送最低有效位,从而导致相同的传输。该标准还提到接收器应将其计算的 FCS 与接收的 FCS 进行比较,但另一种方法是在数据 + FCS 上生成 CRC,从而产生一个固定的非零值,具体取决于实现。【参考方案3】:http://en.wikipedia.org/wiki/Cyclic_redundancy_check
拥有以太网的所有数据和大量重要细节,例如(至少)有 2 个约定将多项式编码为 32 位值,最大项在前或最小项在前。
【讨论】:
【参考方案4】:通常需要进行一些试验和错误才能使 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找出第一个不同的地方,并逐个修复差异。
【讨论】:
以上是关于以太网 CRC32 计算 - 软件与算法结果的主要内容,如果未能解决你的问题,请参考以下文章