CS144 Lab Checkpoint 5: down the stack (the network interface)

网络层 (NetworkLayer)
  1. 发送数据报 (send_datagram):应用层调用 send_datagram 方法,传递需要发送的IP数据包和下一跳的IP地址。
  2. IP数据报:将数据报封装成一个IP数据包。
  3. 查找ARP缓存:检查ARP缓存中是否有目标IP地址的MAC地址。
  4. 找到目标MAC地址?:检查ARP缓存中是否有目标IP地址的MAC地址。
    • :构建以太网帧 (Build Ethernet Frame)。
    • :发送ARP请求 (send_arp_request)。
  5. 发送ARP请求 (send_arp_request):发送ARP请求,查询目标IP地址的MAC地址。
  6. 缓存ARP请求:缓存发送的ARP请求,以避免重复请求。
  7. 数据报入队:将待发送的IP数据报排队,等待ARP回复。
链路层 (DataLinkLayer)
  1. 构建以太网帧 (Build Ethernet Frame):构建包含IP数据包的以太网帧。
  2. 发送以太网帧 (Send Ethernet Frame):将以太网帧发送到TAP设备。
  3. 接收以太网帧 (Receive Ethernet Frame):TAP设备接收到以太网帧后,调用 recv_frame 方法。
  4. 解析以太网帧 (Parse Ethernet Frame):解析接收到的以太网帧,检查类型字段。
  5. 类型字段=IPv4?:检查以太网帧的类型字段是否为IPv4。
    • :处理IPv4数据报 (处理IPv4数据报)。
    • :检查类型字段是否为ARP。
  6. 类型字段=ARP?:检查以太网帧的类型字段是否为ARP。
    • :处理ARP消息 (处理ARP消息)。
    • :更新ARP缓存。
  7. 处理ARP消息:将有效负载解析为ARP消息。
  8. 更新ARP缓存 (Update ARP Cache):如果是ARP消息,更新ARP缓存。
  9. 发送ARP回复 (Send ARP Reply):如果是ARP请求,发送ARP回复。
  10. 处理等待发送的IP数据报:处理等待发送的IP数据报,使用新的MAC地址发送数据。
TAP设备 (TAPDevice)
  1. TAP设备:通过TAP设备发送和接收数据。
  2. 发送数据 (Send Data):通过TAP设备发送以太网帧。
  3. 接收数据 (Receive Data):通过TAP设备接收以太网帧。

附上SequenceDiagram.org流程图资源代码

network_interface.hh:

