【计网实验——prj9】路由器转发实验

本文介绍了一次计网实验,涉及路由器如何处理ARP和IP数据包。实验包括ARP缓存管理、ARP请求和应答处理,以及IP数据包的转发。在实验中,路由器成功实现了不同主机间的ping通信,以及连通性和路径测试。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【计网实验——prj9】路由器转发实验

实验要求

实验内容一

  • 运行给定网络拓扑(router_topo.py)
  • 在r1上执行路由器程序./router,进行数据包的处理
  • 在h1上进行ping实验
    • Ping 10.0.1.1 (r1),能够ping通
    • Ping 10.0.2.22 (h2),能够ping通
    • Ping 10.0.3.33 (h3),能够ping通
    • Ping 10.0.3.11,返回ICMP Destination Host Unreachable
    • Ping 10.0.4.1,返回ICMP Destination Net Unreachable

实验内容二

  • 构造一个包含多个路由器节点组成的网络
    • 手动配置每个路由器节点的路由表
    • 有两个终端节点,通过路由器节点相连,两节点之间的跳数不少于3跳,手动配置其默认路由表
  • 连通性测试
    • 终端节点ping每个路由器节点的入端口IP地址,能够ping通
  • 路径测试
    • 在一个终端节点上traceroute另一节点,能够正确输出路径上每个节点的IP信息

实现方案

  路由器的实现主要分为ARP和IP两个层次的数据包的处理和转发。

1. ARP数据包处理

  路由器在路由表中查找到下一跳IP地址后,需要得到IP地址对应的MAC地址才能实现局域网内数据包的转发。路由器使用ARP机制来查询下一跳IP地址对应的MAC地址,维护一个缓存ARP相关内容的数据结构——arpcachearpcache中缓存IP->MAC映射条目和查找不到IP对应映射条目而等待ARP应答的数据包。

1)ARP缓存管理

  在ARP机制中,路由器转发数据包之前,先在arpcache中查找下一跳IP地址对应的IP->MAC映射条目,如果找到,则填充数据包的目的MAC地址,并转发数据包;否则,将该数据包缓存在arpcache->req_list中,并发送ARP请求。

arpcache.carpcache_lookup 函数

  代码中用 arpcache_lookup 函数实现查找ARP缓存中的IP->MAC映射条目的过程,即遍历ARP缓存中的映射表,查找是否存在与输入IP地址匹配的条目,若存在则返回1,否则返回0。

// lookup the IP->mac mapping
//
// traverse the table to find whether there is an entry with the same IP
// and mac address with the given arguments
int arpcache_lookup(u32 ip4, u8 mac[ETH_ALEN])
{
   
	fprintf(stderr, "TODO: lookup ip address in arp cache.\n");
	pthread_mutex_lock(&arpcache.lock);
	for(int i = 0; i < MAX_ARP_SIZE; i++){
   
		if(ip4 == arpcache.entries[i].ip4 && arpcache.entries[i].valid){
   
			memcpy(mac, arpcache.entries[i].mac, ETH_ALEN);
			pthread_mutex_unlock(&arpcache.lock);
			return 1;
		}
	}
	pthread_mutex_unlock(&arpcache.lock);
	return 0;
}
arpcache.carpcache_append_packet 函数

  arpcache_append_packet函数实现的是在ARP缓存映射表中查找不到目的IP地址对应的映射条目时,将该数据包缓存在arpcache->req_list中,并发送ARP请求的过程。首先需要先查找需要发送的目的IP地址在不在缓存队列中。如果不在,则分配一个空间用来记录需要请求的目的IP地址条目,并配置好相关参数。接着发送ARP请求(这可能已经不是第一次发送请求了),来获得目的IP对应的MAC地址。
  代码实现如下:

// append the packet to arpcache
//
// Lookup in the list which stores pending packets, if there is already an
// entry with the same IP address and iface (which means the corresponding arp
// request has been sent out), just append this packet at the tail of that entry
// (the entry may contain more than one packet); otherwise, malloc a new entry
// with the given IP address and iface, append the packet, and send arp request.
void arpcache_append_packet(iface_info_t *iface, u32 ip4, char *packet, int len)
{
   
	fprintf(stderr, "TODO: append the ip address if lookup failed, and send arp request if necessary.\n");
	pthread_mutex_lock(&arpcache.lock);
	struct arp_req *req_entry = NULL, *q;
	int found_same_ip_entry = 0;
	list_for_each_entry_safe(req_entry, q, &(arpcache.req_list), list){
   
		if(req_entry->ip4 == ip4){
   
			int found_same_ip_entry = 1;
			break;
		}
	}
	if(found_same_ip_entry == 0){
   
		req_entry = (struct arp_req *) safe_malloc(sizeof(struct arp_req));
		init_list_head(&(req_entry->list));
		req_entry->ip4 = ip4;
		init_list_head(&(req_entry->cached_packets));
		req_entry->iface = (iface_info_t *) safe_malloc(sizeof(iface_info_t));
		memcpy(req_entry->iface, iface, sizeof(iface_info_t));
		req_entry->sent = 0;
		req_entry->retries = 0;	
		list_add_tail(&(req_entry->list), &(arpcache.req_list));
	}
	struct cached_pkt *pkt = (struct cached_pkt *) safe_malloc(sizeof(struct cached_pkt));
	pkt->packet = packet;
	pkt->len = len;
	init_list_head(&(pkt->list));
	list_add_tail(&(pkt->list), &(req_entry->cached_packets));
	//send arp request
	arp_send_request(iface, ip4);
	req_entry->retries ++;
	req_entry->sent = time(NULL);
	pthread_mutex_unlock(&arpcache.lock);
}
arpcache.carpcache_insert 函数

  若端口收到ARP应答包,则说明该端口需要将源IP和源MAC地址的映射插入到arpcache中,即调用arpcache_insert处理。arpcache_insert 函数需要将新的IP->MAC的映射写入到arpcachevalid值为0的条目,如果缓存已满,则随机替换掉其中一个(在本实现中,直接在遍历所有条目的最后将最后一个条目替换为新的IP->MAC映射,将遍历和替换操作合并在一个循环中)。然后将在缓存中等待该映射的数据包,依次填充目的MAC地址,调用 arp.c 中的iface_send_packet_by_arp函数转发出去,并删除掉相应缓存数据包。
  代码实现如下:

// insert the IP->mac mapping into arpcache, if there are pending packets
// waiting for this mapping, fill the ethernet header for each of them, and send
// them out
void arpcache_insert(u
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值