路由表的实现位于 routing_table
文件夹,为转发引擎和 RIP Daemon 共用的组件。其基于 Rust 语言编写的 treebitmap 项目实现。算法基本**为带状态压缩的 Trie 树,路由表中每 4 位(称为一个 Nibble)构成树的一层,只要路由表不是过于密集,这样的实现在减少树的体积同时也能大幅增加查找速度。树的每个内部节点可以有至多 16 个子节点,每一个叶节点可以保存 32 个路由表项。查找过程充分利用了节点编号的二进制表示,以不浪费空间。
这一算法性能表现优越,全部 IPv4 BGP 表完全插入后占用空间不超过 5MB,并且在此表上的查找时间量级约为 100ns
。具体**与描述还可参考下列文献:
Eatherton W, Varghese G, Dittia Z. Tree bitmap: hardware/software IP lookups with incremental updates[J]. ACM SIGCOMM Computer Communication Review, 2004, 34(2): 97-122.
实现的 C 接口提供路由表的插入、删除、最长匹配、完全匹配以及遍历,可见 rt.h
中的函数声明,以及 main.c
中的使用示例。
依赖为 Rust 1.31.1
与 Cargo 0.31.1
以及 GCC
。安装完成后,在 routing_table
文件夹下运行 make
,即在 target/{debug,release}/
文件下生成对应的静态链接库。
路由表不能单独运行,但能通过 make test
来运行测试程序。此外,提供编译出的 .a
文件,以供没有 Rust 开发环境时直接链接使用。
转发引擎的实现位于 forwarder
文件夹内。此引擎运行后监听 TCP 800 端口监听路由信息变化,动态更新自身的转发表。除此之外,在初始启动时,可选将直连路由插入转发引擎中。
直接在 forwarder
文件夹中运行 make
即可,该项目自动依赖上述的路由表。编译完成后,在 obj
文件夹下将得到 forwarder.release
与 forwarder.debug
。前者完全静态编译并打开优化选项,后者保留了调试符号。
上述的两个可执行文件均能运行,支持的命令行参数为:
-l:将本机地址和直连网络加入路由表,使引擎能处理目标为这些地址的数据包
-v:调试模式,打印更多信息
-s:加速模式,打印更少信息,跳过一些不必要的步骤
-h:打印版本与帮助信息
推荐的运行参数为 ./forwarder.release -s
,测试时务必不要加入 -v
,否则大量打印会严重影响引擎性能。
默认情况下,引擎会打印所有的路由表变化信息,并在屏幕底部打印当前统计消息(速度、累计包数量等),并且也会打印遇到的错误。
注意:转发引擎本身不会主动发出 ARP 请求,因此如果下一跳的 MAC 地址不在系统的 ARP 缓存中,引擎将不会进行转发。因此,在插入路由表进行测试前,请务必保证系统 ARP 表中有下一跳的表项。
在插入 10000 条路由表项后,进行性能测试。首先使用 1300 字节的大包测试,命令为 iperf3 -c server_ip -u -l 1300 -b 500M -n 20G
,此时有轻微丢包,可以判断转发性能峰值在 470 Mbps 左右。如果采用 64 字节的小包,峰值性能在 7 Mbps 左右。
RIP Daemon 的实现位于 ripd
文件夹内。实现了简单的 RIP 路由协议,启动时组播 REQUEST 报文,每隔五秒组播 REPLY 报文,并处理其他机器发送的 REPLY 报文。这一实现支持水平分裂算法与对接口状态变化的监测。RIP Daemon 会将本机路由表的变化通过 TCP 800 端口发送给转发引擎。
直接在 ripd
文件夹中运行 make
即可,该项目自动依赖上述的路由表。编译完成后,在 obj
文件夹下将得到 ripd.release
与 ripd.debug
。前者完全静态编译并打开优化选项,后者保留了调试符号。
直接执行上述的两个可执行文件之一即可。该程序没有命令行参数。