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


  • 1:ARP请求 。
  • 2:ARP应答 。
  • 3:RARP请求 。
  • 4:RARP应答 。
  • 发送端以太网地址(6) 。
  • 发送端IP地址(4) 。
  • 目的以太网地址(6) 。
  • 目的IP地址(4) 。
  • 小笔记:
    • 看到上述的报文简述后,会发现以太网的数据帧首部和ARP请求数据报中都有发送端的硬件地址 。这个很正常,因为两者所处的OSI层级不一样,前者是链路层处理的数据帧头需要的硬件地址 。后者是网络层处理的ARP请求数据报中的重要信息 。
    • ARP请求有些信息会留空,如ARP请求时,目的端的硬件地址不需要填充 。而协议中保留,是为了实现ARP请求和ARP应答的报文字段一致 。
    ARP简要交互:
    对于一个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数据包拷贝到新的空间,等待发送 。

    经验总结扩展阅读