開放式最短路徑優先

開放式最短路徑優先（Open Shortest Path First，縮寫為 OSPF）是廣泛使用的一種路由協議，它屬於鏈路狀態路由協議，具有路由變化收斂速度快、無路由環路、支援變長子網掩碼（VLSM）和彙總、層次區域劃分等優點。

OSPF 是一種基於 IP 協議的路由協議。它是大中型網路上使用較為廣泛的 IGP 協議。OSPF 是對的一種實現，運作於自治系統內部。OSPF 分為 OSPFv2 和 OSPFv3 兩個版本：OSPFv2 定義於 RFC 2328（1998），支援 IPv4 網路；而 OSPFv3 定義於 RFC 5340（2008），支援 IPv6 網路。

它採用戴克斯特拉演算法來計算最短路徑樹。它使用 “開銷（Cost）” 作為路由度量。鏈路狀態資料庫（LSDB）用來儲存當前網路拓撲結構，路由器上屬於同一區域的鏈路狀態資料庫是相同的（屬於多個區域的路由器會為每個區域維護一份鏈路狀態資料庫）。

OSPF 提出了 “區域（Area）” 的概念，一個網路可以由單一區域或者多個區域組成。其中，一個特別的區域被稱為骨幹區域（Backbone Area），該區域是整個 OSPF 網路的核心區域，並且所有其他的區域都與之直接連線。所有的內部路由都透過骨幹區域傳遞到其他非骨幹區域。所有的區域都必須直接連線到骨幹區域，如果不能建立直接連線，那麼可以透過虛鏈路（virtual link）和骨幹區域建立虛擬連線。

同一個廣播域（Broadcast Domain）的路由器或者一個點對點（Point To Point）連線的兩端的路由器，在發現彼此的時候，建立鄰接（Adjacencies）。多路訪問網路以及非廣播多路訪問網路的路由器會選舉指定路由器（Designated Router, DR）和備份指定路由器（Backup Designated Router, BDR），DR 和 BDR 作為網路的中心負責路由器之間的資訊交換從而降低了網路中的資訊流量。OSPF 協議同時使用單播（Unicast）和群播（Multicast）來發送 Hello 包和鏈路狀態更新（Link State Updates），使用的群播地址為 224.0.0.5 和 224.0.0.6。與 RIP 和 BGP 不同的是，OSPF 協議不使用 TCP 或者 UDP 協議而是直接承載在 IP 協議之上，IP 協議號為 89。

區域

一個 OSPF 網路分為多個區域。區域將網路中的路由器在邏輯上分組並以區域為單位向網路的其餘部分發送彙總路由資訊。區域編號由一個長度為 32 位的欄位所定義，區域編號有兩種表示方法，一種為點分十進位制（如 Area 1.1.1.1，寫法規則同 IPv4 地址）；另外一種為十進位制數字格式（如 Area 1，注意 Area 1 不等於 Area 1.1.1.1，而是 0.0.0.1）。根據 RFC2328 描述，區域編號通常使用 32 bits 的點分十進位表示。區域編號不是 IP 地址，用於 IPv6 網路的 OSPFv3 也使用同樣的（形似 IPv4 地址的）區域編號格式。

區域是以介面（Interface）為單位來劃分的，所以一臺多介面路由器可能屬於多個區域。相同區域內的所有路由器都維護一份相同的鏈路狀態資料庫（LSDB），如果一臺路由器屬於多個區域，那麼它將為每一個區域維護一份 LSDB。

某一區域內的路由器只需要維護該區域的鏈路狀態資料庫，而不用維護整個 OSPF 網路的鏈路狀態資料庫。
將某一區域網路拓撲變化的影響限制在該區域內，不會影響到整個 OSPF 網路，從而減小 OSPF 計算的頻率。
將鏈路狀態通告（LSA）的洪泛限制在本區域內，從而降低 OSPF 協議產生的資料量。
劃分區域可以對網路進行層次化結構設計。
劃分區域有利於資源合理調配，核心區域部署效能較好的裝置資源，邊緣區域部署效能較差的裝置資源即可。

OSPF 有多種區域型別，其中定義了幾種特殊的區域：

1.1 骨幹區域

