跳到主要内容

10. 邻居数据结构

  1. 邻居数据结构(The Neighbor Data Structure)
一台 OSPF 路由器会与它的相邻路由器进行"会话"。每一次独立的会话
都由一个"邻居数据结构"(neighbor data structure)来描述。每次会话
都绑定到某个特定的 OSPF 路由器接口上,并且通过相邻路由器的 OSPF
Router ID 或者其 Neighbor IP address(邻居 IP 地址,见下文)来标识。
因此,如果本 OSPF 路由器与另一台路由器之间有多个共同连接的网络,
就会产生多个会话,每个会话都由一个独立的邻居数据结构描述。在本文中,
每个独立的会话被宽泛地称为一个独立的"邻居"(neighbor)。

邻居数据结构包含与两个邻居之间正在形成或已经形成的 adjacency(邻接)
相关的全部信息。(但请记住,并非所有邻居都会形成 adjacency。)
adjacency 可以看作是两台路由器之间高度发展的会话。


State(状态)
    邻居会话的功能级别。详见 10.1 节。

Inactivity Timer(不活动定时器)
    一个一次性(single shot)定时器,其触发表示最近没有从该邻居
    收到过 Hello Packet。定时器的时长为 RouterDeadInterval 秒。

Master/Slave(主/从)
    当两个邻居交换数据库时,它们会形成一种主/从关系。master
    发送第一个 Database Description Packet,并且是唯一被允许
    重传的一方。slave 只能响应 master 的 Database Description
    Packets。主/从关系是在 ExStart 状态下协商确定的。







DD Sequence Number(DD 序列号)
    当前正在发送给邻居的 Database Description 报文的 DD 序列号。

Last received Database Description packet(最后收到的 Database Description 报文)
    从邻居收到的最后一个 Database Description 报文中所包含的
    initialize(I)、more(M) 和 master(MS) 位、Options 字段以及
    DD 序列号。用于判断从邻居收到的下一个 Database Description
    报文是否是重复报文。

Neighbor ID(邻居 ID)
    相邻路由器的 OSPF Router ID。Neighbor ID 是在从邻居收到
    Hello 报文时学习到的;如果这是一条 virtual adjacency(虚拟邻接),
    则通过配置得到(见 C.4 节)。

Neighbor Priority(邻居优先级)
    相邻路由器的 Router Priority。该项包含在邻居的 Hello 报文中,
    在为所连接网络选举 Designated Router(指定路由器)时使用。

Neighbor IP address(邻居 IP 地址)
    相邻路由器连接到该网络的接口的 IP 地址。当协议报文沿该
    adjacency 以单播方式发送时,用作目的 IP 地址。如果该相邻路由器
    被选为 Designated Router,它还会在 router-LSA 中被用作该
    连接网络的 Link ID(见 12.4.1 节)。Neighbor IP address 是在
    从邻居收到 Hello 报文时学习到的。对于 virtual link(虚链路),
    Neighbor IP address 是在路由表构建过程中学习到的(见第 15 节)。

Neighbor Options(邻居可选项)
    邻居所支持的 OSPF 可选能力。在 Database Exchange(数据库交换)
    过程中学习得到(见 10.6 节)。邻居的 OSPF 可选能力也列在它的
    Hello 报文中。这使得当某些关键的 OSPF 能力不匹配时,收到的
    Hello 报文可以被拒绝(即邻居关系甚至不会开始形成,见 10.5 节)。
    OSPF 可选能力在 4.5 节中说明。







Neighbor's Designated Router(邻居所认为的指定路由器)
    邻居所认为的 Designated Router。如果这就是邻居自身,那么这
    对本地的 Designated Router 计算很重要。仅在 broadcast(广播)
    和 NBMA 网络上定义。

Neighbor's Backup Designated Router(邻居所认为的备份指定路由器)
    邻居所认为的 Backup Designated Router。如果这就是邻居自身,
    那么这对本地的 Backup Designated Router 计算很重要。仅在
    broadcast 和 NBMA 网络上定义。


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


