跳到主要内容

10. 邻居数据结构 (The Neighbor Data Structure)

  1. 邻居数据结构 (The Neighbor Data Structure)
OSPF 路由器会与其相邻路由器进行会话. 每个独立会话由一个 "neighbor data structure" 描述. 每个会话绑定到特定 OSPF 路由器接口, 并由相邻路由器的 OSPF Router ID 或其 Neighbor IP address 标识 (见下文). 因此, 如果 OSPF 路由器与另一台路由器共有多个连接网络, 就会产生多个会话, 每个会话都由唯一的 neighbor data structure 描述. 文中将每个独立会话宽泛地称为一个单独 "neighbor".
neighbor data structure 包含两个邻居之间正在形成或已经形成的邻接关系相关的所有信息. 但是请记住, 并非所有邻居都会成为邻接. 邻接关系可视为两台路由器之间高度发展的会话.


State
邻居会话的功能级别. Section 10.1 中更详细描述.

Inactivity Timer
一个 single shot timer, 其触发表示最近没有从该邻居看到 Hello Packet. 定时器长度为 RouterDeadInterval 秒.

Master/Slave
当两个邻居交换数据库时, 它们形成 master/slave 关系. master 发送第一个 Database Description Packet, 且是唯一允许重传的一方. slave 只能响应 master 的 Database Description Packets. master/slave 关系在 ExStart 状态中协商.

DD Sequence Number
当前正发送给邻居的 Database Description packet 的 DD Sequence number.

Last received Database Description packet
从邻居收到的最后一个 Database Description packet 中包含的 initialize(I), more (M) 和 master(MS) 位、Options 字段以及 DD sequence number. 用于判断从邻居收到的下一个 Database Description packet 是否为重复包.

Neighbor ID
相邻路由器的 OSPF Router ID. Neighbor ID 在从邻居收到 Hello packets 时学习到; 如果这是虚邻接 (见 Section C.4), 则通过配置获得.

Neighbor Priority
相邻路由器的 Router Priority. 该项包含在邻居的 Hello packets 中, 在为所连接网络选择 Designated Router 时使用.

Neighbor IP address
相邻路由器通往所连接网络的接口 IP 地址. 当协议报文沿该邻接关系以单播方式发送时, 用作 Destination IP address. 如果相邻路由器被选为 Designated Router, 它还在 router-LSAs 中用作所连接网络的 Link ID (见 Section 12.4.1). Neighbor IP address 在从邻居收到 Hello packets 时学习到. 对虚链路, Neighbor IP address 在路由表构建过程中学习到 (见 Section 15).

Neighbor Options
邻居支持的可选 OSPF 能力. 在 Database Exchange 过程中学习到 (见 Section 10.6). 邻居的可选 OSPF 能力也列在其 Hello packets 中. 如果某些关键 OSPF 能力不匹配, 这使收到的 Hello Packets 可以被拒绝, 即邻居关系甚至不会开始形成 (见 Section 10.5). OSPF 可选能力记录在 Section 4.5.

Neighbor's Designated Router
邻居所认为的 Designated Router. 如果这是邻居自身, 这对本地 Designated Router 计算很重要. 只在广播和 NBMA 网络上定义.

Neighbor's Backup Designated Router
邻居所认为的 Backup Designated Router. 如果这是邻居自身, 这对本地 Backup Designated Router 计算很重要. 只在广播和 NBMA 网络上定义.


下一组变量是 LSA 列表. 这些列表描述区域链路状态数据库的子集. 本备忘录定义五种不同类型的 LSA, 它们都可能出现在区域链路状态数据库中: router-LSAs, network-LSAs, Type 3 和 4 summary-LSAs (都存储在区域数据结构中), 以及 AS-external-LSAs (存储在全局数据结构中).


Link state retransmission list
已在此邻接关系上泛洪但尚未确认的 LSA 列表. 这些 LSA 会按间隔重传, 直到被确认, 或直到邻接关系被销毁.

Database summary list
当邻居进入 Database Exchange 状态时, 构成区域链路状态数据库的完整 LSA 列表. 该列表会在 Database Description packets 中发送给邻居.

Link state request list
为同步两个邻居的链路状态数据库, 需要从该邻居接收的 LSA 列表. 该列表在收到 Database Description packets 时创建, 随后在 Link State Request packets 中发送给邻居. 随着适当的 Link State Update packets 被接收, 该列表逐渐耗尽.


10.1. 邻居状态 (Neighbor states)

