UIP协议栈笔记·二

转载地址:http://blog.chinaunix.net/uid-23247944-id-2974928.html

1. 网卡如何与uIP协议交互(包括arp, icmp等)
   在我看来,CP2200提供了读取网络数据的能力,而UIP提供的是一种如何封装网路数据的策略。对用户数
据不断封装,最后交给CP2200发送,在UIP协议中有一个uip_buf缓冲用来接收和发送数据。

(转自:维库电子开发网>子通列表 > 协议栈)

   ARP请求和应答
在UIP协议中定义了一个ARP的struct。维护了一张
缓存表。

  1. struct arp_entry {
  2. u16_t ipaddr[2];  // 保存的是IP地址
  3. struct uip_eth_addr ethaddr; // 保存的是mac地址
  4. u8_t time;       // 缓存更新时间
  5. };

    ARP请求发送函数:void uip_arp_out(void)
* 为传出的IP包添加以太网头并看是否需要发送ARP请求. 
* 此函数应该在发送IP包时调用,它会检查IP包的目的IP地址,看看以太网应该使用什么目的MAC地址.
* 如果目的IP地址是在局域网中(由IP地址与子网掩码的与逻辑决定),函数就会从ARP缓存表中查找有
* 无对应项.若有,就取对应的MAC地址,加上以太网头,并返回,否则uip_buf[]中的数据包会被替换成一个
* 目的IP在址的ARP请求.原来的IP包会被简单的仍掉,此函数假设高层协议(如TCP)会最终重传扔掉的包.
* 如果目标IP地址并非一个局域网IP,则会使用默认路由的IP地址.
* uip_len.函数返回时,uip_buf[]中已经有了一个包,其长度由uip_len指定.

  1. void uip_arp_out(void)
  2. {
  3.   struct arp_entry *tabptr=0;
  4.   // 在ARP表中找到目的IP地址,构成以太网头.如果目的IP地址不在局域网中,则使用默认路由的IP.
  5.   // 如果ARP表中找不到,则将原来的IP包替换成一个ARP请求.  
  6.   // 首先检查目标是不是广播
  7.   if(uip_ipaddr_cmp(IPBUF->destipaddr, broadcast_ipaddr))
  8.   {
  9.     memcpy(IPBUF->ethhdr.dest.addr, broadcast_ethaddr.addr, 6);
  10.   } 
  11.   else 
  12.   {
  13.         /* 检查目标地址是否在局域网内 */
  14.         if(!uip_ipaddr_maskcmp(IPBUF->destipaddr, uip_hostaddr, uip_netmask))
  15.         {
  16.               /* 目的地址不在局域网内,所以保用默认路由器的地址来确在MAC地址 */
  17.               uip_ipaddr_copy(ipaddr, uip_draddr);
  18.         } 
  19.         else 
  20.         {
  21.             /* 否则,使用目标IP地址 */
  22.           uip_ipaddr_copy(ipaddr, IPBUF->destipaddr);
  23.         }
  24.         //这里遍历表,对比目的IP与ARP缓存表中的IP.
  25.         for(= 0; i < UIP_ARPTAB_SIZE; ++i)
  26.         {
  27.              tabptr = &arp_table[i];
  28.              if(uip_ipaddr_cmp(ipaddr, tabptr->ipaddr))
  29.              {
  30.                  break;
  31.              }
  32.          }
  33.          
  34.          if(== UIP_ARPTAB_SIZE)
  35.          {
  36.             /* 如果遍历到头没找到,将原IP包替换为ARP请求并返回 */
  37.               memset(BUF->ethhdr.dest.addr, 0xff, 6);  // 以太网目的地址
  38.               memset(BUF->dhwaddr.addr, 0x00, 6);      // 目的以太网地址
  39.               memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6);  //
  40.               memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6);  // 源以太网地址
  41.     
  42.               uip_ipaddr_copy(BUF->dipaddr, ipaddr);  // 目的IP地址
  43.               uip_ipaddr_copy(BUF->sipaddr, uip_hostaddr);  // 源IP地址
  44.               BUF->opcode = HTONS(ARP_REQUEST);  // ARP 请求
  45.               BUF->hwtype = HTONS(ARP_HWTYPE_ETH);  // 硬件类型 值为1
  46.               BUF->protocol = HTONS(UIP_ETHTYPE_IP); // 协议类型 值为0x8000表示IP地址
  47.               BUF->hwlen = 6;  
  48.               BUF->protolen = 4
  49.               BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP);  
  50.  
  51.               uip_appdata = &uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN];
  52.               uip_len = sizeof(struct arp_hdr);
  53.               return;
  54.           }
  55.  
  56.         // 如果是在局域网中,且在ARP缓存中找到了(如果没找到进行不到这一步,在上面就返回了),则构建以太网头
  57.          memcpy(IPBUF->ethhdr.dest.addr, tabptr->ethaddr.addr, 6);
  58.   }
  59.   memcpy(IPBUF->ethhdr.src.addr, uip_ethaddr.addr, 6);
  60.   IPBUF->ethhdr.type = HTONS(UIP_ETHTYPE_IP);
  61.   uip_len += sizeof(struct uip_eth_hdr);
  62. }

 (以上翻译摘自:USR嵌入式技术社区  群组  联盟直属  资料翻译组  UIP文档中文翻译组 uIP的ARP协议代码分析之一 ARP请求 )
ARP报文格式,请自行去学习:
ARP分组格式(帧格式,报文格式)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值