Link state retransmission list(链路状态重传列表)
    已在该 adjacency 上泛洪(flooded)但尚未被确认的 LSA 列表。
    这些 LSA 将按一定间隔重传,直到被确认,或直到该 adjacency
    被销毁。

Database summary list(数据库摘要列表)
    在邻居进入 Database Exchange 状态那一刻,构成区域链路状态
    数据库的全部 LSA 列表。该列表通过 Database Description
    报文发送给邻居。

Link state request list(链路状态请求列表)
    为了使两个邻居的链路状态数据库同步,需要从该邻居接收的
    LSA 列表。该列表在接收 Database Description 报文的过程中
    创建,然后通过 Link State Request 报文发送给邻居。随着相应的
    Link State Update 报文被接收,该列表逐渐被清空。









10.1.  邻居状态(Neighbor states)

    邻居的状态(实际上是与相邻路由器所进行会话的状态)在以下
    各节中说明。这些状态按功能递进的顺序列出。例如,最先列出的
    是非工作状态,接着是一系列中间状态,最后是完全可用的最终
    状态。本规范利用这一顺序,有时会使用诸如"状态大于 X 的那些
    邻居/adjacency"这样的表述。图 12 和图 13 展示了邻居状态变化
    的图。图中的弧线用引起状态变化的事件标注。邻居事件在 10.2 节
    中说明。

    图 12 中的图展示了由 Hello Protocol 引发的状态变化。Hello
    Protocol 负责邻居的获取与维护,并确保邻居之间的双向通信。

    图 13 中的图展示了 adjacency 的形成过程。并非每两台相邻路由器
    都会形成 adjacency(见 10.4 节)。当邻居处于 ExStart 状态时,
    adjacency 开始形成。在两台路由器确定了各自的主/从状态之后,
    状态转换为 Exchange。此时该邻居开始被用于泛洪过程,两台相邻
    路由器开始同步它们的数据库。当同步完成后,邻居处于 Full 状态,
    我们称这两台路由器已经完全邻接(fully adjacent)。此时该
    adjacency 会被列入 LSA 中。

    关于邻居状态变化的更详细描述,以及每次变化所涉及的附加动作,
    见 10.3 节。


    Down
        这是邻居会话的初始状态。它表示最近没有从该邻居收到任何
        信息。在 NBMA 网络上,仍然可以向处于 "Down" 状态的邻居
        发送 Hello 报文,只是频率会降低(见 9.5.1 节)。







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

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

            除图中所示的状态转换外,
            事件 SeqNumberMismatch 强制进入 ExStart 状态,
            事件 BadLSReq 强制进入 ExStart 状态,
            事件 1-Way 强制进入 Init 状态,
            事件 KillNbr 总是强制进入 Down 状态,
            事件 InactivityTimer 总是强制进入 Down 状态,
            事件 LLDown 总是强制进入 Down 状态,
            事件 AdjOK? 会导致 adjacency 的建立/拆除

    Attempt
        该状态仅对连接到 NBMA 网络的邻居有效。它表示最近没有从
        该邻居收到任何信息,但应当做出更积极的努力去联系该邻居。
        具体做法是以 HelloInterval 为间隔向该邻居发送 Hello 报文
        (见 9.5.1 节)。

    Init
        在该状态下,最近曾从该邻居收到过 Hello 报文。但是,尚未
        与该邻居建立双向通信(即路由器自身没有出现在邻居的
        Hello 报文中)。所有







        处于该状态(或更高状态)的邻居,都会被列在从相应接口
        发出的 Hello 报文中。

    2-Way
        在该状态下,两台路由器之间的通信是双向的。这一点已由
        Hello Protocol 的运行所保证。这是在开始建立 adjacency
        之前最高级的状态。(Backup)Designated Router 是从处于
        2-Way 或更高状态的邻居集合中选举出来的。

    ExStart
        这是在两台相邻路由器之间创建 adjacency 的第一步。这一步
        的目标是决定哪台路由器是 master,并确定初始 DD 序列号。
        处于该状态或更高状态的邻居会话被称为 adjacency。

    Exchange
        在该状态下,路由器通过向邻居发送 Database Description
        报文来描述它的整个链路状态数据库。每个 Database
        Description 报文都有一个 DD 序列号,并且会被显式确认。
        任何时刻只允许有一个 Database Description 报文处于未确认
        状态。在该状态下,也可以发送 Link State Request 报文,
        请求邻居更新的 LSA。所有处于 Exchange 或更高状态的
        adjacency 都会被泛洪过程使用。事实上,这些 adjacency
        已经完全有能力发送和接收所有类型的 OSPF 路由协议报文。

    Loading
        在该状态下,会向邻居发送 Link State Request 报文,请求
        在 Exchange 状态中已发现(但尚未接收)的、更新的 LSA。

    Full
        在该状态下,相邻路由器之间已完全邻接。这些 adjacency
        现在会出现在 router-LSA 和 network-LSA 中。








