1

我看到了一些实现,但我决定看看规范是如何调用 FCS 进行编码的。

所以说我的输入如下:

dst: 0xAA AA AA AA AA AA
src: 0x55 55 55 55 55 55
len: 0x00 04
msg: 0xDE AD BE EF

以似乎在格式中指定的顺序(以及稍后在规范中表达的顺序)连接它似乎表明我的输入是:

M(x) = 0xAA AA AA AA AA AA 55 55 55 55 55 55 00 04 DE AD BE EF

a) “帧的前 32 位被补码。”

complemented first 32 MSB of M(x): 0x55 55 55 55 AA AA 55 55 55 55 55 55 00 04 DE AD BE EF

b) “然后,受保护字段的 n 位被认为是 n – 1 次多项式 M(x) 的系数。(目标地址字段的第一位对应于 x(n–1) 项和MAC 客户端数据字段(或填充字段,如果存在)的最后一位对应于 x0 项。)"

我以前做过这个。见 M(x)

c) “M(x) 乘以 x^32 并除以 G(x),产生度数 <=31 的余数 R(x)。”

网上的一些选项似乎忽略了第 33 位来表示 x^32。我将忽略本练习的那些简化快捷方式,因为它似乎没有在规范中指定。它说将 M(x) 乘以 x^32。所以这只是在 LSB 上填充 32 个零。(即如果m(x) = 1x^3 + 1,那么m(x) * x^2 = 1x^5 + 1x^2 + 0

padded: 0x55 55 55 55 AA AA 55 55 55 55 55 55 00 04 DE AD BE EF 00 00 00 00

下一步是划分。我正在划分整个 M(x) / G(x)。可以直接使用异或移位吗?我看到一些二进制除法示例的除数为 101,除数为 110,余数为 11。其他示例说明通过转换为十进制,您不能除法。该标准的术语是哪一个?

我的余数结果是选项 1(使用 XOR 而不考虑进位、移位、无填充)是:

0x15 30 B0 FE

d) “R(x) 的系数被认为是一个 32 位序列。”

e) “位序列被补码,结果是CRC。”

CRC = 0xEA CF 4F 01

所以我的整个以太网帧应该是:

0xAA AA AA AA AA AA 55 55 55 55 55 55 00 04 DE AD BE EF EA CF 4F 01

其中我的 dst 地址是它的原始值。

当我使用在线 CRC32 BZIP2 计算器检查我的工作时,我看到了以下结果:0xCACF4F01

是否有其他选项或在线工具来计算以太网 FCS 字段?(不仅仅是众多 CRC32 计算器之一)

我错过了哪些步骤?我应该填充 M(x) 吗?我应该补充 32 个 LSB 吗?

更新

我的软件中的 CRC 输出出现错误。复制矢量是一个小问题。我对 CRC 的最新结果是(补码前)35 30 B0 FE

后补是:(CA CF 4F 01匹配大多数在线 CRC32 BZIP2 版本)。

所以根据我的编程,我的以太网目前是:

0xAA AA AA AA AA AA 55 55 55 55 55 55 00 04 DE AD BE EF CA CF 4F 01
4

2 回答 2

2

您需要的 CRC 通常在 zlib 和其他库中作为标准 PKZip CRC-32 提供。它以小端顺序存储在消息中。所以你的 CRC 框架将是:

AA AA AA AA AA AA 55 55 55 55 55 55 00 04 DE AD BE EF B0 5C 5D 85

这是一个在线计算器,其中列出的第一个结果是通常的 CRC-320x855D5CB0.

下面是 C 中用于计算 CRC 的简单示例代码(使用NULLfor调用mem会给出初始 CRC):

unsigned long crc32iso_hdlc(unsigned long crc, void const *mem, size_t len) {
    unsigned char const *data = mem;
    if (data == NULL)
        return 0;
    crc ^= 0xffffffff;
    while (len--) {
        crc ^= *data++;
        for (unsigned k = 0; k < 8; k++)
            crc = crc & 1 ? (crc >> 1) ^ 0xedb88320 : crc >> 1;
    }
    return crc ^ 0xffffffff;
}

反映0xedb88320常数。0x04c11db7

库中使用的实际代码更复杂、速度更快。

这是相同 CRC(在 Mathematica 中)的计算,使用 IEEE 802.3 文档中描述的多项式方法,因此您可以看到用于余数计算的x的正确结果幂:

显示 x 的幂

如果您单击图像,它将更容易阅读权力。

于 2020-12-02T05:53:43.987 回答
0

这里令人困惑的因素是 802.3 规范。它提到第一位是 LSB(最低有效位 == 位 0)仅在一个地方,在第 3.2.3-b 节中,它提到对于 CRC,“目标地址字段的第一位对应于 x^ (n-1) term",因此输入到 CRC 计算的每个字节都是位反映的。

使用这个在线计算器:

http://www.sunshine2k.de/coding/javascript/crc/crc_js.html

选择 CRC-32 | CRC32,点击自定义,输入反映,结果反映关闭。有了这些数据:

AA AA AA AA AA AA 55 55 55 55 55 55 00 04 DE AD BE EF

根据规范,计算出的 CRC 为 0x0D3ABAA1,存储和传输如下所示:

bit 0 first                                           | bit 7 first
AA AA AA AA AA AA 55 55 55 55 55 55 00 04 DE AD BE EF | 0D 3A BA A1

为了简化输出以始终首先传输位 0,位反映 CRC 字节:

bit 0 first                                           | bit 0 first
AA AA AA AA AA AA 55 55 55 55 55 55 00 04 DE AD BE EF | B0 5C 5D 85

请注意,位 0 始终是第一个方法导致传输的位与规范相同。

更改 CRC 计算器的结果设置,输入反映,结果反映。有了这些数据:

AA AA AA AA AA AA 55 55 55 55 55 55 00 04 DE AD BE EF

计算出的 CRC 为 0x855D5CB0,首先存储最低有效字节并发送,如下所示:

bit 0 first                                           | bit 0 first
AA AA AA AA AA AA 55 55 55 55 55 55 00 04 DE AD BE EF | B0 5C 5D 85

为了验证接收到的数据,而不是比较接收到的数据的计算 CRC 与接收到的 CRC,该过程可以计算接收到的数据和 CRC 的 CRC。假设替代设置首先接收所有字节位 0,然后接收此接收帧或任何帧而没有错误

bit 0 first                                           | bit 0 first
AA AA AA AA AA AA 55 55 55 55 55 55 00 04 DE AD BE EF | B0 5C 5D 85

计算出的 CRC 将始终为 0x2144DF1C。在硬件实现的情况下,CRC 的后补通常在位移出时一次一位地执行,在用于计算 CRC 的逻辑之外,在这种情况下,在接收到无错误的帧之后, CRC 寄存器将始终包含 0xDEBB20E3 (0x2144DF1C ^ 0xFFFFFFFF)。因此,验证是通过在接收到的帧上计算 CRC 并将 CRC 与 32 位常数(0x2144DF1C 或 0xDEBB20E3)进行比较来完成的。

于 2020-12-02T12:26:47.877 回答