lwip之ARP协议

                                            ARP缓存表
/*****************************************************************************************************************
ARP协议的核心是ARP缓存表,ARP的实质就是对缓存表的建立、更新、查询等操作
lwip通过数组的方式来创建缓存表    struct etharp_entry arp_table[ARP_TABLE_SIZE]
数组arp_table的基本元素为缓存表项,定义如下:
    struct etharp_entry{
          struct pbuf *q;            // 单个IP数据包缓冲指针
        ip_addr_t ipaddr;        // 存储一对IP地址和MAC地址,这是ARP缓存表项的核心部分
        struct eth_addr ethaddr;
#if LWIP_SNMP
          struct netif *netif;
#endif
        u8_t state;                // 描述该缓存表项的状态,一共3种:ETHARP_STATE_EMPTY,ETHARP_STATE_PENDING,ETHARP_STATE_STABLE
        u8_t ctime;                // 该缓存表项的计数器,判断ARP超时用
    }
    
#define ARP_MAXAGE         240    // 处于稳定状态下的ARP缓存表项最大生存时间计数值
#define ARP_MAXPENDING     2    // 处于pending状态下的ARP缓存表项最大生存时间计数值
lwip通过定时函数etharp_tmr来删除那些超时的ARP缓存表项,该函数以5s为周期被调用
void etharp_tmr(void)    
{
    u8_t i;
    
    // 遍历整个ARP缓存表,删除超时的ARP缓存表项
    for (i = 0; i < ARP_TABLE_SIZE; ++i)
    {
        u8_t state = arp_table[i].state;
        
        if (state != ETHARP_STATE_EMPTY)
        {
            // 先将每个缓存表项的计数值加1
            arp_table[i].ctime++;
            
            // 判断是否超时
            if ((arp_table[i].ctime >= ARP_MAXAGE) ||
              ((state == ETHARP_STATE_PENDING)  && (arp_table[i].ctime >= ARP_MAXPENDING)))
              {
                  // 判断要删除的缓存表项上是否挂有数据
                  if (arp_table[i].q != NULL)
                  {
                      // 释放挂在缓存表项里的数据空间
                      free_etharp_q(arp_table[i].q);
                    arp_table[i].q = NULL;
                  }
                  
                  // 将该缓存表项标记为未用状态
                  arp_table[i].state = ETHARP_STATE_EMPTY;
              }
        }
    }
}
*****************************************************************************************************************/

                                            ARP报文
/*****************************************************************************************************************
lwip使用一个eth_hdr的结构体来描述以太网数据帧首部的14个字节:
                                                            struct eth_hdr{
                                                                struct eth_addr dest;    // 目的MAC地址
                                                                struct eth_addr src;    // 源MAC地址
                                                                u16_t type;                // 类型,主要用到2种:0x0800 - IP    0x0806 - ARP
                                                            }
以太网数据包最大帧长1518字节,最小帧长64字节,当无法满足最小64字节后,末尾用trailer字段来填充补足64字节

ARP和IP是两个独立的协议,都属于网络层,都依赖以太网数据帧来传输自身的协议数据                                                            
lwip使用一个etharp_hdr的结构体来描述ARP协议包:
                                                struct etharp_hdr{
                                                    u16_t hwtype;                // 硬件接口类型    ,以太网固定为0x0001
                                                    u16_t proto;                // 高一层协议类型,IP固定为0x0800
                                                    u8_t  hwlen;                // 硬件地址(MAC)长度,固定值6
                                                    u8_t  protolen;                // 高一层协议地址(IP)长度,固定值4
                                                    u16_t opcode;                // 操作码,1 - ARP请求    2 - ARP回复
                                                    struct eth_addr shwaddr;    // 源MAC
                                                    struct ip_addr2 sipaddr;    // 源IP
                                                    struct eth_addr dhwaddr;    // 目的MAC
                                                    struct ip_addr2 dipaddr;    // 目的IP
                                                }            
*****************************************************************************************************************/

                                            ARP层数据包输入
/*****************************************************************************************************************
ARP层数据包的输入由2部分组成:
1. 如果输入的是IP包,对于同网段的IP/MAC地址对,需要更新ARP缓存表
void etharp_ip_input(struct netif *netif, struct pbuf *p)
{
    struct eth_hdr *ethhdr;
      struct ip_hdr *iphdr;
      ip_addr_t iphdr_src;
      
      ethhdr = (struct eth_hdr *)p->payload;                        // 获取以太网协议首部
      iphdr = (struct ip_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR);    // 获取IP协议首部
      
      // 如果对方IP与本地IP在不同网段,则直接返回
      ip_addr_copy(iphdr_src, iphdr->src);
    if (!ip_addr_netcmp(&iphdr_src, &(netif->ip_addr), &(netif->netmask)))
        return;
    
    // 只有与本地IP在同网段的IP才会更新ARP缓存表
    update_arp_entry(netif, &iphdr_src, &(ethhdr->src), ETHARP_FLAG_FIND_ONLY);
}

2. 如果输入的是ARP包,则处理ARP数据包,更新ARP缓存表,对ARP请求进行应答
static void etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
{
    struct etharp_hdr *hdr;
    struct eth_hdr *ethhdr;
    ip_addr_t sipaddr, dipaddr;
      u8_t for_us;
    
}
*****************************************************************************************************************/
                                                                                        

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值