跳转至

第三部分:转发引擎设计

硬件转发引擎的主要模块包括转发逻辑、转发表(路由表)以及 ARP 缓存。同时,本实验 建议 ARP 协议的处理也采用硬件实现,原因如后文所述。

ARP 报文接收

与 Loopback 不同,在本节中,实验者需要对收到的以太网帧进行解析,判断其 EtherType。如果该帧是一个 ARP 报文,则实验者需要提取出发送者的 MAC 地址以及 IP 地址,然后更新或插入到 ARP 缓存中。此处的更新是指,当 ARP 缓存中存在对应 IP 地址的条目时,更新其 MAC 地址,当不存在时,不进行其他操作;插入是指,当 ARP 缓存中存在对应 IP 地址的条目时,更新其 MAC 地址,当不存在时,插入该 IP 地址和 MAC 地址的对应关系。当处理完成后,实验者即可将此 ARP 报文丢弃。实现完成后,实验者可以通过仿真来进行测试,然后使用 ILA 在实验板上进行观察。

实验者可以在与实验路由器相连的主机上使用 arping 命令来不断发送 ARP 请求,以便调试。除 ILA 外,实验者也可以尝试把信号接到 LED 上进行观察。请注意,如果信号变化的频率过快,会导致 LED 闪烁过快,人眼是难以观察的。

ARP 协议的更多细节请参见 RFC 826: An Ethernet Address Resolution Protocol,实验者可以重点关注 Packet Generation 以及 Packet Reception 两节。

思考

  1. 以太网帧的 EtherType 在哪个位置?ARP 协议对应的 EtherType 是多少?
  2. 操作系统一般会在什么情况下发送 ARP 报文到路由器?
  3. 如何向操作系统添加一条指向实验路由器的路由表项?
  4. 何时 更新 ARP 缓存表项?何时 插入 ARP 缓存表项?

ARP 回复发送

事实上,本实验中,实验者可以把 ARP 回复实现在硬件中,也可以实现在软件中。本实验建议 ARP 回复采用硬件实现,其优点为方便调试,不需要等到 CPU 及软件实现完毕后再进行调试;但是,如果软件需要访问 ARP 缓存,则需要额外的工作。

如果实验者选择由硬件实现 ARP 回复,则首先需要对 ARP 请求进行判断。若 ARP 请求的目标 IP 地址为当前实验路由器对应接口上的 IP 地址,则实验路由器需要构造一个 ARP 回复并发送至相同接口。其中,实验路由器四个接口的四个 IP 地址和四个 MAC 地址可以由实验者自行配置,但需要在能够用于自由分配的地址段中选取。特别地,请实验者注意这四个 IP 地址应当在不同的子网,同时不要将 MAC 地址错误地配置为组播地址。

如果实现正确,实验者就可以通过 arping 得到稳定的低延迟的回复了。

思考

  1. 什么样的 ARP 报文不需要回复?
  2. 在构造 ARP 回复报文时,以太网帧头部以及 ARP 报文的各个字段(如源 MAC 地址等)应当如何填写?

路由查询和转发

转发引擎接收到 IP 分组后,需要先判断如何处理。对于目标 IP 地址为路由器自身或目标 IP 地址为 RIP 组播地址等 IP 分组,转发引擎需要将其传递给 CPU 上的软件进行处理。在实验者实现 CPU 及软件前,可暂时丢弃这些 IP 分组,但需要为其预留好接口。对于其他 IP 分组,实验路由器需要进行转发,基本流程为:

  • 验证 IP 分组头部校验和;
    • 若验证失败,静默丢弃该 IP 分组;
    • 为简洁,本实验中可选。
  • 根据目标 IP 地址查询转发表,获得下一跳接口(出接口)以及下一跳的 IP 地址;
    • 特别地,若查询到直连路由,那么下一跳 IP 地址与目标 IP 地址相同。
  • 检查 IP 分组头部 TTL 是否过小(<= 1);
    • 若过小,丢弃该 IP 分组;
    • 此外,还应当生成一个 ICMP 错误消息并发送给源 IP 地址,但本实验中可选。
  • 将 TTL 减少 1,并增量更新校验和;
  • 根据需要,如本实验采用以太网,还需要根据下一跳的 IP 地址查询 ARP 缓存,获得下一跳 MAC 地址;
  • 更新以太网帧头部的目标 MAC 地址及 源 MAC 地址
    • 目标 MAC 地址更新为下一跳的 MAC 地址;
    • 源 MAC 地址更新为实验路由器下一跳接口上配置的 MAC 地址。
  • 设置出接口,向下一跳接口发送。

请注意,在转发 IP 分组时不需要修改其目标 IP 地址,工作在以太网之上的路由器是通过设置目标 MAC 地址来将 IP 分组转发至下一跳路由器或主机的,虽然它们在网络层(IP 层)使用下一跳 IP 地址来标识。此外,为了实现简洁,本实验暂不考虑 MTU 问题以及 IP 分组分片。同时,对于头部含选项(IHL ≠ 5)的 IP 分组,转发引擎可暂时将其丢弃。最后,为了提高转发引擎的性能,实验者需要尽量使得转发表查询和 IP 分组接收并行进行,如采用流水线的设计。