10.2.  引起邻居状态变化的事件

    状态变化可以由多种事件引发。这些事件显示在图 12 和图 13 中
    弧线的标注上。标注的定义如下:


    HelloReceived
        已从邻居收到一个 Hello 报文。

    Start
        这表示现在应当以 HelloInterval 秒为间隔向该邻居发送
        Hello 报文。该事件仅针对与 NBMA 网络关联的邻居生成。

    2-WayReceived
        两台相邻路由器之间已实现双向通信。这是通过路由器在邻居的
        Hello 报文中看到自己来体现的。

    NegotiationDone
        主/从关系已协商完毕,DD 序列号也已交换。这标志着开始
        发送/接收 Database Description 报文。关于该事件的生成,
        更多信息请参见 10.8 节。

    ExchangeDone
        两台路由器都已成功发送了完整的 Database Description
        报文序列。现在每台路由器都知道自己链路状态数据库中哪些
        部分已经过时。关于该事件的生成,更多信息请参见 10.8 节。

    BadLSReq
        收到了针对数据库中不存在的某个 LSA 的 Link State
        Request。这表示 Database Exchange 过程中出现了错误。

    Loading Done
        已收到数据库中所有过时部分对应的 Link State Update。





        这是通过 Database Exchange 过程完成之后 Link state
        request list 变为空来体现的。

    AdjOK?
        必须做出决定:是否应当与该邻居建立/维持 adjacency。
        该事件会使一些 adjacency 开始形成,也会销毁另一些
        adjacency。


    以下事件会使已充分发展的邻居退回到较低的状态。与上述事件不同,
    这些事件可能在邻居会话处于多种状态中的任意一种时发生。


    SeqNumberMismatch
        收到了一个 Database Description 报文,它 a) 具有非预期的
        DD 序列号,或 b) 出乎意料地设置了 Init 位,或 c) 其
        Options 字段与上一次在 Database Description 报文中收到的
        Options 字段不同。上述任一条件都表明在建立 adjacency
        的过程中发生了某种错误。

    1-Way
        从邻居收到了一个 Hello 报文,但其中没有提到本路由器。
        这表明与该邻居的通信不是双向的。

    KillNbr
        这表示与该邻居的所有通信现在都已不可能,从而强制该邻居
        退回到 Down 状态。

    InactivityTimer
        不活动定时器已触发。这意味着最近没有从该邻居收到 Hello
        报文。该邻居退回到 Down 状态。

    LLDown
        这是来自较低层协议的指示,表明该邻居现在不可达。例如,
        在 X.25 网络上,这可能通过带有相应 cause 和 diagnostic





        字段的 X.25 clear indication 来指示。该事件强制该邻居
        进入 Down 状态。