#pragma once
#include <chrono>#include<unordered_map>
#include <queue>
#include <memory>#include "address.hh"
#include "ethernet_frame.hh"
#include "ipv4_datagram.hh"// 一个连接IP(互联网层或网络层)与Ethernet(网络访问层或链路层)的“网络接口”。// 该模块是TCP/IP协议栈的最低层(将IP与较低层网络协议,例如Ethernet,连接起来)。
// 但是同一个模块也作为路由器的一部分被重复使用:
// 路由器通常具有许多网络接口,路由器的工作是在这些不同的接口之间路由Internet数据报。// 网络接口将数据报(来自“客户”,例如TCP/IP协议栈或路由器)转换为Ethernet帧。
// 为了填写Ethernet目标地址,它会查找每个数据报的下一个IP跳的Ethernet地址,使用地址解析协议(ARP)进行请求。
// 在相反的方向上,网络接口接受Ethernet帧,检查它们是否是为其目的地的,如果是,则根据其类型处理有效载荷。
// 如果是IPv4数据报,网络接口将其传递给上层协议栈。如果是ARP请求或回复,网络接口会根据需要处理帧并学习或回复。
class NetworkInterface
{
public:// 一个物理输出端口的抽象,网络接口在其中发送Ethernet帧class OutputPort{public:virtual void transmit(const NetworkInterface& sender, const EthernetFrame& frame) = 0;virtual ~OutputPort() = default;};// 使用给定的Ethernet(网络访问层)和IP(互联网层)地址构造网络接口NetworkInterface(std::string_view name,std::shared_ptr<OutputPort> port,const EthernetAddress& ethernet_address,const Address& ip_address);// 发送Internet数据报,封装在Ethernet帧中(如果已知Ethernet目标地址)。// 将使用ARP查找下一跳的Ethernet目标地址。发送通过在帧上调用“transmit”(成员变量)完成。void send_datagram(const InternetDatagram& dgram, const Address& next_hop);// 接收Ethernet帧并做出适当的响应。// 如果类型是IPv4,则将数据报推送到datagrams_in队列。// 如果类型是ARP请求,则从“发送者”字段中学习映射,并发送ARP回复。// 如果类型是ARP回复,则从“发送者”字段中学习映射。void recv_frame(const EthernetFrame& frame);// 当时间流逝时定期调用void tick(size_t ms_since_last_tick);// 访问器const std::string& name() const { return name_; }const OutputPort& output() const { return *port_; }OutputPort& output() { return *port_; }std::queue<InternetDatagram>& datagrams_received() { return datagrams_received_; }private:// IPv4创建以太网帧bool create_IPv4frame(const InternetDatagram& dgram, uint32_t next_hop, EthernetFrame& frame);// ARP创建以太网帧bool create_ARPframe(const ARPMessage & arp_msg);// 发送ARP请求获取目标MAC地址void send_arp_request(uint32_t next_hop_ip);bool reply_arp_request(const ARPMessage & arp_msg);void prints();// 接口的人类可读名称std::string name_;// 物理输出端口(+一个使用它发送Ethernet帧的辅助函数“传输”)std::shared_ptr<OutputPort> port_;void transmit(const EthernetFrame& frame) const { port_->transmit(*this, frame); }// 接口的Ethernet(也称为硬件、网络访问层或链路层)地址EthernetAddress ethernet_address_;// 接口的IP(也称为互联网层或网络层)地址Address ip_address_;// 已接收的数据报std::queue<InternetDatagram> datagrams_received_ {};// ARP映射std::unordered_map<uint32_t,EthernetAddress> ipToEthernetMap;// ARP请求时间队列std::unordered_map<uint32_t,uint64_t> recent_arp_requests;// 等待发送的数据报std::unordered_map<uint32_t,InternetDatagram> waiting_datagrams_;// 当前时间uint64_t currentTime = 0;
};

network_interface.cc:

