南京大学本科生实验报告¶
课程名称: 计算机网络 任课教师:田臣
学院 | 工程管理学院 | 专业(方向) | 计算机金融 |
---|---|---|---|
学号 | 211275022 | 姓名 | 田昊东 |
1040880153@qq.com | 开始/完成日期 | 2023/4/16~2023/4/16 |
实验名称¶
Lab3 Respond to ARP¶
实验目的¶
- 本实验是ipv4路由器章节的第一部分,主要任务是实现有关arp包的接受、处理、缓存等操作的路由器程序。
- 本实验主要分为对arp包进行存储和对arp包进行缓存两部分
实验内容¶
task2 Handle ARP Request¶
实现原理¶
-
代码分为两部分
-
第一部分是在构造函数中获取路由器个端口的ip和mac地址,建立字典存储映射关系,方便后续进行查找
python self.interfaces={} for item in net.interfaces(): self.interfaces[item.ipaddr]=item.ethaddr
-
第二部分在nandle_packet中,需要先判断是不是发向路由器某个端口的arp请求包,如果是的话就根据第一部分的到的字典构造回复包并发送
python arp = packet.get_header(Arp) if arp is not None and arp.operation == ArpOperation.Request and arp.targetprotoaddr in self.interfaces: #构造arp回复包 res = create_ip_arp_reply(self.interfaces[arp.targetprotoaddr], arp.senderhwaddr, arp.targetprotoaddr, arp.senderprotoaddr) #发送arp回复包 self.net.send_packet(ifaceName, res) return
给定测试结果¶
自定义测试¶
测试思路¶
- 测试包共包含三种情况:
- 发送向路由器一个端口的arp请求,应该答复
- 发送向非路由器端口的arp请求,应该丢弃
- 发送向路由器端口的非arp包,应该丢弃
def test_router():
s = TestScenario("router tests")
s.add_interface('eth0', '10:00:00:00:00:01','1.0.0.1')
s.add_interface('eth1', '10:00:00:00:00:02','1.0.0.2')
s.add_interface('eth2', '10:00:00:00:00:03','1.0.0.3')
# 发送向路由器一个端口的arp请求,应该答复
receive_pkt = create_ip_arp_request("20:00:00:00:00:01", "2.2.2.2", "1.0.0.1")
s.expect(PacketInputEvent("eth0", receive_pkt), "An Arp package from 2.2.2.2(20:00:00:00:00:01) to 1.0.0.1(10:00:00:00:00:01) should arrive on eth0")
send_pkt = create_ip_arp_reply("10:00:00:00:00:01","20:00:00:00:00:01","1.0.0.1","2.2.2.2")
s.expect(PacketOutputEvent("eth0", send_pkt), "Ethernet frame destined to 20:00:00:00:00:02 should be send from eth0")
# 发送向非路由器端口的arp请求,应该丢弃
receive_pkt = create_ip_arp_request("20:00:00:00:00:01", "2.2.2.2", "2.0.0.1")
s.expect(PacketInputEvent("eth0", receive_pkt), "An Arp package from 2.2.2.2(20:00:00:00:00:01) to 2.0.0.1(10:00:00:00:00:01) should arrive on eth0")
s.expect(PacketInputTimeoutEvent(1.0), "No packet should send to eth0")
# 发送像路由器端口的非arp包,应该丢弃
receive_pkt = new_packet("20:00:00:00:00:01", "10:00:00:00:00:01", "2.2.2.2", "1.0.0.1")
s.expect(PacketInputEvent("eth0", receive_pkt), "An eternet package from 2.2.2.2(20:00:00:00:00:01) to 1.0.0.1(10:00:00:00:00:01) should arrive on eth0")
s.expect(PacketInputTimeoutEvent(1.0), "No packet should send to eth0")
return s
测试结果¶
抓包分析¶
- 从server1向10.1.1.2(路由器的一个端口)进行ping操作
- 可以看到server1先发送了arp请求包询问目标ip对应的mac地址,由于这个地址是一个路由器端口,因此路由器会进行答复,返回一个arp答复包
- 从抓包信息可以看到:请求包中的目的mac地址为全0,进行了广播,这是因为现在只知道目的地址的ip而不知道mac,否则就不需要发送arp了
- 从接受到的路由器返回的arp答复包中可以看到,地址不再有空缺,现在已将有了对话双方的ip和mac地址的全部信息
-
之后发送了三个icmp包,但是都没有收到答复,这是因为当前阶段的路由器只会处理发向自己的arp包,其他包都会被直接丢弃
task3 Cached ARP Table¶
-
arp表类结构:
-
```python class Arptable: def init(self): self.table = {} self.timeout = 100
# 添加或更新arp缓存 def update(self, ip, mac): # 先删除超时的arp缓存 self.check() # 添加或更新arp缓存 self.table[ip] = (mac, time.time()) # 打印arp缓存 print("arp cache: ", self.table) # 删除超时的arp缓存 def check(self): for ip, (mac, t) in self.table.items(): if time.time() - t > self.timeout: del self.table[ip]
```
-
使用一个字典来维护ip和mac的对应关系
-
目前提供两种操作:
update
:如果ip已经在表中了,则更新mac地址,并重置时间;如果不在则直接添加进来check
:检查是否有表项超时,如果有则删除
-
测试:
-
先用server1 ping server2可以看到表项中多了server1的信息
- 再立即用server2 ping server1可以看到表中又多了server2的信息
- 等待一段时间后用用server1 ping client 表中只有server1的信息,这说明之前的缓存信息已经由于超时被删除
实验总结¶
- 这次实验总体上任务比较少,也比较简单,只实现了路由器与arp相关的部分功能
- 期待逐步完善,最终实现一个较为完整的ipv4路由器程序