第四阶段:转发引擎¶
硬件转发引擎的主要模块包括转发逻辑、转发表(路由表)以及邻居缓存。其中,邻居缓存和转发表已经设计完成,补充转发逻辑即可形成转发引擎。
路由查询和转发¶
转发引擎接收到 IP 分组后,需要先判断如何处理。对于目标 IP 地址为路由器自身或目标 IP 地址为 RIPng 组播地址等 IP 分组,转发引擎需要将其传递给 CPU 上的软件进行处理。特别地,若实验者实现了 ND 协议的硬件处理,那么 ND 报文可以不传递给 CPU。在实验者实现 CPU 及软件前,可暂时丢弃这些需要传递给 CPU 的 IP 分组,但需要为其预留好接口。对于其他 IP 分组,实验路由器需要进行转发,基本流程为:
- 根据目标 IP 地址查询转发表,获得下一跳接口(出接口)以及下一跳的 IP 地址;
- 特别地,若查询到直连路由,那么下一跳 IP 地址与目标 IP 地址相同。
- 检查 IP 分组头部 hop limit 是否过小(≤ 1);
- 若过小,丢弃该 IP 分组;
- 此外,还应当生成一个 ICMP 错误消息并发送给源 IP 地址,但本实验中可选。
- 将 hop limit 减少 1;
- 根据需要,如本实验采用以太网,还需要根据下一跳的 IP 地址查询邻居缓存,获得下一跳 MAC 地址;
- 更新以太网帧头部的目标 MAC 地址及 源 MAC 地址 ;
- 目标 MAC 地址更新为下一跳的 MAC 地址;
- 源 MAC 地址更新为实验路由器下一跳接口上配置的 MAC 地址。
- 设置出接口,向下一跳接口发送。
请注意,在转发 IP 分组时不需要修改其目标 IP 地址,工作在以太网之上的路由器是通过设置目标 MAC 地址来将 IP 分组转发至下一跳路由器或主机的,虽然它们在网络层(IP 层)使用下一跳 IP 地址来标识。进一步,根据分层原则,在转发 IP 分组时也不需要读取或修改 IP 分组的有效载荷部分,因为其是上层协议的数据。此外,为了实现简洁,本实验暂不考虑 MTU 问题。最后,为了提高转发引擎的性能,实验者需要尽量使得转发表查询和 IP 分组接收并行进行,如采用流水线的设计。
实现完成后,实验者可以使用实验框架提供的 testbench 对转发引擎进行仿真测试。实验者需要在仿真中仔细观察转发表和邻居缓存查询的结果,以及以太网帧更新后的内容(即发出的以太网帧),并分析各个字段是否正确,主要为出接口编号、以太网帧头部的目标 MAC 地址以及源 MAC 地址、IP 分组头部 hop limit 等字段。若实验者认为这些字段正确,可以进一步尝试借助硬编码的转发表(例如,仅包含有直连路由的转发表),搭建一个测试网络,用两台主机互相 ping,同时抓包查看具体情况。此时,实验者可以利用 ILA 查看转发引擎中间每一步的情况,方便调试。另外,建议实验者使用 Linux 系统进行测试,因为它可以关闭许多不相关的流量,同样能够方便调试。
思考
- 如果在转发表中没有查到下一跳信息,应如何处理?
- 如果在邻居缓存中没有查到对应的 MAC 地址,应如何处理?
- 实验者可能会选择在问题 2 中丢弃没有查到 MAC 地址的 IP 分组,而发送一个组播 Neighbor Solicitation。本实验允许这样实现,但这样可能导致什么问题?
转发引擎的功能测试和性能测试¶
在上一节 ping 测试通过的基础上,实验者还需要进一步测试转发引擎的功能正确性和性能。
功能正确性测试主要包括如下几点:
- IP 分组头部的各种情况都能正确计算,可以通过减少 ping 的间隔(
ping -f <IP 地址>
)来测试; - 各种大小的 IP 分组均可以正常转发,可以通过 ping 指定分组大小或者用 iperf3 测速来测试。
- 用 iperf3 测试时,需要在一台主机 A 上运行
iperf3 -s
开启 iperf3 服务器,然后在另一台主机 B 上运行iperf3 -c <服务器 IP 地址>
来测试主机 B 向主机 A 通过 TCP 传输数据的速率。在主机 B 上运行iperf3 -c <服务器 IP 地址> -R
可以测试主机 A 到主机 B 的速率,其中-R
代表反向。这样,实验者就可以测试出主机 A 和主机 B 之间,通过路由器后,两个方向分别的速率(单工速率)。进一步,实验者还可以在主机 A 上开启两个服务器(另一个服务器需要添加-p <不同的端口号>
来指定一个不同的端口号,防止端口冲突)。同时,实验者需要在主机 B 同时开启两个客户端,一个使用本节开头的参数(-c <服务器 IP 地址>
);另一个使用-c <服务器 IP 地址> -R -p <上述端口号>
,连接主机 A 的另一个服务器,并同时测试相反方向传输数据的速率。这样,实验者就可以测试出主机 A 和主机 B 之间,通过路由器后,两个方向同时传输数据时,两个方向分别的速率(其总和为双工速率)。
- 用 iperf3 测试时,需要在一台主机 A 上运行
转发引擎的性能测试主要分为吞吐量测试以及小包转发速率测试。对于吞吐量测试,实验者可以按上述方法通过 iperf3 进行测速,并查看速率。对于小包转发速率测试,由于普通计算机难以按千兆线速的速率(如下文所述)发送小包,此处建议实验者进行仿真测试。关于 iperf3 的使用方法,还可以参考 How to use iperf, a complete tutorial。
对于吞吐量,iperf3 显示的速率为 TCP 分段中传输的有效载荷的速率。考虑到基于以太网的 IP 协议的开销(每个以太网帧的 8 字节前导码、14 字节头部、4 字节校验码、12 字节的帧间隙,以及每个 IP 分组的 40 字节头部)、TCP 协议自身开销(TCP 分段的 20 字节头部)以及以太网的 MTU 为 1500,每个最大的以太网帧在线路上占用 1538 个字节(8 + 14 + 1500 + 4 + 12)的时间,其中 TCP 分段的有效载荷为 1440 个字节(1500 - 40 - 20)。因此,对于千兆以太网,其上的 TCP 协议传输有效载荷的速率不会超过 1440 ÷ 1538 × 1000Mbps ≈ 936.28Mbps。实践中,由于其他一些额外开销,测试结果一般在 930Mbps 附近。对于带宽效率的更多讨论,请参阅:https://en.wikipedia.org/wiki/Jumbo_frame#Bandwidth_efficiency
对于小包转发速率,考虑到以太网帧最短帧长为 64 字节(包含头部、有效载荷以及校验码),以及 20 个字节的前导码和帧间隙,在千兆以太网上,每秒能够发送的以太网帧数量最多为 1000Mb ÷ (64 + 20) ÷ 8b ≈ 1.488M。若这些以太网帧均承载 IP 分组,那么这一数值为小包转发速率的上限(即线速)。
最后,当实验路由器四个接口同时进行收发时,吞吐量以及小包转发速率应分别达到 3.745Gbps(或 3.720Gbps)、5.952Mpps。
此外,测试时如果出现速度突然降到零并且后续 ping 测试失败的情况,一般说明转发引擎部分逻辑不够鲁棒。此时,实验者可以通过 ILA 查看转发引擎内部状态,找到出问题的部分;实验者也可以在 testbench 中增加以太网帧发送速率,模拟性能测试,然后寻找问题。
思考
- PHY/MAC 提供的 AXI-Stream 的接收端没有
ready
信号,意味着发送方需要时刻准备好接收数据。请检查实验框架,了解如何实现缓冲区。 - 有时会发生冲突而不得不丢包。请检查实验框架,了解 AXI-Stream 如何完整地丢弃一个以太网帧。