邻居状态, 实际上是与相邻路由器保持的会话状态, 记录在以下小节中. 这些状态按功能递进顺序列出. 例如, 不可运行状态最先列出, 后面是若干中间状态, 最终达到完全可用状态. 本规范有时通过诸如 "those neighbors/adjacencies in state greater than X" 的引用来利用这种排序. Figures 12 和 13 显示邻居状态变化图. 图中的弧用导致状态变化的事件标记. 邻居事件记录在 Section 10.2.

Figure 12 中的图显示 Hello Protocol 导致的状态变化. Hello Protocol 负责邻居获取和维护, 并确保邻居之间双向通信.

Figure 13 中的图显示邻接关系的形成. 并非每两台相邻路由器都会成为邻接 (见 Section 10.4). 当邻居处于 ExStart 状态时, 邻接关系开始形成. 两台路由器发现自己的 master/slave 状态后, 状态转换为 Exchange. 此时邻居开始用于泛洪过程, 两台相邻路由器开始同步其数据库. 同步完成后, 邻居处于 Full 状态, 我们称两台路由器完全邻接. 此时该邻接关系列入 LSA 中.

关于邻居状态变化以及每次变化涉及的额外动作的更详细描述, 见 Section 10.3.


Down
这是邻居会话的初始状态. 它表示最近没有从该邻居收到任何信息. 在 NBMA 网络上, 仍可能向 "Down" 邻居发送 Hello packets, 但频率较低 (见 Section 9.5.1).


+----+
|Down|
+----+
                                   |\
| \Start
| \ +-------+
Hello | +---->|Attempt|
Received | +-------+
| |
+----+<-+ |HelloReceived
|Init|<---------------+
+----+<--------+
| |
|2-Way |1-Way
|Received |Received
| |
+-------+ | +-----+
|ExStart|<--------+------->|2-Way|
+-------+ +-----+
          Figure 12: 邻居状态变化 (Hello Protocol)

除图中所示状态转换外,
Event KillNbr 始终强制进入 Down State,
Event InactivityTimer 始终强制进入 Down State,
Event LLDown 始终强制进入 Down State
                              +-------+
|ExStart|
+-------+
|
NegotiationDone|
+->+--------+
|Exchange|
+--+--------+
|
Exchange|
Done |
+----+ | +-------+
|Full|<---------+----->|Loading|
+----+<-+ +-------+
| LoadingDone |
+------------------+
        Figure 13: 邻居状态变化 (Database Exchange)

除图中所示状态转换外,
Event SeqNumberMismatch 强制进入 ExStart state,
Event BadLSReq 强制进入 ExStart state,
Event 1-Way 强制进入 Init state,
Event KillNbr 始终强制进入 Down State,
Event InactivityTimer 始终强制进入 Down State,
Event LLDown 始终强制进入 Down State,
Event AdjOK? 导致邻接形成/断开

Attempt
该状态只对连接到 NBMA 网络的邻居有效. 它表示最近没有从邻居收到信息, 但应更集中地尝试联系该邻居. 这是通过每 HelloInterval 间隔向邻居发送 Hello packets 完成的 (见 Section 9.5.1).

Init
在此状态下, 最近从邻居看到了 Hello packet. 但是, 与邻居的双向通信尚未建立, 即路由器自身未出现在邻居的 Hello packet 中. 处于此状态或更高状态的所有邻居都会列在关联接口发送的 Hello packets 中.

2-Way
在此状态下, 两台路由器之间的通信是双向的. 这是通过 Hello Protocol 的运行保证的. 这是开始建立邻接之前的最高级状态. (Backup) Designated Router 从状态为 2-Way 或更高的邻居集合中选择.

ExStart
这是在两台相邻路由器之间创建邻接关系的第一步. 该步骤的目标是决定哪台路由器是 master, 并决定初始 DD sequence number. 处于此状态或更高状态的邻居会话称为 adjacencies.

Exchange
在此状态下, 路由器通过向邻居发送 Database Description packets 来描述自己的完整链路状态数据库. 每个 Database Description Packet 都有 DD sequence number, 并被显式确认. 任意时刻只允许有一个未完成的 Database Description Packet. 在此状态下, 也可以发送 Link State Request Packets 来请求邻居更新的 LSA. 处于 Exchange 或更高状态的所有邻接关系都会被泛洪过程使用. 实际上, 这些邻接完全能够发送和接收所有类型的 OSPF 路由协议报文.

