第四章:链路层测试——MAC地址学习与老化、VLAN转发规则验证、流控(PFC/802.3x)测试
链路层测试,说白了就是验证你的芯片能不能像个合格的“交通警察”一样,管好数据帧的进出。MAC地址学习、VLAN隔离、流控机制,这三板斧砍下来,基本能看出芯片的底子硬不硬。
我个人习惯把链路层测试分成三个维度:转发正确性、表项管理、拥塞控制。咱们一个一个来聊。
4.1 MAC地址学习与老化测试
MAC地址学习,是交换芯片最基础的功能。你想想看,芯片得知道哪个MAC在哪个端口上,才能把数据帧准确送过去。这个机制要是出问题,整个网络就乱套了。
4.1.1 学习功能验证
测试思路很简单:从端口A发一个源MAC为M1的帧,然后查芯片的MAC表,看M1是不是关联到了端口A。
我在项目中遇到过一个问题:芯片学习到了MAC,但老化时间不对。默认300秒,结果60秒就清掉了。后来发现是硬件定时器的分频系数配错了。
核心测试用例:
- 基础学习:从不同端口发送不同源MAC,验证表项正确性
- MAC迁移:同一个MAC从不同端口出现,验证表项更新
- 广播抑制:大量MAC同时学习,验证表项容量和性能
// 测试脚本伪代码
send_frame(port=0, src_mac="00:11:22:33:44:01", dst_mac="ff:ff:ff:ff:ff:ff")
sleep(100ms)
mac_entry = read_mac_table("00:11:22:33:44:01")
assert(mac_entry.port == 0, "MAC学习失败")
// 测试MAC迁移
send_frame(port=1, src_mac="00:11:22:33:44:01", dst_mac="ff:ff:ff:ff:ff:ff")
sleep(100ms)
mac_entry = read_mac_table("00:11:22:33:44:01")
assert(mac_entry.port == 1, "MAC迁移失败")
4.1.2 老化机制验证
老化测试,说白了就是看芯片能不能按时把“过时”的表项清掉。嗯,这里要注意:老化时间不能太短,否则频繁刷新浪费资源;也不能太长,否则表项占着茅坑不拉屎。
我的经验: 老化测试最好用自动化脚本跑,设置不同的老化时间(比如60s、120s、300s),然后发帧、等待、再发帧,看表项是否按预期老化。我曾经踩过一个坑:芯片在老化过程中,如果同时有新的MAC学习请求,会触发死锁。后来加了超时保护才解决。
| 测试项 | 预期结果 | 实际结果 |
|---|---|---|
| 老化时间=60s,60s内无流量 | 表项清除 | 通过 |
| 老化时间=60s,30s时有流量 | 表项保留,老化计时器重置 | 通过 |
| 老化时间=0(禁用老化) | 表项永久保留 | 通过 |
4.2 VLAN转发规则验证
VLAN测试,核心就一句话:同一个VLAN内的帧能互通,不同VLAN的帧不能互通。但实际测试中,细节多得很。
4.2.1 基于端口的VLAN
这是最基础的VLAN模式。把端口划分到不同VLAN,然后验证隔离性。
我记得有一次测试,端口配置了VLAN 10,但帧就是转发不过去。查了半天,发现是端口的PVID没配。你想想看,芯片收到不带VLAN标签的帧,得知道它属于哪个VLAN,PVID就是干这个的。
常见坑点:
- PVID和允许通过的VLAN列表要同时配置
- Trunk端口要配置Tagged模式,Access端口配Untagged模式
- VLAN 1是默认VLAN,很多芯片会特殊处理
4.2.2 基于802.1Q的VLAN
带标签的VLAN测试,要验证Tag的添加、删除、替换逻辑。我建议用抓包工具同时看入口和出口的报文,对比Tag字段的变化。
// VLAN转发测试用例
// 测试1:同VLAN内互通
configure_port(port0, pvid=10, allowed_vlans=[10])
configure_port(port1, pvid=10, allowed_vlans=[10])
send_frame(port0, vlan_tag=None) // 不带Tag
// 预期:port1收到帧,且带VLAN 10的Tag
// 测试2:不同VLAN隔离
configure_port(port0, pvid=10, allowed_vlans=[10])
configure_port(port1, pvid=20, allowed_vlans=[20])
send_frame(port0, vlan_tag=None)
// 预期:port1不会收到帧
// 测试3:Trunk端口转发
configure_port(port0, mode="trunk", allowed_vlans=[10, 20])
send_frame(port0, vlan_tag=10)
// 预期:只有属于VLAN 10的端口能收到
4.3 流控测试(PFC / 802.3x)
流控测试,是验证芯片在拥塞时能不能“踩刹车”。802.3x是全局流控,PFC是优先级流控。我个人觉得PFC更实用,也更难测。
4.3.1 802.3x 全局流控
802.3x通过PAUSE帧实现。当接收端缓存快满时,发送PAUSE帧给发送端,让对方暂停发送。
测试方法:构造一个拥塞场景,比如让多个端口往同一个端口发数据,然后看芯片是否发出了PAUSE帧。
测试步骤:
- 配置端口A为接收端,端口B、C为发送端
- 端口B、C以线速向端口A发送数据
- 监控端口A的出口,看是否发出PAUSE帧
- 验证PAUSE帧的MAC地址(目的MAC为01:80:C2:00:00:01)
4.3.2 PFC 优先级流控
PFC(Priority Flow Control)是802.1Qbb标准,它把流量分成8个优先级,每个优先级独立流控。这在RoCEv2网络中特别重要。
我曾经在测试PFC时遇到一个诡异问题:高优先级流量把低优先级流量饿死了。后来发现是PFC的阈值配置不合理,高优先级占用了太多缓存。
PFC测试要点:
- 验证每个优先级独立流控,互不影响
- 测试PFC死锁场景:两个端口互相发送PFC帧
- 验证PFC帧的格式:Opcode、Time参数是否正确
- 测试PFC恢复:拥塞解除后,流量是否恢复正常
// PFC测试伪代码
// 配置端口A的优先级3开启PFC
configure_pfc(port=0, priority=3, enable=True)
// 构造拥塞:端口B以线速向端口A发送优先级3的流量
start_traffic(src_port=1, dst_port=0, priority=3, rate="line_rate")
// 等待PFC触发
sleep(500ms)
pfc_frame = capture_pfc_frame(port=0)
assert(pfc_frame.priority == 3, "PFC优先级错误")
assert(pfc_frame.time > 0, "PFC Time参数为0")
// 停止流量,验证恢复
stop_traffic()
sleep(200ms)
assert(no_pfc_frame_captured(), "PFC未正常恢复")
4.4 本章小结
链路层测试,说白了就是验证芯片的“记忆力”和“规则意识”。MAC地址学习看芯片记不记得住,VLAN转发看芯片守不守规矩,流控测试看芯片懂不懂刹车。
我建议你在测试时,多关注边界条件:表项满了怎么办?老化时间到了但还有流量怎么办?PFC帧丢了怎么办?这些才是真正考验芯片设计的地方。
核心要点回顾:
- MAC学习:验证学习、迁移、老化三个核心机制
- VLAN转发:验证隔离性、Tag处理、PVID配置
- 流控测试:802.3x全局流控 + PFC优先级流控
- 边界条件:表项满、老化冲突、PFC死锁