CS144计算机网络 Lab6

一、简介

这里记录了笔者学习 CS144 计算机网络 Lab6 的一些笔记 - IP Router 路由器 的实现

CS144 Lab6 实验指导书 - Lab Checkpoint 6: building an IP router

个人 CS144 实验项目地址 - github

在这个实验中,我们将完成一个简易路由器,其功能是:对于给定的数据包,确认发送接口以及下一跳的 IP 地址。为了简化实验难度,该实验中无需处理任何复杂路由协议,实验代码最多只需30行。

image-20211118175306520

二、环境配置

当前我们的实验代码位于 master 分支,而在完成 Lab 之前需要合并一些依赖代码,因此执行以下命令:

1
git merge origin/lab6-startercode

之后重新 make 编译即可。

三、Router 的实现

这里的 Router 实现比较简单,只需实现一下 IP 最长匹配并将数据包转发即可。

类私有成员实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Router {
//! The router's collection of network interfaces
std::vector<AsyncNetworkInterface> _interfaces{};

//! Send a single datagram from the appropriate outbound interface to the next hop,
//! as specified by the route with the longest prefix_length that matches the
//! datagram's destination address.
void route_one_datagram(InternetDatagram &dgram);

struct RouterTableEntry {
const uint32_t route_prefix;
const uint8_t prefix_length;
const std::optional<Address> next_hop;
const size_t interface_idx;
};
std::vector<RouterTableEntry> _router_table{};

public:
[...]
}

类函数方法实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
//! \param[in] route_prefix The "up-to-32-bit" IPv4 address prefix to match the datagram's destination address against
//! \param[in] prefix_length For this route to be applicable, how many high-order (most-significant) bits of the route_prefix will need to match the corresponding bits of the datagram's destination address?
//! \param[in] next_hop The IP address of the next hop. Will be empty if the network is directly attached to the router (in which case, the next hop address should be the datagram's final destination).
//! \param[in] interface_num The index of the interface to send the datagram out on.
void Router::add_route(const uint32_t route_prefix,
const uint8_t prefix_length,
const optional<Address> next_hop,
const size_t interface_num) {
cerr << "DEBUG: adding route " << Address::from_ipv4_numeric(route_prefix).ip() << "/" << int(prefix_length)
<< " => " << (next_hop.has_value() ? next_hop->ip() : "(direct)") << " on interface " << interface_num << "\n";

_router_table.push_back({route_prefix, prefix_length, next_hop, interface_num});
}

//! \param[in] dgram The datagram to be routed
void Router::route_one_datagram(InternetDatagram &dgram) {
const uint32_t dst_ip_addr = dgram.header().dst;
auto max_matched_entry = _router_table.end();
// 开始查询
for (auto router_entry_iter = _router_table.begin(); router_entry_iter != _router_table.end();
router_entry_iter++) {
// 如果前缀匹配匹配长度为 0,或者前缀匹配相同
if (router_entry_iter->prefix_length == 0 ||
(router_entry_iter->route_prefix ^ dst_ip_addr) >> (32 - router_entry_iter->prefix_length) == 0) {
// 如果条件符合,则更新最匹配的条目
if (max_matched_entry == _router_table.end() ||
max_matched_entry->prefix_length < router_entry_iter->prefix_length)
max_matched_entry = router_entry_iter;
}
}
// 将数据包 TTL 减去1
// 如果存在最匹配的,并且数据包仍然存活,则将其转发
if (max_matched_entry != _router_table.end() && dgram.header().ttl-- > 1) {
const optional<Address> next_hop = max_matched_entry->next_hop;
AsyncNetworkInterface &interface = _interfaces[max_matched_entry->interface_idx];
if (next_hop.has_value())
interface.send_datagram(dgram, next_hop.value());
else
interface.send_datagram(dgram, Address::from_ipv4_numeric(dst_ip_addr));
}
// 其他情况下则丢弃该数据包
}

四、测试

这是 CS144 的测试网络拓扑:

image-20211118175644978

以下是我的测试结果:

image-20211118210129124

  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2020-2024 Kiprey
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~