Loading
在此状态下, Link State Request packets 被发送给邻居, 请求在 Exchange 状态中发现但尚未收到的更新 LSA.

Full
在此状态下, 相邻路由器完全邻接. 这些邻接关系现在会出现在 router-LSAs 和 network-LSAs 中.


10.2. 导致邻居状态变化的事件

多个事件可以导致状态变化. 这些事件显示为 Figures 12 和 13 中弧的标签. 标签定义如下:


HelloReceived
已从邻居收到 Hello packet.

Start
指示现在应每 HelloInterval 秒向邻居发送 Hello Packets. 该事件只为与 NBMA 网络关联的邻居生成.

2-WayReceived
两台相邻路由器之间已实现双向通信. 这由路由器在邻居的 Hello packet 中看到自己来表示.

NegotiationDone
Master/Slave 关系已协商完成, DD sequence numbers 已交换. 这标志 Database Description packets 的发送/接收开始. 关于该事件生成的更多信息, 见 Section 10.8.

ExchangeDone
两台路由器都已成功传输完整的 Database Description packets 序列. 每台路由器现在都知道自己链路状态数据库的哪些部分已经过期. 关于该事件生成的更多信息, 见 Section 10.8.

BadLSReq
收到一个针对数据库中不存在 LSA 的 Link State Request. 这表明 Database Exchange 过程中发生错误.

Loading Done
已收到数据库所有过期部分的 Link State Updates. 这由 Database Exchange 过程完成后 Link state request list 变为空表示.

AdjOK?
必须决定是否应与邻居建立/维护邻接关系. 该事件会启动某些邻接形成, 并销毁其他邻接.


以下事件会导致已发展较充分的邻居回退到较低状态. 与上述事件不同, 这些事件可在邻居会话处于多种状态时发生.


SeqNumberMismatch
收到的 Database Description packet 满足以下之一: a) DD sequence number 异常, b) Init bit 意外置位, 或 c) Options 字段不同于上一次从 Database Description packet 收到的 Options 字段. 任一情况都表明邻接建立期间发生了某种错误.

1-Way
已从邻居收到 Hello packet, 但其中没有提到该路由器. 这表示与邻居的通信不是双向的.

KillNbr
指示与邻居的所有通信现在都不可能, 强制邻居回退到 Down state.

InactivityTimer
inactivity Timer 已触发. 这意味着最近没有从邻居看到 Hello packets. 邻居回退到 Down state.

LLDown
这是来自低层协议的指示, 表示邻居现在不可达. 例如, 在 X.25 网络上, 这可由具有适当 cause 和 diagnostic 字段的 X.25 clear indication 表示. 该事件强制邻居进入 Down state.


10.3. 邻居状态机

下面详细描述邻居状态变化. 每次状态变化由事件调用 (Section 10.2). 该事件可能根据邻居当前状态产生不同影响. 因此, 下面的状态机按当前邻居状态和收到的事件组织. 状态机中的每个条目描述得到的新邻居状态和所需的额外动作集合.

当邻居状态变化时, 可能需要重新运行 Designated Router 选举算法. 这取决于是否生成 interface NeighborChange 事件 (见 Section 9.2). 此外, 如果 Interface 处于 DR 状态 (路由器自身是 Designated Router), 邻居状态变化可能导致产生新的 network-LSA (见 Section 12.4).

当邻居状态机需要调用接口状态机时, 应作为 scheduled task 执行 (见 Section 4.4). 这通过确保两个状态机都不会递归执行来简化事情.


State(s): Down

Event: Start

New state: Attempt

Action: 向邻居发送 Hello Packet (该邻居始终与 NBMA 网络关联), 并启动该邻居的 Inactivity Timer. 定时器稍后触发将表示未能与该邻居建立通信.


State(s): Attempt

Event: HelloReceived

New state: Init

Action: 重启该邻居的 Inactivity Timer, 因为现在已听到该邻居.


State(s): Down

Event: HelloReceived

New state: Init

Action: 启动该邻居的 Inactivity Timer. 定时器稍后触发将表示该邻居已失效.


State(s): Init or greater

Event: HelloReceived

New state: No state change.

Action: 重启该邻居的 Inactivity Timer, 因为再次听到该邻居.


State(s): Init

Event: 2-WayReceived

New state: Depends upon action routine.

Action: 判断是否应与该邻居建立邻接关系 (见 Section 10.4). 如果不应建立, 新邻居状态为 2-Way.

