メインコンテンツへスキップ
  1. ネットワーク 記事一覧/
  2. OSPF記事一覧/

OSPFの状態遷移

目次

OSPFの状態遷移とは

OSPFのルータは、同じリンク上のルータをHelloパケットで発見してから、LSDBを同期して隣接関係(アジャセンシー)を確立するまでの間に、いくつかの状態を順に通過します。この状態はネイバーごとに管理され、show ospf neighborState欄に表示されます。

障害切り分けの場面では、「どの状態で止まっているか」が原因の切り分けにそのまま使えます。たとえばInitのままならHelloは届いているが相手に自分が見えていない、ExStartのままならMTUが一致していない、といった具合です。本記事では、各状態の意味と遷移のきっかけを整理し、実機(Cisco IOS XR)のログとパケットキャプチャで実際の遷移を確認します。パケットの中身についてはOSPFパケットの種類とヘッダーフォーマットを参照してください。

ネイバーの状態一覧

状態説明
DownネイバーからHelloを受信していない初期状態。Deadインターバルが満了してネイバーが消えたときもこの状態になる。
AttemptNBMAネットワークでのみ使われる状態。手動設定したネイバーに対してユニキャストでHelloを送り、応答を待っている。
InitネイバーからHelloを受信したが、そのHelloのネイバー一覧に自分のルータIDが含まれていない状態。通信が片方向でしか確認できていない。
2-WayネイバーのHelloに自分のルータIDが載り、双方向の通信が確認できた状態。マルチアクセスネットワークでは、この時点でDR/BDRの選出が行われる。
ExStartLSDBを同期する準備として、DBDを交換してマスター/スレーブと初期シーケンス番号を決めている状態。ルータIDが大きい方がマスターになる。
ExchangeDBDでLSDBの目次(LSAヘッダーの一覧)を交換している状態。
LoadingDBDで判明した不足分のLSAをLSRで要求し、LSUで受け取っている状態。
FullLSDBの同期が完了し、隣接関係が確立した状態。

パケットと状態の対応

各状態は、やり取りされるパケットと1対1で対応しています。

  • Init: 相手からHelloを受信した時点。まだ相手のHelloのネイバー一覧に自分のルータIDは載っていません。
  • 2-Way: 相手のHelloのネイバー一覧に自分のルータIDを見つけた時点。ここで双方向の通信が確認できます。
  • ExStart: 最初のDBD(I・M・MSビットがすべて1)を交換し、ルータIDの大きい方をマスターとして決めます。
  • Exchange: LSAヘッダーを載せたDBDを交換します。
  • Loading: 不足しているLSAをLSRで要求し、LSUで受け取ります。
  • Full: 要求したLSAをすべて受け取り、LSDBの同期が完了した時点。

状態はネイバーごとに独立して管理されるため、R1から見たR2の状態とR2から見たR1の状態は、遷移の途中では一致しないことがあります。

show ospf neighborに表示されるのは「自分から見た相手の状態」です。片側だけがExStartで止まっている、といった非対称な状態も起こりうるため、切り分けでは両側の出力を確認します。

2-Wayで止まるケース

マルチアクセスネットワークでは、DR・BDRのいずれでもないルータ(DROther)同士は隣接関係を結ばず、2-Wayのまま維持されます。これは異常ではなく、LSAの交換をDR経由に集約するためのOSPFの設計です。DROther同士がLSDBの同期を行わなくても、DRを介して同じLSAが配られるため、エリア内のLSDBは一致します。DR/BDRの選出については、DRとBDRで解説します。

なお、ルータ2台だけが接続されたイーサネットリンクでは、片方がDR、もう片方がBDRになるため、両者はFullになります。

状態が進まないときに疑うポイント

止まる状態よくある原因
Down のままHelloが届いていない。インタフェースのダウン、OSPFの有効化漏れ、パッシブインタフェース設定、ACLによるブロックなど。
Init のまま片方向でしかHelloが届いていない。認証設定の不一致、片側のみのACL、マルチキャストが通らない構成など。
2-Way のまま(DROther以外)Helloパラメータの不一致。エリアID、Hello/Deadインターバル、サブネットマスク、スタブエリアのフラグなどが一致していないと、ネイバー関係が成立しない。
ExStart / Exchange を繰り返すインタフェースMTUの不一致が代表的な原因。DBDに載っているInterface MTUが自身のMTUより大きいと、受信側はそのDBDを破棄する。状態は固定されず、Init・2-Way・ExStart・Downを繰り返す(後述の検証)。
Loading のまま要求したLSAが返ってこない。LSAの破損やパケットロスなど。

