Chinaunix首页 | 论坛 | 博客
  • 博客访问: 121432
  • 博文数量: 15
  • 博客积分: 1581
  • 博客等级: 上尉
  • 技术积分: 411
  • 用 户 组: 普通用户
  • 注册时间: 2010-01-29 09:48
文章分类

全部博文(15)

文章存档

2011年(8)

2010年(7)

我的朋友

分类: C/C++

2011-10-19 13:50:53

网卡如何与UIP协议交互(包括arp, icmp等) 接上文
    接下来看看UIP如何处理ARP应答的情况,在主循环中一段代码:
  1. else if(BUF->type == htons(UIP_ETHTYPE_ARP)) 
  2. {  
  3.     uip_arp_arpin();  // 处理ARP应答
  4.     /* If the above function invocation resulted in data that
  5.        should be sent out on the network, the global variable
  6.        uip_len is set to a value > 0. */
  7.    // 如果上面的函数返回的结果需要发送到网络上,那么uip_len就必须设置 > 0
  8.     if(uip_len > 0)
  9.     {
  10.         network_device_send(); // 回应ARP包
  11.     }
  12. }

在uip_arp_arpin()函数中主要是处理ARP应答。
    这个函数是在设备接收到ARP包时,由驱动程序调用的.如果收到是ARP包是一个对本地主机上次发送的ARP请求的应答,那么就从包中取得自己想要的主机的MAC地址,加入自己的ARP缓存表中.如果收到是一个ARP请求,那就把自己的MAC地址打包成一个ARP应答,发送给请求的主机.看代码uip_arp.c的254行:
  1. void uip_arp_arpin(void)
  2. {
  3.   if(uip_len < sizeof(struct arp_hdr))
  4.   {
  5.     uip_len = 0;
  6.     return;
  7.   }
  8.   uip_len = 0;
  9.   
  10.   switch(BUF->opcode)  // 操作码
  11.   {
  12.       case HTONS(ARP_REQUEST):
  13.       // 如果是一个ARP请求,则发送应答
  14.       if(uip_ipaddr_cmp(BUF->dipaddr, uip_hostaddr))
  15.       {
  16.           // 首先,我们将发送请求的主机注册到ARP缓存表中,因为我们很
  17.           // 可能要跟它要有更多的交流
  18.           uip_arp_update(BUF->sipaddr, &BUF->shwaddr);  
  19.       
  20.           // 回应的操作码是 2.
  21.           BUF->opcode = HTONS(2);
  22.           // 将收到的ARP包的发送端以太网地址,变为目的以太网地址
  23.           memcpy(BUF->dhwaddr.addr, BUF->shwaddr.addr, 6);
  24.           // 将自己的以太网地址,赋值给ARP包的发送端以太网地址
  25.           memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6);
  26.           // 对应以太网源地址
  27.           memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6);
  28.           // 对应以太网目的地址
  29.           memcpy(BUF->ethhdr.dest.addr, BUF->dhwaddr.addr, 6);
  30.       
  31.           BUF->dipaddr[0] = BUF->sipaddr[0];
  32.           BUF->dipaddr[1] = BUF->sipaddr[1];
  33.           BUF->sipaddr[0] = uip_hostaddr[0];
  34.           BUF->sipaddr[1] = uip_hostaddr[1];

  35.           BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP);
  36.           uip_len = sizeof(struct arp_hdr);
  37.      }
  38.      break;
  39.     // 如果收到的是一个ARP应答,而且也是我们所要的应答的话,就插件
  40.     // 并更新ARP缓存表
  41.     case HTONS(ARP_REPLY): 
  42.     if(uip_ipaddr_cmp(BUF->dipaddr, uip_hostaddr))
  43.     {
  44.       uip_arp_update(BUF->sipaddr, &BUF->shwaddr);
  45.     }
  46.     break;
  47.   }

  48.   return;
  49. }
还有一个是ARP周期处理函数,在主循环中代码如下:
// 每10秒运行一次
if(timer_expired(&arp_timer))
{
    timer_reset(&arp_timer);

    uip_arp_timer();
}
具体的代码:
  1. void uip_arp_timer(void)
  2. {
  3.   struct arp_entry *tabptr;
  4.   ++arptime;    // 这个是个全局变量,结合uip_arp_update来更新缓存表
  5.   for(i = 0; i < UIP_ARPTAB_SIZE; ++i)
  6.   {
  7.     tabptr = &arp_table[i];
  8.     // 把超过20分钟都没有更新的项扔掉
  9.     if((tabptr->ipaddr[0] | tabptr->ipaddr[1]) != 0 &&
  10.        arptime - tabptr->time >= UIP_ARP_MAXAGE)
  11.     {
  12.       memset(tabptr->ipaddr, 0, 4);
  13.     }
  14.   }
  15. }
 (以上翻译摘自:USR嵌入式技术社区>群组>联盟直属>资料翻译组>UIP文档中文翻译组>uIP的ARP协议代码分析之一 ARP请求 )
阅读(6685) | 评论(0) | 转发(3) |
给主人留下些什么吧!~~