2. 以太网 MAC 接收路径基本帧接收验证
任务说明
本案例搭建一个最小可运行的 MAC 接收路径验证环境:向 MAC 接收端注入一个合法以太网帧(含前导码、SFD、目的/源 MAC、类型、载荷、FCS),检查 MAC 是否正确剥离前导码与 SFD、校验 FCS,并把上层可见的帧(不含前导码/SFD/FCS)上报。验证通过条件:上报帧的字节序列与原始载荷一致,且 FCS 校验标志为通过。
帧结构与接收路径
环境与依赖
- 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 错误被丢弃")
运行与验证
- 保存为
mac_rx.py,执行python mac_rx.py。 - 观察输出:打印
PASS: 合法帧上报正确, FCS 错误被丢弃即通过。 - 判定标准:合法帧的
payload与注入一致、rx_error==0;篡改 FCS 后返回None且rx_error==1。