骨幹區域（Backbone Area），Area 0（點分十進位制表示為 0.0.0.0），是整個 OSPF 域的核心區域。所有其他非骨幹區域必須和骨幹區域直接或間接相連。骨幹區域的功能是在不同的非骨幹區域之間分發路由資訊。

骨幹區域必須是唯一而且連續的，但不需要在物理上連續：它可以使用虛擬連線。

1.2 傳送區域

傳送區域連線至少 2 個其他區域，它將通告從一個區域傳送到另一個區域。

1.3 末梢區域

末梢區域（Stub Area）是一個不允許 AS 外部路由通告（AS External LSA，即型別 5 LSA）在其內部進行洪泛擴散的區域。末梢區域的 ABR 會通告一條預設路由（default route）到該區域內所有路由器，任何發往 AS 外部網路的資料流都將依據預設路由來轉發。

1.3.1 不完全末梢區域

非純末梢區域（Not-So-Stubby Area，NSSA）允許引入 AS 外部路由並且擴散到其他區域，但是 NSSA 仍舊不允許其他區域通告的 AS 外部路由進入該區域。為了使 NSSA 能夠引入 AS 外部路由，OSPF 定義了新的 LSA 型別，即 NSSA External LSA（型別 7 LSA）。NSSA ASBR 將產生型別 7 LSA，並在 NSSA 區域內洪泛。NSSA ABR 將會把型別 7 LSA 轉換成 5 類 LSA，並洪泛到其他區域。

1.3.2 完全末梢區域

完全末梢區域（Totally Stubby Areas）是 Cisco 特有的區域型別。完全末梢區域不僅不允許 AS 外部路由通告在其內部洪泛，還不允許區域間彙總路由（Network Summary LSA

，即類 3 LSA）在其內部洪泛。同末梢區域一樣，完全末梢區域 ABR 也會向該區域內所有路由器通告一條預設路由，任何發往其他區域以及 AS 外部網路的資料流都將依據預設路由來轉發。將區域設定為完全末梢區域可以顯著的降低路由表條目的數量。

1.3.3 完全非純末梢區域

完全非純末梢區域（Totally NSSA）也是 Cisco 特有的區域型別，該種區域除了擁有和 NSSA 相同的特性外，還不允許型別 3 LSA 在該區域內部洪泛。完全非純末梢區域 ABR 也會向該區域內所有路由器通告一條預設路由。將區域設定為完全非純末梢區域也會顯著的降低路由表條目的數量。

OSPF 路由器型別

OSPF 定義了以下 4 種路由器型別：

內部路由器（Internal Router）
骨幹路由器（Backbone Router）
區域邊界路由器（Area Border Router，ABR）
自治系統邊界路由器（Autonomous System Boundary Router，ASBR）

一臺路由器可以同時屬於多種型別，如右圖所示，R2 同時屬於多種型別路由器。

每一臺 OSPF 路由器都有一個路由器識別符號（Identifier），一般寫作路由器 ID。路由器 ID 由一個長度為 32 bits 的欄位所定義，通常用 IPv4 地址格式來表示（如 1.2.2.2）。如果沒有顯式的設定路由器 ID，則該路由器上最大的活躍邏輯介面 IP 地址將成為路由器 ID；如果路由器不存在邏輯介面，則最大的活躍物理介面 IP 地址將成為路由器 ID。注意，不要將路由器型別和指定路由器（Designated Router，DR）、備份指定路由器（Backup Designated Router，BDR）混淆，DR 和 BDR 是路由器介面屬性，而不是整個路由器的屬性。

2.1 內部路由器

如果一臺路由器上所有啟用了 OSPF 的介面都在同一區域，那麼這臺路由器就是內部路由器。

2.2 骨幹路由器

骨幹路由器是指至少有一個啟用了 OSPF 的介面是和骨幹區域（Area 0）相連的路由器。一臺骨幹路由器也可以同時是 ABR 或 ASBR，如上圖中的 R2 和 R3。

2.3 區域邊界路由器

區域邊界路由器是指連線一個或者多個區域的路由器。區域邊界路由器為每一個與之相連的區域維護一份鏈路狀態資料庫，因此區域邊界路由器需要比內部路由器更多的記憶體資源和更高效能的處理器。

2.4 自治系統邊界路由器

