邻居子系统 1.1

1.什么是邻居子系统

邻居:是指同一个IP局域网内的主机,或者邻居之间在三层上仅相隔一跳距离。

邻居子系统:提供了三层协议地址与二层协议地址之间的映射关系。同时还提供了二层首部缓存,用以加速发送数据报文,

以ipv4 发送数据为例,在发送数据时,先进行路由查找,如果查找到目的地址路径,再查看邻居表中是否存在响应的映射关系,

如果没有则新建邻居关系,然后判断邻居是否可用,如果不可用则将报文缓存到发送队列,然后发送建立邻居请求,在接收到应答后,

将邻居设置为可用状态,并且将缓存中的报文发送出去。如果在指定时间内没有收到响应报文,则将对应邻居设置为无用状态,并且超时后将

缓存报文丢弃。简单来说就是为 :为每个协议缓存L3到L2的地址提供缓存的添加,删除,改变和查找 ,为每个协议缓存的数据项提供老化机制,为每个邻居提供一个请求队列

2、邻居系统相关参数

2.1邻居子系统的状态

/*
 *    Neighbor Cache Entry States.
 */

#define NUD_INCOMPLETE    0x01
#define NUD_REACHABLE    0x02
#define NUD_STALE    0x04
#define NUD_DELAY    0x08
#define NUD_PROBE    0x10
#define NUD_FAILED    0x20

/* Dummy states */
#define NUD_NOARP    0x40
#define NUD_PERMANENT    0x80
#define NUD_NONE    0x00

/* NUD_NOARP & NUD_PERMANENT are pseudostates, they never change
   and make no address resolution or NUD.
   NUD_PERMANENT is also cannot be deleted by garbage collectors.
 */

/*
 * NUD stands for "neighbor unreachability detection"
 */
#define NUD_IN_TIMER    (NUD_INCOMPLETE|NUD_REACHABLE|NUD_DELAY|NUD_PROBE)
#define NUD_VALID    (NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE|NUD_PROBE|NUD_STALE|NUD_DELAY)
#define NUD_CONNECTED    (NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE)
NUD_INCOMPLETE  :该状态是请求报文已发送,但尚未收到应答的状态。该状态下还没解析到硬件地址,因此尚无可用硬件地址,如果有报文要输出到该邻居,会将其缓存起来。
这个状态会启动一个定时器,如果在定时器到期时还没有接收到邻居的回应,则会重复发送请求报文,否则发送请求报文的次数打到上限,便会进入NUD_FAILED。
NUD_REACHABLE :该状态以及得到并缓存了邻居的硬件地址。进入该状态首先设置邻居项相关的output函数(该状态使用neighbors_ops结构的connectd_outpt),
然后查看是否存在要发送给该邻居的报文。如果在该状态下闲置时间达到上限,便会进入NUD_STATLE。
NUD_STALE :该状态一旦有报文要输出到该邻居,则会进入NUD_DELAY并将该报文输出。如果在该状态下闲置时间达到上限,且此时的引用计数为1,
则通过垃圾回收机制将其删除,在该状态下,报文的输出不收限制,使用慢速发送过程
NUD_DELAY :该状态下表示NUD_STATE状态下发送的报文已经发出,需得到邻居的可达性确认的状态。在为接收到邻居的应答或确认时也会定时地重发请求,
如果发送请求报文的次数到上限,如果收到邻居的应答,进入NUD_REACHABLE,否则进入NUD_FAILED,在该状态下,报文的输出不收限制,使用慢速发送过程。
NUD_PROBE :过渡状态,和NUD_INCOMPLETE 状态类似,在未收到邻居状态的应答或者确认时,也会定时的重发请求,直到收到邻居的应答、确认、或者尝试发送请求报文的次数达到上限,如果收到
应答或者确认就会进入NUD_REACHABLE,如果尝试发送请求到达上限,则进入NUD_FAILD状态,在该状态,报文的输出也不受限制,使用慢速发送过程。
NUD_FAILED  :由于没有收到应答报文而无法访问状态,
NUD_NOARP   :标识邻居无需将三层地址协议映射到二层地址协议。发往lo回环接口的报文其arp表项为NUD_NOARP
NUD_PERMANENT : 设置邻居表项的硬件地址已经变味静态,不需要去将三层地址翻译映射到二层
地址。

这些是基本状态,根据这些基本状态组合了几个相对有语义的状态。

  • NUD_VALID 表示该地址会是一个有效的地址

    NUD_PERMANENT    NUD_NOARP          NUD_REACHABLE              NUD_PROBE             NUD_STALE               NUD_DELAY

  • NUD_CONNECTED 是 NUD_VALID 的子集,去除了待决的中间状态

    NUD_PERMANENT               NUD_NOARP               NUD_REACHABLE

  • NUD_IN_TIMER 表示在这个状态下正在执行一个定时任务,一般是状态不明了的时候根据状态变迁图可以看到那些状态需要设置定时器

    NUD_INCOMPLETE                 NUD_DELAY               NUD_PROBE


2.2 邻居表项的添加和删除

应用层可以通过arp ip 命令添加 删除邻居表项;在添加路由项和路径绑定时也会触发创建邻居项。当接收到并非请求的应答报文同样也能触发创建邻居表项。

邻居表项的删除除了ip arp 外就是在垃圾定时器回收回调中处理。

 有关邻居操作的netlink消息:

struct ndmsg {
    __u8        ndm_family; //地址族
    __u8        ndm_pad1;
    __u16        ndm_pad2;
    __s32        ndm_ifindex; //邻居项的网络设备索引号
    __u16        ndm_state;  //邻居项的状态
    __u8        ndm_flags;// NTF_PROXY 代理项 NTF_ROUTER  路由
    __u8        ndm_type;
};

enum {//neigh netlink 消息的扩展属性字段
    NDA_UNSPEC,
    NDA_DST,
    NDA_LLADDR,
    NDA_CACHEINFO,
    NDA_PROBES,
    __NDA_MAX
};

#define NDA_MAX (__NDA_MAX - 1)

/*
 *    Neighbor Cache Entry Flags
 */

#define NTF_USE        0x01
#define NTF_PROXY    0x08    /* == ATF_PUBL */
#define NTF_ROUTER    0x80

#define NTF_SELF    0x02
#define NTF_MASTER    0x04

执行ip neighbour del 等 会调用内核的neigh_del  neigh_add 函数

static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) 详见 内核,再次不做详细说明

原文地址:https://www.cnblogs.com/codestack/p/11809145.html