CS144-Lab6 计算机网络:路由转发

路由转发

这个实验就是最后一个需要写代码的实验了。主要需要解决的问题是一个IP数据包传入之后,如何通过已有的路由表确定下一跳的IP地址

这个实验中主要的问题点就是CIDR的匹配。解决这个问题,我们只需要先将CIDR转为子网掩码,也就是以0为基数,左移(32 - 前缀)位,最后得到的也是子网掩码的值。但是这里有一个问题就是,当mask是uint32_t的时候,如果前缀的长度为0,那么子网掩码会变成255.255.255.255,但是实际上应该是0,因此我们需要对前缀是否为0进行判断。

在判断完毕之后,只需要将网关的IP地址和子网掩码按位与运算,然后将目标IP地址也和子网掩码按位与运算,如果最后的结果相同,那么就说明子网匹配

1
2
3
4
5
6
7
8
9
10
11
auto path = _route_table.end();
const auto &dst_ip = dgram.header().dst;
for (auto entry = _route_table.begin(); entry != _route_table.end(); entry++) {
// CIDR的子网位数是多少,相当于就是在0的基础上补多少个1,但是当prefix_length == 0的时候,
// 由于位运算的特性,子网掩码会全部变成1,也就相当于是/32的情况。因此当检测到子网掩码是0的时候要直接跳过
const uint32_t &mask = entry->prefix_length ? (~0U) << (32 - entry->prefix_length) : 0;
const auto network_address = entry->route_prefix & mask;
if ((dst_ip & mask) == network_address) {
path = entry;
}
}

如果没有匹配到对应的路由规则,或者这个数据包已经经过了太多次转发都没有找到目的地,那么就将这个数据包丢弃掉。

1
2
3
4
// 检查是否存在对应的路由规则,或者TTL可否生存,如果不符合则丢弃
if (path == _route_table.end() || dgram.header().ttl-- <= 1) {
return;
}

如果没有丢弃的话,那么就只需要按照正确的接口将数据包发送出去就行,如果没有下一跳的IP地址,说明数据包已经到达了对应的目的地,只需要直接发送给目标IP即可

1
2
3
4
5
6
7
// 将数据包发送给正确的接口
AsyncNetworkInterface &interface = _interfaces[path->interface_num];
if (path->next_hop.has_value()) {
interface.send_datagram(dgram, path->next_hop.value());
} else {
interface.send_datagram(dgram, Address::from_ipv4_numeric(dgram.header().dst));
}

终于也是写完了Lab0-6的所有博客总结😭,Lab7的部分不需要写代码,只需要直接运行程序聊天就行,就不写博客总结了


CS144-Lab6 计算机网络:路由转发
https://halc.top/p/195b5fa9
作者
HalcyonAzure
发布于
2023年4月24日
许可协议