ARP: 地址解析协议(Address Resolution Protocol)。 负责讲L3(网络层)地址转换成L2(数据链路层)地址。IPv4中,请求和应答分别为ARP请求和ARP应答。
IPv6 NDISC: 邻居发现协议(Neighbour Discovery Protocol, NDISC),邻居子系统为了执行L3到L2的映射提供了独立于协议的基础设施。请求和应答分别为邻居请求和邻居应答。
NDISC协议用来避免重复的IPv4地址的机制
邻居子系统的作用:
在第2层发生数据包时,为创建L2层包头,需要使用L2目标地址,使用邻居子系统进行请求和应答,便可以根据主机的L3地址获悉其L2层地址(或者获悉这样的L3地址不存在)。在常用的数据链路层(L2)---以太网中,主机的L2地址为MAC地址。
通过广播、组播发现映射关系
有时不需要邻居子系统也能够获得目标地址。比如发送广播 FF:FF:FF:FF:FF:FF, 或者发送目标地址是组播地址时,L3组播地址和L2组播的映射关系是固定的。
邻居子系统的基本数据结构
在当前数据链路层的网络结点中,用结构体 struct neighbour 来表示, 具体如下:
邻居表
为了避免每次传输数据都发送ARP请求,内核将L3到L2地址之间的映射关系存储在邻居表的数据结构中。IPv4中,这个表叫ARP表或者ARP缓存。IPv6中,邻居表叫NDISC表(NDISC缓存),ARP表和NDISC表都是结构体 struct neigh_table 的实例, 具体结构如下:
ARP的数据处理
使用邻居子系统的每种L3协议都注册了一个协议处理程序。 IPv4,ARP的数据包处理程序为arp_rcv().
邻居对象的数据操作方法
每个邻居对象的结构 struct neigh_ops 中定义了一组方法,源码如下:
创建和释放邻居
邻居的创建
邻居的创建是由_neigh_create() 来处理。
在函数的最后,将dead标志初始化为0,并将邻居对象添加到邻居散列表中。
邻居的删除
邻居的删除是由 neigh_release() 来处理。
方法neigh_release() 将邻居的引用计数器减1,如果变成0,将调用方法 neigh_destroy方法将邻居对象释放。
添加、删除邻居条目
ip neigh add ...
ip neigh del ...
ARP 协议(IPv4)
在以太网中,硬地址被称为MAC, 长度为48位, MAC地址独一无二。在发生IPv4的数据包时,目标IP地址已知,但需要创建目标以太网包头,其中包括目标MAC地址,根据IPv4地址可以确定MAC地址的工作有ARP协议来完成,ARP表示一个neigh_table 结构示例:
ARP(发送请求)
首先调用方法 _ipv4_neigh_lookup_noref, 在ARP表中查找下一跳IPv4地址。
如果没有找到匹配的邻居条目,就调用_neigh_create()来创建一个。
ARP(接收请求和应答)
ARP的请求和应答的处理在ipv4_rcv()函数中:
在方法arp_process()中, 只处理ARP请求和ARP相应操作。对ARP请求, 将使用方法ip_route_input_noref()执行路由选择子系统查找。如果ARP数据包是发送给当前主机的(路由选择条目的rt_type为RTN_LOCAL),就接着检查一些条件。如果所以检查全部通过,就使用方法 arp_send() 发送ARP应答。