実機での検証

検証環境

OSPFとはと同じ、Cisco IOS XR(XRd)ルータ3台を直線に接続したシングルエリア構成で検証します。R1でclear ospf 1 processを実行して隣接関係を張り直し、R1側で状態遷移を追いかけます。

状態遷移のログ

IOS XRではdebug ospf <プロセスID> adjで、隣接関係の確立過程を詳細に記録できます。デバッグの出力はログバッファに入るため、show loggingで読み出せます。

デバッグの有効化と無効化
RP/0/RP0/CPU0:R1#debug ospf 1 adj
RP/0/RP0/CPU0:R1#show debug
####  debug flags set from tty 'vty0'  ####
ospf 1 adj flag is ON with value 0

(確認後)
RP/0/RP0/CPU0:R1#undebug all
show debugの出力にあるとおり、デバッグの設定は実行したセッション(tty)に紐づきます。SSHでログインしてデバッグを有効にした場合、そのセッションを閉じるとデバッグも解除されるため、デバッグの有効化・事象の再現・ログの確認は同じセッション内で行う必要があります。デバッグは負荷が高いため、確認が終わったらundebug allで必ず止めます。

デバッグを有効にした状態でR1のclear ospf 1 processを実行し、隣接関係が張り直される過程を記録したものです。

R1 隣接関係の確立過程(debug ospf 1 adj)
RP/0/RP0/CPU0:Sep  5 06:56:44.755 UTC: ospf[1035]:  intf Loopback0 going Down
RP/0/RP0/CPU0:Sep  5 06:56:44.755 UTC: ospf[1035]:  1.1.1.1 address 1.1.1.1 on Loopback0 is dead, state DOWN
RP/0/RP0/CPU0:Sep  5 06:56:44.755 UTC: ospf[1035]:  intf GigabitEthernet0/0/0/0 going Down
RP/0/RP0/CPU0:Sep  5 06:56:44.755 UTC: ospf[1035]:  1.1.1.1 address 10.1.2.1 on GigabitEthernet0/0/0/0 is dead, state DOWN
RP/0/RP0/CPU0:Sep  5 06:56:44.755 UTC: ospf[1035]:        DR: 2.2.2.2(Id) 10.1.2.2(IP Addr)
RP/0/RP0/CPU0:Sep  5 06:56:44.755 UTC: ospf[1035]:       BDR: none 
RP/0/RP0/CPU0:Sep  5 06:56:44.755 UTC: ospf[1035]:  2.2.2.2 address 10.1.2.2 on GigabitEthernet0/0/0/0 is dead, state DOWN
RP/0/RP0/CPU0:Sep  5 06:56:44.756 UTC: ospf[1035]:        DR: none 
RP/0/RP0/CPU0:Sep  5 06:56:44.756 UTC: ospf[1035]:       BDR: none 
RP/0/RP0/CPU0:Sep  5 06:56:44.769 UTC: ospf[1035]:  intf Loopback0 going Up in area 0
RP/0/RP0/CPU0:Sep  5 06:56:44.769 UTC: ospf[1035]:  intf GigabitEthernet0/0/0/0 going Up in area 0
RP/0/RP0/CPU0:Sep  5 06:56:53.509 UTC: ospf[1035]:  2 Way Communication to 2.2.2.2 on GigabitEthernet0/0/0/0, state 2WAY
RP/0/RP0/CPU0:Sep  5 06:56:53.509 UTC: ospf[1035]:  Backup event seen before WAIT timer on GigabitEthernet0/0/0/0
RP/0/RP0/CPU0:Sep  5 06:56:53.509 UTC: ospf[1035]:        DR: 2.2.2.2(Id) 10.1.2.2(IP Addr)
RP/0/RP0/CPU0:Sep  5 06:56:53.509 UTC: ospf[1035]:       BDR: 1.1.1.1(Id) 10.1.2.1(IP Addr)
RP/0/RP0/CPU0:Sep  5 06:56:53.509 UTC: ospf[1035]:  Send DBD  to 2.2.2.2(10.1.2.2) on GigabitEthernet0/0/0/0 seq 0x4fd22be0 opt 0x52 flag 0x7 len 32
RP/0/RP0/CPU0:Sep  5 06:56:53.514 UTC: ospf[1035]:  Rcv DBD  from 2.2.2.2(10.1.2.2) on GigabitEthernet0/0/0/0 seq 0x597a68d5 opt 0x52 flag 0x7 len 32 mtu 1500 state EXSTART vrf default vrfid 0x60000000
RP/0/RP0/CPU0:Sep  5 06:56:53.514 UTC: ospf[1035]:  NBR Negotiation Done. We are the SLAVE for nbr 2.2.2.2 on GigabitEthernet0/0/0/0, area 0
RP/0/RP0/CPU0:Sep  5 06:56:53.514 UTC: ospf[1035]:  Send DBD  to 2.2.2.2(10.1.2.2) on GigabitEthernet0/0/0/0 seq 0x597a68d5 opt 0x52 flag 0x2 len 52
RP/0/RP0/CPU0:Sep  5 06:56:53.520 UTC: ospf[1035]:  Rcv DBD  from 2.2.2.2(10.1.2.2) on GigabitEthernet0/0/0/0 seq 0x597a68d6 opt 0x52 flag 0x1 len 92 mtu 1500 state EXCHANGE vrf default vrfid 0x60000000
RP/0/RP0/CPU0:Sep  5 06:56:53.520 UTC: ospf[1035]:  Exchange Done with 2.2.2.2 on GigabitEthernet0/0/0/0
RP/0/RP0/CPU0:Sep  5 06:56:53.520 UTC: ospf[1035]:  sent LS REQ packet to 10.1.2.2, length 36
RP/0/RP0/CPU0:Sep  5 06:56:53.520 UTC: ospf[1035]:  Send DBD  to 2.2.2.2(10.1.2.2) on GigabitEthernet0/0/0/0 seq 0x597a68d6 opt 0x52 flag 0 len 32
RP/0/RP0/CPU0:Sep  5 06:56:53.525 UTC: ospf[1035]:  Synchronized with 2.2.2.2 on GigabitEthernet0/0/0/0, state FULL
RP/0/RP0/CPU0:Sep  5 06:56:53.525 UTC: ospf[1035]:  Received LS REQ packet from 2.2.2.2/10.1.2.2, length 12
RP/0/RP0/CPU0:Sep  5 06:57:03.315 UTC: ospf[1035]:        DR: 2.2.2.2(Id) 10.1.2.2(IP Addr)
RP/0/RP0/CPU0:Sep  5 06:57:03.315 UTC: ospf[1035]:       BDR: 1.1.1.1(Id) 10.1.2.1(IP Addr)