自治系統邊界路由器（ASBR）用來把從其他路由協議（如 BGP、EIGRP、其他程序號的 OSPF 等）學習到的路由以路由重分發的方式注入到 OSPF 程序中，從而使得整個 OSPF 域內的路由器都可以學習到這些路由（除了末梢區域內的路由器）。一臺 ASBR 可以是 OSPF 域內非末梢區域的任何路由器，它可以是內部路由器、區域邊界路由器、骨幹路由器。

OSPF 網路型別

OSPF 定義了以下 4 種網路型別：

點到點網路（point-to-point）
廣播網路（broadcast）
非廣播多路訪問網路（non-broadcast multi-access，NBMA）
點到多點網路（Point-to-MultiPoint）

3.1 點到點網路

點到點網路，例如 E1、SONET，是單獨連線一對路由器的網路。點到點網路上的一對 OSPF 路由器形成完全鄰接關係（Full Adjacency），並且不進行 DR 和 BDR 的選舉。點到點網路上的路由器使用群播地址 224.0.0.5 傳送 OSPF 協議資料包。

3.2 廣播網路

廣播網路即可以同時連線多於兩臺裝置的網路，如乙太網、令牌環網、FDDI。廣播網路上的路由器傳送的群播 / 廣播資料包會被其他與之相連的路由器收到。在廣播網路上的 OSPF 路由器會選舉一臺指定路由器（DR）和一臺備份指定路由器（BDR）。所有始發於 DR 和 BDR 的 OSPF 資料包使用目的地址 224.0.0.5，以群播方式傳送到所有其他 OSPF 路由器，所有其他的路由器都將使用目的地址 224.0.0.6，以群播方式傳送 OSPF 資料包到 DR 和 BDR。所有其他的路由器只與 DR 和 BDR 建立完全鄰接關係。

3.3 非廣播多路訪問網路

NBMA 網路，諸如 X.25、幀中繼、ATM 等，可以同時連線兩臺以上的路由器，但是這種網路沒有廣播資料包的能力。一臺處於 NBMA 網路上的路由器傳送的群播 / 廣播資料包將不能被其他與之相連的路由器收到。在 NBMA 網路上需要選舉 DR 和 BDR，並且所有的 OSPF 資料包都是單播發送的。

3.4 點到多點網路

點到多點網路是 NBMA 網路的一個特殊設定，可以看作是一群點到點鏈路的集合，因此在該種網路上不必選舉 DR 和 BDR。點到多點網路上 OSPF 的行為和點到點網路 OSPF 的行為一樣，也使用群播地址 224.0.0.5 傳送 OSPF 協議資料包。

虛鏈路

虛鏈路被路由器認為是沒有編號的點到點網路的一種特殊設定，在虛鏈路上 OSPF 資料包是以單播方式傳送的。不能人工設定一個介面的網路型別為虛鏈路。

此外還有一種特殊的網路型別，稱之 Loopback 型別。OSPF 路由器上的環回介面在預設狀態下均為此型別。不能人工設定一個介面的網路型別為 Loopback。

指定路由器和備份指定路由器

在廣播多路訪問網路和 NBMA 網路上會選舉 DR 和 BDR。所有其他路由器只與 DR 和 BDR 建立完全鄰居關係，其他路由器之間的鄰居狀態停留在 2-Way 狀態。所有其他路由器使用群播目的地址 224.0.0.6 向 DR 和 BDR 傳送鏈路狀態更新。

如果在多路訪問網路中不選舉 DR，所有路由器之間都建立完全鄰接關係，會產生很多不必要的 LSA。假設一個多路訪問網路上有 n 臺路由器，那麼就會建立 n (n-1)/2 個鄰接關係。每臺路由器都會產生 n-1 條 LSA 到與之建立鄰接關係的路由器，再加上 1 條網路 LSA，最終這個網路上會產生 n² 條 LSA，並且其中很多都是重複的 LSA 副本。

DR 完成以下工作：

描述該多路訪問網路和與其相連的路由器。
管理該多路訪問網路上的 LSA 洪泛擴散過程。

DR 本後的概念是將多路訪問網路看作一個 “偽節點（Pseudo Node）”。當 SPF 進行計算的時候，把鏈路看作一個節點，與該鏈路相連的路由器也是連線到這個節點上的。從與偽節點相連的路由器到這個偽節點的代價是該路由器與這個多路訪問網路相連的介面的出站代價，從偽節點到任何與之相連的路由器的代價都為 0。一臺路由器可能連線到多個多路訪問網路，該路由器可能是它所連線的其中一個多路訪問網路的 DR，也可能不是它所連線的另一個多路訪問網路的 DR，也就是說，DR 是路由器介面的屬性，而不是整個路由器的屬性。

