网卡如何与UIP协议交互(包括arp, icmp等) 接上文
接下来看看UIP如何处理ARP应答的情况,在主循环中一段代码:
- else if(BUF->type == htons(UIP_ETHTYPE_ARP))
- {
-
uip_arp_arpin(); // 处理ARP应答
-
/* If the above function invocation resulted in data that
-
should be sent out on the network, the global variable
-
uip_len is set to a value > 0. */
- // 如果上面的函数返回的结果需要发送到网络上,那么uip_len就必须设置 > 0
-
if(uip_len > 0)
-
{
-
network_device_send(); // 回应ARP包
-
}
- }
在uip_arp_arpin()函数中主要是处理ARP应答。
这个函数是在设备接收到ARP包时,由驱动程序调用的.如果收到是ARP包是一个对本地主机上次发送的ARP请求的应答,那么就从包中取得自己想要的主机的MAC地址,加入自己的ARP缓存表中.如果收到是一个ARP请求,那就把自己的MAC地址打包成一个ARP应答,发送给请求的主机.看代码uip_arp.c的254行:
- void uip_arp_arpin(void)
-
{
-
if(uip_len < sizeof(struct arp_hdr))
- {
-
uip_len = 0;
-
return;
-
}
-
uip_len = 0;
-
-
switch(BUF->opcode) // 操作码
- {
-
case HTONS(ARP_REQUEST):
- // 如果是一个ARP请求,则发送应答
-
if(uip_ipaddr_cmp(BUF->dipaddr, uip_hostaddr))
- {
-
// 首先,我们将发送请求的主机注册到ARP缓存表中,因为我们很
- // 可能要跟它要有更多的交流
-
uip_arp_update(BUF->sipaddr, &BUF->shwaddr);
-
-
// 回应的操作码是 2.
-
BUF->opcode = HTONS(2);
-
// 将收到的ARP包的发送端以太网地址,变为目的以太网地址
-
memcpy(BUF->dhwaddr.addr, BUF->shwaddr.addr, 6);
-
// 将自己的以太网地址,赋值给ARP包的发送端以太网地址
- memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6);
- // 对应以太网源地址
-
memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6);
- // 对应以太网目的地址
-
memcpy(BUF->ethhdr.dest.addr, BUF->dhwaddr.addr, 6);
-
-
BUF->dipaddr[0] = BUF->sipaddr[0];
-
BUF->dipaddr[1] = BUF->sipaddr[1];
-
BUF->sipaddr[0] = uip_hostaddr[0];
-
BUF->sipaddr[1] = uip_hostaddr[1];
-
-
BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP);
-
uip_len = sizeof(struct arp_hdr);
-
}
-
break;
- // 如果收到的是一个ARP应答,而且也是我们所要的应答的话,就插件
- // 并更新ARP缓存表
-
case HTONS(ARP_REPLY):
-
if(uip_ipaddr_cmp(BUF->dipaddr, uip_hostaddr))
- {
-
uip_arp_update(BUF->sipaddr, &BUF->shwaddr);
-
}
-
break;
-
}
-
-
return;
-
}
还有一个是ARP周期处理函数,在主循环中代码如下:
// 每10秒运行一次
if(timer_expired(&arp_timer))
{
timer_reset(&arp_timer);
uip_arp_timer();
}
具体的代码:
- void uip_arp_timer(void)
-
{
-
struct arp_entry *tabptr;
-
++arptime; // 这个是个全局变量,结合uip_arp_update来更新缓存表
-
for(i = 0; i < UIP_ARPTAB_SIZE; ++i)
- {
-
tabptr = &arp_table[i];
- // 把超过20分钟都没有更新的项扔掉
-
if((tabptr->ipaddr[0] | tabptr->ipaddr[1]) != 0 &&
-
arptime - tabptr->time >= UIP_ARP_MAXAGE)
- {
-
memset(tabptr->ipaddr, 0, 4);
-
}
-
}
-
}
(以上翻译摘自:USR嵌入式技术社区>群组>联盟直属>资料翻译组>UIP文档中文翻译组>uIP的ARP协议代码分析之一 ARP请求
)
阅读(494) | 评论(0) | 转发(0) |