【lwip】08-ARP协议一图笔记及源码实现( 二 )


当系统收到一份目的端为本机的ARP请求报文后,它就把硬件地址填进去,然后用两个目的端地址分别替换两个发送端地址,并把操作字段置为2(ARP应答),最后把它发送回去 。
ARP交互报文例子图,wireshark分析:

【lwip】08-ARP协议一图笔记及源码实现

文章插图
8.4 ARP缓存表8.4.1 ARP缓存表简介每台主机或路由器在其内存中具有一个ARP缓存表(ARP table),这张表包含IP地址到MAC地址的映射关系 。
网络层的IP数据包需要经过链路层转发时,可以直接查询缓存表是否有这个IP映射的MAC 。
如果有,目标链路层数据帧的目标MAC就直接使用这个MAC,就能转发了 。
如果没有,通过ARP协议,往链路层局域网内广播一下,询问下有没有这个IP对应的结点设备,如果有就把这个IP对应的链路层设备的MAC返回到这个主机,然后这个主机的链路层使用这个MAC发送数据帧出去 。而且可以把这个MAC及其对应的IP保存到自己的ARP缓存表中,方便下次直接使用 。当然,这个映射也有过期检查,需要超时机制维护 。
8.4.2 LWIP中的缓存表lwip的缓存表:static struct etharp_entry arp_table[ARP_TABLE_SIZE];
ARP_TABLE_SIZE默认为10,即是默认能缓存10条ARP映射记录 。
8.4.3 ARP缓存表数据结构struct etharp_entry
struct etharp_entry {#if ARP_QUEUEING/* 指向此ARP表项上挂起的数据包队列的指针. */struct etharp_q_entry *q;#else /* ARP_QUEUEING *//* 指向此ARP表项上的单个挂起的数据包队列的指针 */struct pbuf *q;#endif /* ARP_QUEUEING *//* 目标IP地址 */ip4_addr_t ipaddr;/* 当前ARP映射记录对应网卡信息 */struct netif *netif;/* 目标IP对应的MAC地址 */struct eth_addr ethaddr;/* 当前netry的生存时间 */u16_t ctime;/* 当前netry的状态信息 */u8_t state;};
【lwip】08-ARP协议一图笔记及源码实现

文章插图
8.4.4 ARP缓存表数据缓冲队列struct etharp_q_entry *q;
这个字段用于指向缓存表的数据包缓冲队列 。
在IP层发送一个数据包时,会先在ARP映射表中查找与目的IP地址对应的MAC地址,这样才能封装以太网?。?才能在链路层把数据包发送出去 。
但是如果IP层发送一个数据包时 , 在ARP映射表中查不到对应的硬件地址MAC,就发送一个ARP请求包,在请求过程中,把这个IP层的数据包缓存到这个队列q先 , 直到请求成功后,获取这个IP层数据包IP对应的MAC地址或请求失败为止 。
对于PBUFF_ERFPBUF_POOLPBUF_RAM类型的数据包是不允许直接挂到ARP entry的挂起缓存队列上的,因为内核等待目标主机的ARP应答期间 , 这些数据有可能会被上层改动,所以LwIP需要将这些pbuf数据包拷贝到新的空间,等待发送 。
这个队列的数据结构:
  • 在memp.h的MEMP_ARP_QUEUE内存池中有这个数据结构的内存资源 。共有MEMP_NUM_ARP_QUEUE个,默认为30个 。
#if ARP_QUEUEINGstruct etharp_q_entry {struct etharp_q_entry *next; /* 下一个节点 */struct pbuf *p; /* pbuf */};#endif /* ARP_QUEUEING */8.4.5 ARP缓存表entry状态信息u8_t state;
/** ARP states */enum etharp_state {ETHARP_STATE_EMPTY = 0, /* 空闲态 */ETHARP_STATE_PENDING, /* pending态 */ETHARP_STATE_STABLE, /* 有效态 */ETHARP_STATE_STABLE_REREQUESTING_1, /* 有效过渡态1 */ETHARP_STATE_STABLE_REREQUESTING_2 /* 有效过渡态2 */#if ETHARP_SUPPORT_STATIC_ENTRIES, ETHARP_STATE_STATIC /* 静态entry */#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */};当前netry的状态信息:
  • ETHARP_STATE_EMPTY:空状态 。当前entry资源无效,可以被填充使用 。
  • ETHARP_STATE_PENDING:PENDING态 。当前entry正在ARP请求,但是还没收到ARP响应 。
  • ETHARP_STATE_STABLE:有效态 。当前entry记录的IP地址与MAC地址映射有效 。
  • ETHARP_STATE_STABLE_REREQUESTING_1:有效过渡态1 。就是为了防止entry块过期前频繁发起ARP请求 。
  • ETHARP_STATE_STABLE_REREQUESTING_2:有效过渡态2 。
  • ETHARP_STATE_STATIC:静态条目 。手动配置的ARP映射,一直有效 。
当表项是ETHARP_STATE_STABLE的时候又发送一个ARP请求包,那么表项状态会暂时被设置为THARP_STATE_STABLE_REREQUESTING_1 , 然后被设置为ETHARP_STATE_STABLE_REREQUESTING_2状态,这些是一个过渡状态,当收到ARP应答后,表项又会被设置为ETHARP_STATE_STABLE , 这样能保持表项的有效 。

推荐阅读