【斯坦福CS144】Lab5

一、实验目的

在现有的NetworkInterface基础上实现一个IP路由器。

二、实验内容

在本实验中,你将在现有的NetworkInterface基础上实现一个IP路由器,从而结束本课程。路由器有几个网络接口,可以在其中任何一个接口上接收互联网数据报。路由器的工作是根据路由表转发它得到的数据报:一个规则列表,它告诉路由器,对于任何给定的数据报:

发送到哪个接口;

下一跳的IP地址 ;

你的工作是实现一个路由器,它可以为任何给定的数据报计算出这两件事。(你不需要实现设置路由表的算法,例如RIP、OSPF、BGP或SDN控制器,只需要实现跟随路由表的算法)。

你对路由器的实现将使用带有新的Router类的Sponge库,以及在模拟网络中检查你的路由器功能的测试。本实验建立在你在上一个实验中对NetworkInterface的实现之上,但不使用你在之前实验中实现的TCP栈。IP路由器不需要知道任何关于TCP、ARP或以太网的信息(仅限IP)。我们希望你的实现将需要大约25-30行的代码。

三、实验过程

在minnow目录下输入git merge origin/check5-startercode获取Lab5

用文本编辑器打开./src/router.hh

修改代码

用文本编辑器打开./src/router.cc

修改代码

在build目录下输入make进行编译

输入make check5进行测试

测试成功,实验结束

四、实验体会

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

2.需要注意的是,联系计算机网络理论课和实验所学习的内容,在实际网络中,路由表会根据网络拓扑和路由策略进行配置,以确保数据包能够正确地转发到目标。路由表中的路由条目根据目标网络地址的前缀匹配来确定数据包的转发规则。当无法找到匹配的路由条目时,数据包将根据默认路由进行转发,或者如果没有默认路由,则会被丢弃。

五、代码附录

router.hh

#pragma once#include "network_interface.hh"#include <optional>
#include <queue>// A wrapper for NetworkInterface that makes the host-side
// interface asynchronous: instead of returning received datagrams
// immediately (from the `recv_frame` method), it stores them for
// later retrieval. Otherwise, behaves identically to the underlying
// implementation of NetworkInterface.
class AsyncNetworkInterface : public NetworkInterface
{std::queue<InternetDatagram> datagrams_in_ {};public:using NetworkInterface::NetworkInterface;// Construct from a NetworkInterfaceexplicit AsyncNetworkInterface( NetworkInterface&& interface ) : NetworkInterface( interface ) {}// \brief Receives and Ethernet frame and responds appropriately.// - If type is IPv4, pushes to the `datagrams_out` queue for later retrieval by the owner.// - If type is ARP request, learn a mapping from the "sender" fields, and send an ARP reply.// - If type is ARP reply, learn a mapping from the "target" fields.//// \param[in] frame the incoming Ethernet framevoid recv_frame( const EthernetFrame& frame ){auto optional_dgram = NetworkInterface::recv_frame( frame );if ( optional_dgram.has_value() ) {datagrams_in_.push( std::move( optional_dgram.value() ) );}};// Access queue of Internet datagrams that have been receivedstd::optional<InternetDatagram> maybe_receive(){if ( datagrams_in_.empty() ) {return {};}InternetDatagram datagram = std::move( datagrams_in_.front() );datagrams_in_.pop();return datagram;}
};// A router that has multiple network interfaces and
// performs longest-prefix-match routing between them.
// class Router
// {
//   // The router's collection of network interfaces
//   std::vector<AsyncNetworkInterface> interfaces_ {};//   struct Route_entry//route_entry_
//   {
//     uint32_t route_prefix{};
//     uint8_t prefix_length{};
//     std::optional<Address> next_hop;
//     size_t interface_num{};
//   };
//   //static typedef struct route_entry_ Route_entry;
//   std::vector<Route_entry> route_table_{};
class Router
{// The router's collection of network interfacesstd::vector<AsyncNetworkInterface> interfaces_ {};struct Route_entry{uint32_t route_prefix {};uint8_t prefix_length {};std::optional<Address> next_hop;size_t interface_num {};};std::vector<Route_entry> route_table_ {};//std::vector<Route_entry>::iterator longest_prefix_match_( uint32_t dst_ip );//static int match_length_( uint32_t src_ip, uint32_t tgt_ip, uint8_t tgt_len );
public:// Add an interface to the router// interface: an already-constructed network interface// returns the index of the interface after it has been added to the routersize_t add_interface( AsyncNetworkInterface&& interface ){interfaces_.push_back( std::move( interface ) );return interfaces_.size() - 1;}// Access an interface by indexAsyncNetworkInterface& interface( size_t N ) { return interfaces_.at( N ); }// Add a route (a forwarding rule)void add_route( uint32_t route_prefix,uint8_t prefix_length,std::optional<Address> next_hop,size_t interface_num );// Route packets between the interfaces. For each interface, use the// maybe_receive() method to consume every incoming datagram and// send it on one of interfaces to the correct next hop. The router// chooses the outbound interface and next-hop as specified by the// route with the longest prefix_length that matches the datagram's// destination address.void route();std::vector<Route_entry>::iterator longest_prefix_match_( uint32_t dst_ip );int match_length_( uint32_t src_ip, uint32_t tgt_ip, uint8_t tgt_len );// std::vector<Route_entry>::iterator longest_prefix_match_( uint32_t dst_ip );// int match_length_( uint32_t src_ip, uint32_t tgt_ip, uint8_t tgt_len );
};