否则, 即应建立邻接关系, 邻居状态转换为 ExStart. 进入此状态时, 路由器递增邻居数据结构中的 DD sequence number. 如果这是第一次尝试建立邻接关系, DD sequence number 应分配某个唯一值 (例如一天中的时间时钟). 然后它声明自己为 master (将 master/slave bit 设置为 master), 并开始发送 Database Description Packets, 其中 initialize (I), more (M) 和 master (MS) 位均置位. 该 Database Description Packet 除此之外应为空. 该 Database Description Packet 应按 RxmtInterval 间隔重传, 直到进入下一状态 (见 Section 10.8).


State(s): ExStart

Event: NegotiationDone

New state: Exchange

Action: 路由器必须在邻居 Database summary list 中列出其完整区域链路状态数据库的内容. 区域链路状态数据库由区域结构中包含的 router-LSAs, network-LSAs 和 summary-LSAs, 以及全局结构中包含的 AS-external-LSAs 组成. AS-external-LSAs 会从虚邻居的 Database summary list 中省略. 如果区域已配置为 stub (见 Section 3.6), 也会从 Database summary list 中省略 AS-external-LSAs. age 等于 MaxAge 的 LSA 则会加入邻居的 Link state retransmission list. Database summary list 的摘要将在 Database Description packets 中发送给邻居. 每个 Database Description Packet 都有 DD sequence number, 并被显式确认. 任意时刻只允许有一个未完成的 Database Description Packet. 关于发送和接收 Database Description packets 的更多细节, 见 Sections 10.8 和 10.6.


State(s): Exchange

Event: ExchangeDone

New state: Depends upon action routine.

Action: 如果邻居 Link state request list 为空, 新邻居状态为 Full. 不需要其他动作. 这是邻接关系的最终状态.

否则, 新邻居状态为 Loading. 开始 (或继续) 向邻居发送 Link State Request packets (见 Section 10.9). 这些是对邻居更新 LSA 的请求, 这些 LSA 在 Exchange 状态中已发现但尚未收到. 这些 LSA 列在与该邻居关联的 Link state request list 中.


State(s): Loading

Event: Loading Done

New state: Full

Action: 不需要动作. 这是邻接关系的最终状态.


State(s): 2-Way

Event: AdjOK?

New state: Depends upon action routine.

Action: 判断是否应与相邻路由器形成邻接关系 (见 Section 10.4). 如果不应形成, 邻居状态保持 2-Way. 否则, 将邻居状态转换为 ExStart, 并执行上述状态机条目中 state Init 和 event 2-WayReceived 关联的动作.


State(s): ExStart or greater

Event: AdjOK?

New state: Depends upon action routine.

Action: 判断相邻路由器是否仍应保持邻接. 如果是, 状态不变, 不需要进一步动作.

否则, 必须销毁可能已部分形成的邻接关系. 邻居状态转换为 2-Way. Link state retransmission list, Database summary list 和 Link state request list 都清空 LSA.


State(s): Exchange or greater

Event: SeqNumberMismatch

New state: ExStart

Action: 拆除可能已部分形成的邻接关系, 然后尝试重新建立. 邻居状态首先转换为 ExStart. Link state retransmission list, Database summary list 和 Link state request list 都清空 LSA. 然后路由器递增邻居数据结构中的 DD sequence number, 声明自己为 master (将 master/slave bit 设置为 master), 并开始发送 Database Description Packets, 其中 initialize (I), more (M) 和 master (MS) 位均置位. 该 Database Description Packet 除此之外应为空 (见 Section 10.8).


State(s): Exchange or greater

Event: BadLSReq

New state: ExStart

Action: event BadLSReq 的动作与 neighbor event SeqNumberMismatch 完全相同. 拆除可能已部分形成的邻接关系, 然后尝试重新建立. 更多信息见状态为 Exchange 或更高且生成 event SeqNumberMismatch 时调用的邻居状态机条目.


State(s): Any state

Event: KillNbr

New state: Down

Action: Link state retransmission list, Database summary list 和 Link state request list 都清空 LSA. 此外, 禁用 Inactivity Timer.


State(s): Any state

Event: LLDown

New state: Down

Action: Link state retransmission list, Database summary list 和 Link state request list 都清空 LSA. 此外, 禁用 Inactivity Timer.


State(s): Any state

Event: InactivityTimer

New state: Down

Action: Link state retransmission list, Database summary list 和 Link state request list 都清空 LSA.


State(s): 2-Way or greater

