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
看流程。可以从测试程序推出大部分逻辑。
InternetDatagram
即IPv4Datagram
。包含一个IPv4Header
和一个Buffer
数组payload。
IPv4Header
包含ip头信息。
INTERNET PROTOCOL(https://www.rfc-editor.org/rfc/rfc791)
make_datagram
用两个ip地址生成一个ip包。payload是”hello”。
SendDatagram
调用NetworkInterface
的send_datagram
发ip包。
EthernetFrame
包含EthernetHeader
和Buffer
数组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地址。需要维护Address
到EthernetAddress
的对应关系。
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秒有效期,需判断到期重发。