各行を状態と対応させると、次のようになります。

時刻ログ対応する状態
06:56:44.755intf GigabitEthernet0/0/0/0 going Down / 2.2.2.2 ... is dead, state DOWNプロセス再起動により、いったんすべてのネイバーがDownになる
06:56:44.769intf GigabitEthernet0/0/0/0 going Up in area 0インタフェースでOSPFが再び有効になり、Helloの送信を開始
06:56:53.5092 Way Communication to 2.2.2.2 ... state 2WAYR2のHelloに自分のルータIDが載り、2-Wayに遷移
06:56:53.509DR: 2.2.2.2(Id) / BDR: 1.1.1.1(Id)2-Wayの時点でDR/BDRが決まる(R2がDR、R1がBDR)
06:56:53.509〜514Send DBD ... flag 0x7 / Rcv DBD ... flag 0x7 ... state EXSTARTI・M・MSビットを立てたDBDを交換するExStart
06:56:53.514NBR Negotiation Done. We are the SLAVE for nbr 2.2.2.2ルータIDの大きいR2がマスター、R1がスレーブに決定
06:56:53.520Rcv DBD ... flag 0x1 ... state EXCHANGE / Exchange DoneLSAヘッダーを載せたDBDを交換するExchange
06:56:53.520sent LS REQ packet to 10.1.2.2不足しているLSAを要求するLoading
06:56:53.525Synchronized with 2.2.2.2 ... state FULLLSDBの同期が完了しFullに到達

Helloを受信して2-Wayになるまでに約9秒かかっている一方、2-WayからFullまでは16ミリ秒しかかかっていません。前半はネイバーのHello(10秒間隔)を待つ時間で、後半のDBD・LSR・LSU・LSAckのやり取りは一瞬で終わることが分かります。

show ospf neighbor での状態表示

show ospf neighborState欄は、状態/そのリンクでのネイバーの役割という形式で表示されます。