Event: 1-WayReceived

New state: Init

Action: Link state retransmission list, Database summary list 和 Link state request list 都清空 LSA.


State(s): 2-Way or greater

Event: 2-WayReceived

New state: No state change.

Action: 不需要动作.


State(s): Init

Event: 1-WayReceived

New state: No state change.

Action: 不需要动作.


10.4. 是否成为邻接

邻接关系会与路由器邻居的某个子集建立. 通过点到点网络、Point-to-MultiPoint 网络和虚链路连接的路由器始终成为邻接. 在广播和 NBMA 网络上, 所有路由器都会与 Designated Router 和 Backup Designated Router 成为邻接.

邻接形成决策在邻居状态机中的两个位置发生. 第一是在与邻居最初建立双向通信时; 第二是在所连接网络的 (Backup) Designated Router 身份变化时. 如果决定不尝试建立邻接, 邻居通信状态停留在 2-Way.

当至少满足以下条件之一时, 应与双向邻居建立邻接关系:

o 底层网络类型为 point-to-point
o 底层网络类型为 Point-to-MultiPoint
o 底层网络类型为 virtual link
o 路由器自身是 Designated Router
o 路由器自身是 Backup Designated Router
o 相邻路由器是 Designated Router
o 相邻路由器是 Backup Designated Router


10.5. 接收 Hello Packets

本节解释收到 Hello Packet 的详细处理 (Hello packets 格式见 Section A.3.2). OSPF 报文的通用输入处理已经检查 IP 头部和 OSPF 报文头部的有效性. 接下来, 必须将收到 Hello packet 中 Network Mask, HelloInterval 和 RouterDeadInterval 字段的值与接收接口配置值比较. 任何不匹配都会导致处理停止并丢弃该报文. 换句话说, 上述字段实际描述的是所连接网络的配置. 但上述规则有一个例外: 在点到点网络和虚链路上, 应忽略收到 Hello Packet 中的 Network Mask.

接收接口连接到单个 OSPF 区域 (这可以是 backbone). Hello Packet 的 Options 字段中 E-bit 的设置必须匹配该区域的 ExternalRoutingCapability. 如果 AS-external-LSAs 不被泛洪进入/遍及该区域, 即该区域是 "stub", 则收到的 Hello Packets 中 E-bit 必须清零; 否则 E-bit 必须置位. 不匹配会导致处理停止并丢弃报文. Hello Packet 的 Options 字段中其余位的设置应被忽略.

此时, 尝试将 Hello Packet 的来源与接收接口的某个邻居匹配. 如果接收接口连接到 broadcast, Point-to-MultiPoint 或 NBMA 网络, 来源由 Hello 的 IP 头部中的 IP 源地址标识. 如果接收接口连接到点到点链路或虚链路, 来源由 Hello 的 OSPF 报文头部中的 Router ID 标识. 接口当前邻居列表包含在接口数据结构中. 如果找不到匹配的邻居结构, 即这是第一次检测到该邻居, 则创建一个. 新创建邻居的初始状态设置为 Down.

在广播、Point-to-MultiPoint 或 NBMA 网络上从邻居收到 Hello Packet 时, 将邻居结构的 Neighbor ID 设置为报文 OSPF 头部中的 Router ID. 对这些网络类型, 邻居结构的 Router Priority 字段、Neighbor's Designated Router 字段和 Neighbor's Backup Designated Router 字段也设置为收到 Hello Packet 中相应字段的值; 这些字段的变化应记录下来, 以便在以下步骤中可能使用. 在点到点网络 (但不是虚链路) 上收到 Hello 时, 将邻居结构的 Neighbor IP address 设置为报文的 IP 源地址.

现在检查 Hello Packet 的其余部分, 生成要交给邻居和接口状态机的事件. 这些状态机被指定为执行或调度 (见 Section 4.4). 例如, 下面指定邻居状态机内联执行, 因此单个收到的 Hello 可导致若干邻居状态转换:

o 每个 Hello Packet 都导致使用事件 HelloReceived 执行邻居状态机.

o 随后检查 Hello Packet 中包含的邻居列表. 如果路由器自身出现在该列表中, 应使用事件 2-WayReceived 执行邻居状态机. 否则, 应使用事件 1-WayReceived 执行邻居状态机, 并停止处理该报文.

o 接下来, 如果记录到邻居的 Router Priority 字段变化, 则以事件 NeighborChange 调度接收接口的状态机.