实现完成后,实验者可以使用实验框架提供的 testbench 对转发引擎进行仿真测试。实验者需要在仿真中仔细观察转发表和 ARP 缓存查询的结果,以及以太网帧更新后的内容(即发出的以太网帧),并分析各个字段是否正确,主要为出接口编号、以太网帧头部的目标 MAC 地址以及源 MAC 地址、IP 分组头部 TTL 以及校验和等字段。若实验者认为这些字段正确,可以进一步尝试借助硬编码的转发表,搭建一个测试网络,用两台主机互相 ping,同时抓包查看具体情况。此时,实验者可以利用 ILA 查看转发引擎中间每一步的情况,方便调试。另外,建议实验者使用 Linux 系统进行测试,因为它可以关闭许多不相关的流量,同样能够方便调试。

思考

  1. 如果在转发表中没有查到下一跳信息,应如何处理?
  2. 如果在 ARP 缓存中没有查到对应的 MAC 地址,应如何处理?
  3. 实验者可能会选择在问题 2 中丢弃没有查到 MAC 地址的 IP 分组,而发送一个 ARP 请求。本实验允许这样实现,但这样可能导致什么问题?
  4. 对于 IP 分组头部校验和更新,若采用增量更新的算法,会出现哪些特殊情况?(提示:RFC 也犯过的错)

另请阅读:

  1. RFC 1071: Computing the Internet Checksum
  2. RFC 1141: Incremental Updating of the Internet Checksum
  3. RFC 1624: Computation of the Internet Checksum via Incremental Update

转发引擎的功能测试和性能测试

在上一节 ping 测试通过的基础上,实验者还需要进一步测试转发引擎的功能正确性和性能。

功能正确性测试主要包括如下几点:

  1. IP 分组头部校验和的各种情况都能正确计算,可以通过减少 ping 的间隔(ping -f <IP 地址>)来测试;
  2. 各种大小的 IP 分组均可以正常转发,可以通过 ping 指定分组大小或者用 iperf3 测速来测试。
    • 用 iperf3 测试时,需要在一台主机 A 上运行 iperf3 -s 开启 iperf3 服务器,然后在另一台主机 B 上运行 iperf3 -c <服务器 IP 地址> 来测试主机 B 向主机 A 通过 TCP 传输数据的速率。在主机 B 上运行 iperf3 -c <服务器 IP 地址> -R 可以测试主机 A 到主机 B 的速率。

转发引擎的性能测试主要分为吞吐量测试以及小包转发速率测试。对于吞吐量测试,实验者可以通过 iperf3 进行测速,并查看速率。对于小包转发速率测试,由于普通计算机难以按千兆线速的速率(如下文所述)发送小包,此处建议实验者进行仿真测试。

对于吞吐量,iperf3 显示的速率为 TCP 分段中传输的有效载荷的速率。考虑到基于以太网的 IP 协议的开销(每个以太网帧的 8 字节前导码、14 字节头部、4 字节校验码、12 字节的帧间隙,以及每个 IP 分组的 20 字节头部)、 TCP 协议自身开销(TCP 分段的 20 字节头部)以及以太网的 MTU 为 1500,每个最大的以太网帧在线路上占用 1538 个字节(8 + 14 + 1500 + 4 + 12)的时间,其中 TCP 分段的有效载荷为 1460 个字节(1500 - 20 - 20)。因此,对于千兆以太网,其上的 TCP 协议传输有效载荷的速率不会超过 1460 ÷ 1538 × 1000Mbps ≈ 949.28Mbps。实践中,由于其他一些额外开销,测试结果一般在 940Mbps 附近。对于带宽效率的更多讨论,请参阅:https://en.wikipedia.org/wiki/Jumbo_frame#Bandwidth_efficiency

对于小包转发速率,考虑到以太网帧最短帧长为 64 字节(包含头部、有效载荷以及校验码),以及 20 个字节的前导码和帧间隙,在千兆以太网上,每秒能够发送的以太网帧数量最多为 1000Mb ÷ (64 + 20) ÷ 8b ≈ 1.488M。若这些以太网帧均承载 IP 分组,那么这一数值为小包转发速率的上限(即线速)。

最后,当实验路由器四个接口同时进行收发时,吞吐量以及小包转发速率应分别达到3.797Gbps、5.952Mpps。

此外,测试时如果出现速度突然降到零并且后续 ping 测试失败的情况,一般说明转发引擎部分逻辑不够鲁棒。此时,实验者可以通过 ILA 查看转发引擎内部状态,找到出问题的部分;实验者也可以在 testbench 中增加以太网帧发送速率,模拟性能测试,然后寻找问题。

思考

  1. PHY/MAC 提供的 AXI-Stream 的接收端没有 ready 信号,意味着发送方需要时刻准备好接收数据。请检查实验框架,了解如何实现缓冲区。
  2. 有时会发生冲突而不得不丢包。请检查实验框架,了解 AXI-Stream 如何完整地丢弃一个以太网帧。

最后更新: 2020年10月27日
作者: Harry Chen (26.88%), Wende Tan (73.12%)