為了避免因 DR 失效導致的單點故障，多路訪問網路上還將選舉 BDR。DR 失效時，BDR 將成為 DR，由於網路上其他路由器已經和 BDR 形成了完全鄰接關係，因此可以將 DR 失效對網路的影響降至最低。

DR 和 BDR 的相關選舉規則如下：

如果一臺 OSPF 路由器的介面優先順序（Priority）為 0，那麼這臺路由器永遠不能成為 DR 或 BDR。
具有最高優先順序的路由器將會選舉為 DR，具有次高優先順序的路由器將會選舉為 BDR。
如果同時有多臺路由器具有相同的優先順序，那麼具有最高路由器 ID 的路由器將會選舉為 DR。
當 DR 失效時，BDR 將成為 DR，並將重新選舉一個 BDR。
優先順序的取值範圍為 0-255，更高的優先順序意味著路由器有更大的機會成為 DR。
如果一臺具有更高優先順序的路由器在選舉完 DR 和 BDR 之後接入網路，該路由器將不會成為 DR 或 BDR，直到 DR 和 BDR 失效，當 DR 失效，具有更高優先順序的路由器也只會成為 BDR。即 DR 和 BDR 的選舉不是搶佔式的。

OSPF 鄰接關係

在 OSPF 路由器之間互相交換資訊之前，必須先建立鄰接關係。

兩臺 OSPF 路由器要建立完全鄰接關係，以下引數必須相同：

Hello 時間間隔
Dead 時間間隔
區域編號
認證（如果啟用了認證）
鏈路 MTU 大小
子網掩碼
子網號
末梢區域設定

一般來說，建立 OSPF 完全鄰接時會經過以下狀態：

失效狀態（Down）：這是鄰居會話的初始狀態，表示最近沒有從鄰居收到資訊。在 NBMA 網路上，可能仍然會以較低頻率向處於 Down 狀態的鄰居傳送 Hello 資料包。
嘗試狀態（Attempt）：該狀態僅僅適用於連線在 NBMA 網路上的鄰居。該狀態表示最近沒有從鄰居收到資訊，但仍需要作進一步的嘗試，來聯絡鄰居。這時按某一特定間隔向鄰居傳送 Hello 資料包。
初始狀態（Init）: 在此狀態下，表示最近收到了從鄰居發來的 Hello 資料包。但是，仍然沒有和鄰居建立雙向通訊（Bidirectional Communication），例如，路由器自身並沒有出現在鄰居傳送的 Hello 資料包中。
雙向通訊狀態（2-Way）：此狀態意味著兩臺路由器之間建立了雙向通訊。在此狀態下還將進行 DR 和 BDR 的選舉（只有處於 2-Way 狀態的路由器才有資格參選 DR 和 BDR）
資訊交換初始狀態（ExStart）：這個狀態是建立鄰接關係的第一步。該狀態的目標是決定資訊交換時路由器的主從關係，並確定初始資料庫描述（DD）資料包的序列號。具有最高路由器 ID 的路由器將成為主路由器。
資訊交換狀態（ExChange）：在此狀態的路由器透過向鄰居傳送 DD 資料包來描述其完整的鏈路狀態資料庫。每一個 DD 資料包都有一個序列號，並且需要被顯式的確認。在任何時候，每次只能傳送一個 DD 資料包。在此狀態下，路由器也可以傳送鏈路狀態請求資料包，用來向鄰居請求最新的 LSA。實際上，這些狀態的鄰接關係完全有能力傳送和接收所有型別的 OSPF 協議資料包。
資訊載入狀態（Loading）：在此狀態下，路由器將會向鄰居路由器傳送鏈路狀態請求資料包，用來請求資訊交換狀態發現的最新的 LSA。
完全鄰接狀態（Full）：在此狀態下，鄰居路由器形成完全鄰接關係。這些鄰接關係將會在路由器 LSA 和網路 LSA 中被描述。

OSPFv2 資料包型別和格式

OSPFv2 定義了以下 5 種協議資料包型別：

