前言
本文介绍ARP地址解析协议的主要流程及关键算法,tcp/ip协议详细信息请参考机械工业出版社出版的《TCP/IP详解》,本文部分图片摘自该书籍。
ARP协议介绍
介绍
地址解析协议(ARP)用于实现IP地址到网络接口硬件地址的映射。
链路层通信以MAC地址标识源及目标设备,ip数据包往其他设备发送时,需要经过链路层封装,因此我们需要知道目标设备的MAC地址,通过ARP协议即可用ip获取到目标设备的地址。
(特别说明:目标设备的MAC地址并不一定就是ip地址对应的最终设备的MAC地址,而往往是下一跳的地址,因为在路由报文经过路由器时,路由器会对对报文中的MAC修改为自己的下一跳MAC地址。)
报文格式
IEEE 802.2/802.3(RFC 1042)和以太网的封装格式(RFC 894)
ARP协议实现
gratuitous ARP(免费ARP)
网卡设备启动时发送一个gratuitous ARP请求自己的mac,检查是否在网络中存在相同的ip以及更新缓存arp路由信息,详细信息请参考
http://baike.baidu.com/link?url=4XpOyapItBlRAwcS-uuR9guKo88Lx1epNNve9-KZM951vUVr6EETwFvxe-fsiRQr4xenzIRCio3RU9oS3nO_fGIe6jtqwUGLFY4nVKpVO6q。
ARP实现
查看并清除arp缓存
(此处操作不是必须的)
在Windows下以管理员权限使用arp -a查看arp缓存,arp -d清除所有arp,如下图所示:
arp请求
(报文格式请参考1.1.2 IEEE 802.2/802.3(RFC 1042)和以太网的封装格式(RFC 894))
gratuitous ARP请求主要过程为:网卡上电 -> 发送ARP请求(填充源、目标设备ip地址,填充源mac地址,目标mac为0xffffffffffff) -> 发送到物理网卡,其函数调用栈如下:
etharp_request第一个参数为当前网卡,该结构体绑定了网卡的ip相关信息及网卡收发函数,第二个参数为目标设备的ip地址,通过这两个参数的信息即可组装arp请求报文;
low_level_output第一个参数为当前网卡,第二个参数为arp报文(pbuf实现请参考《TCP/IP详解》mbuf相关章节)。
arp报文通过网卡直接发送到直连的交换机后,因为目标mac为广播地址0xffffffffffff,交换机将该报文网所有端口进行转发,这就会出现两种情况,当前设备接收到该报文,其他设备接收到该报文:
其他设备接收到该报文时,如果ip地址有冲突(ip地址与发送设备ip地址相同),则发送arp应答报文,不相同则添加到arp缓存或者更新arp表项过期时间为0(因为arp定时器在不断统计arp表项的过期时间,当过期时,会清除该表项),arp更新及应答请参考“arp更新”、“arp应答”章节。
arp更新
arp更新有三种情况:收到arp报文,收到ip报文,arp表项过期。
收到arp报文时,判断该请求或者应答是否是发送给自己,如果是,则更新arp表项,如果不是发送给自己但是arp缓存中已经有对应ip的arp缓存,则同样更新arp表项;(不是发给自己的请求有两种情况,一是网卡没有配置ip,二是arp请求的目标ip不是自己的ip。)
如果是发给自己的arp请求,则需要把自己的mac地址填充到arp应答报文中,并发送到网卡;如果是应答报文(自己应答自己的报文)或者不是发给自己的报文,则不处理。
如果收到的是ip报文,判断目标ip是否是自己的,如果是,则更新arp表项,不是,则不处理,然后将报文交给网络层处理(以太网首部有可能在链路层丢弃,也可能在网络层丢弃,不同实现代码不一定相同)。
arp表项过期删除请参考“arp更新定时器”章节。
更新arp表项时,如果ip已经在arp缓存表中,则更新已经存在的,如果没有空闲的表项,则将最老的表项替换(最久没有更新的表项)。
arp应答
arp报文处理函数调用栈如下所示:
ethernetif_input主要用于接收网卡数据,并解析以太网报文首部,判断该报文是ip报文还是arp报文。
如果是arp报文则调用etharp_arp_input进行处理,该函数既处理arp请求,也处理arp应答,同时更新arp表项,处理流程请参考上一节“arp更新”。
ARP更新定时器
介绍
在上前面章节我们已经详细介绍了在接收到ip、arp报文时怎么更新arp表过期时间及状态;要是没有收到相关报文呢,假如arp缓存表中某设备已经不在了,或者dhcp租约时间过期并且更换了ip,因此,我们需要定时更新arp表。
arp表项状态转移
arp表项无效时的状态为empty,发送arp请求时,更新状态为pending,收到ip、arp报文时,更新对应的状态为stable,pending、stable状态下的arp表项过期时,更新为empty状态。
arp更新定时器
arp更新定时器实现比较简单,就是一个循环定时器,不断对stable、pending状态的arp表项过期时间进行累加,超过最大值时,更新为empty状态,该过期时间也可在没有可用arp表项时用来替换最老未更新的表项。
ARP其他说明
通常我们发送ip报文时,目标ip对应的arp表项不一定存在,此时需要先通过arp协议获取目标设备的mac地址,在发送arp请求的同时,将ip报文保存在pending状态arp表项的附加字符,当该arp表项由pending变为stable时(即获取到目标设备的mac地址),封装mac地址到arp表项附加字段并发送出去(对于tcp报文,我们就不需要等待tcp协议的超时重传了;对于无连接的udp协议,也不至于丢失udp报文)。