router.cc

#include "router.hh"#include <iostream>
#include <limits>
using namespace std;// route_prefix: The "up-to-32-bit" IPv4 address prefix to match the datagram's destination address against
// 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?
// 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).
// 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() << "/"
//        << static_cast<int>( prefix_length ) << " => " << ( next_hop.has_value() ? next_hop->ip() : "(direct)" )
//        << " on interface " << interface_num << "\n";//   // (void)route_prefix;
//   // (void)prefix_length;
//   // (void)next_hop;
//   // (void)interface_num;//   route_table_.emplace_back(route_prefix, prefix_length, next_hop, interface_num);
//   return;
// }// void Router::route()
// {
//   for ( auto& current_interface : interfaces_ ) {
//     auto received_dgram = current_interface.maybe_receive();
//     if ( received_dgram.has_value() ) {
//       auto& dgram = received_dgram.value();
//       if ( dgram.header.ttl > 1 ) {
//         dgram.header.ttl--;
//         // NOTE: important!!!
//         dgram.header.compute_checksum();
//         auto dst_ip = dgram.header.dst;
//         auto it = longest_prefix_match_( dst_ip );
//         if ( it != route_table_.end() ) {
//           auto& target_interface = interface( it->interface_num );
//           target_interface.send_datagram( dgram, it->next_hop.value_or( Address::from_ipv4_numeric( dst_ip ) ) );
//         }
//       }
//     }
//   }
// }// std::vector<Router::Route_entry>::iterator Router::longest_prefix_match_( uint32_t dst_ip )
// {
//   auto res = route_table_.end();
//   int max_length = 0;
//   for ( auto it = route_table_.begin(); it != route_table_.end(); ++it ) {
//     int len = match_length_( dst_ip, it->route_prefix, it->prefix_length );
//     if ( len > max_length ) {
//       max_length = len;
//       res = it;
//     }
//   }
//   return res;
// }// int Router::match_length_( uint32_t src_ip, uint32_t tgt_ip, uint8_t tgt_len )
// {
//   if ( tgt_len == 0 ) {
//     return 0;
//   }//   if ( tgt_len > 32 ) {
//     return -1;
//   }//   // tgt_len < 32
//   uint8_t const len = 32U - tgt_len;
//   src_ip = src_ip >> len;
//   tgt_ip = tgt_ip >> len;
//   return src_ip == tgt_ip ? tgt_len : -1;
// }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() << "/"<< static_cast<int>( prefix_length ) << " => " << ( next_hop.has_value() ? next_hop->ip() : "(direct)" )<< " on interface " << interface_num << "\n";route_table_.emplace_back( route_prefix, prefix_length, next_hop, interface_num );
}void Router::route()
{for (uint32_t i=0; i<interfaces_.size();i++) {auto received_dgram = interface(i).maybe_receive();if ( received_dgram.has_value() ) {auto dgram = received_dgram.value();if ( dgram.header.ttl > 1 ) {dgram.header.ttl--;dgram.header.compute_checksum();auto dst_ip = dgram.header.dst;auto it = longest_prefix_match_( dst_ip );if ( it != route_table_.end() ) {//这里的buginterface( it->interface_num ).send_datagram( dgram, it->next_hop.value_or( Address::from_ipv4_numeric( dst_ip ) ) );}}}}
}std::vector<Router::Route_entry>::iterator Router::longest_prefix_match_( uint32_t dst_ip )
{auto res = route_table_.end();int max_length = -1;for ( auto it = route_table_.begin(); it != route_table_.end(); ++it ) {int len = match_length_( dst_ip, it->route_prefix, it->prefix_length );if ( len > max_length ) {max_length = len;res = it;}}return res;
}int Router::match_length_( uint32_t src_ip, uint32_t tgt_ip, uint8_t tgt_len )
{if ( tgt_len == 0 ) {return 0;}if ( tgt_len > 32 ) {return -1;}// tgt_len < 32uint8_t len = 32U - tgt_len;src_ip = src_ip >> len;tgt_ip = tgt_ip >> len;return src_ip == tgt_ip ? tgt_len : -1;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1559093.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

搜狗翻译体验,2024四大翻译工具解析!

为了满足广大用户的需求&#xff0c;市面上涌现出了众多优秀的翻译工具&#xff0c;福昕在线翻译、福昕翻译客户端、海鲸AI翻译、搜狗翻译等。今天&#xff0c;我们就来对比一下这些翻译工具&#xff0c;看看它们各自的特点和优势。 福昕在线翻译&#xff1a;专业精准&#xf…

高效开发,低代码平台如何助力构建内部工具

Zoho Creator是低代码平台&#xff0c;助力快速构建内部工具&#xff0c;如审批、订单、销售管理等&#xff0c;提升生产力、客户满意度&#xff0c;并减轻管理负担。平台提供拖放界面、集成数据库等功能&#xff0c;入选Gartner低代码平台“魔力象限”。 一、什么是内部工具&a…

虚拟机没有网络怎么解决

CentOS7为例 进入虚拟网络编辑器 1.更改设置 2.选中NAT模式点击3点击移除网络 4添加网络&#xff0c;随便选一个 5.点开NAT设置&#xff0c;记住网关 6.DHCP设置&#xff0c;注意虚拟机设置ip必须在起始ip和结束ip范围内 进入虚拟机网络适配器&#xff0c;自定义选中第4步操作…

五、Python基础语法(程序的输入和输出)

一、输入 输入&#xff1a;输入就是获取键盘输入的数据&#xff0c;使用input()函数。代码会从上往下执行&#xff0c;当遇到input()函数&#xff0c;就会暂停执行&#xff0c;输入内容后&#xff0c;敲回车键&#xff0c;表示本次的输入结束。input函数得到的数据类型都是字符…

python none代表什么

python中None代表一个特殊的空值&#xff0c;即为一个空对象&#xff0c;没有任何的值。 一般用于assert&#xff0c;判断&#xff0c;函数无返回时的默认&#xff0c;具体如下&#xff1a; 1、assert断言&#xff1a; mylist [a, b, c] >>> assert len(mylist) is…

用包目录结构Python脚本,简陋而强大

模块清晰易于管理&#xff0c;模块代码以*.py脚本呈现&#xff0c;方便维护和扩展。 (笔记模板由python脚本于2024年10月09日 18:21:52创建&#xff0c;本篇笔记适合喜欢Python和编程的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https://www.python.org/ …

java内存控制

Java 内存控制是一个相对复杂但至关重要的主题&#xff0c;它涉及到如何高效地管理Java应用程序中的内存资源。在Java中&#xff0c;内存管理主要由Java虚拟机&#xff08;JVM&#xff09;负责&#xff0c;包括内存的分配和回收。尽管如此&#xff0c;作为开发者&#xff0c;我…

Kali Linux中安装配置影音资源下载神器Amule

一、Debian系列Linux安装amule命令&#xff1a; sudo apt update sudo apt-get install amule amule-utils 二、配置Amule的要点&#xff1a; 1、首次运行Amule&#xff0c;提示是否下载服务器列表&#xff0c;点击是。 2、搜索选项的类型选择全球&#xff0c;类型的默认选项…

openwrt 配置4G网卡 simcom7600ce

文章目录 概述配置并烧录系统&#xff0c;实现识别4G模组编译选项配置修改usb的option.c文件编译源码&#xff0c;烧录固件 配置4G模组成为网卡设置4G模组驱动参数模组拨号添加网卡接口ping百度验证网络 开机启动脚本 概述 在mt7628芯片上&#xff0c;操作系统使用openwrt21.0…

每日OJ题_牛客_AB13【模板】拓扑排序_C++_Java

目录 牛客_AB13【模板】拓扑排序 题目解析 C代码 Java代码 牛客_AB13【模板】拓扑排序 【模板】拓扑排序_牛客题霸_牛客网 (nowcoder.com) 描述&#xff1a; 给定一个包含nn个点mm条边的有向无环图&#xff0c;求出该图的拓扑序。若图的拓扑序不唯一&#xff0c;输出任意合法…

【C++】面向对象之继承

不要否定过去&#xff0c;也不要用过去牵扯未来。不是因为有希望才去努力&#xff0c;而是努力了&#xff0c;才能看到希望。&#x1f493;&#x1f493;&#x1f493; 目录 ✨说在前面 &#x1f34b;知识点一&#xff1a;继承的概念及定义 •&#x1f330;1.继承的概念 •&…

小赢卡贷公益行:乡村振兴与多元公益并进

在金融科技的浪潮中&#xff0c;小赢卡贷不仅以其创新的金融产品和服务赢得了市场的广泛认可&#xff0c;更以其背后的公益之心&#xff0c;积极履行社会责任&#xff0c;传递着温暖与希望。小赢公益基金会&#xff0c;作为小赢卡贷社会责任的延伸&#xff0c;主要聚焦于乡村振…

衡石分析平台系统管理手册-智能运维之系统设置

系统设置​ HENGSHI 系统设置中展示了系统运行时的一些参数&#xff0c;包括主程序相关信息&#xff0c;Base URL、HTTP 代理、图表数据缓存周期、数据集缓存大小、租户引擎等相关信息。 主程序​ 系统设置中展示了主程序相关信息&#xff0c;这些信息是系统自动生成的&#…

springboot宿舍管理-计算机毕业设计源码40740

摘要 宿舍管理系统作为一种利用信息技术改善学生住宿管理的工具&#xff0c;在大学宿舍管理中具有重要的实际意义。本文通过对国内外研究现状的调查和总结&#xff0c;探讨了宿舍管理系统的论文主题、研究背景、研究目的、研究意义以及主要研究内容。 首先&#xff0c;宿舍管理…

心觉:购物选择困难症! 为什么你总是挑不出“最完美”的商品?

Hi&#xff0c;我是心觉&#xff0c;与你一起玩转潜意识、脑波音乐和吸引力法则&#xff0c;轻松掌控自己的人生&#xff01; 挑战每日一省写作194/1000天 你有没有遇到过这样一种情况&#xff1a;打算买一款新的电子产品、家具或者衣服 但在网上和实体店翻来覆去&#xff0…

编译链接的过程发生了什么?

一&#xff1a;程序的翻译环境和执行环境 在 ANSI C 的任何一种实现中&#xff0c;存在两个不同的环境。 第 1 种是翻译环境&#xff0c;在这个环境中源代码被转换为可执行的机器指令。 第 2 种是执行环境&#xff0c;它用于实际执行代码 也就是说&#xff1a;↓ 1&#xff1…

ai免费写论文是原创吗?分享5款ai写作免费一键生成助手

在当今的学术研究和写作领域&#xff0c;AI技术的应用越来越广泛&#xff0c;尤其是在论文写作方面。许多AI写作工具声称能够一键生成高质量的论文&#xff0c;并且保证原创性。然而&#xff0c;这些工具是否真的能生成完全原创的论文&#xff0c;仍然是一个值得探讨的问题。 …

【动态规划-最长递增子序列(LIS)】【hard】力扣1671. 得到山形数组的最少删除次数

我们定义 arr 是 山形数组 当且仅当它满足&#xff1a; arr.length > 3 存在某个下标 i &#xff08;从 0 开始&#xff09; 满足 0 < i < arr.length - 1 且&#xff1a; arr[0] < arr[1] < … < arr[i - 1] < arr[i] arr[i] > arr[i 1] > … &g…

掌握甘特图,没有Excel也能轻松制作的技巧

甘特图是项目管理中常用工具&#xff0c;由亨利甘特发明。不擅长Excel者可用ZohoProjects等软件创建甘特图&#xff0c;其直观展示项目时间和任务&#xff0c;支持实时协作、工时管理等功能&#xff0c;广泛应用于各领域项目管理。 一、甘特图的由来 甘特图最初是由工程师和管…

tp5 fastadmin列表页图片批量压缩并下载

记录&#xff1a;tp5 fastadmin对列表页选中数据的多张图片进行压缩并下载。 html代码 <a href"javascript:;" class"btn btn-info btn-apple btn-disabled disabled {:$auth->check(zhuanli/zhuanli/xiazai)?:hide}" title"批量下载专利证书…