10.3.  邻居状态机(The Neighbor state machine)

    下面是对邻居状态变化的详细描述。每次状态变化都由一个事件
    (10.2 节)触发。取决于邻居的当前状态,同一事件可能产生
    不同的效果。因此,下面的状态机按"当前邻居状态"和"收到的事件"
    来组织。状态机中的每一条目描述了产生的新邻居状态以及所需的
    附加动作集合。

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

    当邻居状态机需要调用接口状态机时,应当以调度任务(scheduled
    task)的方式进行(见 4.4 节)。这样可以确保两个状态机都不会
    被递归执行,从而简化实现。


     状态(State(s)):  Down

        事件(Event):  Start

    新状态(New state):  Attempt

       动作(Action):  向该邻居发送一个 Hello 报文(该邻居总是
                与 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 或更高

        事件(Event):  HelloReceived

    新状态(New state):  状态不变。

       动作(Action):  重启该邻居的 Inactivity Timer,因为再次
                收到了该邻居的消息。


     状态(State(s)):  Init

        事件(Event):  2-WayReceived

    新状态(New state):  取决于动作例程。

       动作(Action):  判断是否应当与该邻居建立 adjacency
                (见 10.4 节)。若不应当,则新的邻居状态为 2-Way。

                否则(应当建立 adjacency),邻居状态转换到
                ExStart。进入该状态时,路由器将邻居数据结构中的
                DD






                序列号加一。如果这是首次尝试建立 adjacency,
                则 DD 序列号应被赋予某个唯一值(例如当前时钟
                时间)。然后它宣布自己为 master(将 master/slave
                位置为 master),并开始发送设置了 initialize(I)、
                more(M) 和 master(MS) 位的 Database Description
                报文。该 Database Description 报文除此之外应为空。
                该 Database Description 报文应以 RxmtInterval 为
                间隔重传,直到进入下一状态(见 10.8 节)。


     状态(State(s)):  ExStart

        事件(Event):  NegotiationDone

    新状态(New state):  Exchange

       动作(Action):  路由器必须将其整个区域链路状态数据库的
                内容列入邻居的 Database summary list。区域链路
                状态数据库由区域结构中包含的 router-LSA、
                network-LSA 和 summary-LSA,以及全局结构中包含的
                AS-external-LSA 组成。对于 virtual neighbor
                (虚拟邻居),AS-external-LSA 从 Database summary
                list 中省略。如果该区域被配置为 stub(末梢区域),
                AS-external-LSA 也从 Database summary list 中省略
                (见 3.6 节)。age 等于 MaxAge 的 LSA 则改为加入
                该邻居的 Link state retransmission list。Database
                summary list 的摘要将通过 Database Description
                报文发送给邻居。每个 Database Description 报文都
                有一个 DD 序列号,并且会被显式确认。任何时刻只
                允许有一个 Database Description 报文处于未确认
                状态。关于 Database Description 报文的发送与接收
                的更多细节,见 10.8 节和 10.6 节。









     状态(State(s)):  Exchange

        事件(Event):  ExchangeDone

    新状态(New state):  取决于动作例程。

       动作(Action):  如果邻居的 Link state request list 为空,
                则新的邻居状态为 Full。不需要其他动作。这是
                adjacency 的最终状态。

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


     状态(State(s)):  Loading

        事件(Event):  Loading Done

    新状态(New state):  Full

       动作(Action):  不需要动作。这是 adjacency 的最终状态。


     状态(State(s)):  2-Way

        事件(Event):  AdjOK?

    新状态(New state):  取决于动作例程。

       动作(Action):  判断是否应当与该相邻路由器形成
                adjacency(见 10.4 节)。若不应当,则邻居状态
                保持为 2-Way。否则,将邻居状态转换到 ExStart,
                并执行上文中"状态 Init、事件 2-WayReceived"这一
                状态机条目所关联的动作。







     状态(State(s)):  ExStart 或更高

        事件(Event):  AdjOK?

    新状态(New state):  取决于动作例程。

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

                否则,必须销毁(可能只是部分形成的)adjacency。
                邻居状态转换为 2-Way。Link state retransmission
                list、Database summary list 和 Link state request
                list 中的 LSA 都被清空。


     状态(State(s)):  Exchange 或更高

        事件(Event):  SeqNumberMismatch

    新状态(New state):  ExStart

       动作(Action):  拆除(可能只是部分形成的)adjacency,
                然后尝试重新建立。邻居状态首先转换到 ExStart。
                Link state retransmission list、Database summary
                list 和 Link state request list 中的 LSA 被清空。
                然后路由器将邻居数据结构中的 DD 序列号加一,
                宣布自己为 master(将 master/slave 位置为
                master),并开始发送设置了 initialize(I)、
                more(M) 和 master(MS) 位的 Database Description
                报文。该 Database Description 报文除此之外应为空
                (见 10.8 节)。


     状态(State(s)):  Exchange 或更高

        事件(Event):  BadLSReq







    新状态(New state):  ExStart

       动作(Action):  事件 BadLSReq 的动作与邻居事件
                SeqNumberMismatch 完全相同。拆除(可能只是部分
                形成的)adjacency,然后尝试重新建立。更多信息
                请参见在 Exchange 或更高状态下生成
                SeqNumberMismatch 事件时所调用的邻居状态机条目。


     状态(State(s)):  任意状态

        事件(Event):  KillNbr

    新状态(New state):  Down

       动作(Action):  Link state retransmission list、Database
                summary list 和 Link state request list 中的 LSA
                被清空。同时,禁用 Inactivity Timer。


     状态(State(s)):  任意状态

        事件(Event):  LLDown

    新状态(New state):  Down

       动作(Action):  Link state retransmission list、Database
                summary list 和 Link state request list 中的 LSA
                被清空。同时,禁用 Inactivity Timer。


     状态(State(s)):  任意状态

        事件(Event):  InactivityTimer

    新状态(New state):  Down

       动作(Action):  Link state retransmission list、Database
                summary list 和 Link state request list 中的 LSA
                被清空。






     状态(State(s)):  2-Way 或更高

        事件(Event):  1-WayReceived

    新状态(New state):  Init

       动作(Action):  Link state retransmission list、Database
                summary list 和 Link state request list 中的 LSA
                被清空。


     状态(State(s)):  2-Way 或更高

        事件(Event):  2-WayReceived

    新状态(New state):  状态不变。

       动作(Action):  不需要动作。


     状态(State(s)):  Init

        事件(Event):  1-WayReceived

    新状态(New state):  状态不变。

       动作(Action):  不需要动作。


10.4.  是否成为邻接(Whether to become adjacent)

    adjacency 只与路由器的部分邻居建立。通过 point-to-point
    (点到点)网络、Point-to-MultiPoint(点到多点)网络以及
    virtual link 连接的路由器总是会成为邻接。在 broadcast 和
    NBMA 网络上,所有路由器都会与 Designated Router 和 Backup
    Designated Router 建立 adjacency。

    形成 adjacency 的决策在邻居状态机中的两个位置发生。第一次是
    在与邻居初次建立双向通信时;第二次是在所连接网络的
    (Backup)Designated







    Router 身份发生变化时。如果决定不尝试建立 adjacency,则邻居
    通信的状态停留在 2-Way。

    当满足以下至少一个条件时,应当与一个双向邻居建立 adjacency:


    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 报文

    本节说明收到 Hello 报文后的详细处理过程。(Hello 报文的格式
    见 A.3.2 节。)OSPF 报文的通用输入处理已经检查过 IP 头和
    OSPF 报文头的有效性。接下来,必须将收到的 Hello 报文中的
    Network Mask、HelloInterval 和 RouterDeadInterval 字段的值
    与接收接口所配置的值进行比对。任何不匹配都会导致处理停止并
    丢弃该报文。换句话说,上述字段实际上描述的是所连接网络的
    配置。不过,上述规则有一个例外:在 point-to-point 网络和
    virtual link 上,应当忽略收到的 Hello 报文中的 Network Mask。

    接收接口连接到单个 OSPF 区域(这可能是 backbone,即骨干区域)。
    Hello 报文 Options 字段中 E-bit 的设置必须与该区域的





    ExternalRoutingCapability 匹配。如果 AS-external-LSA 不被泛洪
    进入/贯穿该区域(即该区域是 "stub"),则收到的 Hello 报文中
    E-bit 必须清零;否则 E-bit 必须置位。不匹配将导致处理停止并
    丢弃该报文。Hello 报文 Options 字段中其余各位的设置应当被忽略。

    此时,会尝试将该 Hello 报文的源与接收接口的某个邻居进行匹配。
    如果接收接口连接的是 broadcast、Point-to-MultiPoint 或 NBMA
    网络,则通过 Hello 报文 IP 头中的 IP 源地址来标识来源。如果
    接收接口连接的是 point-to-point 链路或 virtual link,则通过
    Hello 报文 OSPF 头中的 Router ID 来标识来源。接口当前的邻居
    列表包含在接口的数据结构中。如果找不到匹配的邻居结构(即这是
    首次检测到该邻居),则创建一个。新创建的邻居的初始状态被设为
    Down。

    当在 broadcast、Point-to-MultiPoint 或 NBMA 网络上从邻居收到
    Hello 报文时,将邻居结构的 Neighbor ID 设为报文 OSPF 头中的
    Router ID。对于这些网络类型,邻居结构的 Router Priority 字段、
    Neighbor's Designated Router 字段和 Neighbor's Backup
    Designated Router 字段也被设为收到的 Hello 报文中相应字段的
    值;这些字段的变化应当被记录下来,以便在下面的步骤中使用。
    当在 point-to-point 网络(但不是 virtual link)上收到 Hello
    时,将邻居结构的 Neighbor IP address 设为报文的 IP 源地址。

    现在检查 Hello 报文的其余部分,生成要提交给邻居状态机和接口
    状态机的事件。这些状态机被指定为立即执行或调度执行(见 4.4 节)。
    例如,通过在下文中指定邻居状态机就地(in line)执行,单个收到
    的 Hello 可能引发多次邻居状态转换:









    o   每个 Hello 报文都会导致邻居状态机以事件 HelloReceived
        执行。

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

    o   接下来,如果注意到邻居的 Router Priority 字段发生了变化,
        则接收接口的状态机以事件 NeighborChange 被调度执行。

    o   如果该邻居既宣称自己是 Designated Router(Hello 报文的
        Designated Router 字段 = Neighbor IP address),并且报文中
        的 Backup Designated Router 字段等于 0.0.0.0,且接收接口
        处于 Waiting 状态,则接收接口的状态机以事件 BackupSeen
        被调度执行。否则,如果该邻居现在宣称自己是 Designated
        Router 而之前并未如此,或者该邻居之前宣称自己是
        Designated Router 而现在不再如此,则接收接口的状态机以
        事件 NeighborChange 被调度执行。

    o   如果该邻居宣称自己是 Backup Designated Router(Hello 报文
        的 Backup Designated Router 字段 = Neighbor IP address),
        且接收接口处于 Waiting 状态,则接收接口的状态机以事件
        BackupSeen 被调度执行。否则,如果该邻居现在宣称自己是
        Backup Designated Router 而之前并未如此,或者该邻居之前
        宣称自己是 Backup Designated Router 而现在不再如此,则
        接收接口的状态机以事件 NeighborChange 被调度执行。

    在 NBMA 网络上,收到 Hello 报文还可能导致向该邻居回送一个
    Hello 报文作为响应。详见 9.5.1 节。









10.6.  接收 Database Description 报文

    本节说明收到 Database Description 报文后的详细处理过程。
    进入的 Database Description 报文已经由通用输入报文处理
    (8.2 节)关联到某个邻居和接收接口。该 Database Description
    报文是否应被接受,以及若被接受应如何进一步处理,取决于邻居
    的状态。

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

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

    Down
        该报文应被拒绝。

    Attempt
        该报文应被拒绝。

    Init
        应以事件 2-WayReceived 执行邻居状态机。这会导致状态立即
        变为 2-Way 或 ExStart。如果新状态是 ExStart,则应在该新
        状态下继续处理当前报文,即向下贯穿(fall through)到下面
        的 ExStart 情形。









    2-Way
        该报文应被忽略。Database Description 报文仅用于建立
        adjacency 的目的。[7]

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

        o   initialize(I)、more(M) 和 master(MS) 位均置位,报文
            内容为空,且邻居的 Router ID 大于本路由器自身的
            Router ID。此时本路由器成为 Slave。将 master/slave
            位置为 slave,并将邻居数据结构的 DD 序列号设为 master
            所指定的值。

        o   initialize(I) 和 master(MS) 位均清零,报文的 DD 序列号
            等于邻居数据结构中的 DD 序列号(表示确认),且邻居的
            Router ID 小于本路由器自身的 Router ID。此时本路由器
            为 Master。

    Exchange
        重复的 Database Description 报文会被 master 丢弃,并会使
        slave 重传它上一次发送的 Database Description 报文。
        否则(该报文不是重复报文):

        o   如果 MS-bit 的状态与连接的主/从状态不一致,则生成
            邻居事件 SeqNumberMismatch 并停止处理该报文。

        o   如果 initialize(I) 位被置位,则生成邻居事件
            SeqNumberMismatch 并停止处理该报文。







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

        o   Database Description 报文必须按报文的 DD 序列号所
            指示的顺序处理。如果本路由器是 master,则收到的下一个
            报文的 DD 序列号应等于邻居数据结构中的 DD 序列号。
            如果本路由器是 slave,则收到的下一个报文的 DD 序列号
            应等于邻居数据结构中存储的 DD 序列号加一。无论哪种
            情况,如果该报文是序列中的下一个,就应被接受,并按
            下文所述处理其内容。

        o   否则,生成邻居事件 SeqNumberMismatch 并停止处理该报文。

    Loading 或 Full
        在该状态下,路由器已经发送并接收了完整的 Database
        Description 报文序列。此时收到的报文应当只可能是重复报文
        (见上文)。特别地,报文的 Options 字段应与该邻居之前
        指示的 OSPF 可选能力集合相匹配(存储在邻居结构的 Neighbor
        Options 字段中)。收到任何其他报文,包括收到设置了
        Initialize(I) 位的报文,都应生成邻居事件
        SeqNumberMismatch。[8] 重复报文应被 master 丢弃。slave
        必须通过重发它上一次发送的 Database Description 报文来
        响应重复报文。


    当路由器接受一个收到的 Database Description 报文作为序列中的
    下一个报文时,其报文内容按如下方式处理。对于所列的每个 LSA,
    检查该 LSA 的 LS type 是否有效。如果 LS type 未知(例如不是
    本规范定义的 LS type 1-5 之一),或者这是一个 AS-external-LSA
    (LS type = 5)而该邻居关联的是





    stub 区域,则生成邻居事件 SeqNumberMismatch 并停止处理该报文。
    否则,路由器在其数据库中查找该 LSA,看是否也拥有该 LSA 的一个
    实例。如果没有,或者数据库中的副本较旧(见 13.1 节),则将该
    LSA 放入 Link state request list,以便(立即或稍后)通过
    Link State Request 报文进行请求。

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


    Master
        将邻居数据结构中的 DD 序列号加一。如果路由器已经发送完
        它的整个 Database Description 报文序列,并且刚刚接受的
        报文中 more 位(M)被置为 0,则生成邻居事件 ExchangeDone。
        否则,它应向 slave 发送一个新的 Database Description 报文。

    Slave
        将邻居数据结构中的 DD 序列号设为收到报文中出现的 DD
        序列号。slave 必须回复一个 Database Description 报文。
        如果收到的报文中 more 位(M)被置为 0,并且 slave 将要
        发送的报文中 M 位也将被置为 0,则生成邻居事件
        ExchangeDone。注意,slave 总是先于 master 生成该事件。


10.7.  接收 Link State Request 报文

    本节说明收到 Link State Request 报文后的详细处理过程。收到的
    Link State Request 报文指定了邻居希望接收的 LSA 列表。当邻居
    处于 Exchange、Loading 或 Full 状态时,应当接受 Link State
    Request 报文。在所有其他状态下,Link State Request 报文应被
    忽略。









    Link State Request 报文中指定的每个 LSA 都应在路由器的数据库
    中找到,并复制到 Link State Update 报文中发送给该邻居。这些
    LSA 不应被放入该邻居的 Link state retransmission list。如果
    在数据库中找不到某个 LSA,说明 Database Exchange 过程出了
    问题,应生成邻居事件 BadLSReq。


10.8.  发送 Database Description 报文

    本节描述如何向邻居发送 Database Description 报文。Database
    Description 报文的 Interface MTU 字段被设为可以从发送接口
    发出而无需分片的最大 IP 数据报的大小。Internet 上常用的 MTU
    可在 [Ref22] 的表 7-1 中找到。在通过 virtual link 发送的
    Database Description 报文中,Interface MTU 应设为 0。

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

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

    在 Exchange 状态下,Database Description 报文实际包含路由器
    数据库中链路状态信息的摘要。区域链路状态数据库中的每个 LSA
    (在邻居转换到 Exchange 状态时的那一刻)都列在邻居的 Database
    summary list 中。每个新的 Database






    Description 报文从邻居数据结构中复制其 DD 序列号,然后描述
    Database summary list 当前的头部内容。当前一个报文被确认后,
    相应条目会从 Database summary list 中移除。

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


    Master
        在以下情况下发送 Database Description 报文:a) slave 通过
        回显 DD 序列号确认了前一个 Database Description 报文;
        或 b) 经过 RxmtInterval 秒仍未收到确认,此时重传前一个
        Database Description 报文。

    Slave
        仅在响应从 master 收到的 Database Description 报文时才
        发送 Database Description 报文。如果从 master 收到的
        Database Description 报文是新的,则发送一个新的 Database
        Description 报文;否则重发前一个 Database Description
        报文。


    在 Loading 和 Full 状态下,slave 必须重发它最后一个 Database
    Description 报文,以响应从 master 收到的重复 Database
    Description 报文。因此,slave 必须等待 RouterDeadInterval 秒
    之后才能释放最后一个 Database Description 报文。在该间隔之后
    再从 master 收到 Database Description 报文,将生成
    SeqNumberMismatch 邻居事件。


