路由转发
这个实验就是最后一个需要写代码的实验了。主要需要解决的问题是一个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++) { 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
| 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的部分不需要写代码,只需要直接运行程序聊天就行,就不写博客总结了