2. 以太网 MAC 接收路径基本帧接收验证

任务说明

本案例搭建一个最小可运行的 MAC 接收路径验证环境:向 MAC 接收端注入一个合法以太网帧(含前导码、SFD、目的/源 MAC、类型、载荷、FCS),检查 MAC 是否正确剥离前导码与 SFD、校验 FCS,并把上层可见的帧(不含前导码/SFD/FCS)上报。验证通过条件:上报帧的字节序列与原始载荷一致,且 FCS 校验标志为通过。

帧结构与接收路径

注入字节流: [前导码 7B] [SFD 1B] [DST 6B] [SRC 6B] [TYPE 2B] [PAYLOAD N] [FCS 4B] 剥离前导码+SFD 解析 DST/SRC/TYPE 计算并校验 FCS 上报上层帧(无FCS) FCS 校验失败 → 丢弃并置 rx_error,不上报

环境与依赖

  • Python 3.8+,仅用标准库 zlib(CRC32 与以太网 FCS 多项式一致,可直接复用)。
  • 无需第三方库,单文件即可运行。

完整实现

import zlib

PREAMBLE = b"\x55" * 7
SFD = b"\xd5"

def build_frame(dst, src, eth_type, payload):
    """构造合法以太网帧:前导码+SFD+DST+SRC+TYPE+PAYLOAD+FCS"""
    body = dst + src + eth_type + payload
    fcs = zlib.crc32(body) & 0xFFFFFFFF
    return PREAMBLE + SFD + body + fcs.to_bytes(4, "little")

class MacRx:
    def __init__(self):
        self.rx_frames = []      # 上报上层的帧
        self.rx_error = 0        # FCS 错误计数

    def receive(self, raw):
        # 1. 剥离前导码与 SFD
        if not raw.startswith(PREAMBLE + SFD):
            self.rx_error += 1
            return None
        frame = raw[len(PREAMBLE) + len(SFD):]

        # 2. 分离 FCS 并校验
        if len(frame) < 4:
            self.rx_error += 1
            return None
        body, fcs_rx = frame[:-4], frame[-4:]
        fcs_calc = (zlib.crc32(body) & 0xFFFFFFFF).to_bytes(4, "little")
        if fcs_calc != fcs_rx:
            self.rx_error += 1
            return None

        # 3. 解析字段并上报上层(不含前导码/SFD/FCS)
        dst, src, eth_type = body[0:6], body[6:12], body[12:14]
        payload = body[14:]
        up = {"dst": dst, "src": src, "type": eth_type, "payload": payload}
        self.rx_frames.append(up)
        return up

# ---- 验证 ----
if __name__ == "__main__":
    dst = bytes.fromhex("001122334455")
    src = bytes.fromhex("66778899aabb")
    eth_type = bytes.fromhex("0800")
    payload = b"HELLO-MAC-RX"

    mac = MacRx()
    raw = build_frame(dst, src, eth_type, payload)
    up = mac.receive(raw)

    assert up is not None, "合法帧应被接收"
    assert up["payload"] == payload, "上报载荷应与原始载荷一致"
    assert up["dst"] == dst and up["src"] == src and up["type"] == eth_type
    assert mac.rx_error == 0

    # 破坏 FCS 的负向用例
    bad = bytearray(raw); bad[-1] ^= 0xFF
    assert mac.receive(bytes(bad)) is None
    assert mac.rx_error == 1

    print("PASS: 合法帧上报正确, FCS 错误被丢弃")

运行与验证

  1. 保存为 mac_rx.py,执行 python mac_rx.py。
  2. 观察输出:打印 PASS: 合法帧上报正确, FCS 错误被丢弃 即通过。
  3. 判定标准:合法帧的 payload 与注入一致、rx_error==0;篡改 FCS 后返回 None 且 rx_error==1。