o 如果邻居既声明自己为 Designated Router (Hello Packet 的 Designated Router 字段 = Neighbor IP address), 且报文中的 Backup Designated Router 字段等于 0.0.0.0, 并且接收接口处于 Waiting 状态, 则以事件 BackupSeen 调度接收接口的状态机. 否则, 如果邻居正在声明自己为 Designated Router 而之前没有声明, 或者邻居不再在之前声明的位置声明自己为 Designated Router, 则以事件 NeighborChange 调度接收接口的状态机.

o 如果邻居声明自己为 Backup Designated Router (Hello Packet 的 Backup Designated Router 字段 = Neighbor IP address), 且接收接口处于 Waiting 状态, 则以事件 BackupSeen 调度接收接口的状态机. 否则, 如果邻居正在声明自己为 Backup Designated Router 而之前没有声明, 或者邻居不再在之前声明的位置声明自己为 Backup Designated Router, 则以事件 NeighborChange 调度接收接口的状态机.

在 NBMA 网络上, 收到 Hello Packet 还可能导致响应性地向邻居发回 Hello Packet. 更多细节见 Section 9.5.1.


10.6. 接收 Database Description Packets

本节解释收到 Database Description Packet 的详细处理. 通用输入报文处理 (Section 8.2) 已经将传入 Database Description Packet 与一个邻居和接收接口关联. Database Description packet 是否应被接受, 以及如果接受应如何进一步处理, 取决于邻居状态.

如果 Database Description packet 被接受, 以下报文字段应保存在对应邻居数据结构的 "last received Database Description packet" 下: 报文的 initialize(I), more (M) 和 master(MS) 位、Options 字段以及 DD sequence number. 如果连续从邻居收到的两个 Database Description packets 中这些字段设置完全相同, 则第二个 Database Description packet 在下面描述的处理中被视为 "duplicate".

如果 Database Description packet 中的 Interface MTU 字段指示的 IP 数据报大小超过路由器在接收接口上无需分片即可接受的大小, 则拒绝该 Database Description packet. 否则, 如果邻居状态为:

Down
应拒绝该报文.

Attempt
应拒绝该报文.

Init
应使用事件 2-WayReceived 执行邻居状态机. 这会导致立即状态变化为 2-Way 或 ExStart. 如果新状态为 ExStart, 则当前报文处理应通过落入下面的 ExStart 情况在该新状态中继续.

2-Way
应忽略该报文. Database Description Packets 只用于建立邻接关系.[7]

ExStart
如果收到的报文匹配以下情况之一, 则应使用事件 NegotiationDone 执行邻居状态机 (导致状态转换为 Exchange), 应将报文的 Options 字段记录在邻居结构的 Neighbor Options 字段中, 并应接受该报文作为序列中的下一个报文并进一步处理 (见下文). 否则, 应忽略该报文.

o initialize(I), more (M) 和 master(MS) 位均置位, 报文内容为空, 且邻居的 Router ID 大于路由器自身. 在这种情况下, 路由器现在是 Slave. 将 master/slave bit 设置为 slave, 并将邻居数据结构的 DD sequence number 设置为 master 指定的值.

o initialize(I) 和 master(MS) 位关闭, 报文的 DD sequence number 等于邻居数据结构中的 DD sequence number (表示确认), 且邻居的 Router ID 小于路由器自身. 在这种情况下, 路由器是 Master.

Exchange
重复的 Database Description packets 由 master 丢弃, 并导致 slave 重传自己上次发送的 Database Description packet. 否则, 即报文不是重复包:

o 如果 MS-bit 状态与连接的 master/slave 状态不一致, 生成 neighbor event SeqNumberMismatch 并停止处理该报文.

o 如果 initialize(I) bit 置位, 生成 neighbor event SeqNumberMismatch 并停止处理该报文.

o 如果报文的 Options 字段指示的可选 OSPF 能力集合不同于之前从邻居收到的集合 (记录在邻居结构的 Neighbor Options 字段中), 生成 neighbor event SeqNumberMismatch 并停止处理该报文.

o Database Description packets 必须按序处理, 由报文的 DD sequence numbers 指示. 如果路由器是 master, 下一个收到的报文应具有等于邻居数据结构中 DD sequence number 的 DD sequence number. 如果路由器是 slave, 下一个收到的报文应具有比邻居数据结构中存储的 DD sequence number 大 1 的 DD sequence number. 无论哪种情况, 如果报文是序列中的下一个, 应接受它并按下文指定处理其内容.

