type
Post
status
Published
slug
2023/08/12/CS144-2023-Spring-network_interface.cc-function-part-implementation-explanation
summary
tags
开发
思考
category
学习思考
icon
password
new update day
Property
Oct 22, 2023 01:31 PM
created days
Last edited time
Oct 22, 2023 01:31 PM
类头文件简介
网络接口这个类,涉及到数据包发送(
send_datagram
)、数据包收取(recv_frame
)、时间控制(tick
)、尝试发送(
maybe_send
)、查看 arp 缓存并发送数据包(check_arp_send_frame
)这些方法,其中 check_arp_send_frame
是私有工具方法,是我添加到里面辅助处理数据的,具体的定义可以看下面的 .hh
文件。其中在类
NetworkInterface
中定义了两个私有类 ArpTableEntry
与 ArpWaitingEntry
,分别用来表示 arp 表中的一条条目,以及已经发送 arp 请求但是还没有收到对应的回复信息的 ARP 条目。- ethernet_address_
- 该接口的网络地址
- ip_address_
- 该接口的 IP 地址
- arp_table_
std::unordered_map<uint32_t, ArpTableEntry> arp_table_
- arp 缓存表
- key:ip地址对应的 int 值
- value:
ArpTableEntry
time_ticks_
- 时钟数
- ip 地址对应的 int 数值
- waiting_for_arp_queue_
std::unordered_map<uint32_t, std::queue<std::shared_ptr<EthernetFrame>>> waiting_for_arp_queue_
- key:ip地址对应的 int 值
- value:对应 ip 地址的 arp 请求队列,保存的是对应的以太网请求帧的智能指针。
- waiting_for_ack_arp_
std::unordered_map<uint32_t, std::shared_ptr<ArpWaitingEntry>> waiting_for_ack_arp_
- key:ip地址对应的 int 值
- value:已经发送 arp 请求包等待回应的
ArpWaitingEntry
time_ticks_
- 时钟数
std::shared_ptr<EthernetFrame> frame_;
- 发送的以太网帧
- ethernet_queue_
std::queue<std::shared_ptr<EthernetFrame>>
- 队列内部是排队需要发送的以太网帧
- arp_entry_timeout_
- arp 条目默认超时时间:
30000
- arp_request_timeout_
- arp 以太网请求包超时时间:
5000
network_interface.hh
class NetworkInterface { private: class ArpTableEntry { public: // The time ticks uint64_t time_ticks_; EthernetAddress ethernet_address_; }; class ArpWaitingEntry { public: uint64_t time_ticks_; std::shared_ptr<EthernetFrame> frame_; }; // Ethernet (known as hardware, network-access, or link-layer) address of the interface EthernetAddress ethernet_address_; // IP (known as Internet-layer or network-layer) address of the interface Address ip_address_; // The ARP table maps IP addresses to Ethernet addresses std::unordered_map<uint32_t, ArpTableEntry> arp_table_; // The ARP queue maps IP addresses to a queue of Ethernet frames awaiting resolution of the // corresponding Ethernet address std::unordered_map<uint32_t, std::queue<std::shared_ptr<EthernetFrame>>> waiting_for_arp_queue_; std::unordered_map<uint32_t, std::shared_ptr<ArpWaitingEntry>> waiting_for_ack_arp_; // The Ethernet queue is a queue of Ethernet frames awaiting transmission std::queue<std::shared_ptr<EthernetFrame>> ethernet_queue_; // The time ticks for ARP uint64_t arp_entry_timeout_ = 30000; uint64_t arp_request_timeout_ = 5000; void check_arp_send_frame( EthernetAddress& ethernet_address, uint32_t& ip_address ); public: // Construct a network interface with given Ethernet (network-access-layer) and IP (internet-layer) // addresses NetworkInterface( const EthernetAddress& ethernet_address, const Address& ip_address ); // Access queue of Ethernet frames awaiting transmission std::optional<EthernetFrame> maybe_send(); // Sends an IPv4 datagram, encapsulated in an Ethernet frame (if it knows the Ethernet destination // address). Will need to use [ARP](\ref rfc::rfc826) to look up the Ethernet destination address // for the next hop. // ("Sending" is accomplished by making sure maybe_send() will release the frame when next called, // but please consider the frame sent as soon as it is generated.) void send_datagram( const InternetDatagram& dgram, const Address& next_hop ); // Receives an Ethernet frame and responds appropriately. // If type is IPv4, returns the datagram. // 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 "sender" fields. std::optional<InternetDatagram> recv_frame( const EthernetFrame& frame ); // Called periodically when time elapses void tick( size_t ms_since_last_tick ); };
方法简介
send_datagram
方法函数原型如下,即上层应用程序给我一个 IP 数据报文,和报文需要发送到的下一跳地址,我们需要将其发送到对应的地址上去:
void NetworkInterface::send_datagram( const InternetDatagram& dgram, const Address& next_hop )
算法流程
- 查看
arp_table_
是否存在对应 ip 的以太网 mac 地址
- 查看
waiting_for_ack_arp_
是否存在已经发送过的对应 ip 地址的 arp 请求包。
- 如果 两者都不存在
- 新建一个以太网帧智能指针对象
- arp 广播请求包
- 放入到网络接口发送队列
ethernet_queue_
中 - 更新
waiting_for_ack_arp_
对 arp 请求报文进行追踪
- 如果 arp 请求包已经发送
- 新建一个以太网帧
- 如果 arp 条目存在
- 将以太网帧设置为对应目标的 mac 地址
- 否则
- 将目标地址设置为广播地址
- 解析 ip 数据报内容,设置对应的类型与 payload 信息
- 如果 arp 条目存在
- 直接放入发送队列
- 否则
- 将对应的帧放入对应 ip 的 arp 等待队列中(都是需要向这个 ip 发送的数据帧)
recv_frame
方法函数原型如下:即在一个以太网帧到来的时候需要采取的动作
optional<InternetDatagram> NetworkInterface::recv_frame( const EthernetFrame& frame )
方法流程:
- 如果目的地址不对,且不是广播地址
- 返回空
optional<InternetDatagram>
- 如果是 ARP 类型的帧
- 解析 payload
- 如果是请求帧
- 如果目标 ip 地址是本机地址
- 构建以太网 arp 回复帧,智能指针,准备将自己的 mac 地址返回
- 压入接口的发送缓存队列
- 调用
check_arp_send_frame
工具函数,检查是否需要更新对应的 arp 缓存项,或者是否有等待 arp 地址的以太网帧队列。 - 如果是回复帧
- 更新 arp 缓存表
- 调用
check_arp_send_frame
工具函数,检查是否需要更新对应的 arp 缓存项,或者是否有等待 arp 地址的以太网帧队列。
- 如果是 ipv4 类型的数据包
- 直接解析数据帧,交付将 IP数据报交付上层
- 如果是其他类型
- 返回空
optional<InternetDatagram>
tick
函数原型为:用来更新自上次调用此方法以来的毫秒数,用来跟踪与更新数据包的时间,控制超时行为
void NetworkInterface::tick( const size_t ms_since_last_tick )
方法行为
- 遍历 arp 缓存表,对应的缓存项目
- 加上
ms_since_last_tick
- 如果超时
- 将对应的条目删除,并更新迭代器
- 否则
- 更新迭代器
- 遍历 arp 请求缓存表
- 加上
ms_since_last_tick
- 如果超时
- 将对应的条目删除,并更新迭代器
- 否则
- 更新迭代器
maybe_send
函数原型为:如果此网络接口的缓存队列中有数据,直接发送,如果没有就返回空
optional<EthernetFrame> NetworkInterface::maybe_send()
check_arp_send_frame
函数原型:此工具函数输入参数为 mac 地址和 ip 地址
void NetworkInterface::check_arp_send_frame( EthernetAddress& ethernet_address, uint32_t& ip_address )
函数逻辑:
- 如果 arp 缓存表中包含对应的 ip 条目
- 如果 arp 缓存表中的 mac 地址与传入的 mac 地址不一致
- 更新 arp 缓存表
- 如果等待 arp 确认缓存表中存在此 ip 地址的信息
- 取消追踪
- 如果不存在对应 ip 条目
- 将对应的 ip 、mac 地址对加入到 arp 缓存表中
- 如果等待 arp 确认的发送队列
waiting_for_arp_queue_
不为空 - 取出对应 ip 地址的智能指针队列
- 遍历队列
- 取出队列头
- 如果数据帧的目的地址与 arp 缓存表中的地址不一样(肯定不一样,因为放入队列的时候是广播地址)
- 更新目的 mac 地址
- 放入发送缓存队列中
- 删除队列头
- 清除对某 ip 的 arp 等待 ack 队列追踪
欢迎加入“喵星计算机技术研究院”,原创技术文章第一时间推送。

- 作者:tangcuyu
- 链接:https://expoli.tech/articles/2023/08/12/CS144-2023-Spring-network_interface.cc-function-part-implementation-explanation
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
相关文章