cs144网络课程4 network interface#

环境#

https://cs144.github.io/assignments/check4.pdf

commit lab3的代码。

merge lab4的代码
git merge origin/check4-startercode

编译/测试
cmake --build build
cmake --build build --target check4

network interface#

隔了两个月继续做lab。前面的代码细节忘了很多,但仍能很快上手,继续下面的lab。
这也是这些协议分层的好处,可以不用纠结某些细节。只要有一定基础知识,就能把握住整体流程。


network interface其实是要实现arp协议,完成NetworkInterface类。
An Ethernet Address Resolution Protocol(https://www.rfc-editor.org/rfc/rfc826)

tests/net_interface.cc看流程。可以从测试程序推出大部分逻辑。

InternetDatagramIPv4Datagram。包含一个IPv4Header和一个Buffer数组payload。

IPv4Header包含ip头信息。
INTERNET PROTOCOL(https://www.rfc-editor.org/rfc/rfc791)

make_datagram用两个ip地址生成一个ip包。payload是”hello”。

SendDatagram调用NetworkInterfacesend_datagram发ip包。

EthernetFrame包含EthernetHeaderBuffer数组payload。

EthernetHeader包含源和目标的以太网地址EthernetAddress。和包的长度和类型等。
类型可以是ip包,或者arp请求。

ETHERNET_BROADCAST是一个特殊的地址。 constexpr EthernetAddress ETHERNET_BROADCAST = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };

ExpectFrame一个ETHERNET_BROADCAST的包。意思就是初始状态调用send_datagram时,我们得按协议流程生成一个arp请求。
因为初始状态我们没有任何地址转换信息,必须广播arp请求,获取到网络上的arp信息,然后才能把ip包发到对应的地址。
这个就是arp的基本功能。

我们network interface的地址数据是在测试初始化时指定的。
const EthernetAddress local_eth = random_private_ethernet_address(); NetworkInterfaceTestHarness test { "typical ARP workflow", local_eth, Address( "4.3.2.1", 0 ) };

Address即ip地址。需要维护AddressEthernetAddress的对应关系。

Serializer相关在util/parser.hh

SendDatagram { datagram, Address( "192.168.0.1", 0 ) }发ip包到”192.168.0.1”。
此时不知道”192.168.0.1”的以太网地址,所以要发arp请求它的以太网地址。
( ARPMessage::OPCODE_REQUEST, local_eth, "4.3.2.1", {}, "192.168.0.1" ) 并且发ip包的请求需要存起来。等arp请求得到回复后,再发这个ip包。

然后测试程序生成一个随机target_eth作为回复,我们在NetworkInterface::recv_frame里处理这个回复,维护地址的对应关系。
此时要把之前发ip包的请求发出。

recv_frame收到的数据,如果目标以太网地址不是我们的地址,忽略。

recv_frame收到ip包时,解析并返回ip包,也就是交给上层协议继续处理。

到此可以通过第一个基本测试。


别人发到我这的,如果请求的是我的ip转换,要返回我的以太网地址。

如果别人请求我arp时,如果它的ip转换在我这不存在,顺便更新。

5秒内不要重发相同的arp请求。

我们维护的arp数据,每次更新后只有30秒有效期,需判断到期重发。