Hello 包 HELLO
資料庫描述包 DBD
鏈路狀態請求包 LSR
鏈路狀態更新包 LSU
鏈路狀態確認包 LSAck

7.1 OSPF 包頭

5 種 OSPF 訊息有共通的 24 位元組的頭部結構。其結構如下：

7.2 Hello 包

Hello 包的 OSPF 包型別為 1。這些包被週期性的從各個介面（包括虛鏈路）發出，用來建立和維護鄰居關係。另外，在支援群播或廣播的物理網路上，Hello 包使用群播地址（通常為 224.0.0.5) 傳送。

Hello 包的傳送間隔由 HelloInterval 指定（通常為 10s），路由器將會先發出不包含鄰居欄位的空 Hello 包，當收到鄰接路由器的 Hello 包之後，將對方的路由器標識放入本機的 Hello 包中進行群播，這種包含鄰居欄位的包，也被稱為 HelloSeen 包。假如在間隔達到 RouterDeadInterval 所規定的時長（通常為 40s）內仍未收到一個已建立連線的路由器的 Hello 包，路由器將會終止這一連線。將對方的狀態轉為 Down。

Hello 包的格式如下：

7.3 資料庫描述包

資料庫描述包（Database Description）的 OSPF 包型別為 2。當鄰接關係初始化後，便開始交換這些資料包。它們描述了鏈路狀態資料庫的摘要資訊（只包含 LSA 的頭部資訊）。

資料庫描述包包含兩種，即空資料庫描述包和包含 LSA 頭部資訊的資料庫描述包。

當兩個路由器互相收到 HelloSeen 包之後，他們將會開始互相傳送空資料庫描述包，空資料庫描述包被用來進行主從關係的確定。

通常以路由標識較大的為 Master，當主從關係確立之後，從機將會使用主機的序號向主機發送第一個包含 LSA 頭部資訊的資料庫描述包。主機將會在收到從機的資料庫描述包之後傳送自己的序號加一的資料庫描述包，作為對於從機的收到確認。在這樣的互動過程中，只有主機可以更改序號 (DD sequence number)，從機使用主機序號。資料庫描述包的格式如下：

7.4 鏈路狀態請求包

鏈路狀態請求包（Link State Request）的 OSPF 包型別為 3。在交換資料庫描述包之後，路由器便知道其自身鏈路狀態資料庫缺少哪些 LSA，以及哪些 LSA 是過期的。這時就可以傳送鏈路狀態請求包來請求對方傳送缺少的 LSA 和最新的 LSA。鏈路狀態請求包格式如下：

7.5 鏈路狀態更新包

鏈路狀態更新包（Link State Update）的 OSPF 包型別為 4。LSA 的洪泛就是由此型別的包實現的。每一個鏈路狀態更新包可能包含多條 LSA 資訊。這裡的 LSA 資訊是完整的，而不像資料庫描述包只包含 LSA 的頭部資訊。

鏈路狀態更新包的格式如下：

7.6 鏈路狀態確認包

鏈路狀態確認包（Link State Acknowledgement）的 OSPF 包型別為 5。為了確保 LSA 的洪泛是可靠的，LSA 資訊必須被顯式的確認。鏈路狀態確認包的格式如下：

LSA 型別

OSPF 定義了 11 種 LSA，所有型別的 LSA 都以一個 20 位元組的通用 LSA 頭部開始。這些不同型別的 LSA 共同描述了 OSPF 域內的網路拓撲結構。所有的 LSA 都儲存在 LSDB 中。SPF 演算法根據 LSDB 中的資訊計算出最佳路徑。

