设为首页 加入收藏

TOP

LWIP学习记录---ARP协议(2)ARP数据包接收过程(一)
2023-07-23 13:28:51 】 浏览:78
Tags:LWIP 习记录 ---ARP 协议 ARP 包接收

(一)ARP之 数据包接收过程

?

? 先看一下整个数据流的传输过程。


  1. 首先etherneti_input()函数 从底层网卡驱动接收到原始数据,若是ip包或者ARP包则调用ethernet_input()。

    s32_t ethernetif_input(struct netif *netif)
    {
      struct ethernetif *ethernetif;          //网络接口信息结构体,此处无用。
      struct eth_hdr *ethhdr;                  //以太网帧 头部结构体指针。
      struct pbuf *p;
    
      ethernetif = netif->state;
    
      p = low_level_input(netif);            //!!调用底层函数读取一个数据包。
    
      if (p == NULL) 
      {
      	return 0;
      }
      
      ethhdr = p->payload;                  //将ethhdr指针指向数据包中以太网头部
    
      switch (htons(ethhdr->type)) {       //判断数据包中的帧类型 ,要大小端转换。
      case ETHTYPE_IP:
      case ETHTYPE_ARP:
        /* full packet send to tcpip_thread to process */
        if (netif->input(p, netif)!=ERR_OK)  //调用netif->input 进行处理。
         { 
           pbuf_free(p);                      //释放Pbuf
           p = NULL;
         }
        break;
    
      default:
        pbuf_free(p);
        p = NULL;
        break;
      }
    
      return 1;
    }
    


可见,此函数未作实质性的处理,只是判断以太网中帧类型,并调用中netif->input函数指针处理,此处指向的就是 ethernet_input函数。我们来看看ethernet_input函数做了哪些事情。(不停地套娃~)
err_t ethernet_input(struct pbuf *p, struct netif *netif)
{
  struct eth_hdr* ethhdr;                  //以太网帧头部结构体指针
  u16_t type;

  if (p->len <= SIZEOF_ETH_HDR) {     //长度校验,ARP包必须包含在第一个PBUF的数据区。
    goto free_and_return;
  }

  ethhdr = (struct eth_hdr *)p->payload;   //以太网帧指针 指向以太网帧头部

  type = ethhdr->type;                      //获取帧类型

  switch (type) {
    case PP_HTONS(ETHTYPE_IP):
#if ETHARP_TRUST_IP_MAC
      /* update ARP table */
      etharp_ip_input(netif, p);   //使用IP头部以及 以太网头部MAC 更新 ARP表。
#endif /* ETHARP_TRUST_IP_MAC */
          
      /* skip Ethernet header */
      if(pbuf_header(p, -ip_hdr_offset)) {  //去掉以太网头部
        goto free_and_return;       //若操作失败,则释放pbuf
      } else {
        /* pass to IP layer */
        ip_input(p, netif);         //若头部去除成功,则调用IP输入处理函数处理数据。
      }
      break;
      
    case PP_HTONS(ETHTYPE_ARP):    //若是ARP数据包
      /* pass p to ARP module */
      etharp_arp_input(netif, (struct eth_addr*)(netif->hwaddr), p);  //调用ARP数据包处理函数。
      break;


    default:
      goto free_and_return;
  }

  return ERR_OK;

free_and_return:
  pbuf_free(p);
  return ERR_OK;
}


? 这个函数也很简单,就是根据数据包的type 类型进行判断 是IP包还是ARP包?是IP包则去掉 **以太网帧头部**,调用 **ip_input** 函数处理,若是ARP包,则调用 **etharp_arp_input() **处理数据包。

那我们接下来看看数据包是怎么处理的呢?

(二)ARP之 数据包处理过程

从之前讲述的知识可以了解到 etharp_arp_input()函数有两个功能:

  • 若接收到是ARP应答包,则需要根据应答信息更新ARP缓存表。

  • 若接收到ARP请求包,则需要:

    1. 若这个请求包,与本机IP地址不符合,则不需要应答,但是要将请求包中的 IP和MAC加入到自己的缓存表中,以备到时候需要使用。

    2. 若这个请求包,与本机IP地址符号,除了要将源主机的IP与MAC加入缓存表之外,还要回复一个应答,告诉本机的MAC地址是多少。


好,有了上面的思路,我们具体来看一看代码是怎么实现的。

(1)etharp_arp_input()函数分析

细细品味~~

static void etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
{
  struct etharp_hdr *hdr;      //ARP数据包包头部结构指针。
  struct eth_hdr *ethhdr;      //以太网头部结构体指针 
  ip_addr_t sipaddr, dipaddr;
  u8_t for_us;                //指示ARP包是否发送给本机的。


  /* drop short ARP packets: we have to check for p->len instead of p->tot_len here
     since a struct etharp_hdr is pointed to p->payload, so it musn't be chained! */
  if (p->len < SIZEOF_ETHARP_PACKET) {          //arp 数据包不能分装在两个PBUF中,不然不能用指针来操作内部了。
    pbuf_free(p);
    return;
  }

  ethhdr = (struct eth_hdr *)p->payload;
  hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR);  //hdr 指向ARP数据包首部

  /* RFC 826 "Packet Reception": */
  if ((hdr->hwtype != PP_HTONS(HWTYPE_ETHERNET)) ||  //判断ARP数据包的合法型,要是不合法,则直接删除该数据包。
      (hdr->hwlen != ETHARP_HWADDR_LEN) ||
      (hdr->protolen != sizeof(ip_addr_t)) ||
      (hdr->proto != PP_HTONS(ETHTYPE_IP)))  {

    pbuf_free(p);
    return;
  }

  /* Copy struct ip_addr2 to aligned ip_addr, to support compilers without
   * structure packing (not using str
首页 上一页 1 2 3 4 下一页 尾页 1/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇北斗协议4.0 下一篇微机原理与系统设计笔记8 | 可编..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目