o 否则, 生成 neighbor event SeqNumberMismatch 并停止处理该报文.

Loading or Full
在此状态下, 路由器已经发送并接收了完整的 Database Description Packets 序列. 唯一应收到的报文是重复包 (见上文). 特别是, 报文的 Options 字段应匹配邻居之前指示的可选 OSPF 能力集合 (存储在邻居结构的 Neighbor Options 字段中). 收到的任何其他报文, 包括收到 Initialize(I) bit 置位的报文, 都应生成 neighbor event SeqNumberMismatch.[8] 重复包应由 master 丢弃. slave 必须通过重复自己上次发送的 Database Description packet 来响应重复包.


当路由器接受收到的 Database Description Packet 作为序列中的下一个时, 按如下方式处理报文内容. 对列出的每个 LSA, 检查该 LSA 的 LS type 有效性. 如果 LS type 未知, 例如不是本规范定义的 LS types 1-5 之一, 或者这是 AS-external-LSA (LS type = 5) 且邻居与 stub area 关联, 则生成 neighbor event SeqNumberMismatch 并停止处理该报文. 否则, 路由器在自己的数据库中查找该 LSA, 以查看自己是否也有该 LSA 的实例. 如果没有, 或者数据库副本较旧 (见 Section 13.1), 则将该 LSA 放入 Link state request list, 以便在 Link State Request Packets 中立即或稍后请求.

当路由器接受收到的 Database Description Packet 作为序列中的下一个时, 还会根据自己是 master 还是 slave 执行以下动作:

Master
递增邻居数据结构中的 DD sequence number. 如果路由器已经发送完整的 Database Description Packets 序列, 且刚接受的报文 more bit (M) 设置为 0, 则生成 neighbor event ExchangeDone. 否则, 应向 slave 发送新的 Database Description.

Slave
将邻居数据结构中的 DD sequence number 设置为收到报文中出现的 DD sequence number. slave 必须发送 Database Description Packet 作为回复. 如果收到的报文 more bit (M) 设置为 0, 且 slave 将发送的报文 M-bit 也将设置为 0, 则生成 neighbor event ExchangeDone. 注意, slave 始终先于 master 生成此事件.


10.7. 接收 Link State Request Packets

本节解释收到 Link State Request packets 的详细处理. 收到的 Link State Request Packets 指定邻居希望接收的 LSA 列表. 当邻居处于 Exchange, Loading 或 Full 状态时, 应接受 Link State Request Packets. 在所有其他状态下, 应忽略 Link State Request Packets.

Link State Request packet 中指定的每个 LSA 都应在路由器数据库中定位, 并复制到 Link State Update packets 中以传输给邻居. 这些 LSA 不应放入该邻居的 Link state retransmission list. 如果数据库中找不到某个 LSA, 说明 Database Exchange 过程出了问题, 应生成 neighbor event BadLSReq.


10.8. 发送 Database Description Packets

本节描述如何向邻居发送 Database Description Packets. Database Description packet 的 Interface MTU 字段设置为可从发送接口发出且无需分片的最大 IP 数据报大小. Internet 中常用 MTU 可在 [Ref22] 的 Table 7-1 中找到. 通过虚链路发送的 Database Description packets 中 Interface MTU 应设置为 0.

路由器的可选 OSPF 能力 (见 Section 4.5) 在 Database Description packet 的 Options 字段中传输给邻居. 路由器应在整个 Database Exchange 和泛洪过程中保持相同的可选能力集合. 如果由于某种原因路由器的可选能力发生变化, 应通过回退到邻居状态 ExStart 来重启 Database Exchange 过程. 本规范定义了一项可选能力 (见 Sections 4.5 和 A.2). 当且仅当所连接网络属于非 stub 区域时, E-bit 应置位. Options 字段中无法识别的位应设置为零.

发送 Database Description packets 取决于邻居状态. 在 ExStart 状态下, 路由器发送空的 Database Description packets, 其中 initialize (I), more (M) 和 master (MS) 位均置位. 这些报文每 RxmtInterval 秒重传一次.

在 Exchange 状态下, Database Description Packets 实际包含路由器数据库中链路状态信息的摘要. 区域链路状态数据库中的每个 LSA (在邻居转换到 Exchange 状态时) 都列在邻居 Database summary list 中. 每个新的 Database Description Packet 从邻居数据结构复制其 DD sequence number, 然后描述 Database summary list 当前顶部. 当前一报文被确认时, 项目从 Database summary list 中移除.

