1. 以太网 MAC 发送路径基本帧传输验证
任务目标
搭建一个最小可运行的 MAC 发送路径验证环境:构造一个最小以太网帧(目的 MAC + 源 MAC + 类型 + 载荷),驱动 MAC 发送逻辑,检查输出到 PHY 接口的字节流是否正确包含前导码(7×0x55)、SFD(0xD5)、原始帧内容以及追加在末尾的 FCS(CRC-32)。
环境与依赖
- Python 3.8+,仅使用标准库
zlib(提供 CRC-32,与以太网 FCS 使用同一多项式,仅需按以太网规则取反并小端输出)。 - 无需第三方库,无需硬件;本案例用软件模型模拟 MAC 发送路径,便于在无 PHY 的情况下验证字节级行为。
实现思路
MAC 发送路径按顺序完成四件事:拼接前导码与 SFD、输出帧内容、计算并追加 FCS、把结果交给 PHY 接口。FCS 计算使用 CRC-32,初值 0xFFFFFFFF,结果按位取反后以小端序追加 4 字节。下面代码把发送路径封装为 mac_send,并用一个断言检查输出结构。
关键完整代码
import zlib
PREAMBLE = b"\x55" * 7
SFD = b"\xd5"
def crc32_fcs(frame: bytes) -> bytes:
# 以太网 FCS:CRC-32 取反后小端输出
crc = zlib.crc32(frame) & 0xFFFFFFFF
crc ^= 0xFFFFFFFF
return crc.to_bytes(4, "little")
def mac_send(dst: bytes, src: bytes, ethertype: bytes, payload: bytes) -> bytes:
assert len(dst) == 6 and len(src) == 6 and len(ethertype) == 2
frame = dst + src + ethertype + payload
fcs = crc32_fcs(frame)
phy_bytes = PREAMBLE + SFD + frame + fcs
return phy_bytes
def verify(phy_bytes: bytes, frame: bytes) -> None:
assert phy_bytes[:7] == PREAMBLE, "前导码错误"
assert phy_bytes[7:8] == SFD, "SFD 错误"
assert phy_bytes[8:8 + len(frame)] == frame, "帧内容错误"
fcs = phy_bytes[8 + len(frame):]
assert fcs == crc32_fcs(frame), "FCS 错误"
print("PASS: 前导码/SFD/帧/FCS 均正确")
if __name__ == "__main__":
dst = bytes.fromhex("001122334455")
src = bytes.fromhex("aabbccddeeff")
ethertype = bytes.fromhex("0800")
payload = b"hello-mac"
frame = dst + src + ethertype + payload
phy = mac_send(dst, src, ethertype, payload)
print("PHY 输出:", phy.hex())
verify(phy, frame)
运行与验证
- 保存为
mac_send.py,执行python mac_send.py。 - 观察输出:应打印一行十六进制 PHY 字节流,并以
PASS: 前导码/SFD/帧/FCS 均正确结束。 - 通过条件:脚本无 AssertionError;PHY 字节流前 7 字节为
55,第 8 字节为d5,随后是 6+6+2+9=23 字节帧内容,最后 4 字节为 FCS。
预期输出(由代码逻辑唯一确定)
PHY 输出: 55555555555555d5001122334455aabbccddeeff080068656c6c6f2d6d6163<4字节FCS>
PASS: 前导码/SFD/帧/FCS 均正确
其中 <4字节FCS> 由 crc32_fcs 对帧内容计算得到,运行脚本即可看到具体值。