路由器 LSA（Router-LSA）：路由器 LSA 的型別為 1。每一臺 OSPF 路由器生成一條路由器 LSA。該 LSA 描述了路由器的介面狀態，以及每一個介面的出站代價。路由器 LSA 只能在始發他們的 OSPF 區域內進行洪泛，不能洪泛到其他區域。
網路 LSA（Network-LSA）：網路 LSA 的型別為 2。網路 LSA 是 DR 為了描述連線到多路訪問網路並且和 DR 建立了完全鄰接關係的路由器而生成的，包括 DR 本身。和路由器 LSA 一樣，網路 LSA 也只能在始發這條 LSA 的區域內進行洪泛。
彙總 LSA（Summary-LSA）：彙總 LSA 的型別為 3。此類 LSA 描述了區域間的網路，由 ABR 生成。對於末梢區域，彙總 LSA 同樣被用於描述預設路由。
ASBR 彙總 LSA（ASBR Summary-LSA）：ASBR 彙總 LSA 的型別為 4，也是由 ABR 生成。ASBR 彙總 LSA 通告的是一臺區域外部的 ASBR 路由器，而不像彙總 LSA 通告的是區域外的網路。
自治系統外部 LSA（AS-External-LSA）：自治系統外部 LSA 的型別為 5，由 ASBR 生成。此類 LSA 描述 AS 外部的網路，並可以洪泛到所有非末梢區域中去。
組成員 LSA（Group-Membership-LSA ）：組成員 LSA 型別為 6。組成員 LSA 是對標準 OSPF 的一個擴充套件，使其支援群播路由功能，擴充套件後的 OSPF 稱之 Multicast Open Shortest Path First（MOSPF）。
NSSA 外部 LSA（NSSA-External-LSA）：NSSA 外部 LSA 型別為 7。此類 LSA 由 NSSA 區域內的 ASBR 生成，也用來描述 AS 外部的網路。NSSA 外部 LSA 僅僅在始發他們的 NSSA 區域內進行洪泛，而不像自治系統外部 LSA 可以洪泛到所有非末梢區域。
鏈路本地 LSA（Link-Local LSA）：鏈路本地 LSA 型別為 8。該 LSA 專門用於 OSPFv3（用於 IPv6 網路的 OSPF）。鏈路本地 LSA 包含了每一個介面的鏈路本地地址和一個 IPv6 地址列表。

RFC2370 定義了 3 種新的 LSA，稱作不透明 LSA（Opaque LSA）。這 3 種新的 LSA 為 OSPF 的擴充套件性提供了通用的機制。它們可以攜帶用於 OSPF 的資訊，也可以直接攜帶應用的資訊。

目前有以下 3 種不透明 LSA，它們的區別主要是洪泛範圍不同：

型別 9 不透明 LSA：洪泛範圍僅僅是本地鏈路。
型別 10 不透明 LSA：洪泛範圍是始發該 LSA 的區域。
型別 11 不透明 LSA：洪泛範圍是整個 OSPF 域。

OSPF 路徑選擇

OSPF 使用 “開銷（Cost）” 作為路由的度量值（Metric），路徑的度量值越低，說明該路徑越好，具有最低度量值的路徑將裝入路由表。開銷是根據介面所配置的頻寬來計算的，頻寬越高，開銷越低。在 Cisco 路由器上，預設情況下使用公式 10^8 / 頻寬（10^8 是基準值，可以調整；頻寬的單位是 bit/s）來計算代價。例如，介面頻寬為 100Mbit/s，則開銷為 1；介面頻寬為 1000Mbit/s，計算所得的開銷還是 1（如果計算所得的開銷小於 1，則按 1 計算）。

OSPF 有以下 4 種路由型別，優先順序由高到低排序如下：

內部路由：去往區域內部網路的路由。
區域間路由：去往不同區域網路的路由。
型別 1 的外部路由：去往 OSPF 域外的路由，型別 1 的外部路由的度量值包括了外部路由的度量值和到 ASBR 的度量值。
型別 2 的外部路由：去往 OSPF 域外的路由，型別 2 的外部路由的度量值只包括了外部路由的度量值。

因此如果有多條去往相同目的地的路由具有相同的度量值，那麼將比較它們的路由型別。假設有兩條去往相同目的地的路由 A 和路由 B 的度量值都是 30，A 是內部路由，B 區域間路由，則 A 將會被裝入路由表。如果有多條去往相同目的地的路由具有相同的型別，相同的度量值，則它們都將被裝入路由表，並在不同路由之間進行負載均衡。

OSPF 的反擊機制

大多數執行 OSPF 的路由器具有一種被稱為 (fight back) 的安全機制。即當一個路由器收到關於自己的虛假或者不正確的 LSA 資訊時，它將立刻發出一個包含自己正確的 LSA 的 LSU 報文，這一機制被稱為反擊或者自反擊。

不過需要注意的是，反擊機制並不是 OSPF 協議官方規定的安全機制。在 RFC2328 中，沒有對此機制的任何描述。