#include <iostream>#include "arp_message.hh"
#include "exception.hh"
#include "network_interface.hh"using namespace std;//! \param[in] ethernet_address 接口的Ethernet(ARP称为“硬件”)地址
//! \param[in] ip_address 接口的IP(ARP称为“协议”)地址
NetworkInterface::NetworkInterface(string_view name,shared_ptr<OutputPort> port,const EthernetAddress& ethernet_address,const Address& ip_address): name_(name),port_(notnull("OutputPort", move(port))),ethernet_address_(ethernet_address),ip_address_(ip_address),ipToEthernetMap(),recent_arp_requests(),waiting_datagrams_()
{cerr << "DEBUG: 网络接口具有以太网地址 " << to_string(ethernet_address) << " 和 IP 地址 " << ip_address.ip() << "\n";
}//! \param[in] dgram 要发送的IPv4数据报
//! \param[in] next_hop 要发送到的接口的IP地址(通常是路由器或默认网关,但也可以是另一台主机,
//  如果直接连接到与目标相同的网络)
//  注意:可以使用Address::ipv4_numeric()方法将Address类型转换为uint32_t(原始的32位IP地址)。
void NetworkInterface::send_datagram(const InternetDatagram& dgram, const Address& next_hop)
{   uint32_t next_hop_ip = next_hop.ipv4_numeric();EthernetFrame frame;    // 若可查询到映射if(create_IPv4frame(dgram,next_hop_ip,frame)) {transmit(frame);return ;}// 如果未知目标以太网地址,发送ARP请求if (((currentTime - recent_arp_requests[next_hop_ip]) >= 5*1000) || (!recent_arp_requests[next_hop_ip] && !currentTime)) {send_arp_request(next_hop_ip);recent_arp_requests[next_hop_ip] = currentTime;}// 待排队发送的的数据报waiting_datagrams_[next_hop_ip] = dgram;
}//! \param[in] frame 输入的Ethernet帧
void NetworkInterface::recv_frame(const EthernetFrame& frame)
{   // 检查帧是否是发给我们的 或者广播if(frame.header.dst != ethernet_address_ && frame.header.dst != ETHERNET_BROADCAST){return ;}// 为IPV4数据报if(frame.header.type == frame.header.TYPE_IPv4){// 处理IPv4帧InternetDatagram dgram;if (parse(dgram, frame.payload)) {// 用于上层通信的数据报datagrams_received_.push(dgram);}}            // 为ARP数据报if(frame.header.type == frame.header.TYPE_ARP){// 处理ARP帧ARPMessage arp_msg;if (parse(arp_msg, frame.payload)) {ipToEthernetMap[arp_msg.sender_ip_address] = arp_msg.sender_ethernet_address;recent_arp_requests[arp_msg.sender_ip_address] = currentTime;// 如果是ARP请求并且目标是我们的IP地址,发送ARP回复if (reply_arp_request(arp_msg)) {return ;}// 如果是ARP回复且目标是我们的IP地址,处理排队的数据报if (create_ARPframe(arp_msg)) {return ;}}}
}//! \param[in] ms_since_last_tick 自上次调用此方法以来的毫秒数
void NetworkInterface::tick(const size_t ms_since_last_tick)
{   currentTime += ms_since_last_tick;for (auto it = recent_arp_requests.begin(); it != recent_arp_requests.end(); ) {// ARP映射记录时间超过30秒删除if (it->second + 30*1000 <= currentTime) {ipToEthernetMap.erase(it->first);it = recent_arp_requests.erase(it);currentTime = 0;} else {++it;}}
}// IPv4创建以太网帧
bool NetworkInterface::create_IPv4frame(const InternetDatagram& dgram, uint32_t next_hop, EthernetFrame& frame)
{auto it = ipToEthernetMap.find(next_hop);if (it != ipToEthernetMap.end()) {frame.header.type = EthernetHeader::TYPE_IPv4;frame.header.dst = it->second;frame.header.src = ethernet_address_;// 序列化IPv4frame.payload = serialize(dgram);return true;}return false; // 返回 false 表示没有找到对应的以太网地址
}// 利用ARP创建以太网帧
bool NetworkInterface::create_ARPframe(const ARPMessage & arp_msg){if(arp_msg.opcode == ARPMessage::OPCODE_REPLY && arp_msg.target_ip_address == ip_address_.ipv4_numeric()){EthernetFrame frame_;auto it = waiting_datagrams_.find(arp_msg.sender_ip_address);       if (it != waiting_datagrams_.end()) {frame_.header.type = EthernetHeader::TYPE_IPv4;frame_.header.src = ethernet_address_;frame_.header.dst = arp_msg.sender_ethernet_address;frame_.payload = serialize(it->second);transmit(frame_);   waiting_datagrams_.erase(it); }return true;}else{return false;}
}// 发送ARP请求获取目标MAC地址
void NetworkInterface::send_arp_request(uint32_t next_hop_ip) {// 构建ARP请求ARPMessage arp_request;arp_request.opcode = ARPMessage::OPCODE_REQUEST;            // 操作码:请求arp_request.sender_ethernet_address = ethernet_address_;    // 发送方MAC地址arp_request.sender_ip_address = ip_address_.ipv4_numeric(); // 发送方IP地址arp_request.target_ethernet_address = EthernetAddress{0, 0, 0, 0, 0, 0}; // 目标MAC地址:全零arp_request.target_ip_address = next_hop_ip; // 目标IP地址// ARP的数据帧EthernetFrame frame;frame.header.src = ethernet_address_;frame.header.dst = ETHERNET_BROADCAST;frame.header.type = EthernetHeader::TYPE_ARP;// 序列化ARP请求Serializer serializer;arp_request.serialize(serializer);frame.payload = serializer.output();transmit(frame);
}// 回复ARP请求
bool NetworkInterface::reply_arp_request(const ARPMessage & arp_msg){if(arp_msg.opcode == ARPMessage::OPCODE_REQUEST && arp_msg.target_ip_address == ip_address_.ipv4_numeric()){// 构建reply ARPARPMessage arp_reply;arp_reply.opcode = ARPMessage::OPCODE_REPLY;arp_reply.sender_ethernet_address = ethernet_address_;arp_reply.sender_ip_address = ip_address_.ipv4_numeric();arp_reply.target_ethernet_address = arp_msg.sender_ethernet_address;arp_reply.target_ip_address = arp_msg.sender_ip_address;EthernetFrame reply_frame;reply_frame.header.type = EthernetHeader::TYPE_ARP;reply_frame.header.src = ethernet_address_;reply_frame.header.dst = arp_msg.sender_ethernet_address;reply_frame.payload = serialize(arp_reply);  transmit(reply_frame);        return true;   }else{return false;}
}void NetworkInterface::prints(){cout<<"当前所有映射 "<<endl;for(auto it = ipToEthernetMap.begin();it != ipToEthernetMap.end();it++){cout<<"IP序列:  "<<it->first<<endl;cout<<"MAC地址: "<<to_string(it->second)<<endl;cout<<"对应时间"<<recent_arp_requests[it->first]<<endl;cout<<"当前时间"<<currentTime<<endl;}
}

已经更新仓库lms2004/minnow: CS 144 networking lab (github.com)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

timm笔记

快速开始 安装 timm pip install timmtimm.create_model (model_name: str,pretrained: bool False,pretrained_cfg:Union None,pretrained_cfg_overlay: Optional None,checkpoint_path: str ,scriptable: Optional None,exportable: Optional None,no_jit: Optiona…

SpringMVC流程

1、SpringMVC常用组件&#xff1a; DispatcherServlet&#xff08;请求分发器&#xff09;&#xff1a;Spring MVC的核心组件之一&#xff0c;负责处理全局配置和将用户请求分发给其他组件进行处理。Controller&#xff08;处理器&#xff09;&#xff1a; 实际处理业务逻辑的…

B站滑块登录之极验点选

滑块登录这些东西都不是很难&#xff0c;我个人的去处理的话一般会考虑三种方案&#xff0c;一个是自动化selenium 二是各类打码平台 三是ocr识别&#xff0c;本文是selenium接打码平台&#xff0c;也是个比较常规的操作。 先常规步骤跟着来吧&#xff0c;做登录的话把基本的模…

Golang:使用wellington/go-libsass对CSS进行预处理

wellington/go-libsass是一个用于预处理CSS文件的库&#xff0c;采用 Go封装&#xff0c;100% 与 Sass 兼容的 libsass 项目 不过需要依赖libsass&#xff0c;现在已经过时了&#xff0c;可以考虑使用dart-sass 文档 https://github.com/wellington/go-libsass 安装 go ge…

淘宝搬家到另一个店铺可以吗?店铺搬家了影响退款吗?

在淘宝平台上&#xff0c;商家可能会因为各种原因需要将店铺迁移到另一个店铺。那么&#xff0c;淘宝搬家到另一个店铺是否可行&#xff0c;搬家对退款又会产生什么影响呢&#xff1f;接下来详细解答这些问题。 一、淘宝搬家到另一个店铺可以吗 可以 1、 淘宝搬家流程&#…

网络编程-TCP并发服务器-多点通信-域套接字

多进程实现TCP并发&#xff1a;依赖于while循环模式可初步实现并发功能&#xff0c;但是由于accpet函数和读写函数是阻塞的&#xff0c;导致必须要等待阻塞结束下一个用户才能连接&#xff0c;所以考虑使用多进程。 思路&#xff1a;将与客户端建立连接设置成父进程&#xff0…

Tower在深度学习中的概念,tower没有确切定义

在论文UniTS中&#xff0c;来自Havard的工作。 tower更像是针对一个task的组件 tower这个概念貌似在REC&#xff08;recommendation&#xff09;推荐系统中使用较多 deep learning - What is a tower? - Data Science Stack Exchange https://developers.google.com/machin…

Android APP在debug模式下,如何避免activity被系统destroy

最近在调式APP时发现&#xff0c;如果在APP运行时&#xff08;比如&#xff1a;进入了某个子模块的某个列表项的详情页&#xff1a;InfoShowActivity&#xff09;&#xff0c;点击home按钮&#xff0c;返回主屏幕。然后再返回APP时&#xff0c;APP不会显示之前的界面&#xff0…

技术前沿 |【VL-BEIT:引领未来的极简单阶段多模态预训练方案】

VL-BEIT&#xff1a;引领未来的极简单阶段多模态预训练方案 引言一、VL-BEIT的基本介绍二、VL-BEIT的原理和工作方式三、VL-BEIT的特点四、VL-BEIT的应用场景五、总结与展望 引言 在人工智能蓬勃发展的今天&#xff0c;多模态预训练模型正逐渐成为研究和应用的热点。这些模型能…

二叉树OJ题目

一.二叉树第k层结点个数 有这样的一个思路&#xff1a;我既然要求第k层的结点个数&#xff0c;我肯定是要用到递归&#xff0c;那么当我在递归到第k层的时候我就开始判断&#xff0c;这一层是不是我所需要的那一层&#xff0c;如果是&#xff0c;就计数有几个节点&#xff0c;…

边框渐变样式

实现样式&#xff1a; 对应代码&#xff1a; div {min-height: 40vh;border: 10px solid transparent;background-image: linear-gradient(#222, #222), var(--gradient);background-origin: border-box;background-clip: padding-box, border-box;border-radius: 10px;positi…

一周开发一个在线客服系统

使用 Go 和 Gin 框架开发在线客服系统是一种高效且性能优越的选择。以下是具体的开发计划&#xff0c;专注于使用 Gin 框架来实现后端&#xff1a; 演示效果&#xff1a;gofly.v1kf.com 第一天&#xff1a;需求分析和设计 需求分析&#xff1a; 确定系统功能&#xff1a;实时聊…

【数组】Leetcode 228. 汇总区间【简单】

汇总区间 给定一个 无重复元素 的 有序 整数数组 nums 。 返回 恰好覆盖数组中所有数字 的 最小有序 区间范围列表 。也就是说&#xff0c;nums 的每个元素都恰好被某个区间范围所覆盖&#xff0c;并且不存在属于某个范围但不属于 nums 的数字 x 。 列表中的每个区间范围 [a,…

粉丝问,有没有UI的统计页面,安排!

移动应用的数据统计页面具有以下几个重要作用&#xff1a; 监控业务指标&#xff1a;数据统计页面可以帮助用户监控关键业务指标和数据&#xff0c;例如用户活跃度、销售额、转化率等。通过实时更新和可视化呈现数据&#xff0c;用户可以及时了解业务的整体状况和趋势。分析用…

每日练习之字符串——得分

得分 题目描述 运行代码 #include <iostream> using namespace std; int main(){int n;cin>>n;while(n--){string s;cin>>s;int ls.length();int a0;int t1;for(int i0;i<l;i){if(s[i]O){at;t;}else if(s[i]X){t1;}}cout<<a<<endl;} } 代码…

QT7_视频知识点笔记_5_线程,数据库

多线程 两种办法&#xff1a;第一种&#xff1a;Qt4.7之前的线程使用的方法&#xff08;简单&#xff09;&#xff1b;第二种&#xff1a;Qt4.7之后的&#xff08;灵活–推荐&#xff09;----connect最后一个参数的作用&#xff1a;默认连接&#xff0c;队列连接&#xff0c;直…

操作系统总结4----死锁的处理策略总结

目录 2.4.2 死锁的处理策略-----预防死锁 &#xff08;1&#xff09;知识总览 &#xff08;2&#xff09;破环互斥条件 &#xff08;3&#xff09;破环不剥夺条件 &#xff08;4&#xff09;破环求情和保持条件 &#xff08;5&#xff09;破环循环等待条件 总结 2.4.3 死…

AI革命:生活无处不智能

AI革命&#xff1a;生活无处不智能 &#x1f604;生命不息&#xff0c;写作不止 &#x1f525; 继续踏上学习之路&#xff0c;学之分享笔记 &#x1f44a; 总有一天我也能像各位大佬一样 &#x1f3c6; 博客首页 怒放吧德德 To记录领地 &#x1f31d;分享学习心得&#xff0…

使用FFmpeg推流实现在B站24小时点歌直播

使用FFmpeg推流实现在B站24小时点歌直播 本文首发于个人博客 安装FFmpeg centos7 https://www.myfreax.com/how-to-install-ffmpeg-on-centos-7/ https://linuxize.com/post/how-to-install-ffmpeg-on-centos-7/ 使用FFmpeg在B站直播 https://zhuanlan.zhihu.com/p/2395…

竞赛 基于深度学习的动物识别 - 卷积神经网络 机器视觉 图像识别

文章目录 0 前言1 背景2 算法原理2.1 动物识别方法概况2.2 常用的网络模型2.2.1 B-CNN2.2.2 SSD 3 SSD动物目标检测流程4 实现效果5 部分相关代码5.1 数据预处理5.2 构建卷积神经网络5.3 tensorflow计算图可视化5.4 网络模型训练5.5 对猫狗图像进行2分类 6 最后 0 前言 &#…