R1 Full到達後
RP/0/RP0/CPU0:R1#show ospf neighbor
Sat Sep  5 07:07:35.271 UTC

* Indicates MADJ interface
# Indicates Neighbor awaiting BFD session up

Neighbors for OSPF 1

Neighbor ID     Pri   State           Dead Time   Address         Interface
2.2.2.2         1     FULL/DR         00:00:37    10.1.2.2        GigabitEthernet0/0/0/0
    Neighbor is up for 00:00:35

Total neighbor count: 1

前述のとおり2-WayからFullまでは一瞬で終わるため、show ospf neighborを繰り返し実行しても途中の状態はほとんど捉えられません。一方、ルータを起動した直後は、DR/BDRの選出を待つWaitタイマー(40秒)が動くため、2-Wayの状態をしばらく観察できます。

R1 起動直後(Waitタイマー動作中)
RP/0/RP0/CPU0:R1#show ospf neighbor
Sat Sep  5 06:54:58.365 UTC

* Indicates MADJ interface
# Indicates Neighbor awaiting BFD session up

Neighbors for OSPF 1

Neighbor ID     Pri   State           Dead Time   Address         Interface
2.2.2.2         1     2WAY/DROTHER    00:00:39    10.1.2.2        GigabitEthernet0/0/0/0
    Neighbor is up for 00:00:00

Total neighbor count: 1

2WAY/DROTHERは「状態は2-Way、この時点ではDRもBDRも決まっていない(DROther扱い)」という意味です。Waitタイマーが満了してDR/BDRが選出されると、FULL/DRのような表示に変わります。

MTU不一致でFullにならない場合

R1のGi0/0/0/0のMTUを1400バイトに変更し、R2(既定の1500バイト)との間で不一致を作ります。

R1 に投入した設定(MTU不一致を作る)
interface GigabitEthernet0/0/0/0
 mtu 1400
!

しばらく待ってから両側の状態を確認すると、隣接関係が確立できていません。R1とR2で見えている状態が異なる点にも注目してください。

R1 の状態
RP/0/RP0/CPU0:R1#show ospf neighbor
Sat Sep  5 07:00:03.667 UTC

Neighbors for OSPF 1

Neighbor ID     Pri   State           Dead Time   Address         Interface
2.2.2.2         1     INIT/DROTHER    00:00:32    10.1.2.2        GigabitEthernet0/0/0/0

Total neighbor count: 1
R2 の状態
RP/0/RP0/CPU0:R2#show ospf neighbor
Sat Sep  5 07:00:13.004 UTC

Neighbors for OSPF 1

Neighbor ID     Pri   State           Dead Time   Address         Interface
1.1.1.1         1     DOWN/DROTHER       -        10.1.2.1        GigabitEthernet0/0/0/0
3.3.3.3         1     FULL/DR         00:00:34    10.2.3.3        GigabitEthernet0/0/0/1
    Neighbor is up for 00:05:11

Total neighbor count: 2

R1側でデバッグを有効にすると、DBDを受信するたびに拒否している様子が記録されます。

R1 MTU不一致時のデバッグ出力
RP/0/RP0/CPU0:Sep  5 07:01:43.600 UTC: ospf[1035]:  Rcv DBD  from 2.2.2.2(10.1.2.2) on GigabitEthernet0/0/0/0 seq 0x3e71af09 opt 0x52 flag 0x7 len 32 mtu 1500 state INIT vrf default vrfid 0x60000000
RP/0/RP0/CPU0:Sep  5 07:01:43.600 UTC: ospf[1035]: Nbr 2.2.2.2 has larger interface MTU
RP/0/RP0/CPU0:Sep  5 07:01:51.182 UTC: ospf[1035]:  2 Way Communication to 2.2.2.2 on GigabitEthernet0/0/0/0, state 2WAY
RP/0/RP0/CPU0:Sep  5 07:01:51.183 UTC: ospf[1035]:  Send DBD  to 2.2.2.2(10.1.2.2) on GigabitEthernet0/0/0/0 seq 0x60209cc9 opt 0x52 flag 0x7 len 32
RP/0/RP0/CPU0:Sep  5 07:01:53.531 UTC: ospf[1035]:  Rcv DBD  from 2.2.2.2(10.1.2.2) on GigabitEthernet0/0/0/0 seq 0x3e71af09 opt 0x52 flag 0x7 len 32 mtu 1500 state EXSTART vrf default vrfid 0x60000000
RP/0/RP0/CPU0:Sep  5 07:01:53.531 UTC: ospf[1035]: Nbr 2.2.2.2 has larger interface MTU
RP/0/RP0/CPU0:Sep  5 07:01:55.885 UTC: ospf[1035]:  2.2.2.2 address 10.1.2.2 on GigabitEthernet0/0/0/0 is dead, state DOWN