10.9.  发送 Link State Request 报文

    在邻居状态 Exchange 或 Loading 下,Link state request list
    包含需要从该邻居获取的 LSA 列表。为了请求这些 LSA,路由器
    将 Link state request list 的开头部分封装在一个 Link State
    Request 报文中发送给邻居。









    当邻居用相应的 Link State Update 报文响应这些请求时,Link
    state request list 会被截短,并发送一个新的 Link State
    Request 报文。该过程持续进行,直到 Link state request list
    变为空。Link state request list 中那些已被请求但尚未收到的
    LSA,会被封装到 Link State Request 报文中,以 RxmtInterval
    为间隔重传。任何时刻最多只应有一个 Link State Request 报文
    处于未响应状态。

    当 Link state request list 变为空,且邻居状态为 Loading 时
    (即已向邻居发送并从邻居接收了完整的 Database Description
    报文序列),生成 Loading Done 邻居事件。


10.10.  一个示例

    图 14 展示了一个 adjacency 形成的示例。路由器 RT1 和 RT2 都
    连接到一个 broadcast 网络。假定 RT2 是该网络的 Designated
    Router,并且 RT2 的 Router ID 高于路由器 RT1。

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

    在图 14 的开始处,路由器 RT1 到该网络的接口变为可用。它开始
    发送 Hello 报文,尽管它还不知道 Designated Router 或任何其他
    相邻路由器的身份。路由器 RT2 听到了这个 hello(使该邻居进入
    Init 状态),并在它的下一个 Hello 报文中表明它自己是
    Designated Router,并且它已经听到了来自 RT1 的 Hello 报文。
    这进而使 RT1 进入 ExStart 状态,因为它开始建立该 adjacency。

    RT1 首先宣称自己是 master。当它发现 RT2 确实是 master 时
    (因为 RT2 的 Router ID 更高),RT1 转换为 slave 状态,并采用
    邻居的 DD 序列号。随后交换 Database Description 报文,由
    master(RT2)发出轮询,slave(RT1)作出响应。这一 Database
    Description












        +---+                                         +---+
        |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
               图 14:adjacency 建立示例





报文序列在轮询及其相应响应的 M 位都关闭时结束。

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