在 Exchange 状态下, 何时发送 Database Description packet 取决于路由器是 master 还是 slave:

Master
在以下任一情况下发送 Database Description packets: a) slave 通过回显 DD sequence number 确认前一个 Database Description packet; 或 b) RxmtInterval 秒过去仍未收到确认, 在这种情况下重传前一个 Database Description packet.

Slave
Database Description packets 只为响应从 master 收到的 Database Description packets 而发送. 如果从 master 收到的 Database Description packet 是新的, 则发送新的 Database Description packet; 否则重新发送前一个 Database Description packet.

在 Loading 和 Full 状态下, slave 必须响应从 master 收到的重复 Database Description packets, 重新发送其最后一个 Database Description packet. 因此, slave 必须等待 RouterDeadInterval 秒后才能释放最后一个 Database Description packet. 在此间隔之后从 master 收到 Database Description packet 将生成 SeqNumberMismatch neighbor event.


10.9. 发送 Link State Request Packets

在邻居状态 Exchange 或 Loading 中, Link state request list 包含需要从邻居获得的 LSA 列表. 为请求这些 LSA, 路由器将 Link state request list 的开头打包到 Link State Request packet 中发送给邻居.

当邻居用适当的 Link State Update packet(s) 响应这些请求时, Link state request list 被截断, 并发送新的 Link State Request packet. 这一过程持续到 Link state request list 变为空. Link state request list 中已请求但尚未收到的 LSA 会被打包进 Link State Request packets, 按 RxmtInterval 间隔重传. 任意时刻最多应有一个未完成的 Link State Request packet.

当 Link state request list 变为空, 且邻居状态为 Loading (即已经向邻居发送并从邻居接收了完整 Database Description packets 序列) 时, 生成 Loading Done neighbor event.


10.10. 示例 (An Example)

Figure 14 显示一个邻接关系形成示例. Routers RT1 和 RT2 都连接到一个广播网络. 假定 RT2 是该网络的 Designated Router, 且 RT2 的 Router ID 高于 Router RT1.

每台路由器实现的邻居状态变化列在图的两侧.

在 Figure 14 开始时, Router RT1 通往网络的接口变为可运行. 它开始发送 Hello Packets, 尽管还不知道 Designated Router 或任何其他相邻路由器的身份. Router RT2 听到这个 hello (将邻居移至 Init 状态), 并在其下一个 Hello Packet 中指示自己是 Designated Router, 且已听到来自 RT1 的 Hello Packets. 这继而导致 RT1 进入 ExStart 状态, 开始建立邻接关系.

RT1 首先声明自己为 master. 当它看到 RT2 确实是 master (因为 RT2 的 Router ID 更高) 时, RT1 转换为 slave 状态, 并采用其邻居的 DD sequence number. 随后交换 Database Description packets, poll 来自 master (RT2), response 来自 slave (RT1). 这一 Database Description Packets 序列在 poll 及其关联 response 的 M-bit 都关闭时结束.


+---+ +---+
|RT1| |RT2|
+---+ +---+

Down Down
Hello(DR=0,seen=0)
------------------------------>
Hello (DR=RT2,seen=RT1,...) Init
<------------------------------
           ExStart        D-D (Seq=x,I,M,Master)
------------------------------>
D-D (Seq=y,I,M,Master) ExStart
<------------------------------
Exchange D-D (Seq=y,M,Slave)
------------------------------>
D-D (Seq=y+1,M,Master) Exchange
<------------------------------
D-D (Seq=y+1,M,Slave)
------------------------------>
...
...
...
D-D (Seq=y+n, Master)
<------------------------------
D-D (Seq=y+n, Slave)
Loading ------------------------------>
LS Request Full
------------------------------>
LS Update
<------------------------------
LS Request
------------------------------>
LS Update
<------------------------------
Full
               Figure 14: 邻接建立示例


在本例中, 假定 RT2 具有完全最新的数据库. 在这种情况下, RT2 立即进入 Full 状态. RT1 在更新其数据库的必要部分后进入 Full 状态. 这是通过发送 Link State Request Packets, 并接收作为响应的 Link State Update Packets 完成的. 注意, 虽然 RT1 在收到完整的 Database Description Packets 集合 (来自 RT2) 后才发送任何 Link State Request Packets, 但并非必须如此. RT1 可以把 Link State Request Packets 的发送与 Database Description Packets 的接收交错进行.