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秒有效期,需判断到期重发。