Lwip入门(2)--ARP

来源:互联网 发布:阿沁美妆淘宝店铺名 编辑:程序博客网 时间:2024/05/18 03:06

         前面提到netif->input()根据eth_hdr数据据构的type项决定下一步将数据传入ARP模块还是送入IP层,那先看看传入ARP模块的ARP数据包(数据结构为etharp_hdr)。etharp_arp_input()通过调用ip_addr_cmp(&dipaddr, &(netif->ip_addr))首先比较数据包里的目的IP地址与本地的IP地址是否相同,判断此数据包是否传给自己,然后调用update_arp_entry()更新ARP表,接着,根据数据包里的ARP数据报头的操作码散转处理,操作码主要是ARP请求和ARP应答。对于ARP请求,将接收到的数据包里的源IP地址和目的IP地址对换,操作码变为ARP应答,源MAC地址与目的MAC地址对换后,调用netif->linkoutput(netif, p)完成对ARP请求的响应,这个分支就到此结束了;对于ARP应答,前面调用update_arp_entry()时,已经处理了。

         完整的ARP数据包由etharp.h里的eth_hdr数据结构定义:

PACK_STRUCT_BEGIN
struct etharp_hdr {
  PACK_STRUCT_FIELD(struct eth_hdr ethhdr);//前面定义过的以太网包头
  PACK_STRUCT_FIELD(u16_t hwtype);//硬件地址类型
  PACK_STRUCT_FIELD(u16_t proto);//协议类型,其值与以太网包头的type值相同
  PACK_STRUCT_FIELD(u16_t _hwlen_protolen);//硬件地址和协议地址的长度
  PACK_STRUCT_FIELD(u16_t opcode);//操作码
  PACK_STRUCT_FIELD(struct eth_addr shwaddr);//源MAC地址
  PACK_STRUCT_FIELD(struct ip_addr2 sipaddr);//源IP地址
  PACK_STRUCT_FIELD(struct eth_addr dhwaddr);//目的MAC地址
  PACK_STRUCT_FIELD(struct ip_addr2 dipaddr);//目的IP地址
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END

同前面一样,PACK_STRUCT_xxx是与编译器字对齐相关的宏定义。ARP实现的核心就是ARP缓存表,ARP缓存表的各表项数据结构如下:

struct etharp_entry {
#if ARP_QUEUEING
  struct etharp_q_entry *q;//数据包缓冲队列指针
#endif
  struct ip_addr ipaddr;//目标IP
  struct eth_addr ethaddr;//目标MAC
  enum etharp_state state;//当前entry状态
  u8_t ctime;//当前entry的时间信息
  struct netif *netif;//网络接口
};

etharp_state有三个值对应三个状态:empty、pending、stable。LwIP通过static struct etharp_entry arp_table[ARP_TABLE_SIZE]建立arp表。etharp_q_entry是数据包缓冲队列,结构如下:

struct etharp_q_entry {
  struct etharp_q_entry *next;
  struct pbuf *p;
};

接着看update_arp_entry()是如何更新ARP表的。

原创粉丝点击