CS144 Check6 — Router
封面由 pysio 提供的迷之路由器,下一篇有可爱全貌。
Check6 相对简单,由于只需要完成路由表,不涉及路由协议等,也没有性能要求,可以非常简单。
Router 管理多个 NetworkInterface,负责将每个 NetworkInterface 内收到后缓存于 datagram_received 内的数据包转发到正确的 NetworkInterface,根据 add_route 添加的路由规则进行转发。
而路由时遵循最长前缀匹配原则(Longest Prefix Match),例如 192.168.1.0/24 代表前缀长度为 24 的路由前缀,匹配时会优先匹配前缀长度更长的规则。
关于 CIDR 的更多信息可以参考百科。
比如 10.1.0.0/16 和 10.0.0.0/8,如果数据包的目标地址是 10.1.2.3,则会优先匹配到 10.1.0.0/16。
唯一困难的地方在于如何快速找到匹配的路由规则,最简单的方式是直接用 std::vector 存储规则,查询时遍历所有路由规则,找到最长前缀匹配的规则。这里有实现 feat: impl router
然而没有附带的 Perf 测试,后续添加了一个
实际上会用 Trie 来实现,BSD 用 Radix Trie,而 Linux 在后续更进一步用 LC-trie。以下会提供一个包含 Patricia Trie 的实现(似乎路径压缩的变体叫 Patricia)。
1 |
|
其中将 /8 的前缀作为索引,存储在 index_ 中,查询时先通过 index_ 找到对应的节点,然后再向下查找,避免每次从根节点开始查找的开销。以及将 data 单独存储在 data_ vector 中,节点只存储索引,优化内存布局。
TODO: 更多关于
std::move的用法,注意到移动语义有可观的提升
此外每传递数据包时,要记得将数据包的 TTL 减 1,如果 TTL 为 0,则丢弃该数据包。
以下是测试结果:
1 | ❯ cmake --build build --target check6 |
说些什么吧!