Nbr 2.2.2.2 has larger interface MTUが原因を示しています。DBDにはInterface MTUが載っており、受信側は自分のインタフェースMTUより大きい値を受け取るとそのDBDを破棄します。R2側では、DBDの再送を繰り返した末にネイバーをダウンと判断したログが残ります。

R2 のログ
RP/0/RP0/CPU0:R2#show logging | include ADJCHG
RP/0/RP0/CPU0:Sep  5 06:56:53.528 UTC: ospf[1035]: %ROUTING-OSPF-5-ADJCHG : Process 1, Nbr 1.1.1.1 on GigabitEthernet0/0/0/0 in area 0 from LOADING to FULL, Loading Done, vrf default vrfid 0x60000000 
RP/0/RP0/CPU0:Sep  5 06:59:46.822 UTC: ospf[1035]: %ROUTING-OSPF-5-ADJCHG : Process 1, Nbr 1.1.1.1 on GigabitEthernet0/0/0/0 in area 0 from EXSTART to DOWN, Neighbor Down: too many DBD retransmissions, vrf default vrfid 0x60000000 

from EXSTART to DOWN, Neighbor Down: too many DBD retransmissionsが、MTU不一致のときの典型的なログです。状態はExStartで固定されるのではなく、Hello受信でInit・2-Wayまで進み、DBDの交換で失敗してDownに戻る、というサイクルを繰り返します。show ospf neighborを実行するタイミングによってINIT・2WAY・EXSTART・DOWNのどれもが見えるのはこのためです。

MTUの値はshow ospf interfaceで確認できます。両側のMTUを比べれば不一致はすぐ分かります。

MTU不一致時のR1(左)とR2(右)の値
R1: Transmit Delay is 1 sec, State DR, Priority 1, MTU 1386, MaxPktSz 1386
R2: Transmit Delay is 1 sec, State DR, Priority 1, MTU 1500, MaxPktSz 1500

R1のインタフェースMTUは1400バイトですが、OSPFが表示するMTUは1386バイトです。これはイーサネットヘッダー14バイトを引いたIPペイロードのMTUを表示しているためです。

本来はMTUを揃えるのが正しい対処ですが、揃えられない事情がある場合は、mtu-ignoreでDBDのMTUチェックを無効にできます。今回はMTUの小さいR1側に設定しました。

R1 に投入した設定(mtu-ignore)
router ospf 1
 area 0
  interface GigabitEthernet0/0/0/0
   mtu-ignore
  !
 !
!
R1 mtu-ignore設定後
RP/0/RP0/CPU0:R1#show ospf neighbor
Sat Sep  5 07:03:33.965 UTC

Neighbors for OSPF 1

Neighbor ID     Pri   State           Dead Time   Address         Interface
2.2.2.2         1     FULL/DR         00:00:31    10.1.2.2        GigabitEthernet0/0/0/0
    Neighbor is up for 00:00:55

Total neighbor count: 1

MTUが1386と1500のままでもFullに到達しました。ただしこれはDBDのチェックを省略しているだけで、実際に大きなパケットが流れると経路上で破棄される可能性は残ります。検証後はmtu-ignoreとMTUの設定を削除し、元の状態に戻しています。

IOS XRでインタフェースのMTU設定を削除するときは、no mtuではなくno mtu 1400のように値まで指定する必要がありました(no mtuでは削除されず、設定が残ったままになります)。

検証Config

検証終了後(MTUを既定値に戻した状態)のR1のrunning-configと、R1・R2のshow ospf neighborshow ospf interfaceshow loggingの出力です。

R1 config(r1_ospf-neighbor-state.cfg) をダウンロード

R1 show出力(r1_ospf-neighbor-state_show.txt) をダウンロード

R2 show出力(r2_ospf-neighbor-state_show.txt) をダウンロード

隣接関係の確立時にやり取りされるパケットそのものは、OSPFパケットの種類とヘッダーフォーマットでキャプチャを添えて解説しています。

参考

RFCタイトル概要
RFC 2328OSPF Version 2ネイバーの状態遷移はSection 10(The Neighbor Data Structure)で定義されている。

関連記事