CS144 Lab6
这里回顾Lab 6: building an IP router。
实验资料:
- https://www.cnblogs.com/kangyupl/p/stanford_cs144_labs.html
- https://kangyupl.gitee.io/cs144.github.io/
- https://gitee.com/kangyupl/sponge
Lab 6: building an IP router
准备工作
下载代码以及跑通流程
git checkout -b lab6-startercode
git fetch
git merge origin/lab6-startercode
cd build
make -j4 && make check_lab6
说明
- 为了实现方便,使用vector存储转发表的每一项
- 当收到datagram时,搜索转发表,找到最长前缀匹配以及interface_num
- 通过interface_num对应的interface发送datagram
代码
router.hh
添加ForwardTableEntry, _forward_table, get_mask:
class ForwardTableEntry {
public:
uint32_t route_prefix = 0;
uint8_t prefix_length = 0;
std::optional<Address> next_hop = {};
size_t interface_num = 0;
};
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);
// add
std::vector<ForwardTableEntry> _forward_table{};
public:
//! Add an interface to the router
//! \param[in] interface an already-constructed network interface
//! \returns The index of the interface after it has been added to the router
size_t add_interface(AsyncNetworkInterface &&interface) {
_interfaces.push_back(std::move(interface));
return _interfaces.size() - 1;
}
//! Access an interface by index
AsyncNetworkInterface &interface(const size_t N) { return _interfaces.at(N); }
//! Add a route (a forwarding rule)
void add_route(const uint32_t route_prefix,
const uint8_t prefix_length,
const std::optional<Address> next_hop,
const size_t interface_num);
//! Route packets between the interfaces
void route();
// add
uint32_t get_mask(uint8_t prefix_length);
};
add_route
直接push到_forward_table即可:
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";
// DUMMY_CODE(route_prefix, prefix_length, next_hop, interface_num);
// Your code here.
ForwardTableEntry entry;
entry.route_prefix = route_prefix;
entry.prefix_length = prefix_length;
entry.next_hop = next_hop;
entry.interface_num = interface_num;
// ForwardTableEntry entry(route_prefix, prefix_length, next_hop, interface_num);
_forward_table.push_back(entry);
}
route_one_datagram
根据说明部分的算法转发datagram:
void Router::route_one_datagram(InternetDatagram &dgram) {
IPv4Header header = dgram.header();
// 最长匹配长度
uint8_t max_l = 0;
int index = -1;
ForwardTableEntry entry;
int n = _forward_table.size();
for (int i = 0; i < n; i++) {
// 路由器搜索路由表,以找到与数据报的目的地址相匹配的路由。我们所说的"匹配"是指目的地址的最高有效`prefix_length`比特与`route_prefix`的最高有效`prefix_length`比特相同的。
uint32_t mask = get_mask(_forward_table[i].prefix_length);
if ((header.dst & mask) == (_forward_table[i].route_prefix & mask)) {
// 注意最长匹配长度可能为0, 所以要通过index判断
if ((index == -1) || (_forward_table[i].prefix_length > max_l)) {
max_l = _forward_table[i].prefix_length;
index = i;
entry = _forward_table[index];
}
}
}
// 如果没有匹配的路由,路由器会丢弃数据报。
if (index == -1) {
return;
}
// 路由器会递减数据报的TTL(生存时间)。如果TTL已经为零,或在递减后为零,路由器应该放弃该数据报。
if (dgram.header().ttl <= 1) {
return;
}
dgram.header().ttl--;
// 选择interface
if (_forward_table[index].next_hop.has_value()) {
// 但如果路由器是通过其他路由器连接到有关网络的,则`next_hop`将包含路径上下一路由器的IP地址。
Address next_hop = _forward_table[index].next_hop.value();
interface(_forward_table[index].interface_num).send_datagram(dgram, next_hop);
} else {
// 如果路由器直接连接到有关的网络,`next_hop`将是一个空的可选项。在这种情况下,`next_hop`是数据报的目标地址。
Address next_hop = Address::from_ipv4_numeric(header.dst);
// 发送
interface(_forward_table[index].interface_num).send_datagram(dgram, next_hop);
}
}
get_mask
根据prefix_length生成mask:
uint32_t Router::get_mask(uint8_t prefix_length) {
if (prefix_length == 0) {
return 0;
} else {
return ~((1 << (32 - prefix_length)) - 1);
}
}
测试
make -j8 && make check_lab6
Test project /home/cs144/sponge/build
Start 29: arp_network_interface
1/2 Test #29: arp_network_interface ............ Passed 0.00 sec
Start 30: router_test
2/2 Test #30: router_test ...................... Passed 0.01 sec
100% tests passed, 0 tests failed out of 2
Total Test time (real) = 0.02 sec
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Doraemonzzz!
评论
ValineLivere